aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/ata_piix.c251
1 files changed, 247 insertions, 4 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 024e6d52eab2..a65c8ae5c461 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -101,9 +101,14 @@ enum {
101 ICH5_PMR = 0x90, /* port mapping register */ 101 ICH5_PMR = 0x90, /* port mapping register */
102 ICH5_PCS = 0x92, /* port control and status */ 102 ICH5_PCS = 0x92, /* port control and status */
103 PIIX_SCC = 0x0A, /* sub-class code register */ 103 PIIX_SCC = 0x0A, /* sub-class code register */
104 PIIX_SIDPR_BAR = 5,
105 PIIX_SIDPR_LEN = 16,
106 PIIX_SIDPR_IDX = 0,
107 PIIX_SIDPR_DATA = 4,
104 108
105 PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ 109 PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
106 PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ 110 PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
111 PIIX_FLAG_SIDPR = (1 << 29), /* SATA idx/data pair regs */
107 112
108 PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, 113 PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
109 PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, 114 PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
@@ -152,6 +157,7 @@ struct piix_map_db {
152 157
153struct piix_host_priv { 158struct piix_host_priv {
154 const int *map; 159 const int *map;
160 void __iomem *sidpr;
155}; 161};
156 162
157static int piix_init_one(struct pci_dev *pdev, 163static int piix_init_one(struct pci_dev *pdev,
@@ -162,6 +168,9 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
162static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev); 168static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
163static int ich_pata_cable_detect(struct ata_port *ap); 169static int ich_pata_cable_detect(struct ata_port *ap);
164static u8 piix_vmw_bmdma_status(struct ata_port *ap); 170static u8 piix_vmw_bmdma_status(struct ata_port *ap);
171static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
172static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
173static void piix_sidpr_error_handler(struct ata_port *ap);
165#ifdef CONFIG_PM 174#ifdef CONFIG_PM
166static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 175static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
167static int piix_pci_device_resume(struct pci_dev *pdev); 176static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -411,6 +420,35 @@ static const struct ata_port_operations piix_vmw_ops = {
411 .port_start = ata_port_start, 420 .port_start = ata_port_start,
412}; 421};
413 422
423static const struct ata_port_operations piix_sidpr_sata_ops = {
424 .tf_load = ata_tf_load,
425 .tf_read = ata_tf_read,
426 .check_status = ata_check_status,
427 .exec_command = ata_exec_command,
428 .dev_select = ata_std_dev_select,
429
430 .bmdma_setup = ata_bmdma_setup,
431 .bmdma_start = ata_bmdma_start,
432 .bmdma_stop = ata_bmdma_stop,
433 .bmdma_status = ata_bmdma_status,
434 .qc_prep = ata_qc_prep,
435 .qc_issue = ata_qc_issue_prot,
436 .data_xfer = ata_data_xfer,
437
438 .scr_read = piix_sidpr_scr_read,
439 .scr_write = piix_sidpr_scr_write,
440
441 .freeze = ata_bmdma_freeze,
442 .thaw = ata_bmdma_thaw,
443 .error_handler = piix_sidpr_error_handler,
444 .post_internal_cmd = ata_bmdma_post_internal_cmd,
445
446 .irq_clear = ata_bmdma_irq_clear,
447 .irq_on = ata_irq_on,
448
449 .port_start = ata_port_start,
450};
451
414static const struct piix_map_db ich5_map_db = { 452static const struct piix_map_db ich5_map_db = {
415 .mask = 0x7, 453 .mask = 0x7,
416 .port_enable = 0x3, 454 .port_enable = 0x3,
@@ -598,7 +636,8 @@ static struct ata_port_info piix_port_info[] = {
598 636
599 [ich8_sata_ahci] = 637 [ich8_sata_ahci] =
600 { 638 {
601 .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI, 639 .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
640 PIIX_FLAG_SIDPR,
602 .pio_mask = 0x1f, /* pio0-4 */ 641 .pio_mask = 0x1f, /* pio0-4 */
603 .mwdma_mask = 0x07, /* mwdma0-2 */ 642 .mwdma_mask = 0x07, /* mwdma0-2 */
604 .udma_mask = ATA_UDMA6, 643 .udma_mask = ATA_UDMA6,
@@ -607,7 +646,8 @@ static struct ata_port_info piix_port_info[] = {
607 646
608 [ich8_2port_sata] = 647 [ich8_2port_sata] =
609 { 648 {
610 .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI, 649 .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
650 PIIX_FLAG_SIDPR,
611 .pio_mask = 0x1f, /* pio0-4 */ 651 .pio_mask = 0x1f, /* pio0-4 */
612 .mwdma_mask = 0x07, /* mwdma0-2 */ 652 .mwdma_mask = 0x07, /* mwdma0-2 */
613 .udma_mask = ATA_UDMA6, 653 .udma_mask = ATA_UDMA6,
@@ -625,7 +665,8 @@ static struct ata_port_info piix_port_info[] = {
625 665
626 [ich8m_apple_sata_ahci] = 666 [ich8m_apple_sata_ahci] =
627 { 667 {
628 .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI, 668 .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
669 PIIX_FLAG_SIDPR,
629 .pio_mask = 0x1f, /* pio0-4 */ 670 .pio_mask = 0x1f, /* pio0-4 */
630 .mwdma_mask = 0x07, /* mwdma0-2 */ 671 .mwdma_mask = 0x07, /* mwdma0-2 */
631 .udma_mask = ATA_UDMA6, 672 .udma_mask = ATA_UDMA6,
@@ -974,6 +1015,180 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
974 do_pata_set_dmamode(ap, adev, 1); 1015 do_pata_set_dmamode(ap, adev, 1);
975} 1016}
976 1017
1018/*
1019 * Serial ATA Index/Data Pair Superset Registers access
1020 *
1021 * Beginning from ICH8, there's a sane way to access SCRs using index
1022 * and data register pair located at BAR5. This creates an
1023 * interesting problem of mapping two SCRs to one port.
1024 *
1025 * Although they have separate SCRs, the master and slave aren't
1026 * independent enough to be treated as separate links - e.g. softreset
1027 * resets both. Also, there's no protocol defined for hard resetting
1028 * singled device sharing the virtual port (no defined way to acquire
1029 * device signature). This is worked around by merging the SCR values
1030 * into one sensible value and requesting follow-up SRST after
1031 * hardreset.
1032 *
1033 * SCR merging is perfomed in nibbles which is the unit contents in
1034 * SCRs are organized. If two values are equal, the value is used.
1035 * When they differ, merge table which lists precedence of possible
1036 * values is consulted and the first match or the last entry when
1037 * nothing matches is used. When there's no merge table for the
1038 * specific nibble, value from the first port is used.
1039 */
1040static const int piix_sidx_map[] = {
1041 [SCR_STATUS] = 0,
1042 [SCR_ERROR] = 2,
1043 [SCR_CONTROL] = 1,
1044};
1045
1046static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
1047{
1048 struct ata_port *ap = dev->link->ap;
1049 struct piix_host_priv *hpriv = ap->host->private_data;
1050
1051 iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
1052 hpriv->sidpr + PIIX_SIDPR_IDX);
1053}
1054
1055static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
1056{
1057 struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
1058
1059 piix_sidpr_sel(dev, reg);
1060 return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
1061}
1062
1063static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
1064{
1065 struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
1066
1067 piix_sidpr_sel(dev, reg);
1068 iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
1069}
1070
1071u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
1072{
1073 u32 val = 0;
1074 int i, mi;
1075
1076 for (i = 0, mi = 0; i < 32 / 4; i++) {
1077 u8 c0 = (val0 >> (i * 4)) & 0xf;
1078 u8 c1 = (val1 >> (i * 4)) & 0xf;
1079 u8 merged = c0;
1080 const int *cur;
1081
1082 /* if no merge preference, assume the first value */
1083 cur = merge_tbl[mi];
1084 if (!cur)
1085 goto done;
1086 mi++;
1087
1088 /* if two values equal, use it */
1089 if (c0 == c1)
1090 goto done;
1091
1092 /* choose the first match or the last from the merge table */
1093 while (*cur != -1) {
1094 if (c0 == *cur || c1 == *cur)
1095 break;
1096 cur++;
1097 }
1098 if (*cur == -1)
1099 cur--;
1100 merged = *cur;
1101 done:
1102 val |= merged << (i * 4);
1103 }
1104
1105 return val;
1106}
1107
1108static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
1109{
1110 const int * const sstatus_merge_tbl[] = {
1111 /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
1112 /* SPD */ (const int []){ 2, 1, 0, -1 },
1113 /* IPM */ (const int []){ 6, 2, 1, 0, -1 },
1114 NULL,
1115 };
1116 const int * const scontrol_merge_tbl[] = {
1117 /* DET */ (const int []){ 1, 0, 4, 0, -1 },
1118 /* SPD */ (const int []){ 0, 2, 1, 0, -1 },
1119 /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
1120 NULL,
1121 };
1122 u32 v0, v1;
1123
1124 if (reg >= ARRAY_SIZE(piix_sidx_map))
1125 return -EINVAL;
1126
1127 if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
1128 *val = piix_sidpr_read(&ap->link.device[0], reg);
1129 return 0;
1130 }
1131
1132 v0 = piix_sidpr_read(&ap->link.device[0], reg);
1133 v1 = piix_sidpr_read(&ap->link.device[1], reg);
1134
1135 switch (reg) {
1136 case SCR_STATUS:
1137 *val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
1138 break;
1139 case SCR_ERROR:
1140 *val = v0 | v1;
1141 break;
1142 case SCR_CONTROL:
1143 *val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
1144 break;
1145 }
1146
1147 return 0;
1148}
1149
1150static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
1151{
1152 if (reg >= ARRAY_SIZE(piix_sidx_map))
1153 return -EINVAL;
1154
1155 piix_sidpr_write(&ap->link.device[0], reg, val);
1156
1157 if (ap->flags & ATA_FLAG_SLAVE_POSS)
1158 piix_sidpr_write(&ap->link.device[1], reg, val);
1159
1160 return 0;
1161}
1162
1163static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
1164 unsigned long deadline)
1165{
1166 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
1167 int rc;
1168
1169 /* do hardreset */
1170 rc = sata_link_hardreset(link, timing, deadline);
1171 if (rc) {
1172 ata_link_printk(link, KERN_ERR,
1173 "COMRESET failed (errno=%d)\n", rc);
1174 return rc;
1175 }
1176
1177 /* TODO: phy layer with polling, timeouts, etc. */
1178 if (ata_link_offline(link)) {
1179 *class = ATA_DEV_NONE;
1180 return 0;
1181 }
1182
1183 return -EAGAIN;
1184}
1185
1186static void piix_sidpr_error_handler(struct ata_port *ap)
1187{
1188 ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
1189 piix_sidpr_hardreset, ata_std_postreset);
1190}
1191
977#ifdef CONFIG_PM 1192#ifdef CONFIG_PM
978static int piix_broken_suspend(void) 1193static int piix_broken_suspend(void)
979{ 1194{
@@ -1304,6 +1519,32 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
1304 return map; 1519 return map;
1305} 1520}
1306 1521
1522static void __devinit piix_init_sidpr(struct ata_host *host)
1523{
1524 struct pci_dev *pdev = to_pci_dev(host->dev);
1525 struct piix_host_priv *hpriv = host->private_data;
1526 int i;
1527
1528 /* check for availability */
1529 for (i = 0; i < 4; i++)
1530 if (hpriv->map[i] == IDE)
1531 return;
1532
1533 if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
1534 return;
1535
1536 if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
1537 pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
1538 return;
1539
1540 if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
1541 return;
1542
1543 hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
1544 host->ports[0]->ops = &piix_sidpr_sata_ops;
1545 host->ports[1]->ops = &piix_sidpr_sata_ops;
1546}
1547
1307static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) 1548static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
1308{ 1549{
1309 static const struct dmi_system_id sysids[] = { 1550 static const struct dmi_system_id sysids[] = {
@@ -1408,8 +1649,10 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1408 } 1649 }
1409 } 1650 }
1410 1651
1411 if (port_flags & ATA_FLAG_SATA) 1652 if (port_flags & ATA_FLAG_SATA) {
1412 piix_init_pcs(host, piix_map_db_table[ent->driver_data]); 1653 piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
1654 piix_init_sidpr(host);
1655 }
1413 1656
1414 /* apply IOCFG bit18 quirk */ 1657 /* apply IOCFG bit18 quirk */
1415 piix_iocfg_bit18_quirk(pdev); 1658 piix_iocfg_bit18_quirk(pdev);