]> Git Repo - u-boot.git/blobdiff - drivers/ata/sata_mv.c
Restore patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"
[u-boot.git] / drivers / ata / sata_mv.c
index 9ced9c0fa8767b7d81e85b0ec15aa9ab4966e3fd..ac78760a33ebabc65e1d97c2e1653c70d3cbd1f6 100644 (file)
  * No port multiplier support
  */
 
-#include <common.h>
 #include <ahci.h>
+#include <blk.h>
+#include <bootdev.h>
 #include <cpu_func.h>
 #include <dm.h>
+#include <log.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <fis.h>
 #include <libata.h>
 #include <malloc.h>
 #include <sata.h>
+#include <time.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <linux/mbus.h>
@@ -285,7 +292,7 @@ static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec)
 /* Cut from sata_mv in linux kernel */
 static int mv_stop_edma_engine(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        int i;
 
        /* Disable eDMA. The disable bit auto clears. */
@@ -306,7 +313,7 @@ static int mv_stop_edma_engine(struct udevice *dev, int port)
 
 static int mv_start_edma_engine(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        u32 tmp;
 
        /* Check preconditions */
@@ -358,7 +365,7 @@ static int mv_start_edma_engine(struct udevice *dev, int port)
 
 static int mv_reset_channel(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
 
        /* Make sure edma is stopped  */
        mv_stop_edma_engine(dev, port);
@@ -373,7 +380,7 @@ static int mv_reset_channel(struct udevice *dev, int port)
 
 static void mv_reset_port(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
 
        mv_reset_channel(dev, port);
 
@@ -399,7 +406,7 @@ static void mv_reset_one_hc(void)
 
 static int probe_port(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        int tries, tries2, set15 = 0;
        u32 tmp;
 
@@ -462,7 +469,7 @@ static int probe_port(struct udevice *dev, int port)
 /* Get request queue in pointer */
 static int get_reqip(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK;
@@ -473,7 +480,7 @@ static int get_reqip(struct udevice *dev, int port)
 
 static void set_reqip(struct udevice *dev, int port, int reqin)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK;
@@ -492,7 +499,7 @@ static int get_next_reqip(struct udevice *dev, int port)
 /* Get response queue in pointer */
 static int get_rspip(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK;
@@ -504,7 +511,7 @@ static int get_rspip(struct udevice *dev, int port)
 /* Get response queue out pointer */
 static int get_rspop(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK;
@@ -521,7 +528,7 @@ static int get_next_rspop(struct udevice *dev, int port)
 /* Set response queue pointer */
 static void set_rspop(struct udevice *dev, int port, int reqin)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        u32 tmp;
 
        tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK;
@@ -547,7 +554,7 @@ static int wait_dma_completion(struct udevice *dev, int port, int index,
 static void process_responses(struct udevice *dev, int port)
 {
 #ifdef DEBUG
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
 #endif
        u32 tmp;
        u32 outind = get_rspop(dev, port);
@@ -575,7 +582,7 @@ static int mv_ata_exec_ata_cmd(struct udevice *dev, int port,
                               struct sata_fis_h2d *cfis,
                               u8 *buffer, u32 len, u32 iswrite)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        struct crqb *req;
        int slot;
        u32 start;
@@ -722,7 +729,7 @@ static u32 mv_sata_rw_cmd(struct udevice *dev, int port, lbaint_t start,
 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);
+       struct blk_desc *desc = dev_get_uclass_plat(dev);
        lbaint_t start, blks;
        u8 *addr;
        int max_blks;
@@ -767,7 +774,7 @@ 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 mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        int i;
        u16 *tp;
 
@@ -803,6 +810,7 @@ static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port,
 static int mv_sata_identify(struct udevice *dev, int port, u16 *id)
 {
        struct sata_fis_h2d h2d;
+       int len;
 
        memset(&h2d, 0, sizeof(struct sata_fis_h2d));
 
@@ -812,13 +820,37 @@ static int mv_sata_identify(struct udevice *dev, int port, u16 *id)
        /* Give device time to get operational */
        mdelay(10);
 
-       return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
-                                         ATA_ID_WORDS * 2, READ_CMD);
+       /* During cold start, with some HDDs, the first ATA ID command does
+        * not populate the ID words. In fact, the first ATA ID
+        * command will only power up the drive, and then the ATA ID command
+        * processing is lost in the process.
+        */
+       len = mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
+                                        ATA_ID_WORDS * 2, READ_CMD);
+
+       /* If drive capacity has been filled in, then it was successfully
+        * identified (the drive has been powered up before, i.e.
+        * this function is invoked during a reboot)
+        */
+       if (ata_id_n_sectors(id) != 0)
+               return len;
+
+       /* Issue the 2nd ATA ID command to make sure the ID words are
+        * populated properly.
+        */
+       mdelay(10);
+       len = mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
+                                        ATA_ID_WORDS * 2, READ_CMD);
+       if (ata_id_n_sectors(id) != 0)
+               return len;
+
+       printf("Err: Failed to identify SATA device %d\n", port);
+       return -ENODEV;
 }
 
 static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
 
        priv->pio = id[ATA_ID_PIO_MODES];
        priv->mwdma = id[ATA_ID_MWDMA_MODES];
@@ -829,7 +861,7 @@ static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id)
 
 static void mv_sata_set_features(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
        struct sata_fis_h2d cfis;
        u8 udma_cap;
 
@@ -881,7 +913,7 @@ static void mvsata_ide_conf_mbus_windows(void)
 
 static int sata_mv_init_sata(struct udevice *dev, int port)
 {
-       struct mv_priv *priv = dev_get_platdata(dev);
+       struct mv_priv *priv = dev_get_plat(dev);
 
        debug("Initialize sata dev: %d\n", port);
 
@@ -938,8 +970,8 @@ static int sata_mv_init_sata(struct udevice *dev, 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);
+       struct blk_desc *desc = dev_get_uclass_plat(dev);
+       struct mv_priv *priv = dev_get_plat(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];
@@ -1001,7 +1033,7 @@ static int sata_mv_scan_sata(struct udevice *dev, int port)
 static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr,
                          lbaint_t blkcnt, void *buffer)
 {
-       struct mv_priv *priv = dev_get_platdata(blk);
+       struct mv_priv *priv = dev_get_plat(blk);
 
        return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
                                buffer, READ_CMD);
@@ -1010,7 +1042,7 @@ static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr,
 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);
+       struct mv_priv *priv = dev_get_plat(blk);
 
        return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
                                (void *)buffer, WRITE_CMD);
@@ -1025,7 +1057,7 @@ 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),
+       .plat_auto      = sizeof(struct mv_priv),
 };
 
 static int sata_mv_probe(struct udevice *dev)
@@ -1037,6 +1069,7 @@ static int sata_mv_probe(struct udevice *dev)
        int nr_ports;
        int ret;
        int i;
+       int status = -ENODEV; /* If the probe fails to detected any SATA port */
 
        /* Get number of ports of this SATA controller */
        nr_ports = min(fdtdec_get_int(blob, node, "nr-ports", -1),
@@ -1044,37 +1077,53 @@ static int sata_mv_probe(struct udevice *dev)
 
        for (i = 0; i < nr_ports; i++) {
                ret = blk_create_devicef(dev, "sata_mv_blk", "blk",
-                                        IF_TYPE_SATA, -1, 512, 0, &blk);
+                                        UCLASS_AHCI, -1, DEFAULT_BLKSZ,
+                                        0, &blk);
                if (ret) {
                        debug("Can't create device\n");
-                       return ret;
+                       continue;
                }
 
-               priv = dev_get_platdata(blk);
+               priv = dev_get_plat(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;
+                       continue;
                }
 
                /* Scan SATA port */
                ret = sata_mv_scan_sata(blk, i);
                if (ret) {
                        debug("%s: Failed to scan bus\n", __func__);
-                       return ret;
+                       continue;
                }
+
+               ret = blk_probe_or_unbind(dev);
+               if (ret < 0)
+                       /* TODO: undo create */
+                       continue;
+
+               ret = bootdev_setup_for_sibling_blk(blk, "sata_bootdev");
+               if (ret) {
+                       printf("%s: Failed to create bootdev\n", __func__);
+                       continue;
+               }
+
+               /* If we got here, the current SATA port was probed
+                * successfully, so set the probe status to successful.
+                */
+               status = 0;
        }
 
-       return 0;
+       return status;
 }
 
 static int sata_mv_scan(struct udevice *dev)
 {
        /* Nothing to do here */
-
        return 0;
 }
 
This page took 0.039308 seconds and 4 git commands to generate.