]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
sata: sata_mv: Add DM support to enable CONFIG_BLK usage
authorStefan Roese <sr@denx.de>
Mon, 11 Mar 2019 12:29:20 +0000 (13:29 +0100)
committerStefan Roese <sr@denx.de>
Fri, 12 Apr 2019 05:04:18 +0000 (07:04 +0200)
This patch adds DM support to the Armada XP SATA driver. This is needed
to enable CONFIG_BLK on this platform. It adds the SATA controller as
AHCI device, which is strictly speaking not correct, as the controller
is not AHCI compatible. But the U-Boot AHCI uclass interface enables
the usage of this DM driver and the creation of the corresponding BLK
devices.

This conversion is done to get rid of the compile warning:
Reviewed-by: Chris Packham <judge.packham@gmail.com>
===================== WARNING ======================
This board does not use CONFIG_DM_SCSI. Please update
the storage controller to use CONFIG_DM_SCSI before the v2019.07 release.
Failure to update by the deadline may result in board removal.
See doc/driver-model/MIGRATION.txt for more info.
====================================================

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
drivers/ata/Kconfig
drivers/ata/sata_mv.c

index 49a056e9416a55333004d03c6e5d27ea63261267..7ebee75c0a5ba82c4befa854f6d8488c148ce70e 100644 (file)
@@ -81,7 +81,9 @@ config MVSATA_IDE
 
 config SATA_MV
        bool "Enable Marvell SATA controller driver support"
 
 config SATA_MV
        bool "Enable Marvell SATA controller driver support"
+       select AHCI
        select LIBATA
        select LIBATA
+       depends on BLK
        help
          Enable this driver to support the SATA controller found in
          some Marvell SoCs.
        help
          Enable this driver to support the SATA controller found in
          some Marvell SoCs.
index a168196fd4d2868f71986472e3cfec770da3df51..d13695d79e4caa7fbbb7050943b61d8cf1d94ef8 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) Excito Elektronik i Skåne AB, 2010.
  * Author: Tor Krill <tor@excito.com>
  *
  * Copyright (C) Excito Elektronik i Skåne AB, 2010.
  * Author: Tor Krill <tor@excito.com>
  *
- * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2015, 2019 Stefan Roese <sr@denx.de>
  */
 
 /*
  */
 
 /*
  */
 
 #include <common.h>
  */
 
 #include <common.h>
+#include <ahci.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
 #include <fis.h>
 #include <libata.h>
 #include <malloc.h>
 #include <fis.h>
 #include <libata.h>
 #include <malloc.h>
@@ -256,6 +260,7 @@ struct mv_priv {
        u16 pio;
        u16 mwdma;
        u16 udma;
        u16 pio;
        u16 mwdma;
        u16 udma;
+       int dev_nr;
 
        void *crqb_alloc;
        struct crqb *request;
 
        void *crqb_alloc;
        struct crqb *request;
@@ -278,9 +283,9 @@ static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec)
 }
 
 /* Cut from sata_mv in linux kernel */
 }
 
 /* Cut from sata_mv in linux kernel */
-static int mv_stop_edma_engine(int port)
+static int mv_stop_edma_engine(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        int i;
 
        /* Disable eDMA. The disable bit auto clears. */
        int i;
 
        /* Disable eDMA. The disable bit auto clears. */
@@ -299,9 +304,9 @@ static int mv_stop_edma_engine(int port)
        return -1;
 }
 
        return -1;
 }
 
-static int mv_start_edma_engine(int port)
+static int mv_start_edma_engine(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        u32 tmp;
 
        /* Check preconditions */
        u32 tmp;
 
        /* Check preconditions */
@@ -351,12 +356,12 @@ static int mv_start_edma_engine(int port)
        return 0;
 }
 
        return 0;
 }
 
-static int mv_reset_channel(int port)
+static int mv_reset_channel(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
 
        /* Make sure edma is stopped  */
 
        /* Make sure edma is stopped  */
-       mv_stop_edma_engine(port);
+       mv_stop_edma_engine(dev, port);
 
        out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST);
        udelay(25);             /* allow reset propagation */
 
        out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST);
        udelay(25);             /* allow reset propagation */
@@ -366,11 +371,11 @@ static int mv_reset_channel(int port)
        return 0;
 }
 
        return 0;
 }
 
-static void mv_reset_port(int port)
+static void mv_reset_port(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
 
 
-       mv_reset_channel(port);
+       mv_reset_channel(dev, port);
 
        out_le32(priv->regbase + EDMA_CMD, 0x0);
        out_le32(priv->regbase + EDMA_CFG, 0x101f);
 
        out_le32(priv->regbase + EDMA_CMD, 0x0);
        out_le32(priv->regbase + EDMA_CFG, 0x101f);
@@ -392,9 +397,9 @@ static void mv_reset_one_hc(void)
        out_le32(SATAHC_BASE + SATAHC_ICR, 0x00);
 }
 
        out_le32(SATAHC_BASE + SATAHC_ICR, 0x00);
 }
 
-static int probe_port(int port)
+static int probe_port(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        int tries, tries2, set15 = 0;
        u32 tmp;
 
        int tries, tries2, set15 = 0;
        u32 tmp;
 
@@ -446,7 +451,7 @@ static int probe_port(int port)
                        tmp &= ~SIR_CFG_GEN2EN;
                        out_le32(priv->regbase + SIR_ICFG, tmp);
 
                        tmp &= ~SIR_CFG_GEN2EN;
                        out_le32(priv->regbase + SIR_ICFG, tmp);
 
-                       mv_reset_channel(port);
+                       mv_reset_channel(dev, port);
                }
        }
 
                }
        }
 
@@ -455,9 +460,9 @@ static int probe_port(int port)
 }
 
 /* Get request queue in pointer */
 }
 
 /* Get request queue in pointer */
-static int get_reqip(int port)
+static int get_reqip(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK;
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK;
@@ -466,9 +471,9 @@ static int get_reqip(int port)
        return tmp;
 }
 
        return tmp;
 }
 
-static void set_reqip(int port, int reqin)
+static void set_reqip(struct udevice *dev, int port, int reqin)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK;
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK;
@@ -477,17 +482,17 @@ static void set_reqip(int port, int reqin)
 }
 
 /* Get next available slot, ignoring possible overwrite */
 }
 
 /* Get next available slot, ignoring possible overwrite */
-static int get_next_reqip(int port)
+static int get_next_reqip(struct udevice *dev, int port)
 {
 {
-       int slot = get_reqip(port);
+       int slot = get_reqip(dev, port);
        slot = (slot + 1) % REQUEST_QUEUE_SIZE;
        return slot;
 }
 
 /* Get response queue in pointer */
        slot = (slot + 1) % REQUEST_QUEUE_SIZE;
        return slot;
 }
 
 /* Get response queue in pointer */
-static int get_rspip(int port)
+static int get_rspip(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK;
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK;
@@ -497,9 +502,9 @@ static int get_rspip(int port)
 }
 
 /* Get response queue out pointer */
 }
 
 /* Get response queue out pointer */
-static int get_rspop(int port)
+static int get_rspop(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK;
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK;
@@ -508,15 +513,15 @@ static int get_rspop(int port)
 }
 
 /* Get next response queue pointer  */
 }
 
 /* Get next response queue pointer  */
-static int get_next_rspop(int port)
+static int get_next_rspop(struct udevice *dev, int port)
 {
 {
-       return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE;
+       return (get_rspop(dev, port) + 1) % RESPONSE_QUEUE_SIZE;
 }
 
 /* Set response queue pointer */
 }
 
 /* Set response queue pointer */
-static void set_rspop(int port, int reqin)
+static void set_rspop(struct udevice *dev, int port, int reqin)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK;
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK;
@@ -525,7 +530,8 @@ static void set_rspop(int port, int reqin)
        out_le32(priv->regbase + EDMA_RSOPR, tmp);
 }
 
        out_le32(priv->regbase + EDMA_RSOPR, tmp);
 }
 
