[U-Boot] [PATCH 2/3] mmc: sh_sdhi: Fix the ACMD handling
Nobuhiro Iwamatsu
iwamatsu at nigauri.org
Wed Aug 2 23:18:00 UTC 2017
Hi,
2017-07-22 6:22 GMT+09:00 Marek Vasut <marek.vasut at gmail.com>:
> The command handling in this driver is awful, esp. because the driver
> depends on command numbers to determine whether this is APPCMD or not.
> Also, handling of command RSP response types is totally wrong.
>
> This patch at least plucks out some of the custom command encoding and
> fixes the APPCMD handling. The RSP handling still needs work, yet that
> might not be needed as it turns out the uniphier-sd.c driver is in much
> better shape and supports the same IP, so we might be able to just drop
> this driver in favor of the uniphier one.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas at gmail.com>
> Cc: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx at renesas.com>
> Cc: Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
> Cc: Jaehoon Chung <jh80.chung at samsung.com>
Reviewed-by: Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
> ---
> arch/arm/mach-rmobile/include/mach/sh_sdhi.h | 5 --
> drivers/mmc/sh_sdhi.c | 103 ++++++++++++++-------------
> 2 files changed, 55 insertions(+), 53 deletions(-)
>
> diff --git a/arch/arm/mach-rmobile/include/mach/sh_sdhi.h b/arch/arm/mach-rmobile/include/mach/sh_sdhi.h
> index 1fb0648b12..00a135faa1 100644
> --- a/arch/arm/mach-rmobile/include/mach/sh_sdhi.h
> +++ b/arch/arm/mach-rmobile/include/mach/sh_sdhi.h
> @@ -49,11 +49,6 @@
>
> /* SDHI CMD VALUE */
> #define CMD_MASK 0x0000ffff
> -#define SDHI_APP 0x0040
> -#define SDHI_MMC_SEND_OP_COND 0x0701
> -#define SDHI_SD_APP_SEND_SCR 0x0073
> -#define SDHI_SD_SWITCH 0x1C06
> -#define SDHI_MMC_SEND_EXT_CSD 0x1C08
>
> /* SDHI_PORTSEL */
> #define USE_1PORT (1 << 8) /* 1 port */
> diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
> index fd710399b6..3c5616e507 100644
> --- a/drivers/mmc/sh_sdhi.c
> +++ b/drivers/mmc/sh_sdhi.c
> @@ -31,6 +31,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 +476,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 +561,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 +593,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 +616,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);
>
> --
> 2.11.0
>
--
Nobuhiro Iwamatsu
iwamatsu at {nigauri.org / debian.org}
GPG ID: 40AD1FA6
More information about the U-Boot
mailing list