diff options
-rw-r--r-- | drivers/ata/ata_piix.c | 167 |
1 files changed, 40 insertions, 127 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 81387ff48937..9d8cb804ee2b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -887,23 +887,9 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
887 | * Serial ATA Index/Data Pair Superset Registers access | 887 | * Serial ATA Index/Data Pair Superset Registers access |
888 | * | 888 | * |
889 | * Beginning from ICH8, there's a sane way to access SCRs using index | 889 | * Beginning from ICH8, there's a sane way to access SCRs using index |
890 | * and data register pair located at BAR5. This creates an | 890 | * and data register pair located at BAR5 which means that we have |
891 | * interesting problem of mapping two SCRs to one port. | 891 | * separate SCRs for master and slave. This is handled using libata |
892 | * | 892 | * slave_link facility. |
893 | * Although they have separate SCRs, the master and slave aren't | ||
894 | * independent enough to be treated as separate links - e.g. softreset | ||
895 | * resets both. Also, there's no protocol defined for hard resetting | ||
896 | * singled device sharing the virtual port (no defined way to acquire | ||
897 | * device signature). This is worked around by merging the SCR values | ||
898 | * into one sensible value and requesting follow-up SRST after | ||
899 | * hardreset. | ||
900 | * | ||
901 | * SCR merging is perfomed in nibbles which is the unit contents in | ||
902 | * SCRs are organized. If two values are equal, the value is used. | ||
903 | * When they differ, merge table which lists precedence of possible | ||
904 | * values is consulted and the first match or the last entry when | ||
905 | * nothing matches is used. When there's no merge table for the | ||
906 | * specific nibble, value from the first port is used. | ||
907 | */ | 893 | */ |
908 | static const int piix_sidx_map[] = { | 894 | static const int piix_sidx_map[] = { |
909 | [SCR_STATUS] = 0, | 895 | [SCR_STATUS] = 0, |
@@ -911,125 +897,38 @@ static const int piix_sidx_map[] = { | |||
911 | [SCR_CONTROL] = 1, | 897 | [SCR_CONTROL] = 1, |
912 | }; | 898 | }; |
913 | 899 | ||
914 | static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg) | 900 | static void piix_sidpr_sel(struct ata_link *link, unsigned int reg) |
915 | { | 901 | { |
916 | struct ata_port *ap = dev->link->ap; | 902 | struct ata_port *ap = link->ap; |
917 | struct piix_host_priv *hpriv = ap->host->private_data; | 903 | struct piix_host_priv *hpriv = ap->host->private_data; |
918 | 904 | ||
919 | iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg], | 905 | iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg], |
920 | hpriv->sidpr + PIIX_SIDPR_IDX); | 906 | hpriv->sidpr + PIIX_SIDPR_IDX); |
921 | } | 907 | } |
922 | 908 | ||
923 | static int piix_sidpr_read(struct ata_device *dev, unsigned int reg) | ||
924 | { | ||
925 | struct piix_host_priv *hpriv = dev->link->ap->host->private_data; | ||
926 | |||
927 | piix_sidpr_sel(dev, reg); | ||
928 | return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); | ||
929 | } | ||
930 | |||
931 | static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val) | ||
932 | { | ||
933 | struct piix_host_priv *hpriv = dev->link->ap->host->private_data; | ||
934 | |||
935 | piix_sidpr_sel(dev, reg); | ||
936 | iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); | ||
937 | } | ||
938 | |||
939 | static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl) | ||
940 | { | ||
941 | u32 val = 0; | ||
942 | int i, mi; | ||
943 | |||
944 | for (i = 0, mi = 0; i < 32 / 4; i++) { | ||
945 | u8 c0 = (val0 >> (i * 4)) & 0xf; | ||
946 | u8 c1 = (val1 >> (i * 4)) & 0xf; | ||
947 | u8 merged = c0; | ||
948 | const int *cur; | ||
949 | |||
950 | /* if no merge preference, assume the first value */ | ||
951 | cur = merge_tbl[mi]; | ||
952 | if (!cur) | ||
953 | goto done; | ||
954 | mi++; | ||
955 | |||
956 | /* if two values equal, use it */ | ||
957 | if (c0 == c1) | ||
958 | goto done; | ||
959 | |||
960 | /* choose the first match or the last from the merge table */ | ||
961 | while (*cur != -1) { | ||
962 | if (c0 == *cur || c1 == *cur) | ||
963 | break; | ||
964 | cur++; | ||
965 | } | ||
966 | if (*cur == -1) | ||
967 | cur--; | ||
968 | merged = *cur; | ||
969 | done: | ||
970 | val |= merged << (i * 4); | ||
971 | } | ||
972 | |||
973 | return val; | ||
974 | } | ||
975 | |||
976 | static int piix_sidpr_scr_read(struct ata_link *link, | 909 | static int piix_sidpr_scr_read(struct ata_link *link, |
977 | unsigned int reg, u32 *val) | 910 | unsigned int reg, u32 *val) |
978 | { | 911 | { |
979 | struct ata_port *ap = link->ap; | 912 | struct piix_host_priv *hpriv = link->ap->host->private_data; |
980 | const int * const sstatus_merge_tbl[] = { | ||
981 | /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 }, | ||
982 | /* SPD */ (const int []){ 2, 1, 0, -1 }, | ||
983 | /* IPM */ (const int []){ 6, 2, 1, 0, -1 }, | ||
984 | NULL, | ||
985 | }; | ||
986 | const int * const scontrol_merge_tbl[] = { | ||
987 | /* DET */ (const int []){ 1, 0, 4, 0, -1 }, | ||
988 | /* SPD */ (const int []){ 0, 2, 1, 0, -1 }, | ||
989 | /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 }, | ||
990 | NULL, | ||
991 | }; | ||
992 | u32 v0, v1; | ||
993 | 913 | ||
994 | if (reg >= ARRAY_SIZE(piix_sidx_map)) | 914 | if (reg >= ARRAY_SIZE(piix_sidx_map)) |
995 | return -EINVAL; | 915 | return -EINVAL; |
996 | 916 | ||
997 | if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) { | 917 | piix_sidpr_sel(link, reg); |
998 | *val = piix_sidpr_read(&ap->link.device[0], reg); | 918 | *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); |
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | v0 = piix_sidpr_read(&ap->link.device[0], reg); | ||
1003 | v1 = piix_sidpr_read(&ap->link.device[1], reg); | ||
1004 | |||
1005 | switch (reg) { | ||
1006 | case SCR_STATUS: | ||
1007 | *val = piix_merge_scr(v0, v1, sstatus_merge_tbl); | ||
1008 | break; | ||
1009 | case SCR_ERROR: | ||
1010 | *val = v0 | v1; | ||
1011 | break; | ||
1012 | case SCR_CONTROL: | ||
1013 | *val = piix_merge_scr(v0, v1, scontrol_merge_tbl); | ||
1014 | break; | ||
1015 | } | ||
1016 | |||
1017 | return 0; | 919 | return 0; |
1018 | } | 920 | } |
1019 | 921 | ||
1020 | static int piix_sidpr_scr_write(struct ata_link *link, | 922 | static int piix_sidpr_scr_write(struct ata_link *link, |
1021 | unsigned int reg, u32 val) | 923 | unsigned int reg, u32 val) |
1022 | { | 924 | { |
1023 | struct ata_port *ap = link->ap; | 925 | struct piix_host_priv *hpriv = link->ap->host->private_data; |
1024 | 926 | ||
1025 | if (reg >= ARRAY_SIZE(piix_sidx_map)) | 927 | if (reg >= ARRAY_SIZE(piix_sidx_map)) |
1026 | return -EINVAL; | 928 | return -EINVAL; |
1027 | 929 | ||
1028 | piix_sidpr_write(&ap->link.device[0], reg, val); | 930 | piix_sidpr_sel(link, reg); |
1029 | 931 | iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); | |
1030 | if (ap->flags & ATA_FLAG_SLAVE_POSS) | ||
1031 | piix_sidpr_write(&ap->link.device[1], reg, val); | ||
1032 | |||
1033 | return 0; | 932 | return 0; |
1034 | } | 933 | } |
1035 | 934 | ||
@@ -1370,28 +1269,28 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, | |||
1370 | return map; | 1269 | return map; |
1371 | } | 1270 | } |
1372 | 1271 | ||
1373 | static void __devinit piix_init_sidpr(struct ata_host *host) | 1272 | static int __devinit piix_init_sidpr(struct ata_host *host) |
1374 | { | 1273 | { |
1375 | struct pci_dev *pdev = to_pci_dev(host->dev); | 1274 | struct pci_dev *pdev = to_pci_dev(host->dev); |
1376 | struct piix_host_priv *hpriv = host->private_data; | 1275 | struct piix_host_priv *hpriv = host->private_data; |
1377 | struct ata_device *dev0 = &host->ports[0]->link.device[0]; | 1276 | struct ata_link *link0 = &host->ports[0]->link; |
1378 | u32 scontrol; | 1277 | u32 scontrol; |
1379 | int i; | 1278 | int i, rc; |
1380 | 1279 | ||
1381 | /* check for availability */ | 1280 | /* check for availability */ |
1382 | for (i = 0; i < 4; i++) | 1281 | for (i = 0; i < 4; i++) |
1383 | if (hpriv->map[i] == IDE) | 1282 | if (hpriv->map[i] == IDE) |
1384 | return; | 1283 | return 0; |
1385 | 1284 | ||
1386 | if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) | 1285 | if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) |
1387 | return; | 1286 | return 0; |
1388 | 1287 | ||
1389 | if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || | 1288 | if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || |
1390 | pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) | 1289 | pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) |
1391 | return; | 1290 | return 0; |
1392 | 1291 | ||
1393 | if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) | 1292 | if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) |
1394 | return; | 1293 | return 0; |
1395 | 1294 | ||
1396 | hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; | 1295 | hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; |
1397 | 1296 | ||
@@ -1399,7 +1298,7 @@ static void __devinit piix_init_sidpr(struct ata_host *host) | |||
1399 | * Give it a test drive by inhibiting power save modes which | 1298 | * Give it a test drive by inhibiting power save modes which |
1400 | * we'll do anyway. | 1299 | * we'll do anyway. |
1401 | */ | 1300 | */ |
1402 | scontrol = piix_sidpr_read(dev0, SCR_CONTROL); | 1301 | piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); |
1403 | 1302 | ||
1404 | /* if IPM is already 3, SCR access is probably working. Don't | 1303 | /* if IPM is already 3, SCR access is probably working. Don't |
1405 | * un-inhibit power save modes as BIOS might have inhibited | 1304 | * un-inhibit power save modes as BIOS might have inhibited |
@@ -1407,18 +1306,30 @@ static void __devinit piix_init_sidpr(struct ata_host *host) | |||
1407 | */ | 1306 | */ |
1408 | if ((scontrol & 0xf00) != 0x300) { | 1307 | if ((scontrol & 0xf00) != 0x300) { |
1409 | scontrol |= 0x300; | 1308 | scontrol |= 0x300; |
1410 | piix_sidpr_write(dev0, SCR_CONTROL, scontrol); | 1309 | piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol); |
1411 | scontrol = piix_sidpr_read(dev0, SCR_CONTROL); | 1310 | piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); |
1412 | 1311 | ||
1413 | if ((scontrol & 0xf00) != 0x300) { | 1312 | if ((scontrol & 0xf00) != 0x300) { |
1414 | dev_printk(KERN_INFO, host->dev, "SCR access via " | 1313 | dev_printk(KERN_INFO, host->dev, "SCR access via " |
1415 | "SIDPR is available but doesn't work\n"); | 1314 | "SIDPR is available but doesn't work\n"); |
1416 | return; | 1315 | return 0; |
1417 | } | 1316 | } |
1418 | } | 1317 | } |
1419 | 1318 | ||
1420 | host->ports[0]->ops = &piix_sidpr_sata_ops; | 1319 | /* okay, SCRs available, set ops and ask libata for slave_link */ |
1421 | host->ports[1]->ops = &piix_sidpr_sata_ops; | 1320 | for (i = 0; i < 2; i++) { |
1321 | struct ata_port *ap = host->ports[i]; | ||
1322 | |||
1323 | ap->ops = &piix_sidpr_sata_ops; | ||
1324 | |||
1325 | if (ap->flags & ATA_FLAG_SLAVE_POSS) { | ||
1326 | rc = ata_slave_link_init(ap); | ||
1327 | if (rc) | ||
1328 | return rc; | ||
1329 | } | ||
1330 | } | ||
1331 | |||
1332 | return 0; | ||
1422 | } | 1333 | } |
1423 | 1334 | ||
1424 | static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) | 1335 | static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) |
@@ -1528,7 +1439,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1528 | /* initialize controller */ | 1439 | /* initialize controller */ |
1529 | if (port_flags & ATA_FLAG_SATA) { | 1440 | if (port_flags & ATA_FLAG_SATA) { |
1530 | piix_init_pcs(host, piix_map_db_table[ent->driver_data]); | 1441 | piix_init_pcs(host, piix_map_db_table[ent->driver_data]); |
1531 | piix_init_sidpr(host); | 1442 | rc = piix_init_sidpr(host); |
1443 | if (rc) | ||
1444 | return rc; | ||
1532 | } | 1445 | } |
1533 | 1446 | ||
1534 | /* apply IOCFG bit18 quirk */ | 1447 | /* apply IOCFG bit18 quirk */ |