Commit 85ffdd28 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  [libata] pata_pcmcia: Add additional id string (corsair, 1GB)
  libata: prevent devices with blank model names from being DMA blacklisted
  ata_piix: SATA 2port controller port map fix
  pata_cs5536: ATA driver for Geode companion chip
  libata: add ST9160821AS / 3.CCD to NCQ blacklist
  libata: fix revalidation issuing after configuration commands
  [libata] sata_nv: add SW NCQ support for MCP51/MCP55/MCP61
  [libata] pata_sil680: Add MMIO support
parents 43d39ae0 77ec15cc
...@@ -272,6 +272,15 @@ config PATA_CS5535 ...@@ -272,6 +272,15 @@ config PATA_CS5535
If unsure, say N. If unsure, say N.
config PATA_CS5536
tristate "CS5536 PATA support (Experimental)"
depends on PCI && X86 && !X86_64 && EXPERIMENTAL
help
This option enables support for the AMD CS5536
companion chip used with the Geode LX processor family.
If unsure, say N.
config PATA_CYPRESS config PATA_CYPRESS
tristate "Cypress CY82C693 PATA support (Very Experimental)" tristate "Cypress CY82C693 PATA support (Very Experimental)"
depends on PCI && EXPERIMENTAL depends on PCI && EXPERIMENTAL
......
...@@ -28,6 +28,7 @@ obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o ...@@ -28,6 +28,7 @@ obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o
obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o
obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o
obj-$(CONFIG_PATA_EFAR) += pata_efar.o obj-$(CONFIG_PATA_EFAR) += pata_efar.o
obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
......
...@@ -130,6 +130,7 @@ enum { ...@@ -130,6 +130,7 @@ enum {
ich8_sata_ahci = 9, ich8_sata_ahci = 9,
piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ piix_pata_mwdma = 10, /* PIIX3 MWDMA only */
tolapai_sata_ahci = 11, tolapai_sata_ahci = 11,
ich9_2port_sata = 12,
/* constants for mapping table */ /* constants for mapping table */
P0 = 0, /* port 0 */ P0 = 0, /* port 0 */
...@@ -238,19 +239,19 @@ static const struct pci_device_id piix_pci_tbl[] = { ...@@ -238,19 +239,19 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* SATA Controller 1 IDE (ICH8) */ /* SATA Controller 1 IDE (ICH8) */
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller 2 IDE (ICH8) */ /* SATA Controller 2 IDE (ICH8) */
{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* Mobile SATA Controller IDE (ICH8M) */ /* Mobile SATA Controller IDE (ICH8M) */
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (ICH9) */ /* SATA Controller IDE (ICH9) */
{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (ICH9) */ /* SATA Controller IDE (ICH9) */
{ 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9) */ /* SATA Controller IDE (ICH9) */
{ 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9M) */ /* SATA Controller IDE (ICH9M) */
{ 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9M) */ /* SATA Controller IDE (ICH9M) */
{ 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9M) */ /* SATA Controller IDE (ICH9M) */
{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (Tolapai) */ /* SATA Controller IDE (Tolapai) */
...@@ -448,6 +449,18 @@ static const struct piix_map_db tolapai_map_db = { ...@@ -448,6 +449,18 @@ static const struct piix_map_db tolapai_map_db = {
}, },
}; };
static const struct piix_map_db ich9_2port_map_db = {
.mask = 0x3,
.port_enable = 0x3,
.map = {
/* PM PS SM SS MAP */
{ P0, NA, P1, NA }, /* 00b */
{ RV, RV, RV, RV }, /* 01b */
{ RV, RV, RV, RV }, /* 10b */
{ RV, RV, RV, RV },
},
};
static const struct piix_map_db *piix_map_db_table[] = { static const struct piix_map_db *piix_map_db_table[] = {
[ich5_sata] = &ich5_map_db, [ich5_sata] = &ich5_map_db,
[ich6_sata] = &ich6_map_db, [ich6_sata] = &ich6_map_db,
...@@ -455,6 +468,7 @@ static const struct piix_map_db *piix_map_db_table[] = { ...@@ -455,6 +468,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
[ich6m_sata_ahci] = &ich6m_map_db, [ich6m_sata_ahci] = &ich6m_map_db,
[ich8_sata_ahci] = &ich8_map_db, [ich8_sata_ahci] = &ich8_map_db,
[tolapai_sata_ahci] = &tolapai_map_db, [tolapai_sata_ahci] = &tolapai_map_db,
[ich9_2port_sata] = &ich9_2port_map_db,
}; };
static struct ata_port_info piix_port_info[] = { static struct ata_port_info piix_port_info[] = {
...@@ -570,6 +584,17 @@ static struct ata_port_info piix_port_info[] = { ...@@ -570,6 +584,17 @@ static struct ata_port_info piix_port_info[] = {
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
}, },
[ich9_2port_sata] =
{
.sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
}; };
static struct pci_bits piix_enable_bits[] = { static struct pci_bits piix_enable_bits[] = {
......
...@@ -3984,6 +3984,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ...@@ -3984,6 +3984,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, }, { "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, },
{ "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, },
{ "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, }, { "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, },
{ "ST9160821AS", "3.CCD", ATA_HORKAGE_NONCQ, },
{ "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, },
{ "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, },
{ "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, },
...@@ -4013,8 +4014,14 @@ int strn_pattern_cmp(const char *patt, const char *name, int wildchar) ...@@ -4013,8 +4014,14 @@ int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
p = strchr(patt, wildchar); p = strchr(patt, wildchar);
if (p && ((*(p + 1)) == 0)) if (p && ((*(p + 1)) == 0))
len = p - patt; len = p - patt;
else else {
len = strlen(name); len = strlen(name);
if (!len) {
if (!*patt)
return 0;
return -1;
}
}
return strncmp(patt, name, len); return strncmp(patt, name, len);
} }
......
...@@ -1363,6 +1363,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) ...@@ -1363,6 +1363,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ata_eh_info *ehi = &qc->dev->link->eh_info;
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd; u8 *cdb = cmd->cmnd;
int need_sense = (qc->err_mask != 0); int need_sense = (qc->err_mask != 0);
...@@ -1376,14 +1377,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ...@@ -1376,14 +1377,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
case ATA_CMD_SET_FEATURES: case ATA_CMD_SET_FEATURES:
if ((qc->tf.feature == SETFEATURES_WC_ON) || if ((qc->tf.feature == SETFEATURES_WC_ON) ||
(qc->tf.feature == SETFEATURES_WC_OFF)) { (qc->tf.feature == SETFEATURES_WC_OFF)) {
ap->link.eh_info.action |= ATA_EH_REVALIDATE; ehi->action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap); ata_port_schedule_eh(ap);
} }
break; break;
case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
case ATA_CMD_SET_MULTI: /* multi_count changed */ case ATA_CMD_SET_MULTI: /* multi_count changed */
ap->link.eh_info.action |= ATA_EH_REVALIDATE; ehi->action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap); ata_port_schedule_eh(ap);
break; break;
} }
......
/*
* pata_cs5536.c - CS5536 PATA for new ATA layer
* (C) 2007 Martin K. Petersen <mkp@mkp.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Documentation:
* Available from AMD web site.
*
* The IDE timing registers for the CS5536 live in the Geode Machine
* Specific Register file and not PCI config space. Most BIOSes
* virtualize the PCI registers so the chip looks like a standard IDE
* controller. Unfortunately not all implementations get this right.
* In particular some have problems with unaligned accesses to the
* virtualized PCI registers. This driver always does full dword
* writes to work around the issue. Also, in case of a bad BIOS this
* driver can be loaded with the "msr=1" parameter which forces using
* the Machine Specific Registers to configure the device.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/libata.h>
#include <scsi/scsi_host.h>
#include <asm/msr.h>
#define DRV_NAME "pata_cs5536"
#define DRV_VERSION "0.0.5"
enum {
CFG = 0,
DTC = 1,
CAST = 2,
ETC = 3,
MSR_IDE_BASE = 0x51300000,
MSR_IDE_CFG = (MSR_IDE_BASE + 0x10),
MSR_IDE_DTC = (MSR_IDE_BASE + 0x12),
MSR_IDE_CAST = (MSR_IDE_BASE + 0x13),
MSR_IDE_ETC = (MSR_IDE_BASE + 0x14),
PCI_IDE_CFG = 0x40,
PCI_IDE_DTC = 0x48,
PCI_IDE_CAST = 0x4c,
PCI_IDE_ETC = 0x50,
IDE_CFG_CHANEN = 0x2,
IDE_CFG_CABLE = 0x10000,
IDE_D0_SHIFT = 24,
IDE_D1_SHIFT = 16,
IDE_DRV_MASK = 0xff,
IDE_CAST_D0_SHIFT = 6,
IDE_CAST_D1_SHIFT = 4,
IDE_CAST_DRV_MASK = 0x3,
IDE_CAST_CMD_MASK = 0xff,
IDE_CAST_CMD_SHIFT = 24,
IDE_ETC_NODMA = 0x03,
};
static int use_msr;
static const u32 msr_reg[4] = {
MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
};
static const u8 pci_reg[4] = {
PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC,
};
static inline int cs5536_read(struct pci_dev *pdev, int reg, int *val)
{
if (unlikely(use_msr)) {
u32 dummy;
rdmsr(msr_reg[reg], *val, dummy);
return 0;
}
return pci_read_config_dword(pdev, pci_reg[reg], val);
}
static inline int cs5536_write(struct pci_dev *pdev, int reg, int val)
{
if (unlikely(use_msr)) {
wrmsr(msr_reg[reg], val, 0);
return 0;
}
return pci_write_config_dword(pdev, pci_reg[reg], val);
}
/**
* cs5536_cable_detect - detect cable type
* @ap: Port to detect on
* @deadline: deadline jiffies for the operation
*
* Perform cable detection for ATA66 capable cable. Return a libata
* cable type.
*/
static int cs5536_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 cfg;
cs5536_read(pdev, CFG, &cfg);
if (cfg & (IDE_CFG_CABLE << ap->port_no))
return ATA_CBL_PATA80;
else
return ATA_CBL_PATA40;
}
/**
* cs5536_set_piomode - PIO setup
* @ap: ATA interface
* @adev: device on the interface
*/
static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
static const u8 drv_timings[5] = {
0x98, 0x55, 0x32, 0x21, 0x20,
};
static const u8 addr_timings[5] = {
0x2, 0x1, 0x0, 0x0, 0x0,
};
static const u8 cmd_timings[5] = {
0x99, 0x92, 0x90, 0x22, 0x20,
};
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct ata_device *pair = ata_dev_pair(adev);
int mode = adev->pio_mode - XFER_PIO_0;
int cmdmode = mode;
int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT;
int cshift = ap->port_no ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
u32 dtc, cast, etc;
if (pair)
cmdmode = min(mode, pair->pio_mode - XFER_PIO_0);
cs5536_read(pdev, DTC, &dtc);
cs5536_read(pdev, CAST, &cast);
cs5536_read(pdev, ETC, &etc);
dtc &= ~(IDE_DRV_MASK << dshift);
dtc |= drv_timings[mode] << dshift;
cast &= ~(IDE_CAST_DRV_MASK << cshift);
cast |= addr_timings[mode] << cshift;
cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT;
etc &= ~(IDE_DRV_MASK << dshift);
etc |= IDE_ETC_NODMA << dshift;
cs5536_write(pdev, DTC, dtc);
cs5536_write(pdev, CAST, cast);
cs5536_write(pdev, ETC, etc);
}
/**
* cs5536_set_dmamode - DMA timing setup
* @ap: ATA interface
* @adev: Device being configured
*
*/
static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
static const u8 udma_timings[6] = {
0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
};
static const u8 mwdma_timings[3] = {
0x67, 0x21, 0x20,
};
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 dtc, etc;
int mode = adev->dma_mode;
int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT;
if (mode >= XFER_UDMA_0) {
cs5536_read(pdev, ETC, &etc);
etc &= ~(IDE_DRV_MASK << dshift);
etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
cs5536_write(pdev, ETC, etc);
} else { /* MWDMA */
cs5536_read(pdev, DTC, &dtc);
dtc &= ~(IDE_DRV_MASK << dshift);
dtc |= mwdma_timings[mode] << dshift;
cs5536_write(pdev, DTC, dtc);
}
}
static struct scsi_host_template cs5536_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
static struct ata_port_operations cs5536_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cs5536_set_piomode,
.set_dmamode = cs5536_set_dmamode,
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = cs5536_cable_detect,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
.irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start,
};
/**
* cs5536_init_one
* @dev: PCI device
* @id: Entry in match table
*
*/
static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cs5536_sht,
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA5,
.port_ops = &cs5536_port_ops,
};
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
u32 cfg;
if (use_msr)
printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n");
cs5536_read(dev, CFG, &cfg);
if ((cfg & IDE_CFG_CHANEN) == 0) {
printk(KERN_ERR DRV_NAME ": disabled by BIOS\n");
return -ENODEV;
}
return ata_pci_init_one(dev, ppi);
}
static const struct pci_device_id cs5536[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), },
{ },
};
static struct pci_driver cs5536_pci_driver = {
.name = DRV_NAME,
.id_table = cs5536,
.probe = cs5536_init_one,
.remove = ata_pci_remove_one,
#ifdef CONFIG_PM
.suspend = ata_pci_device_suspend,
.resume = ata_pci_device_resume,
#endif
};
static int __init cs5536_init(void)
{
return pci_register_driver(&cs5536_pci_driver);
}
static void __exit cs5536_exit(void)
{
pci_unregister_driver(&cs5536_pci_driver);
}
MODULE_AUTHOR("Martin K. Petersen");
MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, cs5536);
MODULE_VERSION(DRV_VERSION);
module_param_named(msr, use_msr, int, 0644);
MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
module_init(cs5536_init);
module_exit(cs5536_exit);
...@@ -353,6 +353,7 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev) ...@@ -353,6 +353,7 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev)
static struct pcmcia_device_id pcmcia_devices[] = { static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_FUNC_ID(4), PCMCIA_DEVICE_FUNC_ID(4),
PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */
PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
...@@ -378,6 +379,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { ...@@ -378,6 +379,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
......
...@@ -279,7 +279,7 @@ static struct ata_port_operations sil680_port_ops = { ...@@ -279,7 +279,7 @@ static struct ata_port_operations sil680_port_ops = {
* Returns the final clock settings. * Returns the final clock settings.
*/ */
static u8 sil680_init_chip(struct pci_dev *pdev) static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
{ {
u32 class_rev = 0; u32 class_rev = 0;
u8 tmpbyte = 0; u8 tmpbyte = 0;
...@@ -297,6 +297,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev) ...@@ -297,6 +297,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
tmpbyte & 1, tmpbyte & 0x30); tmpbyte & 1, tmpbyte & 0x30);
*try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);
switch(tmpbyte & 0x30) { switch(tmpbyte & 0x30) {
case 0x00: case 0x00:
/* 133 clock attempt to force it on */ /* 133 clock attempt to force it on */
...@@ -361,25 +363,76 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, ...@@ -361,25 +363,76 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
}; };
const struct ata_port_info *ppi[] = { &info, NULL }; const struct ata_port_info *ppi[] = { &info, NULL };
static int printed_version; static int printed_version;
struct ata_host *host;
void __iomem *mmio_base;
int rc, try_mmio;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
switch(sil680_init_chip(pdev)) switch (sil680_init_chip(pdev, &try_mmio)) {
{
case 0: case 0:
ppi[0] = &info_slow; ppi[0] = &info_slow;
break; break;
case 0x30: case 0x30:
return -ENODEV; return -ENODEV;
} }
if (!try_mmio)
goto use_ioports;
/* Try to acquire MMIO resources and fallback to PIO if
* that fails
*/
rc = pcim_enable_device(pdev);
if (rc)
return rc;
rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
if (rc)
goto use_ioports;
/* Allocate host and set it up */
host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
if (!host)
return -ENOMEM;
host->iomap = pcim_iomap_table(pdev);
/* Setup DMA masks */
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
return rc;
rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
return rc;
pci_set_master(pdev);
/* Get MMIO base and initialize port addresses */
mmio_base = host->iomap[SIL680_MMIO_BAR];
host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00;
host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80;
host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a;
host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a;
ata_std_ports(&host->ports[0]->ioaddr);
host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08;
host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0;
host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca;
host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca;
ata_std_ports(&host->ports[1]->ioaddr);
/* Register & activate */
return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
&sil680_sht);
use_ioports:
return ata_pci_init_one(pdev, ppi); return ata_pci_init_one(pdev, ppi);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int sil680_reinit_one(struct pci_dev *pdev) static int sil680_reinit_one(struct pci_dev *pdev)
{ {
sil680_init_chip(pdev); int try_mmio;
sil680_init_chip(pdev, &try_mmio);
return ata_pci_device_resume(pdev); return ata_pci_device_resume(pdev);
} }
#endif #endif
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment