Merge tag 'mac80211-for-davem-2016-06-09' of git://git.kernel.org/pub/scm/linux/kerne...
[cascardo/linux.git] / drivers / ata / sata_dwc_460ex.c
index 2cb6f7e..00c2af1 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/dmaengine.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/phy/phy.h>
 #include <linux/libata.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 
-/* Supported DMA engine drivers */
-#include <linux/platform_data/dma-dw.h>
-#include <linux/dma/dw.h>
-
 /* These two are defined in "libata.h" */
 #undef DRV_NAME
 #undef DRV_VERSION
 #define DRV_NAME        "sata-dwc"
 #define DRV_VERSION     "1.3"
 
-#ifndef out_le32
-#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (void __iomem *)(a))
-#endif
-
-#ifndef in_le32
-#define in_le32(a)     __le32_to_cpu(__raw_readl((void __iomem *)(a)))
-#endif
+#define sata_dwc_writel(a, v)  writel_relaxed(v, a)
+#define sata_dwc_readl(a)      readl_relaxed(a)
 
 #ifndef NO_IRQ
 #define NO_IRQ         0
 #endif
 
-#define AHB_DMA_BRST_DFLT      64      /* 16 data items burst length*/
+#define AHB_DMA_BRST_DFLT      64      /* 16 data items burst length */
 
 enum {
        SATA_DWC_MAX_PORTS = 1,
@@ -102,7 +95,7 @@ struct sata_dwc_regs {
        u32 versionr;           /* Version Register */
        u32 idr;                /* ID Register */
        u32 unimpl[192];        /* Unimplemented */
-       u32 dmadr[256]; /* FIFO Locations in DMA Mode */
+       u32 dmadr[256];         /* FIFO Locations in DMA Mode */
 };
 
 enum {
@@ -146,9 +139,14 @@ struct sata_dwc_device {
        struct device           *dev;           /* generic device struct */
        struct ata_probe_ent    *pe;            /* ptr to probe-ent */
        struct ata_host         *host;
-       u8 __iomem              *reg_base;
-       struct sata_dwc_regs    *sata_dwc_regs; /* DW Synopsys SATA specific */
+       struct sata_dwc_regs __iomem *sata_dwc_regs;    /* DW SATA specific */
+       u32                     sactive_issued;
+       u32                     sactive_queued;
+       struct phy              *phy;
+       phys_addr_t             dmadr;
+#ifdef CONFIG_SATA_DWC_OLD_DMA
        struct dw_dma_chip      *dma;
+#endif
 };
 
 #define SATA_DWC_QCMD_MAX      32
@@ -159,25 +157,19 @@ struct sata_dwc_device_port {
        int                     dma_pending[SATA_DWC_QCMD_MAX];
 
        /* DMA info */
-       struct dw_dma_slave             *dws;
        struct dma_chan                 *chan;
        struct dma_async_tx_descriptor  *desc[SATA_DWC_QCMD_MAX];
        u32                             dma_interrupt_count;
 };
 
 /*
- * Commonly used DWC SATA driver Macros
+ * Commonly used DWC SATA driver macros
  */
-#define HSDEV_FROM_HOST(host)  ((struct sata_dwc_device *)\
-                                       (host)->private_data)
-#define HSDEV_FROM_AP(ap)  ((struct sata_dwc_device *)\
-                                       (ap)->host->private_data)
-#define HSDEVP_FROM_AP(ap)   ((struct sata_dwc_device_port *)\
-                                       (ap)->private_data)
-#define HSDEV_FROM_QC(qc)      ((struct sata_dwc_device *)\
-                                       (qc)->ap->host->private_data)
-#define HSDEV_FROM_HSDEVP(p)   ((struct sata_dwc_device *)\
-                                               (hsdevp)->hsdev)
+#define HSDEV_FROM_HOST(host)  ((struct sata_dwc_device *)(host)->private_data)
+#define HSDEV_FROM_AP(ap)      ((struct sata_dwc_device *)(ap)->host->private_data)
+#define HSDEVP_FROM_AP(ap)     ((struct sata_dwc_device_port *)(ap)->private_data)
+#define HSDEV_FROM_QC(qc)      ((struct sata_dwc_device *)(qc)->ap->host->private_data)
+#define HSDEV_FROM_HSDEVP(p)   ((struct sata_dwc_device *)(p)->hsdev)
 
 enum {
        SATA_DWC_CMD_ISSUED_NOT         = 0,
@@ -190,21 +182,6 @@ enum {
        SATA_DWC_DMA_PENDING_RX         = 2,
 };
 
-struct sata_dwc_host_priv {
-       void    __iomem  *scr_addr_sstatus;
-       u32     sata_dwc_sactive_issued ;
-       u32     sata_dwc_sactive_queued ;
-};
-
-static struct sata_dwc_host_priv host_pvt;
-
-static struct dw_dma_slave sata_dwc_dma_dws = {
-       .src_id = 0,
-       .dst_id = 0,
-       .m_master = 1,
-       .p_master = 0,
-};
-
 /*
  * Prototypes
  */
@@ -215,6 +192,93 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status);
 static void sata_dwc_port_stop(struct ata_port *ap);
 static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag);
 
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+
+#include <linux/platform_data/dma-dw.h>
+#include <linux/dma/dw.h>
+
+static struct dw_dma_slave sata_dwc_dma_dws = {
+       .src_id = 0,
+       .dst_id = 0,
+       .m_master = 1,
+       .p_master = 0,
+};
+
+static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct dw_dma_slave *dws = &sata_dwc_dma_dws;
+
+       if (dws->dma_dev != chan->device->dev)
+               return false;
+
+       chan->private = dws;
+       return true;
+}
+
+static int sata_dwc_dma_get_channel_old(struct sata_dwc_device_port *hsdevp)
+{
+       struct sata_dwc_device *hsdev = hsdevp->hsdev;
+       struct dw_dma_slave *dws = &sata_dwc_dma_dws;
+       dma_cap_mask_t mask;
+
+       dws->dma_dev = hsdev->dev;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       /* Acquire DMA channel */
+       hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
+       if (!hsdevp->chan) {
+               dev_err(hsdev->dev, "%s: dma channel unavailable\n",
+                        __func__);
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
+static int sata_dwc_dma_init_old(struct platform_device *pdev,
+                                struct sata_dwc_device *hsdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res;
+
+       hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL);
+       if (!hsdev->dma)
+               return -ENOMEM;
+
+       hsdev->dma->dev = &pdev->dev;
+
+       /* Get SATA DMA interrupt number */
+       hsdev->dma->irq = irq_of_parse_and_map(np, 1);
+       if (hsdev->dma->irq == NO_IRQ) {
+               dev_err(&pdev->dev, "no SATA DMA irq\n");
+               return -ENODEV;
+       }
+
+       /* Get physical SATA DMA register base address */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(hsdev->dma->regs)) {
+               dev_err(&pdev->dev,
+                       "ioremap failed for AHBDMA register address\n");
+               return PTR_ERR(hsdev->dma->regs);
+       }
+
+       /* Initialize AHB DMAC */
+       return dw_dma_probe(hsdev->dma);
+}
+
+static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev)
+{
+       if (!hsdev->dma)
+               return;
+
+       dw_dma_remove(hsdev->dma);
+}
+
+#endif
+
 static const char *get_prot_descript(u8 protocol)
 {
        switch ((enum ata_tf_protocols)protocol) {
@@ -305,21 +369,20 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd
        struct ata_port *ap = qc->ap;
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
        struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
-       dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr;
        struct dma_slave_config sconf;
        struct dma_async_tx_descriptor *desc;
 
        if (qc->dma_dir == DMA_DEV_TO_MEM) {
-               sconf.src_addr = addr;
-               sconf.device_fc = true;
+               sconf.src_addr = hsdev->dmadr;
+               sconf.device_fc = false;
        } else {        /* DMA_MEM_TO_DEV */
-               sconf.dst_addr = addr;
+               sconf.dst_addr = hsdev->dmadr;
                sconf.device_fc = false;
        }
 
        sconf.direction = qc->dma_dir;
-       sconf.src_maxburst = AHB_DMA_BRST_DFLT;
-       sconf.dst_maxburst = AHB_DMA_BRST_DFLT;
+       sconf.src_maxburst = AHB_DMA_BRST_DFLT / 4;     /* in items */
+       sconf.dst_maxburst = AHB_DMA_BRST_DFLT / 4;     /* in items */
        sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 
@@ -336,8 +399,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd
        desc->callback = dma_dwc_xfer_done;
        desc->callback_param = hsdev;
 
-       dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n",
-               __func__, qc->sg, qc->n_elem, &addr);
+       dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pa\n", __func__,
+               qc->sg, qc->n_elem, &hsdev->dmadr);
 
        return desc;
 }
@@ -350,48 +413,38 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
                return -EINVAL;
        }
 
-       *val = in_le32(link->ap->ioaddr.scr_addr + (scr * 4));
-       dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
-               __func__, link->ap->print_id, scr, *val);
+       *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4));
+       dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__,
+               link->ap->print_id, scr, *val);
 
        return 0;
 }
 
 static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val)
 {
-       dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
-               __func__, link->ap->print_id, scr, val);
+       dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__,
+               link->ap->print_id, scr, val);
        if (scr > SCR_NOTIFICATION) {
                dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n",
                         __func__, scr);
                return -EINVAL;
        }
-       out_le32(link->ap->ioaddr.scr_addr + (scr * 4), val);
+       sata_dwc_writel(link->ap->ioaddr.scr_addr + (scr * 4), val);
 
        return 0;
 }
 
-static u32 core_scr_read(unsigned int scr)
-{
-       return in_le32(host_pvt.scr_addr_sstatus + (scr * 4));
-}
-
-static void core_scr_write(unsigned int scr, u32 val)
-{
-       out_le32(host_pvt.scr_addr_sstatus + (scr * 4), val);
-}
-
-static void clear_serror(void)
+static void clear_serror(struct ata_port *ap)
 {
        u32 val;
-       val = core_scr_read(SCR_ERROR);
-       core_scr_write(SCR_ERROR, val);
+       sata_dwc_scr_read(&ap->link, SCR_ERROR, &val);
+       sata_dwc_scr_write(&ap->link, SCR_ERROR, val);
 }
 
 static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
 {
-       out_le32(&hsdev->sata_dwc_regs->intpr,
-                in_le32(&hsdev->sata_dwc_regs->intpr));
+       sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
+                       sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
 }
 
 static u32 qcmd_tag_to_mask(u8 tag)
@@ -412,7 +465,7 @@ static void sata_dwc_error_intr(struct ata_port *ap,
 
        ata_ehi_clear_desc(ehi);
 
-       serror = core_scr_read(SCR_ERROR);
+       sata_dwc_scr_read(&ap->link, SCR_ERROR, &serror);
        status = ap->ops->sff_check_status(ap);
 
        tag = ap->link.active_tag;
@@ -423,7 +476,7 @@ static void sata_dwc_error_intr(struct ata_port *ap,
                hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]);
 
        /* Clear error register and interrupt bit */
-       clear_serror();
+       clear_serror(ap);
        clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR);
 
        /* This is the only error happening now.  TODO check for exact error */
@@ -462,12 +515,12 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
        int handled, num_processed, port = 0;
        uint intpr, sactive, sactive2, tag_mask;
        struct sata_dwc_device_port *hsdevp;
-       host_pvt.sata_dwc_sactive_issued = 0;
+       hsdev->sactive_issued = 0;
 
        spin_lock_irqsave(&host->lock, flags);
 
        /* Read the interrupt register */
-       intpr = in_le32(&hsdev->sata_dwc_regs->intpr);
+       intpr = sata_dwc_readl(&hsdev->sata_dwc_regs->intpr);
 
        ap = host->ports[port];
        hsdevp = HSDEVP_FROM_AP(ap);
@@ -486,12 +539,12 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
        if (intpr & SATA_DWC_INTPR_NEWFP) {
                clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP);
 
-               tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr));
+               tag = (u8)(sata_dwc_readl(&hsdev->sata_dwc_regs->fptagr));
                dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag);
                if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND)
                        dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag);
 
-               host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag);
+               hsdev->sactive_issued |= qcmd_tag_to_mask(tag);
 
                qc = ata_qc_from_tag(ap, tag);
                /*
@@ -505,11 +558,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
                handled = 1;
                goto DONE;
        }
-       sactive = core_scr_read(SCR_ACTIVE);
-       tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
+       sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
+       tag_mask = (hsdev->sactive_issued | sactive) ^ sactive;
 
        /* If no sactive issued and tag_mask is zero then this is not NCQ */
