summaryrefslogtreecommitdiffstats
path: root/drivers/ata/ata_piix.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ata_piix.c')
-rw-r--r--drivers/ata/ata_piix.c148
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