[U-Boot] [PATCH 1/3] mmc: sh_sdhi: Add DM and DT probing support

Add MMC DM and DT probing support into the SH SDHI driver. This patch abstracts out the common bits of the send command and set ios functions, so they can be used both by DM and non DM setups and adds the DM probe support.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com --- drivers/mmc/sh_sdhi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 145 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index d181b63905..fd710399b6 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -13,15 +13,18 @@ #include <common.h> #include <malloc.h> #include <mmc.h> +#include <dm.h> #include <linux/errno.h> -#include <asm/io.h> +#include <linux/compat.h> +#include <linux/io.h> +#include <linux/sizes.h> #include <asm/arch/rmobile.h> #include <asm/arch/sh_sdhi.h>
#define DRIVER_NAME "sh-sdhi"
struct sh_sdhi_host { - unsigned long addr; + void __iomem *addr; int ch; int bus_shift; unsigned long quirks; @@ -50,11 +53,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg) return readw(host->addr + (reg << host->bus_shift)); }
-static void *mmc_priv(struct mmc *mmc) -{ - return (void *)mmc->priv; -} - static void sh_sdhi_detect(struct sh_sdhi_host *host) { sh_sdhi_writew(host, SDHI_OPTION, @@ -634,23 +632,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, return ret; }
-static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) +static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host, + struct mmc_cmd *cmd, struct mmc_data *data) { - struct sh_sdhi_host *host = mmc_priv(mmc); - int ret; - host->sd_error = 0;
- ret = sh_sdhi_start_cmd(host, data, cmd); - - return ret; + return sh_sdhi_start_cmd(host, data, cmd); }
-static int sh_sdhi_set_ios(struct mmc *mmc) +static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc) { int ret; - struct sh_sdhi_host *host = mmc_priv(mmc);
ret = sh_sdhi_clock_control(host, mmc->clock); if (ret) @@ -674,9 +666,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc) return 0; }
-static int sh_sdhi_initialize(struct mmc *mmc) +static int sh_sdhi_initialize_common(struct sh_sdhi_host *host) { - struct sh_sdhi_host *host = mmc_priv(mmc); int ret = sh_sdhi_sync_reset(host);
sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT); @@ -692,6 +683,34 @@ static int sh_sdhi_initialize(struct mmc *mmc) return ret; }
+#ifndef CONFIG_DM_MMC +static void *mmc_priv(struct mmc *mmc) +{ + return (void *)mmc->priv; +} + +static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct sh_sdhi_host *host = mmc_priv(mmc); + + return sh_sdhi_send_cmd_common(host, cmd, data); +} + +static int sh_sdhi_set_ios(struct mmc *mmc) +{ + struct sh_sdhi_host *host = mmc_priv(mmc); + + return sh_sdhi_set_ios_common(host, mmc); +} + +static int sh_sdhi_initialize(struct mmc *mmc) +{ + struct sh_sdhi_host *host = mmc_priv(mmc); + + return sh_sdhi_initialize_common(host); +} + static const struct mmc_ops sh_sdhi_ops = { .send_cmd = sh_sdhi_send_cmd, .set_ios = sh_sdhi_set_ios, @@ -743,7 +762,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks) }
host->ch = ch; - host->addr = addr; + host->addr = (void __iomem *)addr; host->quirks = quirks;
if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF) @@ -757,3 +776,109 @@ error: free(host); return ret; } + +#else + +struct sh_sdhi_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct sh_sdhi_host *host = dev_get_priv(dev); + + return sh_sdhi_send_cmd_common(host, cmd, data); +} + +int sh_sdhi_dm_set_ios(struct udevice *dev) +{ + struct sh_sdhi_host *host = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return sh_sdhi_set_ios_common(host, mmc); +} + +static const struct dm_mmc_ops sh_sdhi_dm_ops = { + .send_cmd = sh_sdhi_dm_send_cmd, + .set_ios = sh_sdhi_dm_set_ios, +}; + +static int sh_sdhi_dm_bind(struct udevice *dev) +{ + struct sh_sdhi_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + +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); + const u32 quirks = dev_get_driver_data(dev); + fdt_addr_t base; + + base = devfdt_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + host->addr = devm_ioremap(dev, base, SZ_2K); + if (!host->addr) + return -ENOMEM; + + host->quirks = quirks; + + if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF) + host->bus_shift = 2; + else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF) + host->bus_shift = 1; + + plat->cfg.name = dev->name; + plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; + + switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width", + 1)) { + case 8: + plat->cfg.host_caps |= MMC_MODE_8BIT; + break; + case 4: + plat->cfg.host_caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + dev_err(dev, "Invalid "bus-width" value\n"); + return -EINVAL; + } + + sh_sdhi_initialize_common(host); + + plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; + plat->cfg.f_min = CLKDEV_INIT; + plat->cfg.f_max = CLKDEV_HS_DATA; + plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + upriv->mmc = &plat->mmc; + + return 0; +} + +static const struct udevice_id sh_sdhi_sd_match[] = { + { .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF }, + { .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sh_sdhi_mmc) = { + .name = "sh-sdhi-mmc", + .id = UCLASS_MMC, + .of_match = sh_sdhi_sd_match, + .bind = sh_sdhi_dm_bind, + .probe = sh_sdhi_dm_probe, + .priv_auto_alloc_size = sizeof(struct sh_sdhi_host), + .platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat), + .ops = &sh_sdhi_dm_ops, +}; +#endif

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@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com --- 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);