-       if (host_pvt.sata_dwc_sactive_issued == 0 && tag_mask == 0) {
+       if (hsdev->sactive_issued == 0 && tag_mask == 0) {
                if (ap->link.active_tag == ATA_TAG_POISON)
                        tag = 0;
                else
@@ -579,22 +632,19 @@ DRVSTILLBUSY:
         */
 
         /* process completed commands */
-       sactive = core_scr_read(SCR_ACTIVE);
-       tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
+       sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
+       tag_mask = (hsdev->sactive_issued | sactive) ^ sactive;
 
-       if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \
-                                                       tag_mask > 1) {
+       if (sactive != 0 || hsdev->sactive_issued > 1 || tag_mask > 1) {
                dev_dbg(ap->dev,
                        "%s NCQ:sactive=0x%08x  sactive_issued=0x%08x tag_mask=0x%08x\n",
-                       __func__, sactive, host_pvt.sata_dwc_sactive_issued,
-                       tag_mask);
+                       __func__, sactive, hsdev->sactive_issued, tag_mask);
        }
 
-       if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \
-                                       (host_pvt.sata_dwc_sactive_issued)) {
+       if ((tag_mask | hsdev->sactive_issued) != hsdev->sactive_issued) {
                dev_warn(ap->dev,
-                        "Bad tag mask?  sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x  tag_mask=0x%08x\n",
-                        sactive, host_pvt.sata_dwc_sactive_issued, tag_mask);
+                        "Bad tag mask?  sactive=0x%08x sactive_issued=0x%08x  tag_mask=0x%08x\n",
+                        sactive, hsdev->sactive_issued, tag_mask);
        }
 
        /* read just to clear ... not bad if currently still busy */
@@ -656,7 +706,7 @@ STILLBUSY:
         * we were processing --we read status as part of processing a completed
         * command).
         */
-       sactive2 = core_scr_read(SCR_ACTIVE);
+       sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive2);
        if (sactive2 != sactive) {
                dev_dbg(ap->dev,
                        "More completed - sactive=0x%x sactive2=0x%x\n",
@@ -672,15 +722,14 @@ DONE:
 static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
 {
        struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp);
+       u32 dmacr = sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr);
 
        if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) {
-               out_le32(&(hsdev->sata_dwc_regs->dmacr),
-                        SATA_DWC_DMACR_RX_CLEAR(
-                                in_le32(&(hsdev->sata_dwc_regs->dmacr))));
+               dmacr = SATA_DWC_DMACR_RX_CLEAR(dmacr);
+               sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr);
        } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) {
-               out_le32(&(hsdev->sata_dwc_regs->dmacr),
-                        SATA_DWC_DMACR_TX_CLEAR(
-                                in_le32(&(hsdev->sata_dwc_regs->dmacr))));
+               dmacr = SATA_DWC_DMACR_TX_CLEAR(dmacr);
+               sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr);
        } else {
                /*
                 * This should not happen, it indicates the driver is out of
@@ -688,10 +737,9 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
                 */
                dev_err(hsdev->dev,
                        "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n",
-                       __func__, tag, hsdevp->dma_pending[tag],
-                       in_le32(&hsdev->sata_dwc_regs->dmacr));
-               out_le32(&(hsdev->sata_dwc_regs->dmacr),
-                       SATA_DWC_DMACR_TXRXCH_CLEAR);
+                       __func__, tag, hsdevp->dma_pending[tag], dmacr);
+               sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+                               SATA_DWC_DMACR_TXRXCH_CLEAR);
        }
 }
 
@@ -716,7 +764,7 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
                         __func__, qc->tag, qc->tf.command,
                         get_dma_dir_descript(qc->dma_dir),
                         get_prot_descript(qc->tf.protocol),
-                        in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+                        sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
        }
 #endif
 
@@ -725,7 +773,7 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
                        dev_err(ap->dev,
                                "%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n",
                                __func__,
-                               in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+                               sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
                }
 
                hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE;
@@ -742,8 +790,9 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
        u8 status = 0;
        u32 mask = 0x0;
        u8 tag = qc->tag;
+       struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-       host_pvt.sata_dwc_sactive_queued = 0;
+       hsdev->sactive_queued = 0;
        dev_dbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status);
 
        if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX)
@@ -756,10 +805,8 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
 
        /* clear active bit */
        mask = (~(qcmd_tag_to_mask(tag)));
-       host_pvt.sata_dwc_sactive_queued = (host_pvt.sata_dwc_sactive_queued) \
-                                               & mask;
-       host_pvt.sata_dwc_sactive_issued = (host_pvt.sata_dwc_sactive_issued) \
-                                               & mask;
+       hsdev->sactive_queued = hsdev->sactive_queued & mask;
+       hsdev->sactive_issued = hsdev->sactive_issued & mask;
        ata_qc_complete(qc);
        return 0;
 }