-static int wait_dma_completion(int port, int index, u32 timeout_msec)
+static int wait_dma_completion(struct udevice *dev, int port, int index,
+                              u32 timeout_msec)
 {
        u32 tmp, res;
 
 {
        u32 tmp, res;
 
@@ -538,13 +544,13 @@ static int wait_dma_completion(int port, int index, u32 timeout_msec)
        return res;
 }
 
        return res;
 }
 
-static void process_responses(int port)
+static void process_responses(struct udevice *dev, int port)
 {
 #ifdef DEBUG
 {
 #ifdef DEBUG
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
 #endif
        u32 tmp;
 #endif
        u32 tmp;
-       u32 outind = get_rspop(port);
+       u32 outind = get_rspop(dev, port);
 
        /* Ack interrupts */
        tmp = in_le32(SATAHC_BASE + SATAHC_ICR);
 
        /* Ack interrupts */
        tmp = in_le32(SATAHC_BASE + SATAHC_ICR);
@@ -555,20 +561,21 @@ static void process_responses(int port)
        tmp &= ~(BIT(4));
        out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
 
        tmp &= ~(BIT(4));
        out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
 
-       while (get_rspip(port) != outind) {
+       while (get_rspip(dev, port) != outind) {
 #ifdef DEBUG
                debug("Response index %d flags %08x on port %d\n", outind,
                      priv->response[outind].flags, port);
 #endif
 #ifdef DEBUG
                debug("Response index %d flags %08x on port %d\n", outind,
                      priv->response[outind].flags, port);
 #endif
-               outind = get_next_rspop(port);
-               set_rspop(port, outind);
+               outind = get_next_rspop(dev, port);
+               set_rspop(dev, port, outind);
        }
 }
 
        }
 }
 
-static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis,
+static int mv_ata_exec_ata_cmd(struct udevice *dev, int port,
+                              struct sata_fis_h2d *cfis,
                               u8 *buffer, u32 len, u32 iswrite)
 {
                               u8 *buffer, u32 len, u32 iswrite)
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        struct crqb *req;
        int slot;
        u32 start;
        struct crqb *req;
        int slot;
        u32 start;
@@ -579,7 +586,7 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis,
        }
 
        /* Initialize request */
        }
 
        /* Initialize request */
-       slot = get_reqip(port);
+       slot = get_reqip(dev, port);
        memset(&priv->request[slot], 0, sizeof(struct crqb));
        req = &priv->request[slot];
 
        memset(&priv->request[slot], 0, sizeof(struct crqb));
        req = &priv->request[slot];
 
@@ -633,16 +640,16 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis,
                           start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN));
 
        /* Trigger operation */
                           start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN));
 
        /* Trigger operation */
-       slot = get_next_reqip(port);
-       set_reqip(port, slot);
+       slot = get_next_reqip(dev, port);
+       set_reqip(dev, port, slot);
 
        /* Wait for completion */
 
        /* Wait for completion */
-       if (wait_dma_completion(port, slot, 10000)) {
+       if (wait_dma_completion(dev, port, slot, 10000)) {
                printf("ATA operation timed out\n");
                return -1;
        }
 
                printf("ATA operation timed out\n");
                return -1;
        }
 
-       process_responses(port);
+       process_responses(dev, port);
 
        /* Invalidate data on read */
        if (buffer && len) {
 
        /* Invalidate data on read */
        if (buffer && len) {
@@ -654,7 +661,8 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis,
        return len;
 }
 
        return len;
 }
 
