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.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 071d274..6996eb5 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 */
@@ -130,6 +130,7 @@ enum {
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 */
@@ -253,6 +254,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 */
};
@@ -441,12 +444,25 @@ static const struct piix_map_db ich8_map_db = {
},
};
+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 },
+ },
+};
+
static const struct piix_map_db *piix_map_db_table[] = {
[ich5_sata] = &ich5_map_db,
[ich6_sata] = &ich6_map_db,
[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[] = {
@@ -560,6 +576,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: 11: */
+ {
+ .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[] = {
@@ -894,6 +921,13 @@ static int piix_broken_suspend(void)
{
static 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 = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -908,6 +942,13 @@ static int piix_broken_suspend(void)
},
},
{
+ .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"),
@@ -921,7 +962,8 @@ static int piix_broken_suspend(void)
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"),
},
},
- { }
+
+ { } /* terminate list */
};
static const char *oemstrs[] = {
"Tecra M3,",
@@ -1139,6 +1181,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 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
@@ -1200,6 +1277,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
OpenPOWER on IntegriCloud