@@ -767,54 +814,62 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
 static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
 {
        /* Enable selective interrupts by setting the interrupt maskregister*/
-       out_le32(&hsdev->sata_dwc_regs->intmr,
-                SATA_DWC_INTMR_ERRM |
-                SATA_DWC_INTMR_NEWFPM |
-                SATA_DWC_INTMR_PMABRTM |
-                SATA_DWC_INTMR_DMATM);
+       sata_dwc_writel(&hsdev->sata_dwc_regs->intmr,
+                       SATA_DWC_INTMR_ERRM |
+                       SATA_DWC_INTMR_NEWFPM |
+                       SATA_DWC_INTMR_PMABRTM |
+                       SATA_DWC_INTMR_DMATM);
        /*
         * Unmask the error bits that should trigger an error interrupt by
         * setting the error mask register.
         */
-       out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
+       sata_dwc_writel(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
 
        dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n",
-                __func__, in_le32(&hsdev->sata_dwc_regs->intmr),
-               in_le32(&hsdev->sata_dwc_regs->errmr));
+                __func__, sata_dwc_readl(&hsdev->sata_dwc_regs->intmr),
+               sata_dwc_readl(&hsdev->sata_dwc_regs->errmr));
 }
 
-static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
+static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base)
 {
-       struct sata_dwc_device_port *hsdevp = param;
-       struct dw_dma_slave *dws = hsdevp->dws;
+       port->cmd_addr          = base + 0x00;
+       port->data_addr         = base + 0x00;
 
-       if (dws->dma_dev != chan->device->dev)
-               return false;
+       port->error_addr        = base + 0x04;
+       port->feature_addr      = base + 0x04;
 
-       chan->private = dws;
-       return true;
-}
+       port->nsect_addr        = base + 0x08;
 
-static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr = (void __iomem *)base + 0x00;
-       port->data_addr = (void __iomem *)base + 0x00;
+       port->lbal_addr         = base + 0x0c;
+       port->lbam_addr         = base + 0x10;
+       port->lbah_addr         = base + 0x14;
+
+       port->device_addr       = base + 0x18;
+       port->command_addr      = base + 0x1c;
+       port->status_addr       = base + 0x1c;
 
-       port->error_addr = (void __iomem *)base + 0x04;
-       port->feature_addr = (void __iomem *)base + 0x04;
+       port->altstatus_addr    = base + 0x20;
+       port->ctl_addr          = base + 0x20;
+}
 
-       port->nsect_addr = (void __iomem *)base + 0x08;
+static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp)
+{
+       struct sata_dwc_device *hsdev = hsdevp->hsdev;
+       struct device *dev = hsdev->dev;
 
-       port->lbal_addr = (void __iomem *)base + 0x0c;
-       port->lbam_addr = (void __iomem *)base + 0x10;
-       port->lbah_addr = (void __iomem *)base + 0x14;
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+       if (!of_find_property(dev->of_node, "dmas", NULL))
+               return sata_dwc_dma_get_channel_old(hsdevp);
+#endif
 
-       port->device_addr = (void __iomem *)base + 0x18;
-       port->command_addr = (void __iomem *)base + 0x1c;
-       port->status_addr = (void __iomem *)base + 0x1c;
+       hsdevp->chan = dma_request_chan(dev, "sata-dma");
+       if (IS_ERR(hsdevp->chan)) {
+               dev_err(dev, "failed to allocate dma channel: %ld\n",
+                       PTR_ERR(hsdevp->chan));
+               return PTR_ERR(hsdevp->chan);
+       }
 
-       port->altstatus_addr = (void __iomem *)base + 0x20;
-       port->ctl_addr = (void __iomem *)base + 0x20;
+       return 0;
 }
 
 /*
@@ -829,7 +884,6 @@ static int sata_dwc_port_start(struct ata_port *ap)
        struct sata_dwc_device *hsdev;
        struct sata_dwc_device_port *hsdevp = NULL;
        struct device *pdev;
-       dma_cap_mask_t mask;
        int i;
 
        hsdev = HSDEV_FROM_AP(ap);
@@ -853,20 +907,13 @@ static int sata_dwc_port_start(struct ata_port *ap)
        }
        hsdevp->hsdev = hsdev;
 
-       hsdevp->dws = &sata_dwc_dma_dws;
-       hsdevp->dws->dma_dev = hsdev->dev;
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
+       err = sata_dwc_dma_get_channel(hsdevp);
+       if (err)
+               goto CLEANUP_ALLOC;
 
-       /* Acquire DMA channel */
-       hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
-       if (!hsdevp->chan) {
-               dev_err(hsdev->dev, "%s: dma channel unavailable\n",
-                        __func__);
-               err = -EAGAIN;
+       err = phy_power_on(hsdev->phy);
+       if (err)
                goto CLEANUP_ALLOC;
-       }
 
        for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
                hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
