and changed files
[powerpc.git] / drivers / ata / sata_sx4.c
index d9838dc..3a4f445 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_sx4"
-#define DRV_VERSION    "0.9"
+#define DRV_VERSION    "0.10"
 
 
 enum {
+       PDC_MMIO_BAR            = 3,
+       PDC_DIMM_BAR            = 4,
+
        PDC_PRD_TBL             = 0x44, /* Direct command DMA table addr */
 
        PDC_PKT_SUBMIT          = 0x40, /* Command packet pointer addr */
@@ -137,8 +139,6 @@ struct pdc_port_priv {
 };
 
 struct pdc_host_priv {
-       void                    __iomem *dimm_mmio;
-
        unsigned int            doing_hdma;
        unsigned int            hdma_prod;
        unsigned int            hdma_cons;
@@ -151,24 +151,23 @@ struct pdc_host_priv {
 
 
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance);
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
-static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
-static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
+static unsigned int pdc20621_dimm_init(struct ata_host *host);
+static int pdc20621_detect_dimm(struct ata_host *host);
+static unsigned int pdc20621_i2c_read(struct ata_host *host,
                                      u32 device, u32 subaddr, u32 *pdata);
-static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
-static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
+static int pdc20621_prog_dimm0(struct ata_host *host);
+static unsigned int pdc20621_prog_dimm_global(struct ata_host *host);
 #ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
+static void pdc20621_get_from_dimm(struct ata_host *host,
                                   void *psource, u32 offset, u32 size);
 #endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
+static void pdc20621_put_to_dimm(struct ata_host *host,
                                 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
 static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -202,17 +201,17 @@ static const struct ata_port_operations pdc_20621_ops = {
        .phy_reset              = pdc_20621_phy_reset,
        .qc_prep                = pdc20621_qc_prep,
        .qc_issue               = pdc20621_qc_issue_prot,
-       .data_xfer              = ata_mmio_data_xfer,
+       .data_xfer              = ata_data_xfer,
        .eng_timeout            = pdc_eng_timeout,
-       .irq_handler            = pdc20621_interrupt,
        .irq_clear              = pdc20621_irq_clear,
+       .irq_on                 = ata_irq_on,
+       .irq_ack                = ata_irq_ack,
        .port_start             = pdc_port_start,
 };
 
 static const struct ata_port_info pdc_port_info[] = {
        /* board_20621 */
        {
-               .sht            = &pdc_sata_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_SRST | ATA_FLAG_MMIO |
                                  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
@@ -411,16 +410,15 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
        struct scatterlist *sg;
        struct ata_port *ap = qc->ap;
        struct pdc_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host->mmio_base;
-       struct pdc_host_priv *hpriv = ap->host->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+       void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
+       void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
        unsigned int portno = ap->port_no;
        unsigned int i, idx, total_len = 0, sgt_len;
        u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
 
        WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
 
-       VPRINTK("ata%u: ENTER\n", ap->id);
+       VPRINTK("ata%u: ENTER\n", ap->print_id);
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -472,13 +470,12 @@ static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct pdc_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host->mmio_base;
-       struct pdc_host_priv *hpriv = ap->host->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+       void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
+       void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
        unsigned int portno = ap->port_no;
        unsigned int i;
 
-       VPRINTK("ata%u: ENTER\n", ap->id);
+       VPRINTK("ata%u: ENTER\n", ap->print_id);
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -524,7 +521,7 @@ static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
 {
        struct ata_port *ap = qc->ap;
        struct ata_host *host = ap->host;
-       void __iomem *mmio = host->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -578,8 +575,7 @@ static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        unsigned int port_no = ap->port_no;
-       struct pdc_host_priv *hpriv = ap->host->private_data;
-       void *dimm_mmio = hpriv->dimm_mmio;
+       void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
 
        dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
        dimm_mmio += PDC_DIMM_HOST_PKT;
@@ -598,7 +594,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        struct ata_host *host = ap->host;
        unsigned int port_no = ap->port_no;
-       void __iomem *mmio = host->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
        unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
        u8 seq = (u8) (port_no + 1);
        unsigned int port_ofs;
@@ -606,7 +602,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
 
-       VPRINTK("ata%u: ENTER\n", ap->id);
+       VPRINTK("ata%u: ENTER\n", ap->print_id);
 
        wmb();                  /* flush PRD, pkt writes */
 
@@ -627,8 +623,8 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
                readl(mmio + PDC_20621_SEQCTL + (seq * 4));     /* flush */
 
                writel(port_ofs + PDC_DIMM_ATA_PKT,
-                      (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-               readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+                      ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+               readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
                VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
                        port_ofs + PDC_DIMM_ATA_PKT,
                        port_ofs + PDC_DIMM_ATA_PKT,
@@ -673,7 +669,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 
                /* step two - DMA from DIMM to host */
                if (doing_hdma) {
-                       VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
                        /* get drive status; clear intr; complete txn */
                        qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
@@ -684,7 +680,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                /* step one - exec ATA command */
                else {
                        u8 seq = (u8) (port_no + 1 + 4);
-                       VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 
                        /* submit hdma pkt */
@@ -699,20 +695,20 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                /* step one - DMA from host to DIMM */
                if (doing_hdma) {
                        u8 seq = (u8) (port_no + 1);
-                       VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 
                        /* submit ata pkt */
                        writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
                        readl(mmio + PDC_20621_SEQCTL + (seq * 4));
                        writel(port_ofs + PDC_DIMM_ATA_PKT,
-                              (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-                       readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+                              ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+                       readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
                }
 
                /* step two - execute ATA command */
                else {
-                       VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
+                       VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->print_id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
                        /* get drive status; clear intr; complete txn */
                        qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
@@ -740,7 +736,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 static void pdc20621_irq_clear(struct ata_port *ap)
 {
        struct ata_host *host = ap->host;
-       void __iomem *mmio = host->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
        mmio += PDC_CHIP0_OFS;
 
@@ -758,12 +754,12 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance)
 
        VPRINTK("ENTER\n");
 
-       if (!host || !host->mmio_base) {
+       if (!host || !host->iomap[PDC_MMIO_BAR]) {
                VPRINTK("QUICK EXIT\n");
                return IRQ_NONE;
        }
 
-       mmio_base = host->mmio_base;
+       mmio_base = host->iomap[PDC_MMIO_BAR];
 
        /* reading should also clear interrupts */
        mmio_base += PDC_CHIP0_OFS;
@@ -864,7 +860,7 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
 }
 
 
-static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+static void pdc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
        port->cmd_addr          = base;
        port->data_addr         = base;
@@ -883,16 +879,15 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
 
 
 #ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
                                   u32 offset, u32 size)
 {
        u32 window_size;
        u16 idx;
        u8 page_mask;
        long dist;
-       void __iomem *mmio = pe->mmio_base;
-       struct pdc_host_priv *hpriv = pe->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
+       void __iomem *dimm_mmio = host->iomap[PDC_DIMM_BAR];
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -939,16 +934,15 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
 #endif
 
 
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_put_to_dimm(struct ata_host *host, void *psource,
                                 u32 offset, u32 size)
 {
        u32 window_size;
        u16 idx;
        u8 page_mask;
        long dist;
-       void __iomem *mmio = pe->mmio_base;
-       struct pdc_host_priv *hpriv = pe->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
+       void __iomem *dimm_mmio = host->iomap[PDC_DIMM_BAR];
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -990,10 +984,10 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
 }
 
 
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
+static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
                                      u32 subaddr, u32 *pdata)
 {
-       void __iomem *mmio = pe->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
        u32 i2creg  = 0;
        u32 status;
        u32 count =0;
@@ -1026,17 +1020,17 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
 }
 
 
-static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
+static int pdc20621_detect_dimm(struct ata_host *host)
 {
        u32 data=0 ;
-       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+       if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
                             PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
                if (data == 100)
                        return 100;
        } else
                return 0;
 
-       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
+       if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
                if(data <= 0x75)
                        return 133;
        } else
@@ -1046,13 +1040,13 @@ static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
 }
 
 
-static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
+static int pdc20621_prog_dimm0(struct ata_host *host)
 {
        u32 spd0[50];
        u32 data = 0;
        int size, i;
        u8 bdimmsize;
-       void __iomem *mmio = pe->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
        static const struct {
                unsigned int reg;
                unsigned int ofs;
@@ -1075,7 +1069,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
        mmio += PDC_CHIP0_OFS;
 
        for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
-               pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+               pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
                                  pdc_i2c_read_data[i].reg,
                                  &spd0[pdc_i2c_read_data[i].ofs]);
 
@@ -1111,11 +1105,11 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
 }
 
 
-static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
+static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
 {
        u32 data, spd0;
-       int error, i;
-       void __iomem *mmio = pe->mmio_base;
+       int error, i;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -1132,7 +1126,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
        readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
 
        /* Turn on for ECC */
-       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+       pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
                          PDC_DIMM_SPD_TYPE, &spd0);
        if (spd0 == 0x02) {
                data |= (0x01 << 16);
@@ -1159,7 +1153,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
 }
 
 
-static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
+static unsigned int pdc20621_dimm_init(struct ata_host *host)
 {
        int speed, size, length;
        u32 addr,spd0,pci_status;
@@ -1169,7 +1163,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
        u32 ticks=0;
        u32 clock=0;
        u32 fparam=0;
-       void __iomem *mmio = pe->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -1228,18 +1222,18 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
           Read SPD of DIMM by I2C interface,
           and program the DIMM Module Controller.
        */
-       if (!(speed = pdc20621_detect_dimm(pe))) {
+       if (!(speed = pdc20621_detect_dimm(host))) {
                printk(KERN_ERR "Detect Local DIMM Fail\n");
                return 1;       /* DIMM error */
        }
        VPRINTK("Local DIMM Speed = %d\n", speed);
 
        /* Programming DIMM0 Module Control Register (index_CID0:80h) */
-       size = pdc20621_prog_dimm0(pe);
+       size = pdc20621_prog_dimm0(host);
        VPRINTK("Local DIMM Size = %dMB\n",size);
 
        /* Programming DIMM Module Global Control Register (index_CID0:88h) */
-       if (pdc20621_prog_dimm_global(pe)) {
+       if (pdc20621_prog_dimm_global(host)) {
                printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
                return 1;
        }
@@ -1252,20 +1246,20 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
                                '9','8','0','3','1','6','1','2',0,0};
                u8 test_parttern2[40] = {0};
 
-               pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
-               pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
+               pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x10040, 40);
+               pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x40, 40);
 
-               pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+               pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x10040, 40);
+               pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40);
                printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
                       test_parttern2[1], &(test_parttern2[2]));
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
+               pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x10040,
                                       40);
                printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
                       test_parttern2[1], &(test_parttern2[2]));
 
-               pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+               pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x40, 40);
+               pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40);
                printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
                       test_parttern2[1], &(test_parttern2[2]));
        }
@@ -1273,14 +1267,14 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
 
        /* ECC initiliazation. */
 
-       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+       pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
                          PDC_DIMM_SPD_TYPE, &spd0);
        if (spd0 == 0x02) {
                VPRINTK("Start ECC initialization\n");
                addr = 0;
                length = size * 1024 * 1024;
                while (addr < length) {
-                       pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
+                       pdc20621_put_to_dimm(host, (void *) &tmp, addr,
                                             sizeof(u32));
                        addr += sizeof(u32);
                }
@@ -1290,10 +1284,10 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
 }
 
 
