[U-Boot] [PATCH 01/10] mmc: uniphier-sd: Add compatible strings for RCar Gen2

Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 741f9dfd9c..a080674c8a 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -847,6 +847,11 @@ static int uniphier_sd_probe(struct udevice *dev) }
static const struct udevice_id uniphier_sd_match[] = { + { .compatible = "renesas,sdhi-r8a7790", .data = 0 }, + { .compatible = "renesas,sdhi-r8a7791", .data = 0 }, + { .compatible = "renesas,sdhi-r8a7792", .data = 0 }, + { .compatible = "renesas,sdhi-r8a7793", .data = 0 }, + { .compatible = "renesas,sdhi-r8a7794", .data = 0 }, { .compatible = "renesas,sdhi-r8a7795", .data = UNIPHIER_SD_CAP_64BIT }, { .compatible = "renesas,sdhi-r8a7796", .data = UNIPHIER_SD_CAP_64BIT }, { .compatible = "renesas,sdhi-r8a77970", .data = UNIPHIER_SD_CAP_64BIT },

Drop the ad-hoc DT caps parsing in favor of common framework function.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index a080674c8a..6b4e208241 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -799,24 +799,15 @@ static int uniphier_sd_probe(struct udevice *dev) return ret; }
- 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; + ret = mmc_of_parse(dev, &plat->cfg); + if (ret < 0) { + dev_err(dev, "failed to parse host caps\n"); + return ret; }
+ plat->cfg.name = dev->name; + plat->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + if (quirks) { priv->caps = quirks; } else {

Add a quirk to identify that the controller is Renesas RCar variant of the Matsushita SD IP and another quirk indicating it can support Renesas RCar HS200/HS400/SDR104 modes.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- V2: No changes V3: Add RCar Gen2 quirk, since the Gen2 IP is slightly different --- drivers/mmc/uniphier-sd.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 6b4e208241..d21d9625ee 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -134,6 +134,11 @@ struct uniphier_sd_priv { #define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ #define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ #define UNIPHIER_SD_CAP_64BIT BIT(3) /* Controller is 64bit */ +#define UNIPHIER_SD_CAP_RCAR_GEN2 BIT(4) /* Renesas RCar version of IP */ +#define UNIPHIER_SD_CAP_RCAR_GEN3 BIT(5) /* Renesas RCar version of IP */ +#define UNIPHIER_SD_CAP_RCAR_UHS BIT(6) /* Renesas RCar UHS/SDR modes */ +#define UNIPHIER_SD_CAP_RCAR \ + (UNIPHIER_SD_CAP_RCAR_GEN2 | UNIPHIER_SD_CAP_RCAR_GEN3) };
static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) @@ -837,16 +842,21 @@ static int uniphier_sd_probe(struct udevice *dev) return 0; }
+#define RENESAS_GEN2_QUIRKS UNIPHIER_SD_CAP_RCAR_GEN2 +#define RENESAS_GEN3_QUIRKS \ + UNIPHIER_SD_CAP_64BIT | UNIPHIER_SD_CAP_RCAR_GEN3 | \ + UNIPHIER_SD_CAP_RCAR_UHS + static const struct udevice_id uniphier_sd_match[] = { - { .compatible = "renesas,sdhi-r8a7790", .data = 0 }, - { .compatible = "renesas,sdhi-r8a7791", .data = 0 }, - { .compatible = "renesas,sdhi-r8a7792", .data = 0 }, - { .compatible = "renesas,sdhi-r8a7793", .data = 0 }, - { .compatible = "renesas,sdhi-r8a7794", .data = 0 }, - { .compatible = "renesas,sdhi-r8a7795", .data = UNIPHIER_SD_CAP_64BIT }, - { .compatible = "renesas,sdhi-r8a7796", .data = UNIPHIER_SD_CAP_64BIT }, - { .compatible = "renesas,sdhi-r8a77970", .data = UNIPHIER_SD_CAP_64BIT }, - { .compatible = "renesas,sdhi-r8a77995", .data = UNIPHIER_SD_CAP_64BIT }, + { .compatible = "renesas,sdhi-r8a7790", .data = RENESAS_GEN2_QUIRKS }, + { .compatible = "renesas,sdhi-r8a7791", .data = RENESAS_GEN2_QUIRKS }, + { .compatible = "renesas,sdhi-r8a7792", .data = RENESAS_GEN2_QUIRKS }, + { .compatible = "renesas,sdhi-r8a7793", .data = RENESAS_GEN2_QUIRKS }, + { .compatible = "renesas,sdhi-r8a7794", .data = RENESAS_GEN2_QUIRKS }, + { .compatible = "renesas,sdhi-r8a7795", .data = RENESAS_GEN3_QUIRKS }, + { .compatible = "renesas,sdhi-r8a7796", .data = RENESAS_GEN3_QUIRKS }, + { .compatible = "renesas,sdhi-r8a77970", .data = RENESAS_GEN3_QUIRKS }, + { .compatible = "renesas,sdhi-r8a77995", .data = RENESAS_GEN3_QUIRKS }, { .compatible = "socionext,uniphier-sdhc", .data = 0 }, { /* sentinel */ } };

On the Renesas version of the IP, the /1 divider is realized by setting the clock register [7:0] to 0xff instead of setting bit 10 of the register. Check the quirk and handle accordingly.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index d21d9625ee..7ad5c472b0 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -74,6 +74,7 @@ DECLARE_GLOBAL_DATA_PTR; #define UNIPHIER_SD_CLKCTL_DIV4 BIT(0) /* SDCLK = CLK / 4 */ #define UNIPHIER_SD_CLKCTL_DIV2 0 /* SDCLK = CLK / 2 */ #define UNIPHIER_SD_CLKCTL_DIV1 BIT(10) /* SDCLK = CLK */ +#define UNIPHIER_SD_CLKCTL_RCAR_DIV1 0xff /* SDCLK = CLK (RCar ver.) */ #define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) /* stop SDCLK when unused */ #define UNIPHIER_SD_CLKCTL_SCLKEN BIT(8) /* SDCLK output enable */ #define UNIPHIER_SD_SIZE 0x04c /* block size */ @@ -640,7 +641,8 @@ static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
if (divisor <= 1) - val = UNIPHIER_SD_CLKCTL_DIV1; + val = (priv->caps & UNIPHIER_SD_CAP_RCAR) ? + UNIPHIER_SD_CLKCTL_RCAR_DIV1 : UNIPHIER_SD_CLKCTL_DIV1; else if (divisor <= 2) val = UNIPHIER_SD_CLKCTL_DIV2; else if (divisor <= 4)

The DMA READ completion flag position differs on Socionext and Renesas SoCs. It is bit 20 on Socionext SoCs and using bit 17 is a hardware bug and forbidden. It is bit 17 on Renesas SoCs and bit 20 does not work on them.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 7ad5c472b0..c327ab3ace 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -107,8 +107,8 @@ DECLARE_GLOBAL_DATA_PTR; #define UNIPHIER_SD_DMA_RST_RD BIT(9) #define UNIPHIER_SD_DMA_RST_WR BIT(8) #define UNIPHIER_SD_DMA_INFO1 0x420 -#define UNIPHIER_SD_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete*/ -#define UNIPHIER_SD_DMA_INFO1_END_RD BIT(17) /* Don't use! Hardware bug */ +#define UNIPHIER_SD_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete (uniphier) */ +#define UNIPHIER_SD_DMA_INFO1_END_RD BIT(17) /* DMA from device is complete (renesas) */ #define UNIPHIER_SD_DMA_INFO1_END_WR BIT(16) /* DMA to device is complete */ #define UNIPHIER_SD_DMA_INFO1_MASK 0x424 #define UNIPHIER_SD_DMA_INFO2 0x428 @@ -438,7 +438,15 @@ static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) if (data->flags & MMC_DATA_READ) { buf = data->dest; dir = DMA_FROM_DEVICE; - poll_flag = UNIPHIER_SD_DMA_INFO1_END_RD2; + /* + * The DMA READ completion flag position differs on Socionext + * and Renesas SoCs. It is bit 20 on Socionext SoCs and using + * bit 17 is a hardware bug and forbidden. It is bit 17 on + * Renesas SoCs and bit 20 does not work on them. + */ + poll_flag = (priv->caps & UNIPHIER_SD_CAP_RCAR) ? + UNIPHIER_SD_DMA_INFO1_END_RD : + UNIPHIER_SD_DMA_INFO1_END_RD2; tmp |= UNIPHIER_SD_DMA_MODE_DIR_RD; } else { buf = (void *)data->src;

Handle bus width 0 as 1-bit bus to assure valid content of UNIPHIER_SD_OPTION register WIDTH field.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index c327ab3ace..5603c43813 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -603,6 +603,7 @@ static int uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv, u32 val, tmp;
switch (mmc->bus_width) { + case 0: case 1: val = UNIPHIER_SD_OPTION_WIDTH_1; break;

Handle the controller version even if quirks are set. The controller in Renesas Gen3 SoCs does provide the version register, which indicates a controller v10 and the controller does support internal DMA and /1024 divider.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 5603c43813..440f5be438 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -824,16 +824,15 @@ static int uniphier_sd_probe(struct udevice *dev) plat->cfg.name = dev->name; plat->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
- if (quirks) { + if (quirks) priv->caps = quirks; - } else { - priv->version = uniphier_sd_readl(priv, UNIPHIER_SD_VERSION) & - UNIPHIER_SD_VERSION_IP; - dev_dbg(dev, "version %x\n", priv->version); - if (priv->version >= 0x10) { - priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; - priv->caps |= UNIPHIER_SD_CAP_DIV1024; - } + + priv->version = uniphier_sd_readl(priv, UNIPHIER_SD_VERSION) & + UNIPHIER_SD_VERSION_IP; + dev_dbg(dev, "version %x\n", priv->version); + if (priv->version >= 0x10) { + priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; + priv->caps |= UNIPHIER_SD_CAP_DIV1024; }
if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "non-removable",

Factor out the regulator handling into set_ios and add support for selecting pin configuration based on the voltage to support UHS modes.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- V2: Protect vqmmc_dev access in uniphier_sd_set_pins() with an ifdef just like everywhere else V3: Clean up build warnings in uniphier_sd_set_pins() by guarding the code block therein with more ifdefs. Discard return value of the device_get_supply_regulator() since the regulator is optional. --- drivers/mmc/uniphier-sd.c | 55 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 440f5be438..2fda04f81e 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -10,6 +10,7 @@ #include <fdtdec.h> #include <mmc.h> #include <dm.h> +#include <dm/pinctrl.h> #include <linux/compat.h> #include <linux/dma-direction.h> #include <linux/io.h> @@ -140,6 +141,9 @@ struct uniphier_sd_priv { #define UNIPHIER_SD_CAP_RCAR_UHS BIT(6) /* Renesas RCar UHS/SDR modes */ #define UNIPHIER_SD_CAP_RCAR \ (UNIPHIER_SD_CAP_RCAR_GEN2 | UNIPHIER_SD_CAP_RCAR_GEN3) +#ifdef CONFIG_DM_REGULATOR + struct udevice *vqmmc_dev; +#endif };
static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) @@ -692,6 +696,46 @@ static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, udelay(1000); }
+static void uniphier_sd_set_pins(struct udevice *dev) +{ + __maybe_unused struct mmc *mmc = mmc_get_mmc_dev(dev); + +#ifdef CONFIG_DM_REGULATOR + struct uniphier_sd_priv *priv = dev_get_priv(dev); + + if (priv->vqmmc_dev) { + if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) + regulator_set_value(priv->vqmmc_dev, 1800000); + else + regulator_set_value(priv->vqmmc_dev, 3300000); + regulator_set_enable(priv->vqmmc_dev, true); + } +#endif + +#ifdef CONFIG_PINCTRL + switch (mmc->selected_mode) { + case MMC_LEGACY: + case SD_LEGACY: + case MMC_HS: + case SD_HS: + case MMC_HS_52: + case MMC_DDR_52: + pinctrl_select_state(dev, "default"); + break; + case UHS_SDR12: + case UHS_SDR25: + case UHS_SDR50: + case UHS_DDR50: + case UHS_SDR104: + case MMC_HS_200: + pinctrl_select_state(dev, "state_uhs"); + break; + default: + break; + } +#endif +} + static int uniphier_sd_set_ios(struct udevice *dev) { struct uniphier_sd_priv *priv = dev_get_priv(dev); @@ -706,6 +750,7 @@ static int uniphier_sd_set_ios(struct udevice *dev) return ret; uniphier_sd_set_ddr_mode(priv, mmc); uniphier_sd_set_clk_rate(priv, mmc); + uniphier_sd_set_pins(dev);
return 0; } @@ -773,9 +818,6 @@ static int uniphier_sd_probe(struct udevice *dev) fdt_addr_t base; struct clk clk; int ret; -#ifdef CONFIG_DM_REGULATOR - struct udevice *vqmmc_dev; -#endif
base = devfdt_get_addr(dev); if (base == FDT_ADDR_T_NONE) @@ -786,12 +828,7 @@ static int uniphier_sd_probe(struct udevice *dev) return -ENOMEM;
#ifdef CONFIG_DM_REGULATOR - ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev); - if (!ret) { - /* Set the regulator to 3.3V until we support 1.8V modes */ - regulator_set_value(vqmmc_dev, 3300000); - regulator_set_enable(vqmmc_dev, true); - } + device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev); #endif
ret = clk_get_by_index(dev, 0, &clk);

Make bit definitions and IO accessors of the uniphier-sd driver available so they can be used by additional source files, ie. per-SoC SDR104/HS200 tuning implementations
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/uniphier-sd.c | 150 +++++++++------------------------------------- drivers/mmc/uniphier-sd.h | 140 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 123 deletions(-) create mode 100644 drivers/mmc/uniphier-sd.h
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 2fda04f81e..ec4fb16973 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -18,135 +18,32 @@ #include <power/regulator.h> #include <asm/unaligned.h>
-DECLARE_GLOBAL_DATA_PTR; +#include "uniphier-sd.h"
-#define UNIPHIER_SD_CMD 0x000 /* command */ -#define UNIPHIER_SD_CMD_NOSTOP BIT(14) /* No automatic CMD12 issue */ -#define UNIPHIER_SD_CMD_MULTI BIT(13) /* multiple block transfer */ -#define UNIPHIER_SD_CMD_RD BIT(12) /* 1: read, 0: write */ -#define UNIPHIER_SD_CMD_DATA BIT(11) /* data transfer */ -#define UNIPHIER_SD_CMD_APP BIT(6) /* ACMD preceded by CMD55 */ -#define UNIPHIER_SD_CMD_NORMAL (0 << 8)/* auto-detect of resp-type */ -#define UNIPHIER_SD_CMD_RSP_NONE (3 << 8)/* response: none */ -#define UNIPHIER_SD_CMD_RSP_R1 (4 << 8)/* response: R1, R5, R6, R7 */ -#define UNIPHIER_SD_CMD_RSP_R1B (5 << 8)/* response: R1b, R5b */ -#define UNIPHIER_SD_CMD_RSP_R2 (6 << 8)/* response: R2 */ -#define UNIPHIER_SD_CMD_RSP_R3 (7 << 8)/* response: R3, R4 */ -#define UNIPHIER_SD_ARG 0x008 /* command argument */ -#define UNIPHIER_SD_STOP 0x010 /* stop action control */ -#define UNIPHIER_SD_STOP_SEC BIT(8) /* use sector count */ -#define UNIPHIER_SD_STOP_STP BIT(0) /* issue CMD12 */ -#define UNIPHIER_SD_SECCNT 0x014 /* sector counter */ -#define UNIPHIER_SD_RSP10 0x018 /* response[39:8] */ -#define UNIPHIER_SD_RSP32 0x020 /* response[71:40] */ -#define UNIPHIER_SD_RSP54 0x028 /* response[103:72] */ -#define UNIPHIER_SD_RSP76 0x030 /* response[127:104] */ -#define UNIPHIER_SD_INFO1 0x038 /* IRQ status 1 */ -#define UNIPHIER_SD_INFO1_CD BIT(5) /* state of card detect */ -#define UNIPHIER_SD_INFO1_INSERT BIT(4) /* card inserted */ -#define UNIPHIER_SD_INFO1_REMOVE BIT(3) /* card removed */ -#define UNIPHIER_SD_INFO1_CMP BIT(2) /* data complete */ -#define UNIPHIER_SD_INFO1_RSP BIT(0) /* response complete */ -#define UNIPHIER_SD_INFO2 0x03c /* IRQ status 2 */ -#define UNIPHIER_SD_INFO2_ERR_ILA BIT(15) /* illegal access err */ -#define UNIPHIER_SD_INFO2_CBSY BIT(14) /* command busy */ -#define UNIPHIER_SD_INFO2_BWE BIT(9) /* write buffer ready */ -#define UNIPHIER_SD_INFO2_BRE BIT(8) /* read buffer ready */ -#define UNIPHIER_SD_INFO2_DAT0 BIT(7) /* SDDAT0 */ -#define UNIPHIER_SD_INFO2_ERR_RTO BIT(6) /* response time out */ -#define UNIPHIER_SD_INFO2_ERR_ILR BIT(5) /* illegal read err */ -#define UNIPHIER_SD_INFO2_ERR_ILW BIT(4) /* illegal write err */ -#define UNIPHIER_SD_INFO2_ERR_TO BIT(3) /* time out error */ -#define UNIPHIER_SD_INFO2_ERR_END BIT(2) /* END bit error */ -#define UNIPHIER_SD_INFO2_ERR_CRC BIT(1) /* CRC error */ -#define UNIPHIER_SD_INFO2_ERR_IDX BIT(0) /* cmd index error */ -#define UNIPHIER_SD_INFO1_MASK 0x040 -#define UNIPHIER_SD_INFO2_MASK 0x044 -#define UNIPHIER_SD_CLKCTL 0x048 /* clock divisor */ -#define UNIPHIER_SD_CLKCTL_DIV_MASK 0x104ff -#define UNIPHIER_SD_CLKCTL_DIV1024 BIT(16) /* SDCLK = CLK / 1024 */ -#define UNIPHIER_SD_CLKCTL_DIV512 BIT(7) /* SDCLK = CLK / 512 */ -#define UNIPHIER_SD_CLKCTL_DIV256 BIT(6) /* SDCLK = CLK / 256 */ -#define UNIPHIER_SD_CLKCTL_DIV128 BIT(5) /* SDCLK = CLK / 128 */ -#define UNIPHIER_SD_CLKCTL_DIV64 BIT(4) /* SDCLK = CLK / 64 */ -#define UNIPHIER_SD_CLKCTL_DIV32 BIT(3) /* SDCLK = CLK / 32 */ -#define UNIPHIER_SD_CLKCTL_DIV16 BIT(2) /* SDCLK = CLK / 16 */ -#define UNIPHIER_SD_CLKCTL_DIV8 BIT(1) /* SDCLK = CLK / 8 */ -#define UNIPHIER_SD_CLKCTL_DIV4 BIT(0) /* SDCLK = CLK / 4 */ -#define UNIPHIER_SD_CLKCTL_DIV2 0 /* SDCLK = CLK / 2 */ -#define UNIPHIER_SD_CLKCTL_DIV1 BIT(10) /* SDCLK = CLK */ -#define UNIPHIER_SD_CLKCTL_RCAR_DIV1 0xff /* SDCLK = CLK (RCar ver.) */ -#define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) /* stop SDCLK when unused */ -#define UNIPHIER_SD_CLKCTL_SCLKEN BIT(8) /* SDCLK output enable */ -#define UNIPHIER_SD_SIZE 0x04c /* block size */ -#define UNIPHIER_SD_OPTION 0x050 -#define UNIPHIER_SD_OPTION_WIDTH_MASK (5 << 13) -#define UNIPHIER_SD_OPTION_WIDTH_1 (4 << 13) -#define UNIPHIER_SD_OPTION_WIDTH_4 (0 << 13) -#define UNIPHIER_SD_OPTION_WIDTH_8 (1 << 13) -#define UNIPHIER_SD_BUF 0x060 /* read/write buffer */ -#define UNIPHIER_SD_EXTMODE 0x1b0 -#define UNIPHIER_SD_EXTMODE_DMA_EN BIT(1) /* transfer 1: DMA, 0: pio */ -#define UNIPHIER_SD_SOFT_RST 0x1c0 -#define UNIPHIER_SD_SOFT_RST_RSTX BIT(0) /* reset deassert */ -#define UNIPHIER_SD_VERSION 0x1c4 /* version register */ -#define UNIPHIER_SD_VERSION_IP 0xff /* IP version */ -#define UNIPHIER_SD_HOST_MODE 0x1c8 -#define UNIPHIER_SD_IF_MODE 0x1cc -#define UNIPHIER_SD_IF_MODE_DDR BIT(0) /* DDR mode */ -#define UNIPHIER_SD_VOLT 0x1e4 /* voltage switch */ -#define UNIPHIER_SD_VOLT_MASK (3 << 0) -#define UNIPHIER_SD_VOLT_OFF (0 << 0) -#define UNIPHIER_SD_VOLT_330 (1 << 0)/* 3.3V signal */ -#define UNIPHIER_SD_VOLT_180 (2 << 0)/* 1.8V signal */ -#define UNIPHIER_SD_DMA_MODE 0x410 -#define UNIPHIER_SD_DMA_MODE_DIR_RD BIT(16) /* 1: from device, 0: to dev */ -#define UNIPHIER_SD_DMA_MODE_ADDR_INC BIT(0) /* 1: address inc, 0: fixed */ -#define UNIPHIER_SD_DMA_CTL 0x414 -#define UNIPHIER_SD_DMA_CTL_START BIT(0) /* start DMA (auto cleared) */ -#define UNIPHIER_SD_DMA_RST 0x418 -#define UNIPHIER_SD_DMA_RST_RD BIT(9) -#define UNIPHIER_SD_DMA_RST_WR BIT(8) -#define UNIPHIER_SD_DMA_INFO1 0x420 -#define UNIPHIER_SD_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete (uniphier) */ -#define UNIPHIER_SD_DMA_INFO1_END_RD BIT(17) /* DMA from device is complete (renesas) */ -#define UNIPHIER_SD_DMA_INFO1_END_WR BIT(16) /* DMA to device is complete */ -#define UNIPHIER_SD_DMA_INFO1_MASK 0x424 -#define UNIPHIER_SD_DMA_INFO2 0x428 -#define UNIPHIER_SD_DMA_INFO2_ERR_RD BIT(17) -#define UNIPHIER_SD_DMA_INFO2_ERR_WR BIT(16) -#define UNIPHIER_SD_DMA_INFO2_MASK 0x42c -#define UNIPHIER_SD_DMA_ADDR_L 0x440 -#define UNIPHIER_SD_DMA_ADDR_H 0x444 - -/* alignment required by the DMA engine of this controller */ -#define UNIPHIER_SD_DMA_MINALIGN 0x10 +DECLARE_GLOBAL_DATA_PTR;
struct uniphier_sd_plat { struct mmc_config cfg; struct mmc mmc; };
-struct uniphier_sd_priv { - void __iomem *regbase; - unsigned long mclk; - unsigned int version; - u32 caps; -#define UNIPHIER_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ -#define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ -#define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ -#define UNIPHIER_SD_CAP_64BIT BIT(3) /* Controller is 64bit */ -#define UNIPHIER_SD_CAP_RCAR_GEN2 BIT(4) /* Renesas RCar version of IP */ -#define UNIPHIER_SD_CAP_RCAR_GEN3 BIT(5) /* Renesas RCar version of IP */ -#define UNIPHIER_SD_CAP_RCAR_UHS BIT(6) /* Renesas RCar UHS/SDR modes */ -#define UNIPHIER_SD_CAP_RCAR \ - (UNIPHIER_SD_CAP_RCAR_GEN2 | UNIPHIER_SD_CAP_RCAR_GEN3) -#ifdef CONFIG_DM_REGULATOR - struct udevice *vqmmc_dev; +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) +static void uniphier_sd_reset_tuning(struct uniphier_sd_priv *priv) +{ +} + +static int uniphier_sd_execute_tuning(struct udevice *dev, uint opcode) +{ + return -EINVAL; +} +#else +static void uniphier_sd_reset_tuning(struct uniphier_sd_priv *priv) +{ + /* NOP if HS200 is disabled or the controller doesn't implement it. */ +} #endif -};
-static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) +u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) { if (priv->caps & UNIPHIER_SD_CAP_64BIT) return readq(priv->regbase + (reg << 1)); @@ -154,7 +51,7 @@ static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg) return readq(priv->regbase + reg); }
-static void uniphier_sd_writeq(struct uniphier_sd_priv *priv, +void uniphier_sd_writeq(struct uniphier_sd_priv *priv, u64 val, unsigned int reg) { if (priv->caps & UNIPHIER_SD_CAP_64BIT) @@ -163,7 +60,7 @@ static void uniphier_sd_writeq(struct uniphier_sd_priv *priv, writeq(val, priv->regbase + reg); }
-static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg) +u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg) { if (priv->caps & UNIPHIER_SD_CAP_64BIT) return readl(priv->regbase + (reg << 1)); @@ -171,7 +68,7 @@ static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg) return readl(priv->regbase + reg); }
-static void uniphier_sd_writel(struct uniphier_sd_priv *priv, +void uniphier_sd_writel(struct uniphier_sd_priv *priv, u32 val, unsigned int reg) { if (priv->caps & UNIPHIER_SD_CAP_64BIT) @@ -752,6 +649,8 @@ static int uniphier_sd_set_ios(struct udevice *dev) uniphier_sd_set_clk_rate(priv, mmc); uniphier_sd_set_pins(dev);
+ uniphier_sd_reset_tuning(priv); + return 0; }
@@ -770,6 +669,9 @@ static const struct dm_mmc_ops uniphier_sd_ops = { .send_cmd = uniphier_sd_send_cmd, .set_ios = uniphier_sd_set_ios, .get_cd = uniphier_sd_get_cd, +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) + .execute_tuning = uniphier_sd_execute_tuning, +#endif };
static void uniphier_sd_host_init(struct uniphier_sd_priv *priv) @@ -886,6 +788,8 @@ static int uniphier_sd_probe(struct udevice *dev)
upriv->mmc = &plat->mmc;
+ uniphier_sd_reset_tuning(priv); + return 0; }
diff --git a/drivers/mmc/uniphier-sd.h b/drivers/mmc/uniphier-sd.h new file mode 100644 index 0000000000..74ac2f72df --- /dev/null +++ b/drivers/mmc/uniphier-sd.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada yamada.masahiro@socionext.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __MMC_UNIPHIER_SD_H__ +#define __MMC_UNIPHIER_SD_H__ + +#define UNIPHIER_SD_CMD 0x000 /* command */ +#define UNIPHIER_SD_CMD_NOSTOP BIT(14) /* No automatic CMD12 issue */ +#define UNIPHIER_SD_CMD_MULTI BIT(13) /* multiple block transfer */ +#define UNIPHIER_SD_CMD_RD BIT(12) /* 1: read, 0: write */ +#define UNIPHIER_SD_CMD_DATA BIT(11) /* data transfer */ +#define UNIPHIER_SD_CMD_APP BIT(6) /* ACMD preceded by CMD55 */ +#define UNIPHIER_SD_CMD_NORMAL (0 << 8)/* auto-detect of resp-type */ +#define UNIPHIER_SD_CMD_RSP_NONE (3 << 8)/* response: none */ +#define UNIPHIER_SD_CMD_RSP_R1 (4 << 8)/* response: R1, R5, R6, R7 */ +#define UNIPHIER_SD_CMD_RSP_R1B (5 << 8)/* response: R1b, R5b */ +#define UNIPHIER_SD_CMD_RSP_R2 (6 << 8)/* response: R2 */ +#define UNIPHIER_SD_CMD_RSP_R3 (7 << 8)/* response: R3, R4 */ +#define UNIPHIER_SD_ARG 0x008 /* command argument */ +#define UNIPHIER_SD_STOP 0x010 /* stop action control */ +#define UNIPHIER_SD_STOP_SEC BIT(8) /* use sector count */ +#define UNIPHIER_SD_STOP_STP BIT(0) /* issue CMD12 */ +#define UNIPHIER_SD_SECCNT 0x014 /* sector counter */ +#define UNIPHIER_SD_RSP10 0x018 /* response[39:8] */ +#define UNIPHIER_SD_RSP32 0x020 /* response[71:40] */ +#define UNIPHIER_SD_RSP54 0x028 /* response[103:72] */ +#define UNIPHIER_SD_RSP76 0x030 /* response[127:104] */ +#define UNIPHIER_SD_INFO1 0x038 /* IRQ status 1 */ +#define UNIPHIER_SD_INFO1_CD BIT(5) /* state of card detect */ +#define UNIPHIER_SD_INFO1_INSERT BIT(4) /* card inserted */ +#define UNIPHIER_SD_INFO1_REMOVE BIT(3) /* card removed */ +#define UNIPHIER_SD_INFO1_CMP BIT(2) /* data complete */ +#define UNIPHIER_SD_INFO1_RSP BIT(0) /* response complete */ +#define UNIPHIER_SD_INFO2 0x03c /* IRQ status 2 */ +#define UNIPHIER_SD_INFO2_ERR_ILA BIT(15) /* illegal access err */ +#define UNIPHIER_SD_INFO2_CBSY BIT(14) /* command busy */ +#define UNIPHIER_SD_INFO2_BWE BIT(9) /* write buffer ready */ +#define UNIPHIER_SD_INFO2_BRE BIT(8) /* read buffer ready */ +#define UNIPHIER_SD_INFO2_DAT0 BIT(7) /* SDDAT0 */ +#define UNIPHIER_SD_INFO2_ERR_RTO BIT(6) /* response time out */ +#define UNIPHIER_SD_INFO2_ERR_ILR BIT(5) /* illegal read err */ +#define UNIPHIER_SD_INFO2_ERR_ILW BIT(4) /* illegal write err */ +#define UNIPHIER_SD_INFO2_ERR_TO BIT(3) /* time out error */ +#define UNIPHIER_SD_INFO2_ERR_END BIT(2) /* END bit error */ +#define UNIPHIER_SD_INFO2_ERR_CRC BIT(1) /* CRC error */ +#define UNIPHIER_SD_INFO2_ERR_IDX BIT(0) /* cmd index error */ +#define UNIPHIER_SD_INFO1_MASK 0x040 +#define UNIPHIER_SD_INFO2_MASK 0x044 +#define UNIPHIER_SD_CLKCTL 0x048 /* clock divisor */ +#define UNIPHIER_SD_CLKCTL_DIV_MASK 0x104ff +#define UNIPHIER_SD_CLKCTL_DIV1024 BIT(16) /* SDCLK = CLK / 1024 */ +#define UNIPHIER_SD_CLKCTL_DIV512 BIT(7) /* SDCLK = CLK / 512 */ +#define UNIPHIER_SD_CLKCTL_DIV256 BIT(6) /* SDCLK = CLK / 256 */ +#define UNIPHIER_SD_CLKCTL_DIV128 BIT(5) /* SDCLK = CLK / 128 */ +#define UNIPHIER_SD_CLKCTL_DIV64 BIT(4) /* SDCLK = CLK / 64 */ +#define UNIPHIER_SD_CLKCTL_DIV32 BIT(3) /* SDCLK = CLK / 32 */ +#define UNIPHIER_SD_CLKCTL_DIV16 BIT(2) /* SDCLK = CLK / 16 */ +#define UNIPHIER_SD_CLKCTL_DIV8 BIT(1) /* SDCLK = CLK / 8 */ +#define UNIPHIER_SD_CLKCTL_DIV4 BIT(0) /* SDCLK = CLK / 4 */ +#define UNIPHIER_SD_CLKCTL_DIV2 0 /* SDCLK = CLK / 2 */ +#define UNIPHIER_SD_CLKCTL_DIV1 BIT(10) /* SDCLK = CLK */ +#define UNIPHIER_SD_CLKCTL_RCAR_DIV1 0xff /* SDCLK = CLK (RCar ver.) */ +#define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) /* stop SDCLK when unused */ +#define UNIPHIER_SD_CLKCTL_SCLKEN BIT(8) /* SDCLK output enable */ +#define UNIPHIER_SD_SIZE 0x04c /* block size */ +#define UNIPHIER_SD_OPTION 0x050 +#define UNIPHIER_SD_OPTION_WIDTH_MASK (5 << 13) +#define UNIPHIER_SD_OPTION_WIDTH_1 (4 << 13) +#define UNIPHIER_SD_OPTION_WIDTH_4 (0 << 13) +#define UNIPHIER_SD_OPTION_WIDTH_8 (1 << 13) +#define UNIPHIER_SD_BUF 0x060 /* read/write buffer */ +#define UNIPHIER_SD_EXTMODE 0x1b0 +#define UNIPHIER_SD_EXTMODE_DMA_EN BIT(1) /* transfer 1: DMA, 0: pio */ +#define UNIPHIER_SD_SOFT_RST 0x1c0 +#define UNIPHIER_SD_SOFT_RST_RSTX BIT(0) /* reset deassert */ +#define UNIPHIER_SD_VERSION 0x1c4 /* version register */ +#define UNIPHIER_SD_VERSION_IP 0xff /* IP version */ +#define UNIPHIER_SD_HOST_MODE 0x1c8 +#define UNIPHIER_SD_IF_MODE 0x1cc +#define UNIPHIER_SD_IF_MODE_DDR BIT(0) /* DDR mode */ +#define UNIPHIER_SD_VOLT 0x1e4 /* voltage switch */ +#define UNIPHIER_SD_VOLT_MASK (3 << 0) +#define UNIPHIER_SD_VOLT_OFF (0 << 0) +#define UNIPHIER_SD_VOLT_330 (1 << 0)/* 3.3V signal */ +#define UNIPHIER_SD_VOLT_180 (2 << 0)/* 1.8V signal */ +#define UNIPHIER_SD_DMA_MODE 0x410 +#define UNIPHIER_SD_DMA_MODE_DIR_RD BIT(16) /* 1: from device, 0: to dev */ +#define UNIPHIER_SD_DMA_MODE_ADDR_INC BIT(0) /* 1: address inc, 0: fixed */ +#define UNIPHIER_SD_DMA_CTL 0x414 +#define UNIPHIER_SD_DMA_CTL_START BIT(0) /* start DMA (auto cleared) */ +#define UNIPHIER_SD_DMA_RST 0x418 +#define UNIPHIER_SD_DMA_RST_RD BIT(9) +#define UNIPHIER_SD_DMA_RST_WR BIT(8) +#define UNIPHIER_SD_DMA_INFO1 0x420 +#define UNIPHIER_SD_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete (uniphier) */ +#define UNIPHIER_SD_DMA_INFO1_END_RD BIT(17) /* DMA from device is complete (renesas) */ +#define UNIPHIER_SD_DMA_INFO1_END_WR BIT(16) /* DMA to device is complete */ +#define UNIPHIER_SD_DMA_INFO1_MASK 0x424 +#define UNIPHIER_SD_DMA_INFO2 0x428 +#define UNIPHIER_SD_DMA_INFO2_ERR_RD BIT(17) +#define UNIPHIER_SD_DMA_INFO2_ERR_WR BIT(16) +#define UNIPHIER_SD_DMA_INFO2_MASK 0x42c +#define UNIPHIER_SD_DMA_ADDR_L 0x440 +#define UNIPHIER_SD_DMA_ADDR_H 0x444 + +/* alignment required by the DMA engine of this controller */ +#define UNIPHIER_SD_DMA_MINALIGN 0x10 + +struct uniphier_sd_priv { + void __iomem *regbase; + unsigned long mclk; + unsigned int version; + u32 caps; +#define UNIPHIER_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ +#define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ +#define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ +#define UNIPHIER_SD_CAP_64BIT BIT(3) /* Controller is 64bit */ +#define UNIPHIER_SD_CAP_RCAR_GEN2 BIT(4) /* Renesas RCar version of IP */ +#define UNIPHIER_SD_CAP_RCAR_GEN3 BIT(5) /* Renesas RCar version of IP */ +#define UNIPHIER_SD_CAP_RCAR_UHS BIT(6) /* Renesas RCar UHS/SDR modes */ +#define UNIPHIER_SD_CAP_RCAR \ + (UNIPHIER_SD_CAP_RCAR_GEN2 | UNIPHIER_SD_CAP_RCAR_GEN3) +#ifdef CONFIG_DM_REGULATOR + struct udevice *vqmmc_dev; +#endif +}; + +/* IO accessors */ +u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, unsigned int reg); +void uniphier_sd_writeq(struct uniphier_sd_priv *priv, + u64 val, unsigned int reg); +u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg); +void uniphier_sd_writel(struct uniphier_sd_priv *priv, + u32 val, unsigned int reg); + +#endif /* __MMC_UNIPHIER_SD_H__ */

Add code for PHY tuning required for SDR104/HS200 support on Renesas RCar.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/Kconfig | 9 ++ drivers/mmc/Makefile | 1 + drivers/mmc/uniphier-sd-rcar.c | 288 +++++++++++++++++++++++++++++++++++++++++ drivers/mmc/uniphier-sd.c | 7 + drivers/mmc/uniphier-sd.h | 15 +++ 5 files changed, 320 insertions(+) create mode 100644 drivers/mmc/uniphier-sd-rcar.c
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index a1b21fd1bd..51b268bf3d 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -261,6 +261,15 @@ config MMC_UNIPHIER This selects support for the Matsushita SD/MMC Host Controller on SocioNext UniPhier and Renesas RCar SoCs.
+config MMC_RENESAS_TUNING + bool "RCar SDHI Host Controller SDR104/HS200 support" + depends on RCAR_GEN3 + depends on MMC_UNIPHIER + depends on MMC_HS200_SUPPORT + help + This selects support for the SDR104/HS200 tuning on + Renesas RCar Gen3 SoCs. + config MMC_BCM2835 bool "BCM2835 family custom SD/MMC Host Controller support" depends on ARCH_BCM283X diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 42113e2603..16cdd970c3 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -64,4 +64,5 @@ obj-$(CONFIG_MMC_SDHCI_ZYNQ) += zynq_sdhci.o
obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o +obj-$(CONFIG_MMC_RENESAS_TUNING) += uniphier-sd-rcar.o obj-$(CONFIG_MMC_BCM2835) += bcm2835_sdhost.o diff --git a/drivers/mmc/uniphier-sd-rcar.c b/drivers/mmc/uniphier-sd-rcar.c new file mode 100644 index 0000000000..8baa2a9b46 --- /dev/null +++ b/drivers/mmc/uniphier-sd-rcar.c @@ -0,0 +1,288 @@ +/* + * Renesas RCar Gen3 SDHI SDR104/HS200 tuning routine + * + * Copyright (C) 2018 Marek Vasut marek.vasut@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <linux/io.h> +#include <mmc.h> + +/* +#include <clk.h> +#include <fdtdec.h> +#include <dm/pinctrl.h> +#include <linux/compat.h> +#include <linux/dma-direction.h> +#include <power/regulator.h> +#include <asm/unaligned.h> +*/ +#include "uniphier-sd.h" + +/* SCC registers */ +#define SH_MOBILE_SDHI_SCC_DTCNTL 0x800 +#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN BIT(0) +#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT 16 +#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK 0xff +#define SH_MOBILE_SDHI_SCC_TAPSET 0x804 +#define SH_MOBILE_SDHI_SCC_DT2FF 0x808 +#define SH_MOBILE_SDHI_SCC_CKSEL 0x80c +#define SH_MOBILE_SDHI_SCC_CKSEL_DTSEL BIT(0) +#define SH_MOBILE_SDHI_SCC_RVSCNTL 0x810 +#define SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN BIT(0) +#define SH_MOBILE_SDHI_SCC_RVSREQ 0x814 +#define SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR BIT(2) +#define SH_MOBILE_SDHI_SCC_SMPCMP 0x818 +#define SH_MOBILE_SDHI_SCC_TMPPORT2 0x81c + +#define SH_MOBILE_SDHI_MAX_TAP 3 + +static unsigned int uniphier_sd_init_tuning(struct uniphier_sd_priv *priv) +{ + u32 reg; + + /* Initialize SCC */ + uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO1); + + reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL); + reg &= ~UNIPHIER_SD_CLKCTL_SCLKEN; + uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL); + + /* Set sampling clock selection range */ + uniphier_sd_writel(priv, 0x8 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT, + SH_MOBILE_SDHI_SCC_DTCNTL); + + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_DTCNTL); + reg |= SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_DTCNTL); + + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_CKSEL); + reg |= SH_MOBILE_SDHI_SCC_CKSEL_DTSEL; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_CKSEL); + + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL); + reg &= ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL); + + uniphier_sd_writel(priv, 0x300 /* scc_tappos */, + SH_MOBILE_SDHI_SCC_DT2FF); + + reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL); + reg |= UNIPHIER_SD_CLKCTL_SCLKEN; + uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL); + + /* Read TAPNUM */ + return (uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_DTCNTL) >> + SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) & + SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK; +} + +void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) +{ + u32 reg; + + /* Reset SCC */ + reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL); + reg &= ~UNIPHIER_SD_CLKCTL_SCLKEN; + uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL); + + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_CKSEL); + reg &= ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_CKSEL); + + reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL); + reg |= UNIPHIER_SD_CLKCTL_SCLKEN; + uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL); + + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL); + reg &= ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL); + + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL); + reg &= ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL); +} + +static void uniphier_sd_prepare_tuning(struct uniphier_sd_priv *priv, + unsigned long tap) +{ + /* Set sampling clock position */ + uniphier_sd_writel(priv, tap, SH_MOBILE_SDHI_SCC_TAPSET); +} + +static unsigned int sh_mobile_sdhi_compare_scc_data(struct uniphier_sd_priv *priv) +{ + /* Get comparison of sampling data */ + return uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_SMPCMP); +} + +static int uniphier_sd_select_tuning(struct uniphier_sd_priv *priv, + unsigned int tap_num, unsigned int taps, + unsigned int smpcmp) +{ + unsigned long tap_cnt; /* counter of tuning success */ + unsigned long tap_set; /* tap position */ + unsigned long tap_start;/* start position of tuning success */ + unsigned long tap_end; /* end position of tuning success */ + unsigned long ntap; /* temporary counter of tuning success */ + unsigned long match_cnt;/* counter of matching data */ + unsigned long i; + bool select = false; + u32 reg; + + /* Clear SCC_RVSREQ */ + uniphier_sd_writel(priv, 0, SH_MOBILE_SDHI_SCC_RVSREQ); + + /* Merge the results */ + for (i = 0; i < tap_num * 2; i++) { + if (!(taps & BIT(i))) { + taps &= ~BIT(i % tap_num); + taps &= ~BIT((i % tap_num) + tap_num); + } + if (!(smpcmp & BIT(i))) { + smpcmp &= ~BIT(i % tap_num); + smpcmp &= ~BIT((i % tap_num) + tap_num); + } + } + + /* + * Find the longest consecutive run of successful probes. If that + * is more than SH_MOBILE_SDHI_MAX_TAP probes long then use the + * center index as the tap. + */ + tap_cnt = 0; + ntap = 0; + tap_start = 0; + tap_end = 0; + for (i = 0; i < tap_num * 2; i++) { + if (taps & BIT(i)) + ntap++; + else { + if (ntap > tap_cnt) { + tap_start = i - ntap; + tap_end = i - 1; + tap_cnt = ntap; + } + ntap = 0; + } + } + + if (ntap > tap_cnt) { + tap_start = i - ntap; + tap_end = i - 1; + tap_cnt = ntap; + } + + /* + * If all of the TAP is OK, the sampling clock position is selected by + * identifying the change point of data. + */ + if (tap_cnt == tap_num * 2) { + match_cnt = 0; + ntap = 0; + tap_start = 0; + tap_end = 0; + for (i = 0; i < tap_num * 2; i++) { + if (smpcmp & BIT(i)) + ntap++; + else { + if (ntap > match_cnt) { + tap_start = i - ntap; + tap_end = i - 1; + match_cnt = ntap; + } + ntap = 0; + } + } + if (ntap > match_cnt) { + tap_start = i - ntap; + tap_end = i - 1; + match_cnt = ntap; + } + if (match_cnt) + select = true; + } else if (tap_cnt >= SH_MOBILE_SDHI_MAX_TAP) + select = true; + + if (select) + tap_set = ((tap_start + tap_end) / 2) % tap_num; + else + return -EIO; + + /* Set SCC */ + uniphier_sd_writel(priv, tap_set, SH_MOBILE_SDHI_SCC_TAPSET); + + /* Enable auto re-tuning */ + reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL); + reg |= SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN; + uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL); + + return 0; +} + +int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) +{ + struct uniphier_sd_priv *priv = dev_get_priv(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct mmc *mmc = upriv->mmc; + unsigned int tap_num; + unsigned int taps = 0, smpcmp = 0; + int i, ret = 0; + u32 caps; + + /* Only supported on Renesas RCar */ + if (!(priv->caps & UNIPHIER_SD_CAP_RCAR_UHS)) + return -EINVAL; + + /* clock tuning is not needed for upto 52MHz */ + if (!((mmc->selected_mode == MMC_HS_200) || + (mmc->selected_mode == UHS_SDR104) || + (mmc->selected_mode == UHS_SDR50))) + return 0; + + tap_num = uniphier_sd_init_tuning(priv); + if (!tap_num) + /* Tuning is not supported */ + goto out; + + if (tap_num * 2 >= sizeof(taps) * 8) { + dev_err(dev, + "Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n"); + goto out; + } + + /* Issue CMD19 twice for each tap */ + for (i = 0; i < 2 * tap_num; i++) { + uniphier_sd_prepare_tuning(priv, i % tap_num); + + /* Force PIO for the tuning */ + caps = priv->caps; + priv->caps &= ~UNIPHIER_SD_CAP_DMA_INTERNAL; + + ret = mmc_send_tuning(mmc, opcode, NULL); + + priv->caps = caps; + + if (ret == 0) + taps |= BIT(i); + + ret = sh_mobile_sdhi_compare_scc_data(priv); + if (ret == 0) + smpcmp |= BIT(i); + + mdelay(1); + } + + ret = uniphier_sd_select_tuning(priv, tap_num, taps, smpcmp); + +out: + if (ret < 0) { + dev_warn(dev, "Tuning procedure failed\n"); + rcar_gen3_sd_reset_tuning(priv); + } + + return ret; +} diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index ec4fb16973..d05cec5cdb 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -30,10 +30,17 @@ struct uniphier_sd_plat { #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) static void uniphier_sd_reset_tuning(struct uniphier_sd_priv *priv) { + if (priv->caps & UNIPHIER_SD_CAP_RCAR_UHS) + rcar_gen3_sd_reset_tuning(priv); }
static int uniphier_sd_execute_tuning(struct udevice *dev, uint opcode) { + struct uniphier_sd_priv *priv = dev_get_priv(dev); + + if (priv->caps & UNIPHIER_SD_CAP_RCAR_UHS) + return rcar_gen3_sd_execute_tuning(dev, opcode); + return -EINVAL; } #else diff --git a/drivers/mmc/uniphier-sd.h b/drivers/mmc/uniphier-sd.h index 74ac2f72df..38d104296f 100644 --- a/drivers/mmc/uniphier-sd.h +++ b/drivers/mmc/uniphier-sd.h @@ -137,4 +137,19 @@ u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg); void uniphier_sd_writel(struct uniphier_sd_priv *priv, u32 val, unsigned int reg);
+/* Renesas RCar Gen3 tuning procedures */ +#if CONFIG_IS_ENABLED(MMC_RENESAS_TUNING) +void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv); +int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode); +#else +static void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) +{ +} + +static int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) +{ + return -EINVAL; +} +#endif + #endif /* __MMC_UNIPHIER_SD_H__ */

