diff options
Diffstat (limited to 'drivers/ata/ata_piix.c')
-rw-r--r-- | drivers/ata/ata_piix.c | 148 |
1 files changed, 110 insertions, 38 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index a78832ea81f..9ce4aa9c2f2 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -94,7 +94,7 @@ #include <linux/dmi.h> #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.11" +#define DRV_VERSION "2.12" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -123,13 +123,13 @@ enum { ich_pata_33 = 1, /* ICH up to UDMA 33 only */ ich_pata_66 = 2, /* ICH up to 66 Mhz */ ich_pata_100 = 3, /* ICH up to UDMA 100 */ - ich_pata_133 = 4, /* ICH up to UDMA 133 */ ich5_sata = 5, ich6_sata = 6, ich6_sata_ahci = 7, ich6m_sata_ahci = 8, ich8_sata_ahci = 9, piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ + tolapai_sata_ahci = 11, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -198,7 +198,7 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* Intel ICH5 */ - { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, + { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* C-ICH (i810E2) */ { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* ESB (855GME/875P + 6300ESB) UDMA 100 */ @@ -206,7 +206,7 @@ static const struct pci_device_id piix_pci_tbl[] = { /* ICH6 (and 6) (i915) UDMA 100 */ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* ICH7/7-R (i945, i975) UDMA 100*/ - { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, + { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* ICH8 Mobile PATA Controller */ { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, @@ -253,6 +253,8 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9M) */ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, + /* SATA Controller IDE (Tolapai) */ + { 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci }, { } /* terminate list */ }; @@ -287,7 +289,6 @@ static struct scsi_host_template piix_sht = { }; static const struct ata_port_operations piix_pata_ops = { - .port_disable = ata_port_disable, .set_piomode = piix_set_piomode, .set_dmamode = piix_set_dmamode, .mode_filter = ata_pci_default_filter, @@ -315,13 +316,11 @@ static const struct ata_port_operations piix_pata_ops = { .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, }; static const struct ata_port_operations ich_pata_ops = { - .port_disable = ata_port_disable, .set_piomode = piix_set_piomode, .set_dmamode = ich_set_dmamode, .mode_filter = ata_pci_default_filter, @@ -349,14 +348,11 @@ static const struct ata_port_operations ich_pata_ops = { .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, }; static const struct ata_port_operations piix_sata_ops = { - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, @@ -379,7 +375,6 @@ static const struct ata_port_operations piix_sata_ops = { .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, }; @@ -436,7 +431,19 @@ static const struct piix_map_db ich8_map_db = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ { RV, RV, RV, RV }, - { IDE, IDE, NA, NA }, /* 10b (IDE mode) */ + { P0, P2, IDE, IDE }, /* 10b (IDE mode) */ + { RV, RV, RV, RV }, + }, +}; + +static const struct piix_map_db tolapai_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 }, }, }; @@ -447,10 +454,11 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, [ich8_sata_ahci] = &ich8_map_db, + [tolapai_sata_ahci] = &tolapai_map_db, }; static struct ata_port_info piix_port_info[] = { - /* piix_pata_33: 0: PIIX4 at 33MHz */ + [piix_pata_33] = /* PIIX4 at 33MHz */ { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS, @@ -460,7 +468,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_pata_ops, }, - /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ + [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/ { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS, @@ -469,7 +477,8 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = ATA_UDMA2, /* UDMA33 */ .port_ops = &ich_pata_ops, }, - /* ich_pata_66: 2 ICH controllers up to 66MHz */ + + [ich_pata_66] = /* ICH controllers up to 66MHz */ { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS, @@ -479,7 +488,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &ich_pata_ops, }, - /* ich_pata_100: 3 */ + [ich_pata_100] = { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, @@ -489,17 +498,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &ich_pata_ops, }, - /* ich_pata_133: 4 ICH with full UDMA6 */ - { - .sht = &piix_sht, - .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* Check: maybe 0x07 */ - .udma_mask = ATA_UDMA6, /* UDMA133 */ - .port_ops = &ich_pata_ops, - }, - - /* ich5_sata: 5 */ + [ich5_sata] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS, @@ -509,7 +508,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6_sata: 6 */ + [ich6_sata] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, @@ -519,7 +518,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6_sata_ahci: 7 */ + [ich6_sata_ahci] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -530,7 +529,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6m_sata_ahci: 8 */ + [ich6m_sata_ahci] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -541,7 +540,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich8_sata_ahci: 9 */ + [ich8_sata_ahci] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -552,7 +551,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* piix_pata_mwdma: 10: PIIX3 MWDMA only */ + [piix_pata_mwdma] = /* PIIX3 MWDMA only */ { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS, @@ -560,6 +559,17 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ .port_ops = &piix_pata_ops, }, + + [tolapai_sata_ahci] = + { + .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[] = { @@ -588,6 +598,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ + { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ /* end marker */ { 0, } @@ -630,19 +641,20 @@ static int ich_pata_cable_detect(struct ata_port *ap) /** * piix_pata_prereset - prereset for PATA host controller - * @ap: Target port + * @link: Target link * @deadline: deadline jiffies for the operation * * LOCKING: * None (inherited from caller). */ -static int piix_pata_prereset(struct ata_port *ap, unsigned long deadline) +static int piix_pata_prereset(struct ata_link *link, unsigned long deadline) { + struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) return -ENOENT; - return ata_std_prereset(ap, deadline); + return ata_std_prereset(link, deadline); } static void piix_pata_error_handler(struct ata_port *ap) @@ -892,7 +904,14 @@ static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev) #ifdef CONFIG_PM static int piix_broken_suspend(void) { - static struct dmi_system_id sysids[] = { + static const struct dmi_system_id sysids[] = { + { + .ident = "TECRA M3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"), + }, + }, { .ident = "TECRA M5", .matches = { @@ -901,6 +920,20 @@ static int piix_broken_suspend(void) }, }, { + .ident = "TECRA M7", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M7"), + }, + }, + { + .ident = "Satellite U200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"), + }, + }, + { .ident = "Satellite U205", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -914,7 +947,8 @@ static int piix_broken_suspend(void) DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"), }, }, - { } + + { } /* terminate list */ }; static const char *oemstrs[] = { "Tecra M3,", @@ -1088,7 +1122,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, const struct piix_map_db *map_db) { struct piix_host_priv *hpriv = pinfo[0].private_data; - const unsigned int *map; + const int *map; int i, invalid_map = 0; u8 map_value; @@ -1132,6 +1166,41 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, hpriv->map = map; } +static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) +{ + static const struct dmi_system_id sysids[] = { + { + /* Clevo M570U sets IOCFG bit 18 if the cdrom + * isn't used to boot the system which + * disables the channel. + */ + .ident = "M570U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."), + DMI_MATCH(DMI_PRODUCT_NAME, "M570U"), + }, + }, + + { } /* terminate list */ + }; + u32 iocfg; + + if (!dmi_check_system(sysids)) + return; + + /* The datasheet says that bit 18 is NOOP but certain systems + * seem to use it to disable a channel. Clear the bit on the + * affected systems. + */ + pci_read_config_dword(pdev, PIIX_IOCFG, &iocfg); + if (iocfg & (1 << 18)) { + dev_printk(KERN_INFO, &pdev->dev, + "applying IOCFG bit18 quirk\n"); + iocfg &= ~(1 << 18); + pci_write_config_dword(pdev, PIIX_IOCFG, iocfg); + } +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -1193,6 +1262,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) piix_map_db_table[ent->driver_data]); } + /* apply IOCFG bit18 quirk */ + piix_iocfg_bit18_quirk(pdev); + /* On ICH5, some BIOSen disable the interrupt using the * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. * On ICH6, this bit has the same effect, but only when |