-static void pdc_20621_init(struct ata_probe_ent *pe)
+static void pdc_20621_init(struct ata_host *host)
 {
        u32 tmp;
-       void __iomem *mmio = pe->mmio_base;
+       void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
@@ -1324,27 +1318,44 @@ static void pdc_20621_init(struct ata_probe_ent *pe)
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
-       struct ata_probe_ent *probe_ent;
-       unsigned long base;
-       void __iomem *mmio_base;
-       void __iomem *dimm_mmio;
+       const struct ata_port_info *ppi[] =
+               { &pdc_port_info[ent->driver_data], NULL };
+       struct ata_host *host;
+       void __iomem *base;
        struct pdc_host_priv *hpriv;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
        int rc;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
+       /* allocate host */
+       host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
+       hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+       if (!host || !hpriv)
+               return -ENOMEM;
+
+       host->private_data = hpriv;
+
+       /* acquire resources and fill host */
        rc = pcim_enable_device(pdev);
        if (rc)
                return rc;
 
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
+       rc = pcim_iomap_regions(pdev, (1 << PDC_MMIO_BAR) | (1 << PDC_DIMM_BAR),
+                               DRV_NAME);
+       if (rc == -EBUSY)
                pcim_pin_device(pdev);
+       if (rc)
                return rc;
-       }
+       host->iomap = pcim_iomap_table(pdev);
 