-static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt,
+static u32 mv_sata_rw_cmd_ext(struct udevice *dev, int port, lbaint_t start,
+                             u32 blkcnt,
                              u8 *buffer, int is_write)
 {
        struct sata_fis_h2d cfis;
                              u8 *buffer, int is_write)
 {
        struct sata_fis_h2d cfis;
@@ -678,14 +686,14 @@ static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt,
        cfis.sector_count_exp = (blkcnt >> 8) & 0xff;
        cfis.sector_count = blkcnt & 0xff;
 
        cfis.sector_count_exp = (blkcnt >> 8) & 0xff;
        cfis.sector_count = blkcnt & 0xff;
 
-       res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
-                                 is_write);
+       res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer,
+                                 ATA_SECT_SIZE * blkcnt, is_write);
 
        return res >= 0 ? blkcnt : res;
 }
 
 
        return res >= 0 ? blkcnt : res;
 }
 
-static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer,
-                         int is_write)
+static u32 mv_sata_rw_cmd(struct udevice *dev, int port, lbaint_t start,
+                         u32 blkcnt, u8 *buffer, int is_write)
 {
        struct sata_fis_h2d cfis;
        lbaint_t block;
 {
        struct sata_fis_h2d cfis;
        lbaint_t block;
@@ -705,15 +713,16 @@ static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer,
        cfis.lba_low = block & 0xff;
        cfis.sector_count = (u8)(blkcnt & 0xff);
 
        cfis.lba_low = block & 0xff;
        cfis.sector_count = (u8)(blkcnt & 0xff);
 
-       res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
-                                 is_write);
+       res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer,
+                                 ATA_SECT_SIZE * blkcnt, is_write);
 
        return res >= 0 ? blkcnt : res;
 }
 
 
        return res >= 0 ? blkcnt : res;
 }
 
-static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt,
-                           void *buffer, int is_write)
+static u32 ata_low_level_rw(struct udevice *dev, int port, lbaint_t blknr,
+                           lbaint_t blkcnt, void *buffer, int is_write)
 {
 {
+       struct blk_desc *desc = dev_get_uclass_platdata(dev);
        lbaint_t start, blks;
        u8 *addr;
        int max_blks;
        lbaint_t start, blks;
        u8 *addr;
        int max_blks;
@@ -727,22 +736,22 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt,
        max_blks = MV_ATA_MAX_SECTORS;
        do {
                if (blks > max_blks) {
        max_blks = MV_ATA_MAX_SECTORS;
        do {
                if (blks > max_blks) {
-                       if (sata_dev_desc[dev].lba48) {
-                               mv_sata_rw_cmd_ext(dev, start, max_blks, addr,
-                                                  is_write);
+                       if (desc->lba48) {
+                               mv_sata_rw_cmd_ext(dev, port, start, max_blks,
+                                                  addr, is_write);
                        } else {
                        } else {
-                               mv_sata_rw_cmd(dev, start, max_blks, addr,
-                                              is_write);
+                               mv_sata_rw_cmd(dev, port, start, max_blks,
+                                              addr, is_write);
                        }
                        start += max_blks;
                        blks -= max_blks;
                        addr += ATA_SECT_SIZE * max_blks;
                } else {
                        }
                        start += max_blks;
                        blks -= max_blks;
                        addr += ATA_SECT_SIZE * max_blks;
                } else {
-                       if (sata_dev_desc[dev].lba48) {
-                               mv_sata_rw_cmd_ext(dev, start, blks, addr,
+                       if (desc->lba48) {
+                               mv_sata_rw_cmd_ext(dev, port, start, blks, addr,
                                                   is_write);
                        } else {
                                                   is_write);
                        } else {
-                               mv_sata_rw_cmd(dev, start, blks, addr,
+                               mv_sata_rw_cmd(dev, port, start, blks, addr,
                                               is_write);
                        }
                        start += blks;
                                               is_write);
                        }
                        start += blks;
@@ -754,11 +763,11 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt,
        return blkcnt;
 }
 
        return blkcnt;
 }
 
-static int mv_ata_exec_ata_cmd_nondma(int port,
+static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port,
                                      struct sata_fis_h2d *cfis, u8 *buffer,
                                      u32 len, u32 iswrite)
 {
                                      struct sata_fis_h2d *cfis, u8 *buffer,
                                      u32 len, u32 iswrite)
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        int i;
        u16 *tp;
 
        int i;
        u16 *tp;
 
@@ -791,7 +800,7 @@ static int mv_ata_exec_ata_cmd_nondma(int port,
        return len;
 }
 
        return len;
 }
 
-static int mv_sata_identify(int port, u16 *id)
+static int mv_sata_identify(struct udevice *dev, int port, u16 *id)
 {
        struct sata_fis_h2d h2d;
 
 {
        struct sata_fis_h2d h2d;
 
@@ -803,13 +812,13 @@ static int mv_sata_identify(int port, u16 *id)
        /* Give device time to get operational */
        mdelay(10);
 
        /* Give device time to get operational */
        mdelay(10);
 
-       return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id,
+       return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
                                          ATA_ID_WORDS * 2, READ_CMD);
 }
 
                                          ATA_ID_WORDS * 2, READ_CMD);
 }
 
-static void mv_sata_xfer_mode(int port, u16 *id)
+static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
 
        priv->pio = id[ATA_ID_PIO_MODES];
        priv->mwdma = id[ATA_ID_MWDMA_MODES];
 
        priv->pio = id[ATA_ID_PIO_MODES];
        priv->mwdma = id[ATA_ID_MWDMA_MODES];
@@ -818,9 +827,9 @@ static void mv_sata_xfer_mode(int port, u16 *id)
              priv->udma);
 }
 
              priv->udma);
 }
 
