diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 95 |
1 files changed, 67 insertions, 28 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f2277be70c0f..af3565d1fefe 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | enum { | 54 | enum { |
55 | AHCI_PCI_BAR = 5, | 55 | AHCI_PCI_BAR = 5, |
56 | AHCI_MAX_PORTS = 32, | ||
56 | AHCI_MAX_SG = 168, /* hardware max is 64K */ | 57 | AHCI_MAX_SG = 168, /* hardware max is 64K */ |
57 | AHCI_DMA_BOUNDARY = 0xffffffff, | 58 | AHCI_DMA_BOUNDARY = 0xffffffff, |
58 | AHCI_USE_CLUSTERING = 0, | 59 | AHCI_USE_CLUSTERING = 0, |
@@ -77,8 +78,9 @@ enum { | |||
77 | RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ | 78 | RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ |
78 | 79 | ||
79 | board_ahci = 0, | 80 | board_ahci = 0, |
80 | board_ahci_vt8251 = 1, | 81 | board_ahci_pi = 1, |
81 | board_ahci_ign_iferr = 2, | 82 | board_ahci_vt8251 = 2, |
83 | board_ahci_ign_iferr = 3, | ||
82 | 84 | ||
83 | /* global controller registers */ | 85 | /* global controller registers */ |
84 | HOST_CAP = 0x00, /* host capabilities */ | 86 | HOST_CAP = 0x00, /* host capabilities */ |
@@ -169,6 +171,7 @@ enum { | |||
169 | /* ap->flags bits */ | 171 | /* ap->flags bits */ |
170 | AHCI_FLAG_NO_NCQ = (1 << 24), | 172 | AHCI_FLAG_NO_NCQ = (1 << 24), |
171 | AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ | 173 | AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ |
174 | AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ | ||
172 | }; | 175 | }; |
173 | 176 | ||
174 | struct ahci_cmd_hdr { | 177 | struct ahci_cmd_hdr { |
@@ -317,6 +320,16 @@ static const struct ata_port_info ahci_port_info[] = { | |||
317 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 320 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
318 | .port_ops = &ahci_ops, | 321 | .port_ops = &ahci_ops, |
319 | }, | 322 | }, |
323 | /* board_ahci_pi */ | ||
324 | { | ||
325 | .sht = &ahci_sht, | ||
326 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | ||
327 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | ||
328 | ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI, | ||
329 | .pio_mask = 0x1f, /* pio0-4 */ | ||
330 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | ||
331 | .port_ops = &ahci_ops, | ||
332 | }, | ||
320 | /* board_ahci_vt8251 */ | 333 | /* board_ahci_vt8251 */ |
321 | { | 334 | { |
322 | .sht = &ahci_sht, | 335 | .sht = &ahci_sht, |
@@ -353,22 +366,22 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
353 | { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ | 366 | { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ |
354 | { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ | 367 | { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ |
355 | { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ | 368 | { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ |
356 | { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ | 369 | { PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */ |
357 | { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */ | 370 | { PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */ |
358 | { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ | 371 | { PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */ |
359 | { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ | 372 | { PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */ |
360 | { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ | 373 | { PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */ |
361 | { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ | 374 | { PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */ |
362 | { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ | 375 | { PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */ |
363 | { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ | 376 | { PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */ |
364 | { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ | 377 | { PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */ |
365 | { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ | 378 | { PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */ |
366 | { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ | 379 | { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */ |
367 | { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ | 380 | { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */ |
368 | { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ | 381 | { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */ |
369 | { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ | 382 | { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */ |
370 | { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ | 383 | { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */ |
371 | { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ | 384 | { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */ |
372 | 385 | ||
373 | /* JMicron */ | 386 | /* JMicron */ |
374 | { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ | 387 | { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ |
@@ -691,7 +704,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) | |||
691 | } | 704 | } |
692 | 705 | ||
693 | static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, | 706 | static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, |
694 | int n_ports, u32 cap) | 707 | int n_ports, unsigned int port_flags, |
708 | struct ahci_host_priv *hpriv) | ||
695 | { | 709 | { |
696 | int i, rc; | 710 | int i, rc; |
697 | u32 tmp; | 711 | u32 tmp; |
@@ -700,13 +714,12 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, | |||
700 | void __iomem *port_mmio = ahci_port_base(mmio, i); | 714 | void __iomem *port_mmio = ahci_port_base(mmio, i); |
701 | const char *emsg = NULL; | 715 | const char *emsg = NULL; |
702 | 716 | ||
703 | #if 0 /* BIOSen initialize this incorrectly */ | 717 | if ((port_flags & AHCI_FLAG_HONOR_PI) && |
704 | if (!(hpriv->port_map & (1 << i))) | 718 | !(hpriv->port_map & (1 << i))) |
705 | continue; | 719 | continue; |
706 | #endif | ||
707 | 720 | ||
708 | /* make sure port is not active */ | 721 | /* make sure port is not active */ |
709 | rc = ahci_deinit_port(port_mmio, cap, &emsg); | 722 | rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); |
710 | if (rc) | 723 | if (rc) |
711 | dev_printk(KERN_WARNING, &pdev->dev, | 724 | dev_printk(KERN_WARNING, &pdev->dev, |
712 | "%s (%d)\n", emsg, rc); | 725 | "%s (%d)\n", emsg, rc); |
@@ -1363,7 +1376,8 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) | |||
1363 | if (rc) | 1376 | if (rc) |
1364 | return rc; | 1377 | return rc; |
1365 | 1378 | ||
1366 | ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap); | 1379 | ahci_init_controller(mmio, pdev, host->n_ports, |
1380 | host->ports[0]->flags, hpriv); | ||
1367 | } | 1381 | } |
1368 | 1382 | ||
1369 | ata_host_resume(host); | 1383 | ata_host_resume(host); |
@@ -1475,7 +1489,7 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1475 | struct ahci_host_priv *hpriv = probe_ent->private_data; | 1489 | struct ahci_host_priv *hpriv = probe_ent->private_data; |
1476 | struct pci_dev *pdev = to_pci_dev(probe_ent->dev); | 1490 | struct pci_dev *pdev = to_pci_dev(probe_ent->dev); |
1477 | void __iomem *mmio = probe_ent->mmio_base; | 1491 | void __iomem *mmio = probe_ent->mmio_base; |
1478 | unsigned int i, using_dac; | 1492 | unsigned int i, cap_n_ports, using_dac; |
1479 | int rc; | 1493 | int rc; |
1480 | 1494 | ||
1481 | rc = ahci_reset_controller(mmio, pdev); | 1495 | rc = ahci_reset_controller(mmio, pdev); |
@@ -1484,10 +1498,34 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1484 | 1498 | ||
1485 | hpriv->cap = readl(mmio + HOST_CAP); | 1499 | hpriv->cap = readl(mmio + HOST_CAP); |
1486 | hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); | 1500 | hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); |
1487 | probe_ent->n_ports = ahci_nr_ports(hpriv->cap); | 1501 | cap_n_ports = ahci_nr_ports(hpriv->cap); |
1488 | 1502 | ||
1489 | VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", | 1503 | VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", |
1490 | hpriv->cap, hpriv->port_map, probe_ent->n_ports); | 1504 | hpriv->cap, hpriv->port_map, cap_n_ports); |
1505 | |||
1506 | if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) { | ||
1507 | unsigned int n_ports = cap_n_ports; | ||
1508 | u32 port_map = hpriv->port_map; | ||
1509 | int max_port = 0; | ||
1510 | |||
1511 | for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) { | ||
1512 | if (port_map & (1 << i)) { | ||
1513 | n_ports--; | ||
1514 | port_map &= ~(1 << i); | ||
1515 | max_port = i; | ||
1516 | } else | ||
1517 | probe_ent->dummy_port_mask |= 1 << i; | ||
1518 | } | ||
1519 | |||
1520 | if (n_ports || port_map) | ||
1521 | dev_printk(KERN_WARNING, &pdev->dev, | ||
1522 | "nr_ports (%u) and implemented port map " | ||
1523 | "(0x%x) don't match\n", | ||
1524 | cap_n_ports, hpriv->port_map); | ||
1525 | |||
1526 | probe_ent->n_ports = max_port + 1; | ||
1527 | } else | ||
1528 | probe_ent->n_ports = cap_n_ports; | ||
1491 | 1529 | ||
1492 | using_dac = hpriv->cap & HOST_CAP_64; | 1530 | using_dac = hpriv->cap & HOST_CAP_64; |
1493 | if (using_dac && | 1531 | if (using_dac && |
@@ -1519,7 +1557,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1519 | for (i = 0; i < probe_ent->n_ports; i++) | 1557 | for (i = 0; i < probe_ent->n_ports; i++) |
1520 | ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); | 1558 | ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); |
1521 | 1559 | ||
1522 | ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap); | 1560 | ahci_init_controller(mmio, pdev, probe_ent->n_ports, |
1561 | probe_ent->port_flags, hpriv); | ||
1523 | 1562 | ||
1524 | pci_set_master(pdev); | 1563 | pci_set_master(pdev); |
1525 | 1564 | ||