+       base = host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
+       pdc_sata_setup_port(&host->ports[0]->ioaddr, base + 0x200);
+       pdc_sata_setup_port(&host->ports[1]->ioaddr, base + 0x280);
+       pdc_sata_setup_port(&host->ports[2]->ioaddr, base + 0x300);
+       pdc_sata_setup_port(&host->ports[3]->ioaddr, base + 0x380);
+
+       /* configure and activate */
        rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
        if (rc)
                return rc;
@@ -1352,61 +1363,13 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
        if (rc)
                return rc;
 
-       probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL)
-               return -ENOMEM;
-
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       mmio_base = pcim_iomap(pdev, 3, 0);
-       if (mmio_base == NULL)
-               return -ENOMEM;
-       base = (unsigned long) mmio_base;
-
-       hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv)
-               return -ENOMEM;
-
-       dimm_mmio = pcim_iomap(pdev, 4, 0);
-       if (!dimm_mmio)
+       if (pdc20621_dimm_init(host))
                return -ENOMEM;
-
-       hpriv->dimm_mmio = dimm_mmio;
-
-       probe_ent->sht          = pdc_port_info[board_idx].sht;
-       probe_ent->port_flags   = pdc_port_info[board_idx].flags;
-       probe_ent->pio_mask     = pdc_port_info[board_idx].pio_mask;
-       probe_ent->mwdma_mask   = pdc_port_info[board_idx].mwdma_mask;
-       probe_ent->udma_mask    = pdc_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = pdc_port_info[board_idx].port_ops;
-
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-
-       probe_ent->private_data = hpriv;
-       base += PDC_CHIP0_OFS;
-
-       probe_ent->n_ports = 4;
-       pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
-       pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
-       pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
-       pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
+       pdc_20621_init(host);
 
        pci_set_master(pdev);
-
-       /* initialize adapter */
-       /* initialize local dimm */
-       if (pdc20621_dimm_init(probe_ent))
-               return -ENOMEM;
-       pdc_20621_init(probe_ent);
-
-       if (!ata_device_add(probe_ent))
-               return -ENODEV;
-
-       devm_kfree(&pdev->dev, probe_ent);
-       return 0;
+       return ata_host_activate(host, pdev->irq, pdc20621_interrupt,
+                                IRQF_SHARED, &pdc_sata_sht);
 }