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 */ |