Jaehoon,
2018-02-01 0:21 GMT+09:00 Marek Vasut marek.vasut@gmail.com:
Add code for PHY tuning required for SDR104/HS200 support on Renesas RCar.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Please apply whole of the series.
This patch introduces warnings for configs/uniphier_v7_defconfig, but it is trivial to fix it up.
(Please replace 'static' with 'static inline')
CC spl/drivers/core/ofnode.o CC spl/drivers/core/read_extra.o LD spl/drivers/core/built-in.o CC spl/drivers/mmc/mmc.o CC spl/drivers/mmc/mmc-uclass.o CC spl/drivers/mmc/mmc_boot.o CC spl/drivers/mmc/uniphier-sd.o In file included from drivers/mmc/uniphier-sd.c:21:0: drivers/mmc/uniphier-sd.h:149:12: warning: ‘rcar_gen3_sd_execute_tuning’ defined but not used [-Wunused-function] static int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) ^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/uniphier-sd.h:145:13: warning: ‘rcar_gen3_sd_reset_tuning’ defined but not used [-Wunused-function] static void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) ^~~~~~~~~~~~~~~~~~~~~~~~~ LD spl/drivers/mmc/built-in.o CC spl/drivers/mtd/nand/denali_spl.o LD spl/drivers/mtd/nand/built-in.o CC spl/drivers/pinctrl/pinctrl-uclass.o CC spl/drivers/pinctrl/pinctrl-generic.o
drivers/mmc/Kconfig | 9 ++ drivers/mmc/Makefile | 1 + drivers/mmc/uniphier-sd-rcar.c | 288 +++++++++++++++++++++++++++++++++++++++++ drivers/mmc/uniphier-sd.c | 7 + drivers/mmc/uniphier-sd.h | 15 +++ 5 files changed, 320 insertions(+) create mode 100644 drivers/mmc/uniphier-sd-rcar.c
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index a1b21fd1bd..51b268bf3d 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -261,6 +261,15 @@ config MMC_UNIPHIER This selects support for the Matsushita SD/MMC Host Controller on SocioNext UniPhier and Renesas RCar SoCs.
+config MMC_RENESAS_TUNING
bool "RCar SDHI Host Controller SDR104/HS200 support"
depends on RCAR_GEN3
depends on MMC_UNIPHIER
depends on MMC_HS200_SUPPORT
help
This selects support for the SDR104/HS200 tuning on
Renesas RCar Gen3 SoCs.
config MMC_BCM2835 bool "BCM2835 family custom SD/MMC Host Controller support" depends on ARCH_BCM283X diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 42113e2603..16cdd970c3 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -64,4 +64,5 @@ obj-$(CONFIG_MMC_SDHCI_ZYNQ) += zynq_sdhci.o
obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o +obj-$(CONFIG_MMC_RENESAS_TUNING) += uniphier-sd-rcar.o obj-$(CONFIG_MMC_BCM2835) += bcm2835_sdhost.o diff --git a/drivers/mmc/uniphier-sd-rcar.c b/drivers/mmc/uniphier-sd-rcar.c new file mode 100644 index 0000000000..8baa2a9b46 --- /dev/null +++ b/drivers/mmc/uniphier-sd-rcar.c @@ -0,0 +1,288 @@ +/*
- Renesas RCar Gen3 SDHI SDR104/HS200 tuning routine
- Copyright (C) 2018 Marek Vasut marek.vasut@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <dm.h> +#include <linux/io.h> +#include <mmc.h>
+/* +#include <clk.h> +#include <fdtdec.h> +#include <dm/pinctrl.h> +#include <linux/compat.h> +#include <linux/dma-direction.h> +#include <power/regulator.h> +#include <asm/unaligned.h> +*/ +#include "uniphier-sd.h"
+/* SCC registers */ +#define SH_MOBILE_SDHI_SCC_DTCNTL 0x800 +#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN BIT(0) +#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT 16 +#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK 0xff +#define SH_MOBILE_SDHI_SCC_TAPSET 0x804 +#define SH_MOBILE_SDHI_SCC_DT2FF 0x808 +#define SH_MOBILE_SDHI_SCC_CKSEL 0x80c +#define SH_MOBILE_SDHI_SCC_CKSEL_DTSEL BIT(0) +#define SH_MOBILE_SDHI_SCC_RVSCNTL 0x810 +#define SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN BIT(0) +#define SH_MOBILE_SDHI_SCC_RVSREQ 0x814 +#define SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR BIT(2) +#define SH_MOBILE_SDHI_SCC_SMPCMP 0x818 +#define SH_MOBILE_SDHI_SCC_TMPPORT2 0x81c
+#define SH_MOBILE_SDHI_MAX_TAP 3
+static unsigned int uniphier_sd_init_tuning(struct uniphier_sd_priv *priv) +{
u32 reg;
/* Initialize SCC */
uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO1);
reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL);
reg &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL);
/* Set sampling clock selection range */
uniphier_sd_writel(priv, 0x8 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT,
SH_MOBILE_SDHI_SCC_DTCNTL);
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_DTCNTL);
reg |= SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_DTCNTL);
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_CKSEL);
reg |= SH_MOBILE_SDHI_SCC_CKSEL_DTSEL;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_CKSEL);
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL);
reg &= ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL);
uniphier_sd_writel(priv, 0x300 /* scc_tappos */,
SH_MOBILE_SDHI_SCC_DT2FF);
reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL);
reg |= UNIPHIER_SD_CLKCTL_SCLKEN;
uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL);
/* Read TAPNUM */
return (uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_DTCNTL) >>
SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) &
SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK;
+}
+void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) +{
u32 reg;
/* Reset SCC */
reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL);
reg &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL);
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_CKSEL);
reg &= ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_CKSEL);
reg = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL);
reg |= UNIPHIER_SD_CLKCTL_SCLKEN;
uniphier_sd_writel(priv, reg, UNIPHIER_SD_CLKCTL);
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL);
reg &= ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL);
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL);
reg &= ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL);
+}
+static void uniphier_sd_prepare_tuning(struct uniphier_sd_priv *priv,
unsigned long tap)
+{
/* Set sampling clock position */
uniphier_sd_writel(priv, tap, SH_MOBILE_SDHI_SCC_TAPSET);
+}
+static unsigned int sh_mobile_sdhi_compare_scc_data(struct uniphier_sd_priv *priv) +{
/* Get comparison of sampling data */
return uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_SMPCMP);
+}
+static int uniphier_sd_select_tuning(struct uniphier_sd_priv *priv,
unsigned int tap_num, unsigned int taps,
unsigned int smpcmp)
+{
unsigned long tap_cnt; /* counter of tuning success */
unsigned long tap_set; /* tap position */
unsigned long tap_start;/* start position of tuning success */
unsigned long tap_end; /* end position of tuning success */
unsigned long ntap; /* temporary counter of tuning success */
unsigned long match_cnt;/* counter of matching data */
unsigned long i;
bool select = false;
u32 reg;
/* Clear SCC_RVSREQ */
uniphier_sd_writel(priv, 0, SH_MOBILE_SDHI_SCC_RVSREQ);
/* Merge the results */
for (i = 0; i < tap_num * 2; i++) {
if (!(taps & BIT(i))) {
taps &= ~BIT(i % tap_num);
taps &= ~BIT((i % tap_num) + tap_num);
}
if (!(smpcmp & BIT(i))) {
smpcmp &= ~BIT(i % tap_num);
smpcmp &= ~BIT((i % tap_num) + tap_num);
}
}
/*
* Find the longest consecutive run of successful probes. If that
* is more than SH_MOBILE_SDHI_MAX_TAP probes long then use the
* center index as the tap.
*/
tap_cnt = 0;
ntap = 0;
tap_start = 0;
tap_end = 0;
for (i = 0; i < tap_num * 2; i++) {
if (taps & BIT(i))
ntap++;
else {
if (ntap > tap_cnt) {
tap_start = i - ntap;
tap_end = i - 1;
tap_cnt = ntap;
}
ntap = 0;
}
}
if (ntap > tap_cnt) {
tap_start = i - ntap;
tap_end = i - 1;
tap_cnt = ntap;
}
/*
* If all of the TAP is OK, the sampling clock position is selected by
* identifying the change point of data.
*/
if (tap_cnt == tap_num * 2) {
match_cnt = 0;
ntap = 0;
tap_start = 0;
tap_end = 0;
for (i = 0; i < tap_num * 2; i++) {
if (smpcmp & BIT(i))
ntap++;
else {
if (ntap > match_cnt) {
tap_start = i - ntap;
tap_end = i - 1;
match_cnt = ntap;
}
ntap = 0;
}
}
if (ntap > match_cnt) {
tap_start = i - ntap;
tap_end = i - 1;
match_cnt = ntap;
}
if (match_cnt)
select = true;
} else if (tap_cnt >= SH_MOBILE_SDHI_MAX_TAP)
select = true;
if (select)
tap_set = ((tap_start + tap_end) / 2) % tap_num;
else
return -EIO;
/* Set SCC */
uniphier_sd_writel(priv, tap_set, SH_MOBILE_SDHI_SCC_TAPSET);
/* Enable auto re-tuning */
reg = uniphier_sd_readl(priv, SH_MOBILE_SDHI_SCC_RVSCNTL);
reg |= SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN;
uniphier_sd_writel(priv, reg, SH_MOBILE_SDHI_SCC_RVSCNTL);
return 0;
+}
+int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) +{
struct uniphier_sd_priv *priv = dev_get_priv(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct mmc *mmc = upriv->mmc;
unsigned int tap_num;
unsigned int taps = 0, smpcmp = 0;
int i, ret = 0;
u32 caps;
/* Only supported on Renesas RCar */
if (!(priv->caps & UNIPHIER_SD_CAP_RCAR_UHS))
return -EINVAL;
/* clock tuning is not needed for upto 52MHz */
if (!((mmc->selected_mode == MMC_HS_200) ||
(mmc->selected_mode == UHS_SDR104) ||
(mmc->selected_mode == UHS_SDR50)))
return 0;
tap_num = uniphier_sd_init_tuning(priv);
if (!tap_num)
/* Tuning is not supported */
goto out;
if (tap_num * 2 >= sizeof(taps) * 8) {
dev_err(dev,
"Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n");
goto out;
}
/* Issue CMD19 twice for each tap */
for (i = 0; i < 2 * tap_num; i++) {
uniphier_sd_prepare_tuning(priv, i % tap_num);
/* Force PIO for the tuning */
caps = priv->caps;
priv->caps &= ~UNIPHIER_SD_CAP_DMA_INTERNAL;
ret = mmc_send_tuning(mmc, opcode, NULL);
priv->caps = caps;
if (ret == 0)
taps |= BIT(i);
ret = sh_mobile_sdhi_compare_scc_data(priv);
if (ret == 0)
smpcmp |= BIT(i);
mdelay(1);
}
ret = uniphier_sd_select_tuning(priv, tap_num, taps, smpcmp);
+out:
if (ret < 0) {
dev_warn(dev, "Tuning procedure failed\n");
rcar_gen3_sd_reset_tuning(priv);
}
return ret;
+} diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index ec4fb16973..d05cec5cdb 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -30,10 +30,17 @@ struct uniphier_sd_plat { #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) static void uniphier_sd_reset_tuning(struct uniphier_sd_priv *priv) {
if (priv->caps & UNIPHIER_SD_CAP_RCAR_UHS)
rcar_gen3_sd_reset_tuning(priv);
}
static int uniphier_sd_execute_tuning(struct udevice *dev, uint opcode) {
struct uniphier_sd_priv *priv = dev_get_priv(dev);
if (priv->caps & UNIPHIER_SD_CAP_RCAR_UHS)
return rcar_gen3_sd_execute_tuning(dev, opcode);
return -EINVAL;
} #else diff --git a/drivers/mmc/uniphier-sd.h b/drivers/mmc/uniphier-sd.h index 74ac2f72df..38d104296f 100644 --- a/drivers/mmc/uniphier-sd.h +++ b/drivers/mmc/uniphier-sd.h @@ -137,4 +137,19 @@ u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, unsigned int reg); void uniphier_sd_writel(struct uniphier_sd_priv *priv, u32 val, unsigned int reg);
+/* Renesas RCar Gen3 tuning procedures */ +#if CONFIG_IS_ENABLED(MMC_RENESAS_TUNING) +void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv); +int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode); +#else +static void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) +{ +}
+static int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) +{
return -EINVAL;
+} +#endif
#endif /* __MMC_UNIPHIER_SD_H__ */
2.15.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