@@ -877,18 +924,18 @@ static int sata_dwc_port_start(struct ata_port *ap)
        if (ap->port_no == 0)  {
                dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n",
                        __func__);
-               out_le32(&hsdev->sata_dwc_regs->dmacr,
-                        SATA_DWC_DMACR_TXRXCH_CLEAR);
+               sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+                               SATA_DWC_DMACR_TXRXCH_CLEAR);
 
                dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n",
                         __func__);
-               out_le32(&hsdev->sata_dwc_regs->dbtsr,
-                        (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
-                         SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
+               sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr,
+                               (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+                                SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
        }
 
        /* Clear any error bits before libata starts issuing commands */
-       clear_serror();
+       clear_serror(ap);
        ap->private_data = hsdevp;
        dev_dbg(ap->dev, "%s: done\n", __func__);
        return 0;
@@ -903,11 +950,13 @@ CLEANUP:
 static void sata_dwc_port_stop(struct ata_port *ap)
 {
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+       struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
 
        dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id);
 
-       dmaengine_terminate_all(hsdevp->chan);
+       dmaengine_terminate_sync(hsdevp->chan);
        dma_release_channel(hsdevp->chan);
+       phy_power_off(hsdev->phy);
 
        kfree(hsdevp);
        ap->private_data = NULL;
@@ -924,22 +973,20 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap,
                                         struct ata_taskfile *tf,
                                         u8 tag, u32 cmd_issued)
 {
-       unsigned long flags;
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
        dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command,
                ata_get_cmd_descript(tf->command), tag);
 
-       spin_lock_irqsave(&ap->host->lock, flags);
        hsdevp->cmd_issued[tag] = cmd_issued;
-       spin_unlock_irqrestore(&ap->host->lock, flags);
+
        /*
         * Clear SError before executing a new command.
         * sata_dwc_scr_write and read can not be used here. Clearing the PM
         * managed SError register for the disk needs to be done before the
         * task file is loaded.
         */
-       clear_serror();
+       clear_serror(ap);
        ata_sff_exec_command(ap, tf);
 }
 
@@ -992,18 +1039,18 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
        sata_dwc_tf_dump(ap, &qc->tf);
 
        if (start_dma) {
-               reg = core_scr_read(SCR_ERROR);
+               sata_dwc_scr_read(&ap->link, SCR_ERROR, &reg);
                if (reg & SATA_DWC_SERROR_ERR_BITS) {
                        dev_err(ap->dev, "%s: ****** SError=0x%08x ******\n",
                                __func__, reg);
                }
 
                if (dir == DMA_TO_DEVICE)
-                       out_le32(&hsdev->sata_dwc_regs->dmacr,
-                               SATA_DWC_DMACR_TXCHEN);
+                       sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+                                       SATA_DWC_DMACR_TXCHEN);
                else
-                       out_le32(&hsdev->sata_dwc_regs->dmacr,
-                               SATA_DWC_DMACR_RXCHEN);
+                       sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+                                       SATA_DWC_DMACR_RXCHEN);
 
                /* Enable AHB DMA transfer on the specified channel */
                dmaengine_submit(desc);
@@ -1025,36 +1072,12 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc)
        sata_dwc_bmdma_start_by_tag(qc, tag);
 }
 
