GIT 507e9cb31b348b5a7ef5cf1d464a8838f1e41317 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git#ALL commit Author: Jeff Garzik Date: Tue May 1 09:16:50 2007 -0400 [libata] ahci: Marvell code build fix Signed-off-by: Jeff Garzik commit 8fea12e6c71d0057703f8608bd508805d2172162 Author: Jeff Garzik Date: Sun Feb 25 20:30:30 2007 -0500 [libata] AHCI: get Marvell SATA going (PATA portion of chip not supported) Signed-off-by: Jeff Garzik drivers/ata/ahci.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 1ae443d..77411cd 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -81,6 +81,7 @@ enum { board_ahci_vt8251 = 2, board_ahci_ign_iferr = 3, board_ahci_sb600 = 4, + board_ahci_mv = 5, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -170,6 +171,7 @@ enum { AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */ + AHCI_FLAG_MV_PATA = (1 << 28), /* PATA port */ AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | @@ -358,6 +360,17 @@ static const struct ata_port_info ahci_p .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, + /* board_ahci_mv */ + { + .sht = &ahci_sht, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI | + AHCI_FLAG_MV_PATA, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -429,6 +442,9 @@ static const struct pci_device_id ahci_p { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ + /* Marvell */ + { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, @@ -454,11 +470,17 @@ static inline int ahci_nr_ports(u32 cap) return (cap & 0x1f) + 1; } -static inline void __iomem *ahci_port_base(struct ata_port *ap) +static inline void __iomem *__ahci_port_base(struct ata_host *host, + unsigned int port_no) { - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; + void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; - return mmio + 0x100 + (ap->port_no * 0x80); + return mmio + 0x100 + (port_no * 0x80); +} + +static inline void __iomem *ahci_port_base(struct ata_port *ap) +{ + return __ahci_port_base(ap->host, ap->port_no); } /** @@ -501,6 +523,20 @@ static void ahci_save_initial_config(str hpriv->saved_port_map = port_map; } + /* + * Temporary Marvell 6145 hack: PATA port presence + * is asserted through the standard AHCI port + * presence register, as bit 4 (counting from 0) + */ + if (pi->flags & AHCI_FLAG_MV_PATA) { + dev_printk(KERN_ERR, &pdev->dev, + "MV_AHCI HACK: port_map %x -> %x\n", + hpriv->port_map, + hpriv->port_map & 0xf); + + port_map &= 0xf; + } + /* cross check port_map and cap.n_ports */ if (pi->flags & AHCI_FLAG_HONOR_PI) { u32 tmp_port_map = port_map; @@ -784,14 +820,27 @@ static void ahci_init_controller(struct { struct pci_dev *pdev = to_pci_dev(host->dev); void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; + void __iomem *port_mmio; int i, rc; u32 tmp; + if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) { + port_mmio = __ahci_port_base(host, 4); + + writel(0, port_mmio + PORT_IRQ_MASK); + + /* clear port IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); + VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); + if (tmp) + writel(tmp, port_mmio + PORT_IRQ_STAT); + } + for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; - void __iomem *port_mmio = ahci_port_base(ap); const char *emsg = NULL; + port_mmio = ahci_port_base(ap); if (ata_port_is_dummy(ap)) continue; @@ -806,6 +855,9 @@ static void ahci_init_controller(struct VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); writel(tmp, port_mmio + PORT_SCR_ERR); + /* select the IRQ events we're interested in */ + writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); + /* clear port IRQ */ tmp = readl(port_mmio + PORT_IRQ_STAT); VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);