On 02/09/2018 06:28 PM, Masahiro Yamada wrote:
Jaehoon,
2018-02-01 0:21 GMT+09:00 Marek Vasut marek.vasut@gmail.com:
Add code for PHY tuning required for SDR104/HS200 support on Renesas RCar.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Please apply whole of the series.
This patch introduces warnings for configs/uniphier_v7_defconfig, but it is trivial to fix it up.
(Please replace 'static' with 'static inline')
CC spl/drivers/core/ofnode.o CC spl/drivers/core/read_extra.o LD spl/drivers/core/built-in.o CC spl/drivers/mmc/mmc.o CC spl/drivers/mmc/mmc-uclass.o CC spl/drivers/mmc/mmc_boot.o CC spl/drivers/mmc/uniphier-sd.o In file included from drivers/mmc/uniphier-sd.c:21:0: drivers/mmc/uniphier-sd.h:149:12: warning: ‘rcar_gen3_sd_execute_tuning’ defined but not used [-Wunused-function] static int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) ^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/uniphier-sd.h:145:13: warning: ‘rcar_gen3_sd_reset_tuning’ defined but not used [-Wunused-function] static void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) ^~~~~~~~~~~~~~~~~~~~~~~~~ LD spl/drivers/mmc/built-in.o CC spl/drivers/mtd/nand/denali_spl.o LD spl/drivers/mtd/nand/built-in.o CC spl/drivers/pinctrl/pinctrl-uclass.o CC spl/drivers/pinctrl/pinctrl-generic.o
[...] Jaehoon, any news here ?