-/*
- * Function : sata_dwc_qc_prep_by_tag
- * arguments : ata_queued_cmd *qc, u8 tag
- * Return value : None
- * qc_prep for a particular queued command based on tag
- */
-static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
-{
-       struct dma_async_tx_descriptor *desc;
-       struct ata_port *ap = qc->ap;
-       struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-
-       dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n",
-               __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),
-                qc->n_elem);
-
-       desc = dma_dwc_xfer_setup(qc);
-       if (!desc) {
-               dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n",
-                       __func__);
-               return;
-       }
-       hsdevp->desc[tag] = desc;
-}
-
 static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
 {
        u32 sactive;
        u8 tag = qc->tag;
        struct ata_port *ap = qc->ap;
+       struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
 #ifdef DEBUG_NCQ
        if (qc->tag > 0 || ap->link.sactive > 1)
@@ -1068,47 +1091,33 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
 
        if (!ata_is_ncq(qc->tf.protocol))
                tag = 0;
-       sata_dwc_qc_prep_by_tag(qc, tag);
+
+       if (ata_is_dma(qc->tf.protocol)) {
+               hsdevp->desc[tag] = dma_dwc_xfer_setup(qc);
+               if (!hsdevp->desc[tag])
+                       return AC_ERR_SYSTEM;
+       } else {
+               hsdevp->desc[tag] = NULL;
+       }
 
        if (ata_is_ncq(qc->tf.protocol)) {
-               sactive = core_scr_read(SCR_ACTIVE);
+               sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
                sactive |= (0x00000001 << tag);
-               core_scr_write(SCR_ACTIVE, sactive);
+               sata_dwc_scr_write(&ap->link, SCR_ACTIVE, sactive);
 
                dev_dbg(qc->ap->dev,
                        "%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n",
                        __func__, tag, qc->ap->link.sactive, sactive);
 
                ap->ops->sff_tf_load(ap, &qc->tf);
-               sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag,
+               sata_dwc_exec_command_by_tag(ap, &qc->tf, tag,
                                             SATA_DWC_CMD_ISSUED_PEND);
        } else {
-               ata_sff_qc_issue(qc);
+               return ata_bmdma_qc_issue(qc);
        }
        return 0;
 }
 
-/*
- * Function : sata_dwc_qc_prep
- * arguments : ata_queued_cmd *qc
- * Return value : None
- * qc_prep for a particular queued command
- */
-
-static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)
-{
-       if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO))
-               return;
-
-#ifdef DEBUG_NCQ
-       if (qc->tag > 0)
-               dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n",
-                        __func__, qc->tag, qc->ap->link.active_tag);
-
-       return ;
-#endif
-}
-
 static void sata_dwc_error_handler(struct ata_port *ap)
 {
        ata_sff_error_handler(ap);
@@ -1125,17 +1134,22 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class,
        sata_dwc_enable_interrupts(hsdev);
 
        /* Reconfigure the DMA control register */
-       out_le32(&hsdev->sata_dwc_regs->dmacr,
-                SATA_DWC_DMACR_TXRXCH_CLEAR);
+       sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+                       SATA_DWC_DMACR_TXRXCH_CLEAR);
 
        /* Reconfigure the DMA Burst Transaction Size register */
-       out_le32(&hsdev->sata_dwc_regs->dbtsr,
-                SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
-                SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT));
+       sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr,
+                       SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+                       SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT));
 
        return ret;
 }
 
+static void sata_dwc_dev_select(struct ata_port *ap, unsigned int device)
+{
+       /* SATA DWC is master only */
+}
+
 /*
  * scsi mid-layer and libata interface structures
  */
@@ -1148,7 +1162,13 @@ static struct scsi_host_template sata_dwc_sht = {
         */
        .sg_tablesize           = LIBATA_MAX_PRD,
        /* .can_queue           = ATA_MAX_QUEUE, */
-       .dma_boundary           = ATA_DMA_BOUNDARY,
+       /*
+        * Make sure a LLI block is not created that will span 8K max FIS
+        * boundary. If the block spans such a FIS boundary, there is a chance
+        * that a DMA burst will cross that boundary -- this results in an
+        * error in the host controller.
+        */
+       .dma_boundary           = 0x1fff /* ATA_DMA_BOUNDARY */,
 };
 
 static struct ata_port_operations sata_dwc_ops = {
@@ -1157,7 +1177,6 @@ static struct ata_port_operations sata_dwc_ops = {
        .error_handler          = sata_dwc_error_handler,
        .hardreset              = sata_dwc_hardreset,
 
-       .qc_prep                = sata_dwc_qc_prep,
        .qc_issue               = sata_dwc_qc_issue,
 
        .scr_read               = sata_dwc_scr_read,
@@ -1166,6 +1185,8 @@ static struct ata_port_operations sata_dwc_ops = {
        .port_start             = sata_dwc_port_start,
        .port_stop              = sata_dwc_port_stop,
 
+       .sff_dev_select         = sata_dwc_dev_select,
+
        .bmdma_setup            = sata_dwc_bmdma_setup,
        .bmdma_start            = sata_dwc_bmdma_start,
 };
@@ -1184,13 +1205,14 @@ static int sata_dwc_probe(struct platform_device *ofdev)
        struct sata_dwc_device *hsdev;
        u32 idr, versionr;
        char *ver = (char *)&versionr;
-       u8 __iomem *base;
+       void __iomem *base;
        int err = 0;
        int irq;
        struct ata_host *host;
        struct ata_port_info pi = sata_dwc_port_info[0];
        const struct ata_port_info *ppi[] = { &pi, NULL };
        struct device_node *np = ofdev->dev.of_node;
+       struct resource *res;
 
        /* Allocate DWC SATA device */
        host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS);
@@ -1201,57 +1223,33 @@ static int sata_dwc_probe(struct platform_device *ofdev)
        host->private_data = hsdev;
 
        /* Ioremap SATA registers */
-       base = of_iomap(np, 0);
-       if (!base) {
+       res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&ofdev->dev, res);
+       if (IS_ERR(base)) {
                dev_err(&ofdev->dev,
                        "ioremap failed for SATA register address\n");
-               return -ENODEV;
+               return PTR_ERR(base);
        }
-       hsdev->reg_base = base;
        dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");
 
        /* Synopsys DWC SATA specific Registers */
-       hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+       hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET;
+       hsdev->dmadr = res->start + SATA_DWC_REG_OFFSET + offsetof(struct sata_dwc_regs, dmadr);
 
        /* Setup port */
        host->ports[0]->ioaddr.cmd_addr = base;
        host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
-       host_pvt.scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
-       sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base);
+       sata_dwc_setup_port(&host->ports[0]->ioaddr, base);
 
        /* Read the ID and Version Registers */