Hi,
2017-07-22 6:22 GMT+09:00 Marek Vasut marek.vasut@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@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com
Reviewed-by: Nobuhiro Iwamatsu iwamatsu@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

On 07/22/2017 06:22 AM, Marek Vasut wrote:
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@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com Reviewed-by: Nobuhiro Iwamatsu iwamatsu@nigauri.org
Applied to u-boot-mmc. Sorry for late!
Best Regards, Jaehoon Chung
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:
case MMC_CMD_SEND_EXT_CSD:return opc | (data ? 0x1c00 : 0x40);
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:
default:host->app_cmd = 1;
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;
return ret; }host->app_cmd = 0;
- 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);

Since we now have clock driver for the RCar Gen3 , add support for enabling the clock into the SH SDHI driver to prevent hacks in the board files.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com --- drivers/mmc/sh_sdhi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index 3c5616e507..eef061abb2 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -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"
@@ -824,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) @@ -835,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)

Hi,
2017-07-22 6:22 GMT+09:00 Marek Vasut marek.vasut@gmail.com:
Since we now have clock driver for the RCar Gen3 , add support for enabling the clock into the SH SDHI driver to prevent hacks in the board files.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com
Reviewed-by: Nobuhiro Iwamatsu iwamatsu@nigauri.org
drivers/mmc/sh_sdhi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index 3c5616e507..eef061abb2 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -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"
@@ -824,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)
@@ -835,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)
-- 2.11.0

On 07/22/2017 06:22 AM, Marek Vasut wrote:
Since we now have clock driver for the RCar Gen3 , add support for enabling the clock into the SH SDHI driver to prevent hacks in the board files.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com Reviewed-by: Nobuhiro Iwamatsu iwamatsu@nigauri.org
Applied to u-boot-mmc. Sorry for late!
Best Regards, Jaehoon Chung
drivers/mmc/sh_sdhi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index 3c5616e507..eef061abb2 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -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"
@@ -824,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)
@@ -835,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)