-static void mv_sata_set_features(int port)
+static void mv_sata_set_features(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
        struct sata_fis_h2d cfis;
        u8 udma_cap;
 
        struct sata_fis_h2d cfis;
        u8 udma_cap;
 
@@ -842,53 +851,7 @@ static void mv_sata_set_features(int port)
        if (udma_cap == ATA_UDMA3)
                cfis.sector_count = XFER_UDMA_3;
 
        if (udma_cap == ATA_UDMA3)
                cfis.sector_count = XFER_UDMA_3;
 
-       mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD);
-}
-
-int mv_sata_spin_down(int dev)
-{
-       struct sata_fis_h2d cfis;
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
-
-       if (priv->link == 0) {
-               debug("No device on port: %d\n", dev);
-               return 1;
-       }
-
-       memset(&cfis, 0, sizeof(struct sata_fis_h2d));
-
-       cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
-       cfis.command = ATA_CMD_STANDBY;
-
-       return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
-}
-
-int mv_sata_spin_up(int dev)
-{
-       struct sata_fis_h2d cfis;
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
-
-       if (priv->link == 0) {
-               debug("No device on port: %d\n", dev);
-               return 1;
-       }
-
-       memset(&cfis, 0, sizeof(struct sata_fis_h2d));
-
-       cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
-       cfis.command = ATA_CMD_IDLE;
-
-       return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
-}
-
-ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
-{
-       return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD);
-}
-
-ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
-{
-       return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD);
+       mv_ata_exec_ata_cmd_nondma(dev, port, &cfis, NULL, 0, READ_CMD);
 }
 
 /*
 }
 
 /*
@@ -916,25 +879,17 @@ static void mvsata_ide_conf_mbus_windows(void)
        }
 }
 
        }
 }
 
-int init_sata(int dev)
+static int sata_mv_init_sata(struct udevice *dev, int port)
 {
 {
-       struct mv_priv *priv;
+       struct mv_priv *priv = dev_get_platdata(dev);
 
 
-       debug("Initialize sata dev: %d\n", dev);
+       debug("Initialize sata dev: %d\n", port);
 
 
-       if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
-               printf("Invalid sata device %d\n", dev);
+       if (port < 0 || port >= CONFIG_SYS_SATA_MAX_DEVICE) {
+               printf("Invalid sata device %d\n", port);
                return -1;
        }
 
                return -1;
        }
 
-       priv = (struct mv_priv *)malloc(sizeof(struct mv_priv));
-       if (!priv) {
-               printf("Failed to allocate memory for private sata data\n");
-               return -ENOMEM;
-       }
-
-       memset((void *)priv, 0, sizeof(struct mv_priv));
-
        /* Allocate and align request buffer */
        priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE +
                                  CRQB_ALIGN);
        /* Allocate and align request buffer */
        priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE +
                                  CRQB_ALIGN);