-       idr = in_le32(&hsdev->sata_dwc_regs->idr);
-       versionr = in_le32(&hsdev->sata_dwc_regs->versionr);
+       idr = sata_dwc_readl(&hsdev->sata_dwc_regs->idr);
+       versionr = sata_dwc_readl(&hsdev->sata_dwc_regs->versionr);
        dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n",
                   idr, ver[0], ver[1], ver[2]);
 
-       /* Get SATA DMA interrupt number */
-       hsdev->dma->irq = irq_of_parse_and_map(np, 1);
-       if (hsdev->dma->irq == NO_IRQ) {
-               dev_err(&ofdev->dev, "no SATA DMA irq\n");
-               err = -ENODEV;
-               goto error_iomap;
-       }
-
-       /* Get physical SATA DMA register base address */
-       hsdev->dma->regs = of_iomap(np, 1);
-       if (!hsdev->dma->regs) {
-               dev_err(&ofdev->dev,
-                       "ioremap failed for AHBDMA register address\n");
-               err = -ENODEV;
-               goto error_iomap;
-       }
-
        /* Save dev for later use in dev_xxx() routines */
        hsdev->dev = &ofdev->dev;
 
-       hsdev->dma->dev = &ofdev->dev;
-
-       /* Initialize AHB DMAC */
-       err = dw_dma_probe(hsdev->dma);
-       if (err)
-               goto error_dma_iomap;
-
        /* Enable SATA Interrupts */
        sata_dwc_enable_interrupts(hsdev);
 
@@ -1263,6 +1261,25 @@ static int sata_dwc_probe(struct platform_device *ofdev)
                goto error_out;
        }
 
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+       if (!of_find_property(np, "dmas", NULL)) {
+               err = sata_dwc_dma_init_old(ofdev, hsdev);
+               if (err)
+                       goto error_out;
+       }
+#endif
+
+       hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy");
+       if (IS_ERR(hsdev->phy)) {
+               err = PTR_ERR(hsdev->phy);
+               hsdev->phy = NULL;
+               goto error_out;
+       }
+
+       err = phy_init(hsdev->phy);
+       if (err)
+               goto error_out;
+
        /*
         * Now, register with libATA core, this will also initiate the
         * device discovery process, invoking our port_start() handler &
@@ -1276,12 +1293,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
        return 0;
 
 error_out:
-       /* Free SATA DMA resources */
-       dw_dma_remove(hsdev->dma);
-error_dma_iomap:
-       iounmap(hsdev->dma->regs);
-error_iomap:
-       iounmap(base);
+       phy_exit(hsdev->phy);
        return err;
 }
 
@@ -1293,11 +1305,13 @@ static int sata_dwc_remove(struct platform_device *ofdev)
 
        ata_host_detach(host);
 
+       phy_exit(hsdev->phy);
+
+#ifdef CONFIG_SATA_DWC_OLD_DMA
        /* Free SATA DMA resources */
-       dw_dma_remove(hsdev->dma);
+       sata_dwc_dma_exit_old(hsdev);
+#endif
 
-       iounmap(hsdev->dma->regs);
-       iounmap(hsdev->reg_base);
        dev_dbg(&ofdev->dev, "done\n");
        return 0;
 }