Hi Marek,
On 02/14/2018 07:05 AM, Marek Vasut wrote:
On 02/09/2018 06:28 PM, Masahiro Yamada wrote:
Jaehoon,
2018-02-01 0:21 GMT+09:00 Marek Vasut marek.vasut@gmail.com:
Add code for PHY tuning required for SDR104/HS200 support on Renesas RCar.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Please apply whole of the series.
This patch introduces warnings for configs/uniphier_v7_defconfig, but it is trivial to fix it up.
(Please replace 'static' with 'static inline')
CC spl/drivers/core/ofnode.o CC spl/drivers/core/read_extra.o LD spl/drivers/core/built-in.o CC spl/drivers/mmc/mmc.o CC spl/drivers/mmc/mmc-uclass.o CC spl/drivers/mmc/mmc_boot.o CC spl/drivers/mmc/uniphier-sd.o In file included from drivers/mmc/uniphier-sd.c:21:0: drivers/mmc/uniphier-sd.h:149:12: warning: ‘rcar_gen3_sd_execute_tuning’ defined but not used [-Wunused-function] static int rcar_gen3_sd_execute_tuning(struct udevice *dev, uint opcode) ^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/uniphier-sd.h:145:13: warning: ‘rcar_gen3_sd_reset_tuning’ defined but not used [-Wunused-function] static void rcar_gen3_sd_reset_tuning(struct uniphier_sd_priv *priv) ^~~~~~~~~~~~~~~~~~~~~~~~~ LD spl/drivers/mmc/built-in.o CC spl/drivers/mtd/nand/denali_spl.o LD spl/drivers/mtd/nand/built-in.o CC spl/drivers/pinctrl/pinctrl-uclass.o CC spl/drivers/pinctrl/pinctrl-generic.o
[...] Jaehoon, any news here ?
Thanks for reminding ping. Today, i will do to check other patches, also this.
Best Regards, Jaehoon Chung

