diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f66e2a50158b..11e4eb9f304e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
47 | 47 | ||
48 | #define DRV_NAME "ahci" | 48 | #define DRV_NAME "ahci" |
49 | #define DRV_VERSION "2.2" | 49 | #define DRV_VERSION "2.3" |
50 | 50 | ||
51 | 51 | ||
52 | enum { | 52 | enum { |
@@ -81,6 +81,7 @@ enum { | |||
81 | board_ahci_vt8251 = 2, | 81 | board_ahci_vt8251 = 2, |
82 | board_ahci_ign_iferr = 3, | 82 | board_ahci_ign_iferr = 3, |
83 | board_ahci_sb600 = 4, | 83 | board_ahci_sb600 = 4, |
84 | board_ahci_mv = 5, | ||
84 | 85 | ||
85 | /* global controller registers */ | 86 | /* global controller registers */ |
86 | HOST_CAP = 0x00, /* host capabilities */ | 87 | HOST_CAP = 0x00, /* host capabilities */ |
@@ -171,6 +172,8 @@ enum { | |||
171 | AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ | 172 | AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ |
172 | AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */ | 173 | AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */ |
173 | AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */ | 174 | AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */ |
175 | AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */ | ||
176 | AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */ | ||
174 | 177 | ||
175 | AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 178 | AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
176 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | 179 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
@@ -364,6 +367,18 @@ static const struct ata_port_info ahci_port_info[] = { | |||
364 | .udma_mask = ATA_UDMA6, | 367 | .udma_mask = ATA_UDMA6, |
365 | .port_ops = &ahci_ops, | 368 | .port_ops = &ahci_ops, |
366 | }, | 369 | }, |
370 | /* board_ahci_mv */ | ||
371 | { | ||
372 | .sht = &ahci_sht, | ||
373 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | ||
374 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | ||
375 | ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI | | ||
376 | AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI | | ||
377 | AHCI_FLAG_MV_PATA, | ||
378 | .pio_mask = 0x1f, /* pio0-4 */ | ||
379 | .udma_mask = ATA_UDMA6, | ||
380 | .port_ops = &ahci_ops, | ||
381 | }, | ||
367 | }; | 382 | }; |
368 | 383 | ||
369 | static const struct pci_device_id ahci_pci_tbl[] = { | 384 | static const struct pci_device_id ahci_pci_tbl[] = { |
@@ -459,6 +474,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
459 | { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ | 474 | { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ |
460 | { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ | 475 | { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ |
461 | 476 | ||
477 | /* Marvell */ | ||
478 | { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ | ||
479 | |||
462 | /* Generic, PCI class code for AHCI */ | 480 | /* Generic, PCI class code for AHCI */ |
463 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 481 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
464 | PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, | 482 | PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, |
@@ -544,6 +562,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
544 | hpriv->saved_port_map = port_map; | 562 | hpriv->saved_port_map = port_map; |
545 | } | 563 | } |
546 | 564 | ||
565 | /* | ||
566 | * Temporary Marvell 6145 hack: PATA port presence | ||
567 | * is asserted through the standard AHCI port | ||
568 | * presence register, as bit 4 (counting from 0) | ||
569 | */ | ||
570 | if (pi->flags & AHCI_FLAG_MV_PATA) { | ||
571 | dev_printk(KERN_ERR, &pdev->dev, | ||
572 | "MV_AHCI HACK: port_map %x -> %x\n", | ||
573 | hpriv->port_map, | ||
574 | hpriv->port_map & 0xf); | ||
575 | |||
576 | port_map &= 0xf; | ||
577 | } | ||
578 | |||
547 | /* cross check port_map and cap.n_ports */ | 579 | /* cross check port_map and cap.n_ports */ |
548 | if (pi->flags & AHCI_FLAG_HONOR_PI) { | 580 | if (pi->flags & AHCI_FLAG_HONOR_PI) { |
549 | u32 tmp_port_map = port_map; | 581 | u32 tmp_port_map = port_map; |
@@ -856,12 +888,25 @@ static void ahci_init_controller(struct ata_host *host) | |||
856 | struct pci_dev *pdev = to_pci_dev(host->dev); | 888 | struct pci_dev *pdev = to_pci_dev(host->dev); |
857 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; | 889 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; |
858 | int i; | 890 | int i; |
891 | void __iomem *port_mmio; | ||
859 | u32 tmp; | 892 | u32 tmp; |
860 | 893 | ||
894 | if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) { | ||
895 | port_mmio = __ahci_port_base(host, 4); | ||
896 | |||
897 | writel(0, port_mmio + PORT_IRQ_MASK); | ||
898 | |||
899 | /* clear port IRQ */ | ||
900 | tmp = readl(port_mmio + PORT_IRQ_STAT); | ||
901 | VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); | ||
902 | if (tmp) | ||
903 | writel(tmp, port_mmio + PORT_IRQ_STAT); | ||
904 | } | ||
905 | |||
861 | for (i = 0; i < host->n_ports; i++) { | 906 | for (i = 0; i < host->n_ports; i++) { |
862 | struct ata_port *ap = host->ports[i]; | 907 | struct ata_port *ap = host->ports[i]; |
863 | void __iomem *port_mmio = ahci_port_base(ap); | ||
864 | 908 | ||
909 | port_mmio = ahci_port_base(ap); | ||
865 | if (ata_port_is_dummy(ap)) | 910 | if (ata_port_is_dummy(ap)) |
866 | continue; | 911 | continue; |
867 | 912 | ||
@@ -1738,7 +1783,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1738 | if (rc) | 1783 | if (rc) |
1739 | return rc; | 1784 | return rc; |
1740 | 1785 | ||
1741 | if (pci_enable_msi(pdev)) | 1786 | if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev)) |
1742 | pci_intx(pdev, 1); | 1787 | pci_intx(pdev, 1); |
1743 | 1788 | ||
1744 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); | 1789 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); |