@@ -959,11 +914,9 @@ int init_sata(int dev)
        priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) &
                                         ~(CRPB_ALIGN - 1));
 
        priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) &
                                         ~(CRPB_ALIGN - 1));
 
-       sata_dev_desc[dev].priv = (void *)priv;
+       sprintf(priv->name, "SATA%d", port);
 
 
-       sprintf(priv->name, "SATA%d", dev);
-
-       priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE;
+       priv->regbase = port == 0 ? SATA0_BASE : SATA1_BASE;
 
        if (!hw_init) {
                debug("Initialize sata hw\n");
 
        if (!hw_init) {
                debug("Initialize sata hw\n");
@@ -972,9 +925,9 @@ int init_sata(int dev)
                mvsata_ide_conf_mbus_windows();
        }
 
                mvsata_ide_conf_mbus_windows();
        }
 
-       mv_reset_port(dev);
+       mv_reset_port(dev, port);
 
 
-       if (probe_port(dev)) {
+       if (probe_port(dev, port)) {
                priv->link = 0;
                return -ENODEV;
        }
                priv->link = 0;
                return -ENODEV;
        }
@@ -983,19 +936,15 @@ int init_sata(int dev)
        return 0;
 }
 
        return 0;
 }
 
-int reset_sata(int dev)
-{
-       return 0;
-}
-
-int scan_sata(int port)
+static int sata_mv_scan_sata(struct udevice *dev, int port)
 {
 {
+       struct blk_desc *desc = dev_get_uclass_platdata(dev);
+       struct mv_priv *priv = dev_get_platdata(dev);
        unsigned char serial[ATA_ID_SERNO_LEN + 1];
        unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
        unsigned char product[ATA_ID_PROD_LEN + 1];
        u64 n_sectors;
        u16 *id;
        unsigned char serial[ATA_ID_SERNO_LEN + 1];
        unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
        unsigned char product[ATA_ID_PROD_LEN + 1];
        u64 n_sectors;
        u16 *id;
-       struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
 
        if (!priv->link)
                return -ENODEV;
 
        if (!priv->link)
                return -ENODEV;
@@ -1006,7 +955,7 @@ int scan_sata(int port)
                return -ENOMEM;
        }
 
                return -ENOMEM;
        }
 
-       mv_sata_identify(port, id);
+       mv_sata_identify(dev, port, id);
        ata_swap_buf_le16(id, ATA_ID_WORDS);
 #ifdef DEBUG
        ata_dump_id(id);
        ata_swap_buf_le16(id, ATA_ID_WORDS);
 #ifdef DEBUG
        ata_dump_id(id);
@@ -1014,23 +963,23 @@ int scan_sata(int port)
 
        /* Serial number */
        ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
 
        /* Serial number */
        ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
-       memcpy(sata_dev_desc[port].product, serial, sizeof(serial));
+       memcpy(desc->product, serial, sizeof(serial));
 
        /* Firmware version */
        ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
 
        /* Firmware version */
        ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
-       memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware));
+       memcpy(desc->revision, firmware, sizeof(firmware));
 
        /* Product model */
        ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
 
        /* Product model */
        ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
-       memcpy(sata_dev_desc[port].vendor, product, sizeof(product));
+       memcpy(desc->vendor, product, sizeof(product));
 
        /* Total sectors */
        n_sectors = ata_id_n_sectors(id);
 
        /* Total sectors */
        n_sectors = ata_id_n_sectors(id);