On 02/01/2018 12:21 AM, Marek Vasut wrote:
Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Applied to u-boot-mmc. Thanks! Sorry for late. I have checked the previous version..
Best Regards, Jaehoon Chung
drivers/mmc/uniphier-sd.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 741f9dfd9c..a080674c8a 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -847,6 +847,11 @@ static int uniphier_sd_probe(struct udevice *dev) }
static const struct udevice_id uniphier_sd_match[] = {
- { .compatible = "renesas,sdhi-r8a7790", .data = 0 },
- { .compatible = "renesas,sdhi-r8a7791", .data = 0 },
- { .compatible = "renesas,sdhi-r8a7792", .data = 0 },
- { .compatible = "renesas,sdhi-r8a7793", .data = 0 },
- { .compatible = "renesas,sdhi-r8a7794", .data = 0 }, { .compatible = "renesas,sdhi-r8a7795", .data = UNIPHIER_SD_CAP_64BIT }, { .compatible = "renesas,sdhi-r8a7796", .data = UNIPHIER_SD_CAP_64BIT }, { .compatible = "renesas,sdhi-r8a77970", .data = UNIPHIER_SD_CAP_64BIT },

On 02/19/2018 12:23 PM, Jaehoon Chung wrote:
On 02/01/2018 12:21 AM, Marek Vasut wrote:
Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Applied to u-boot-mmc. Thanks! Sorry for late. I have checked the previous version..
Yes, this is so late that it has to be scheduled for 2018.05 cycle. Another cycle missed, sigh.

On 02/20/2018 02:02 AM, Marek Vasut wrote:
On 02/19/2018 12:23 PM, Jaehoon Chung wrote:
On 02/01/2018 12:21 AM, Marek Vasut wrote:
Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Applied to u-boot-mmc. Thanks! Sorry for late. I have checked the previous version..
Yes, this is so late that it has to be scheduled for 2018.05 cycle. Another cycle missed, sigh.
I will revert your patch on master. instead i will apply this patch on next branch. Is it ok?
Best Regards, Jaehoon Chung

On 02/20/2018 01:54 AM, Jaehoon Chung wrote:
On 02/20/2018 02:02 AM, Marek Vasut wrote:
On 02/19/2018 12:23 PM, Jaehoon Chung wrote:
On 02/01/2018 12:21 AM, Marek Vasut wrote:
Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Applied to u-boot-mmc. Thanks! Sorry for late. I have checked the previous version..
Yes, this is so late that it has to be scheduled for 2018.05 cycle. Another cycle missed, sigh.
I will revert your patch on master. instead i will apply this patch on next branch. Is it ok?
Why would you revert it ? Just drop it from the PR and resend the PR.
And then apply it for -next branch, yes.

On 02/20/2018 01:31 PM, Marek Vasut wrote:
On 02/20/2018 01:54 AM, Jaehoon Chung wrote:
On 02/20/2018 02:02 AM, Marek Vasut wrote:
On 02/19/2018 12:23 PM, Jaehoon Chung wrote:
On 02/01/2018 12:21 AM, Marek Vasut wrote:
Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Applied to u-boot-mmc. Thanks! Sorry for late. I have checked the previous version..
Yes, this is so late that it has to be scheduled for 2018.05 cycle. Another cycle missed, sigh.
I will revert your patch on master. instead i will apply this patch on next branch. Is it ok?
Why would you revert it ? Just drop it from the PR and resend the PR.
And then apply it for -next branch, yes.
Which presumably never happened, since those patches are not in -rc1 ?

On 04/08/2018 06:41 PM, Marek Vasut wrote:
On 02/20/2018 01:31 PM, Marek Vasut wrote:
On 02/20/2018 01:54 AM, Jaehoon Chung wrote:
On 02/20/2018 02:02 AM, Marek Vasut wrote:
On 02/19/2018 12:23 PM, Jaehoon Chung wrote:
On 02/01/2018 12:21 AM, Marek Vasut wrote:
Add DT compatible strings for RCar Gen2 SoCs, so that this driver can bind with them. Unlike Gen3, which uses 64bit FIFO, the Gen2 uses 16bit FIFO.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Applied to u-boot-mmc. Thanks! Sorry for late. I have checked the previous version..
Yes, this is so late that it has to be scheduled for 2018.05 cycle. Another cycle missed, sigh.
I will revert your patch on master. instead i will apply this patch on next branch. Is it ok?
Why would you revert it ? Just drop it from the PR and resend the PR.
And then apply it for -next branch, yes.
Which presumably never happened, since those patches are not in -rc1 ?
I will update the patchset and resubmit it, sigh ...
participants (3)
-
Jaehoon Chung
-
Marek Vasut
-
Masahiro Yamada