Hi,
2017-07-22 6:22 GMT+09:00 Marek Vasut marek.vasut@gmail.com:
Add MMC DM and DT probing support into the SH SDHI driver. This patch abstracts out the common bits of the send command and set ios functions, so they can be used both by DM and non DM setups and adds the DM probe support.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com
Reviewed-by: Nobuhiro Iwamatsu iwamatsu@nigauri.org
drivers/mmc/sh_sdhi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 145 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index d181b63905..fd710399b6 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -13,15 +13,18 @@ #include <common.h> #include <malloc.h> #include <mmc.h> +#include <dm.h> #include <linux/errno.h> -#include <asm/io.h> +#include <linux/compat.h> +#include <linux/io.h> +#include <linux/sizes.h> #include <asm/arch/rmobile.h> #include <asm/arch/sh_sdhi.h>
#define DRIVER_NAME "sh-sdhi"
struct sh_sdhi_host {
unsigned long addr;
void __iomem *addr; int ch; int bus_shift; unsigned long quirks;
@@ -50,11 +53,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg) return readw(host->addr + (reg << host->bus_shift)); }
-static void *mmc_priv(struct mmc *mmc) -{
return (void *)mmc->priv;
-}
static void sh_sdhi_detect(struct sh_sdhi_host *host) { sh_sdhi_writew(host, SDHI_OPTION, @@ -634,23 +632,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, return ret; }
-static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
+static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
struct mmc_cmd *cmd, struct mmc_data *data)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
int ret;
host->sd_error = 0;
ret = sh_sdhi_start_cmd(host, data, cmd);
return ret;
return sh_sdhi_start_cmd(host, data, cmd);
}
-static int sh_sdhi_set_ios(struct mmc *mmc) +static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc) { int ret;
struct sh_sdhi_host *host = mmc_priv(mmc); ret = sh_sdhi_clock_control(host, mmc->clock); if (ret)
@@ -674,9 +666,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc) return 0; }
-static int sh_sdhi_initialize(struct mmc *mmc) +static int sh_sdhi_initialize_common(struct sh_sdhi_host *host) {
struct sh_sdhi_host *host = mmc_priv(mmc); int ret = sh_sdhi_sync_reset(host); sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
@@ -692,6 +683,34 @@ static int sh_sdhi_initialize(struct mmc *mmc) return ret; }
+#ifndef CONFIG_DM_MMC +static void *mmc_priv(struct mmc *mmc) +{
return (void *)mmc->priv;
+}
+static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
+{
struct sh_sdhi_host *host = mmc_priv(mmc);
return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+static int sh_sdhi_set_ios(struct mmc *mmc) +{
struct sh_sdhi_host *host = mmc_priv(mmc);
return sh_sdhi_set_ios_common(host, mmc);
+}
+static int sh_sdhi_initialize(struct mmc *mmc) +{
struct sh_sdhi_host *host = mmc_priv(mmc);
return sh_sdhi_initialize_common(host);
+}
static const struct mmc_ops sh_sdhi_ops = { .send_cmd = sh_sdhi_send_cmd, .set_ios = sh_sdhi_set_ios, @@ -743,7 +762,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks) }
host->ch = ch;
host->addr = addr;
host->addr = (void __iomem *)addr; host->quirks = quirks; if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
@@ -757,3 +776,109 @@ error: free(host); return ret; }
+#else
+struct sh_sdhi_plat {
struct mmc_config cfg;
struct mmc mmc;
+};
+int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
+{
struct sh_sdhi_host *host = dev_get_priv(dev);
return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+int sh_sdhi_dm_set_ios(struct udevice *dev) +{
struct sh_sdhi_host *host = dev_get_priv(dev);
struct mmc *mmc = mmc_get_mmc_dev(dev);
return sh_sdhi_set_ios_common(host, mmc);
+}
+static const struct dm_mmc_ops sh_sdhi_dm_ops = {
.send_cmd = sh_sdhi_dm_send_cmd,
.set_ios = sh_sdhi_dm_set_ios,
+};
+static int sh_sdhi_dm_bind(struct udevice *dev) +{
struct sh_sdhi_plat *plat = dev_get_platdata(dev);
return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+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);
const u32 quirks = dev_get_driver_data(dev);
fdt_addr_t base;
base = devfdt_get_addr(dev);
if (base == FDT_ADDR_T_NONE)
return -EINVAL;
host->addr = devm_ioremap(dev, base, SZ_2K);
if (!host->addr)
return -ENOMEM;
host->quirks = quirks;
if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
host->bus_shift = 2;
else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
host->bus_shift = 1;
plat->cfg.name = dev->name;
plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
1)) {
case 8:
plat->cfg.host_caps |= MMC_MODE_8BIT;
break;
case 4:
plat->cfg.host_caps |= MMC_MODE_4BIT;
break;
case 1:
break;
default:
dev_err(dev, "Invalid \"bus-width\" value\n");
return -EINVAL;
}
sh_sdhi_initialize_common(host);
plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
plat->cfg.f_min = CLKDEV_INIT;
plat->cfg.f_max = CLKDEV_HS_DATA;
plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
upriv->mmc = &plat->mmc;
return 0;
+}
+static const struct udevice_id sh_sdhi_sd_match[] = {
{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
{ /* sentinel */ }
+};
+U_BOOT_DRIVER(sh_sdhi_mmc) = {
.name = "sh-sdhi-mmc",
.id = UCLASS_MMC,
.of_match = sh_sdhi_sd_match,
.bind = sh_sdhi_dm_bind,
.probe = sh_sdhi_dm_probe,
.priv_auto_alloc_size = sizeof(struct sh_sdhi_host),
.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
.ops = &sh_sdhi_dm_ops,
+};
+#endif
2.11.0

On 08/03/2017 01:17 AM, Nobuhiro Iwamatsu wrote:
Hi,
2017-07-22 6:22 GMT+09:00 Marek Vasut marek.vasut@gmail.com:
Add MMC DM and DT probing support into the SH SDHI driver. This patch abstracts out the common bits of the send command and set ios functions, so they can be used both by DM and non DM setups and adds the DM probe support.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com
Reviewed-by: Nobuhiro Iwamatsu iwamatsu@nigauri.org
Thanks.
Jaehoon, can you pick those three patches, it's blocking some further board-level cleanups I'd like to get into this release.

On 07/22/2017 06:22 AM, Marek Vasut wrote:
Add MMC DM and DT probing support into the SH SDHI driver. This patch abstracts out the common bits of the send command and set ios functions, so they can be used both by DM and non DM setups and adds the DM probe support.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Hiroyuki Yokoyama hiroyuki.yokoyama.vx@renesas.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Jaehoon Chung jh80.chung@samsung.com Reviewed-by: Nobuhiro Iwamatsu iwamatsu@nigauri.org
Applied to u-boot-mmc. Sorry for late!
Best Regards, Jaehoon Chung
drivers/mmc/sh_sdhi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 145 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index d181b63905..fd710399b6 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -13,15 +13,18 @@ #include <common.h> #include <malloc.h> #include <mmc.h> +#include <dm.h> #include <linux/errno.h> -#include <asm/io.h> +#include <linux/compat.h> +#include <linux/io.h> +#include <linux/sizes.h> #include <asm/arch/rmobile.h> #include <asm/arch/sh_sdhi.h>
#define DRIVER_NAME "sh-sdhi"
struct sh_sdhi_host {
- unsigned long addr;
- void __iomem *addr; int ch; int bus_shift; unsigned long quirks;
@@ -50,11 +53,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg) return readw(host->addr + (reg << host->bus_shift)); }
-static void *mmc_priv(struct mmc *mmc) -{
- return (void *)mmc->priv;
-}
static void sh_sdhi_detect(struct sh_sdhi_host *host) { sh_sdhi_writew(host, SDHI_OPTION, @@ -634,23 +632,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, return ret; }
-static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
+static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
struct mmc_cmd *cmd, struct mmc_data *data)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
int ret;
host->sd_error = 0;
ret = sh_sdhi_start_cmd(host, data, cmd);
return ret;
- return sh_sdhi_start_cmd(host, data, cmd);
}
-static int sh_sdhi_set_ios(struct mmc *mmc) +static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc) { int ret;
struct sh_sdhi_host *host = mmc_priv(mmc);
ret = sh_sdhi_clock_control(host, mmc->clock); if (ret)
@@ -674,9 +666,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc) return 0; }
-static int sh_sdhi_initialize(struct mmc *mmc) +static int sh_sdhi_initialize_common(struct sh_sdhi_host *host) {
struct sh_sdhi_host *host = mmc_priv(mmc); int ret = sh_sdhi_sync_reset(host);
sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
@@ -692,6 +683,34 @@ static int sh_sdhi_initialize(struct mmc *mmc) return ret; }
+#ifndef CONFIG_DM_MMC +static void *mmc_priv(struct mmc *mmc) +{
- return (void *)mmc->priv;
+}
+static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
+{
- struct sh_sdhi_host *host = mmc_priv(mmc);
- return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+static int sh_sdhi_set_ios(struct mmc *mmc) +{
- struct sh_sdhi_host *host = mmc_priv(mmc);
- return sh_sdhi_set_ios_common(host, mmc);
+}
+static int sh_sdhi_initialize(struct mmc *mmc) +{
- struct sh_sdhi_host *host = mmc_priv(mmc);
- return sh_sdhi_initialize_common(host);
+}
static const struct mmc_ops sh_sdhi_ops = { .send_cmd = sh_sdhi_send_cmd, .set_ios = sh_sdhi_set_ios, @@ -743,7 +762,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks) }
host->ch = ch;
- host->addr = addr;
host->addr = (void __iomem *)addr; host->quirks = quirks;
if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
@@ -757,3 +776,109 @@ error: free(host); return ret; }
+#else
+struct sh_sdhi_plat {
- struct mmc_config cfg;
- struct mmc mmc;
+};
+int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
+{
- struct sh_sdhi_host *host = dev_get_priv(dev);
- return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+int sh_sdhi_dm_set_ios(struct udevice *dev) +{
- struct sh_sdhi_host *host = dev_get_priv(dev);
- struct mmc *mmc = mmc_get_mmc_dev(dev);
- return sh_sdhi_set_ios_common(host, mmc);
+}
+static const struct dm_mmc_ops sh_sdhi_dm_ops = {
- .send_cmd = sh_sdhi_dm_send_cmd,
- .set_ios = sh_sdhi_dm_set_ios,
+};
+static int sh_sdhi_dm_bind(struct udevice *dev) +{
- struct sh_sdhi_plat *plat = dev_get_platdata(dev);
- return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+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);
- const u32 quirks = dev_get_driver_data(dev);
- fdt_addr_t base;
- base = devfdt_get_addr(dev);
- if (base == FDT_ADDR_T_NONE)
return -EINVAL;
- host->addr = devm_ioremap(dev, base, SZ_2K);
- if (!host->addr)
return -ENOMEM;
- host->quirks = quirks;
- if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
host->bus_shift = 2;
- else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
host->bus_shift = 1;
- plat->cfg.name = dev->name;
- plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
- switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
1)) {
- case 8:
plat->cfg.host_caps |= MMC_MODE_8BIT;
break;
- case 4:
plat->cfg.host_caps |= MMC_MODE_4BIT;
break;
- case 1:
break;
- default:
dev_err(dev, "Invalid \"bus-width\" value\n");
return -EINVAL;
- }
- sh_sdhi_initialize_common(host);
- plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
- plat->cfg.f_min = CLKDEV_INIT;
- plat->cfg.f_max = CLKDEV_HS_DATA;
- plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
- upriv->mmc = &plat->mmc;
- return 0;
+}
+static const struct udevice_id sh_sdhi_sd_match[] = {
- { .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
- { .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
- { /* sentinel */ }
+};
+U_BOOT_DRIVER(sh_sdhi_mmc) = {
- .name = "sh-sdhi-mmc",
- .id = UCLASS_MMC,
- .of_match = sh_sdhi_sd_match,
- .bind = sh_sdhi_dm_bind,
- .probe = sh_sdhi_dm_probe,
- .priv_auto_alloc_size = sizeof(struct sh_sdhi_host),
- .platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
- .ops = &sh_sdhi_dm_ops,
+}; +#endif
participants (3)
-
Jaehoon Chung
-
Marek Vasut
-
Nobuhiro Iwamatsu