]> git.sur5r.net Git - u-boot/blobdiff - drivers/mmc/sh_sdhi.c
dm: mmc: update mmc_of_parse()
[u-boot] / drivers / mmc / sh_sdhi.c
index fd710399b6830807c9f2fd1e469d8b13a837020b..eef061abb2de49634e9dea648022f7fb2b1e3fee 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sizes.h>
 #include <asm/arch/rmobile.h>
 #include <asm/arch/sh_sdhi.h>
+#include <clk.h>
 
 #define DRIVER_NAME "sh-sdhi"
 
@@ -31,6 +32,7 @@ struct sh_sdhi_host {
        unsigned char wait_int;
        unsigned char sd_error;
        unsigned char detect_waiting;
+       unsigned char app_cmd;
 };
 
 static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
@@ -475,65 +477,64 @@ static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
 static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
                        struct mmc_data *data, unsigned short opc)
 {
-       switch (opc) {
-       case SD_CMD_APP_SEND_OP_COND:
-       case SD_CMD_APP_SEND_SCR:
-               opc |= SDHI_APP;
-               break;
-       case SD_CMD_APP_SET_BUS_WIDTH:
-                /* SD_APP_SET_BUS_WIDTH*/
+       if (host->app_cmd) {
                if (!data)
-                       opc |= SDHI_APP;
-               else /* SD_SWITCH */
-                       opc = SDHI_SD_SWITCH;
-               break;
-       case MMC_CMD_SEND_OP_COND:
-               opc = SDHI_MMC_SEND_OP_COND;
-               break;
+                       host->app_cmd = 0;
+               return opc | BIT(6);
+       }
+
+       switch (opc) {
+       case MMC_CMD_SWITCH:
+               return opc | (data ? 0x1c00 : 0x40);
        case MMC_CMD_SEND_EXT_CSD:
-               if (data)
-                       opc = SDHI_MMC_SEND_EXT_CSD;
-               break;
+               return opc | (data ? 0x1c00 : 0);
+       case MMC_CMD_SEND_OP_COND:
+               return opc | 0x0700;
+       case MMC_CMD_APP_CMD:
+               host->app_cmd = 1;
        default:
-               break;
+               return opc;
        }
-       return opc;
 }
 
 static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
                        struct mmc_data *data, unsigned short opc)
 {
-       unsigned short ret;
-
-       switch (opc) {
-       case MMC_CMD_READ_MULTIPLE_BLOCK:
-               ret = sh_sdhi_multi_read(host, data);
-               break;
-       case MMC_CMD_WRITE_MULTIPLE_BLOCK:
-               ret = sh_sdhi_multi_write(host, data);
-               break;
-       case MMC_CMD_WRITE_SINGLE_BLOCK:
-               ret = sh_sdhi_single_write(host, data);
-               break;
-       case MMC_CMD_READ_SINGLE_BLOCK:
-       case SDHI_SD_APP_SEND_SCR:
-       case SDHI_SD_SWITCH: /* SD_SWITCH */
-       case SDHI_MMC_SEND_EXT_CSD:
-               ret = sh_sdhi_single_read(host, data);
-               break;
-       default:
-               printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
-               ret = -EINVAL;
-               break;
+       if (host->app_cmd) {
+               host->app_cmd = 0;
+               switch (opc) {
+               case SD_CMD_APP_SEND_SCR:
+               case SD_CMD_APP_SD_STATUS:
+                       return sh_sdhi_single_read(host, data);
+               default:
+                       printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n",
+                               opc);
+                       return -EINVAL;
+               }
+       } else {
+               switch (opc) {
+               case MMC_CMD_WRITE_MULTIPLE_BLOCK:
+                       return sh_sdhi_multi_write(host, data);
+               case MMC_CMD_READ_MULTIPLE_BLOCK:
+                       return sh_sdhi_multi_read(host, data);
+               case MMC_CMD_WRITE_SINGLE_BLOCK:
+                       return sh_sdhi_single_write(host, data);
+               case MMC_CMD_READ_SINGLE_BLOCK:
+               case MMC_CMD_SWITCH:
+               case MMC_CMD_SEND_EXT_CSD:;
+                       return sh_sdhi_single_read(host, data);
+               default:
+                       printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
+                       return -EINVAL;
+               }
        }
-       return ret;
 }
 
 static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
                        struct mmc_data *data, struct mmc_cmd *cmd)
 {
        long time;
-       unsigned short opc = cmd->cmdidx;
+       unsigned short shcmd, opc = cmd->cmdidx;
        int ret = 0;
        unsigned long timeout;
 
@@ -561,7 +562,8 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
                }
                sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
        }
-       opc = sh_sdhi_set_cmd(host, data, opc);
+
+       shcmd = sh_sdhi_set_cmd(host, data, opc);
 
        /*
         *  U-Boot cannot use interrupt.
@@ -592,11 +594,12 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
                       INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
                       sh_sdhi_readw(host, SDHI_INFO2_MASK));
 
-       sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(opc & CMD_MASK));
-
+       sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK));
        time = sh_sdhi_wait_interrupt_flag(host);
-       if (!time)
+       if (!time) {
+               host->app_cmd = 0;
                return sh_sdhi_error_manage(host);
+       }
 
        if (host->sd_error) {
                switch (cmd->cmdidx) {
@@ -614,15 +617,20 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
                }
                host->sd_error = 0;
                host->wait_int = 0;
+               host->app_cmd = 0;
                return ret;
        }
-       if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END)
+
+       if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) {
+               host->app_cmd = 0;
                return -EINVAL;
+       }
 
        if (host->wait_int) {
                sh_sdhi_get_response(host, cmd);
                host->wait_int = 0;
        }
+
        if (data)
                ret = sh_sdhi_data_trans(host, data, opc);
 
@@ -817,8 +825,10 @@ static int sh_sdhi_dm_probe(struct udevice *dev)
        struct sh_sdhi_plat *plat = dev_get_platdata(dev);
        struct sh_sdhi_host *host = dev_get_priv(dev);
        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+       struct clk sh_sdhi_clk;
        const u32 quirks = dev_get_driver_data(dev);
        fdt_addr_t base;
+       int ret;
 
        base = devfdt_get_addr(dev);
        if (base == FDT_ADDR_T_NONE)
@@ -828,6 +838,18 @@ static int sh_sdhi_dm_probe(struct udevice *dev)
        if (!host->addr)
                return -ENOMEM;
 
+       ret = clk_get_by_index(dev, 0, &sh_sdhi_clk);
+       if (ret) {
+               debug("failed to get clock, ret=%d\n", ret);
+               return ret;
+       }
+
+       ret = clk_enable(&sh_sdhi_clk);
+       if (ret) {
+               debug("failed to enable clock, ret=%d\n", ret);
+               return ret;
+       }
+
        host->quirks = quirks;
 
        if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)