-       sata_dev_desc[port].lba = n_sectors;
+       desc->lba = n_sectors;
 
        /* Check if support LBA48 */
        if (ata_id_has_lba48(id)) {
 
        /* Check if support LBA48 */
        if (ata_id_has_lba48(id)) {
-               sata_dev_desc[port].lba48 = 1;
+               desc->lba48 = 1;
                debug("Device support LBA48\n");
        }
 
                debug("Device support LBA48\n");
        }
 
@@ -1038,13 +987,110 @@ int scan_sata(int port)
        priv->queue_depth = ata_id_queue_depth(id);
 
        /* Get the xfer mode from device */
        priv->queue_depth = ata_id_queue_depth(id);
 
        /* Get the xfer mode from device */
-       mv_sata_xfer_mode(port, id);
+       mv_sata_xfer_mode(dev, port, id);
 
        /* Set the xfer mode to highest speed */
 
        /* Set the xfer mode to highest speed */
-       mv_sata_set_features(port);
+       mv_sata_set_features(dev, port);
 
        /* Start up */
 
        /* Start up */
-       mv_start_edma_engine(port);
+       mv_start_edma_engine(dev, port);
 
        return 0;
 }
 
        return 0;
 }
+
+static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr,
+                         lbaint_t blkcnt, void *buffer)
+{
+       struct mv_priv *priv = dev_get_platdata(blk);
+
+       return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
+                               buffer, READ_CMD);
+}
+
+static ulong sata_mv_write(struct udevice *blk, lbaint_t blknr,
+                          lbaint_t blkcnt, const void *buffer)
+{
+       struct mv_priv *priv = dev_get_platdata(blk);
+
+       return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
+                               (void *)buffer, WRITE_CMD);
+}
+
+static const struct blk_ops sata_mv_blk_ops = {
+       .read   = sata_mv_read,
+       .write  = sata_mv_write,
+};
+
+U_BOOT_DRIVER(sata_mv_driver) = {
+       .name = "sata_mv_blk",
+       .id = UCLASS_BLK,
+       .ops = &sata_mv_blk_ops,
+       .platdata_auto_alloc_size = sizeof(struct mv_priv),
+};
+
+static int sata_mv_probe(struct udevice *dev)
+{
+       const void *blob = gd->fdt_blob;
+       int node = dev_of_offset(dev);
+       struct mv_priv *priv;
+       struct udevice *blk;
+       int nr_ports;
+       int ret;
+       int i;
+
+       /* Get number of ports of this SATA controller */
+       nr_ports = min(fdtdec_get_int(blob, node, "nr-ports", -1),
+                      CONFIG_SYS_SATA_MAX_DEVICE);
+
+       for (i = 0; i < nr_ports; i++) {
+               ret = blk_create_devicef(dev, "sata_mv_blk", "blk",
+                                        IF_TYPE_SATA, -1, 512, 0, &blk);
+               if (ret) {
+                       debug("Can't create device\n");
+                       return ret;
+               }
+
+               priv = dev_get_platdata(blk);
+               priv->dev_nr = i;
+
+               /* Init SATA port */
+               ret = sata_mv_init_sata(blk, i);
+               if (ret) {
+                       debug("%s: Failed to init bus\n", __func__);
+                       return ret;
+               }
+
+               /* Scan SATA port */
+               ret = sata_mv_scan_sata(blk, i);
+               if (ret) {
+                       debug("%s: Failed to scan bus\n", __func__);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int sata_mv_scan(struct udevice *dev)
+{
+       /* Nothing to do here */
+
+       return 0;
+}
+
+static const struct udevice_id sata_mv_ids[] = {
+       { .compatible = "marvell,armada-370-sata" },
+       { }
+};
+
+struct ahci_ops sata_mv_ahci_ops = {
+       .scan = sata_mv_scan,
+};
+
+U_BOOT_DRIVER(sata_mv_ahci) = {
+       .name = "sata_mv_ahci",
+       .id = UCLASS_AHCI,
+       .of_match = sata_mv_ids,
+       .ops = &sata_mv_ahci_ops,
+       .probe = sata_mv_probe,
+};