From c49d0ac38a76c39f9556638bc9128b0969cb1536 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2019 03:20:31 +0100 Subject: [PATCH 1/6] ARM: dts: rmobile: Increase off-on delay on the SD Vcc regulator An ADATA 16GB Industrial MLC card has so much capacitance on the Vcc pin that the usual toggling of regulator to power the card off and on is insufficient. When the card is calibrated into UHS SDR104 mode, it will remain in that mode across the power cycle and subsequent attempt to communicate with the card will fail. The test with this card is to insert it into an SDHI slot and perform "mmc dev 0 ; mmc dev 0", where the second "mmc dev 0" will fail. Fix this problem by increasing the off-on delay from 0 to 20 mS. Signed-off-by: Marek Vasut Cc: Nobuhiro Iwamatsu --- arch/arm/dts/r8a7795-h3ulcb-u-boot.dts | 4 ++++ arch/arm/dts/r8a7795-salvator-x-u-boot.dts | 8 ++++++++ arch/arm/dts/r8a7796-m3ulcb-u-boot.dts | 4 ++++ arch/arm/dts/r8a7796-salvator-x-u-boot.dts | 8 ++++++++ arch/arm/dts/r8a77965-salvator-x-u-boot.dts | 8 ++++++++ arch/arm/dts/r8a77990-ebisu-u-boot.dts | 2 ++ 6 files changed, 34 insertions(+) diff --git a/arch/arm/dts/r8a7795-h3ulcb-u-boot.dts b/arch/arm/dts/r8a7795-h3ulcb-u-boot.dts index ebbd234d78..3de640724d 100644 --- a/arch/arm/dts/r8a7795-h3ulcb-u-boot.dts +++ b/arch/arm/dts/r8a7795-h3ulcb-u-boot.dts @@ -19,6 +19,10 @@ }; }; +&vcc_sdhi0 { + u-boot,off-on-delay-us = <20000>; +}; + &sdhi2_pins { groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; power-source = <1800>; diff --git a/arch/arm/dts/r8a7795-salvator-x-u-boot.dts b/arch/arm/dts/r8a7795-salvator-x-u-boot.dts index 8be5e41a51..a22028bb31 100644 --- a/arch/arm/dts/r8a7795-salvator-x-u-boot.dts +++ b/arch/arm/dts/r8a7795-salvator-x-u-boot.dts @@ -8,6 +8,14 @@ #include "r8a7795-salvator-x.dts" #include "r8a7795-u-boot.dtsi" +&vcc_sdhi0 { + u-boot,off-on-delay-us = <20000>; +}; + +&vcc_sdhi3 { + u-boot,off-on-delay-us = <20000>; +}; + &sdhi2_pins { groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; power-source = <1800>; diff --git a/arch/arm/dts/r8a7796-m3ulcb-u-boot.dts b/arch/arm/dts/r8a7796-m3ulcb-u-boot.dts index 4e960081f9..612cc87c71 100644 --- a/arch/arm/dts/r8a7796-m3ulcb-u-boot.dts +++ b/arch/arm/dts/r8a7796-m3ulcb-u-boot.dts @@ -19,6 +19,10 @@ }; }; +&vcc_sdhi0 { + u-boot,off-on-delay-us = <20000>; +}; + &sdhi2_pins { groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; power-source = <1800>; diff --git a/arch/arm/dts/r8a7796-salvator-x-u-boot.dts b/arch/arm/dts/r8a7796-salvator-x-u-boot.dts index 44b2f9fb37..c730b90a42 100644 --- a/arch/arm/dts/r8a7796-salvator-x-u-boot.dts +++ b/arch/arm/dts/r8a7796-salvator-x-u-boot.dts @@ -8,6 +8,14 @@ #include "r8a7796-salvator-x.dts" #include "r8a7796-u-boot.dtsi" +&vcc_sdhi0 { + u-boot,off-on-delay-us = <20000>; +}; + +&vcc_sdhi3 { + u-boot,off-on-delay-us = <20000>; +}; + &sdhi2_pins { groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; power-source = <1800>; diff --git a/arch/arm/dts/r8a77965-salvator-x-u-boot.dts b/arch/arm/dts/r8a77965-salvator-x-u-boot.dts index 9e0cd26f40..cfc0f74081 100644 --- a/arch/arm/dts/r8a77965-salvator-x-u-boot.dts +++ b/arch/arm/dts/r8a77965-salvator-x-u-boot.dts @@ -8,6 +8,14 @@ #include "r8a77965-salvator-x.dts" #include "r8a77965-u-boot.dtsi" +&vcc_sdhi0 { + u-boot,off-on-delay-us = <20000>; +}; + +&vcc_sdhi3 { + u-boot,off-on-delay-us = <20000>; +}; + &sdhi2_pins { groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; power-source = <1800>; diff --git a/arch/arm/dts/r8a77990-ebisu-u-boot.dts b/arch/arm/dts/r8a77990-ebisu-u-boot.dts index b030d5c649..4c1669e022 100644 --- a/arch/arm/dts/r8a77990-ebisu-u-boot.dts +++ b/arch/arm/dts/r8a77990-ebisu-u-boot.dts @@ -36,6 +36,7 @@ gpio = <&gpio5 17 GPIO_ACTIVE_HIGH>; enable-active-high; + u-boot,off-on-delay-us = <20000>; }; vccq_sdhi0: regulator-vccq-sdhi0 { @@ -60,6 +61,7 @@ gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>; enable-active-high; + u-boot,off-on-delay-us = <20000>; }; vccq_sdhi1: regulator-vccq-sdhi1 { From 45b01b462feedaecb28c3407a438a245c73fe6d0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2019 05:11:42 +0100 Subject: [PATCH 2/6] clk: renesas: Fix SDH clock divider decoding on Gen2 The gen2_clk_get_sdh_div() function is supposed to look up the $val value read out of the SDCKCR register in the supplied table and return the matching divider value. The current implementation was matching the value from SDCKCR on the divider value in the table, which is wrong. Fix this and rework the function a bit to make it more readable. Signed-off-by: Marek Vasut Cc: Nobuhiro Iwamatsu --- drivers/clk/renesas/clk-rcar-gen2.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 6dfd02f2eb..aedaab723b 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -44,13 +44,17 @@ static const struct clk_div_table cpg_sd01_div_table[] = { { 0, 0 }, }; -static u8 gen2_clk_get_sdh_div(const struct clk_div_table *table, u8 div) +static u8 gen2_clk_get_sdh_div(const struct clk_div_table *table, u8 val) { - while ((*table++).val) { - if ((*table).div == div) - return div; + for (;;) { + if (!(*table).div) + return 0xff; + + if ((*table).val == val) + return (*table).div; + + table++; } - return 0xff; } static int gen2_clk_enable(struct clk *clk) From 4b135d54649eb79d5dfcd20feee82f6675c502c3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2019 05:38:08 +0100 Subject: [PATCH 3/6] clk: renesas: Fix swapped div and mul in debug output on Gen2 The $div and $mul values were swapped in the debug output, fix this. Signed-off-by: Marek Vasut Cc: Nobuhiro Iwamatsu --- drivers/clk/renesas/clk-rcar-gen2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index aedaab723b..34abe784fd 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -121,7 +121,7 @@ static ulong gen2_clk_get_rate(struct clk *clk) case CLK_TYPE_FF: rate = (gen2_clk_get_rate(&parent) * core->mult) / core->div; - debug("%s[%i] FIXED clk: parent=%i div=%i mul=%i => rate=%u\n", + debug("%s[%i] FIXED clk: parent=%i mul=%i div=%i => rate=%u\n", __func__, __LINE__, core->parent, core->mult, core->div, rate); return rate; From 3cb2849c76ddb7b4da6a164b8513e1309715d765 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2019 06:04:02 +0100 Subject: [PATCH 4/6] clk: renesas: Add support for setting MMCIF clock divider on Gen2 Add code for configuring the MMC0CKCR/MMC1CKCR on Gen2 platforms. This allows the MMCIF driver to set higher clock rate if desired. Signed-off-by: Marek Vasut Cc: Nobuhiro Iwamatsu --- drivers/clk/renesas/clk-rcar-gen2.c | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 34abe784fd..13111b341a 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -206,8 +206,50 @@ static ulong gen2_clk_get_rate(struct clk *clk) return -ENOENT; } +static int gen2_clk_setup_mmcif_div(struct clk *clk, ulong rate) +{ + struct gen2_clk_priv *priv = dev_get_priv(clk->dev); + struct cpg_mssr_info *info = priv->info; + const struct cpg_core_clk *core; + struct clk parent, pparent; + u32 val; + int ret; + + ret = renesas_clk_get_parent(clk, info, &parent); + if (ret) { + debug("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); + return ret; + } + + if (renesas_clk_is_mod(&parent)) + return 0; + + ret = renesas_clk_get_core(&parent, info, &core); + if (ret) + return ret; + + if (strcmp(core->name, "mmc0") && strcmp(core->name, "mmc1")) + return 0; + + ret = renesas_clk_get_parent(&parent, info, &pparent); + if (ret) { + debug("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); + return ret; + } + + val = (gen2_clk_get_rate(&pparent) / rate) - 1; + + debug("%s[%i] MMCIF offset=%x\n", __func__, __LINE__, core->offset); + + writel(val, priv->base + core->offset); + + return 0; +} + static ulong gen2_clk_set_rate(struct clk *clk, ulong rate) { + /* Force correct MMC-IF divider configuration if applicable */ + gen2_clk_setup_mmcif_div(clk, rate); return gen2_clk_get_rate(clk); } From f4eaa56a52ce5a6bc348ac37fb3f2a309dff30a0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2019 06:04:17 +0100 Subject: [PATCH 5/6] mmc: sh_mmcif: Set default MMCIF clock rate Set MMCIF clock rate to 97.5 MHz, which is the default according to Gen2 datasheet. Signed-off-by: Marek Vasut Cc: Nobuhiro Iwamatsu Cc: Jaehoon Chung --- drivers/mmc/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 306daf1415..c8875ce8f8 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -696,7 +696,7 @@ static int sh_mmcif_dm_probe(struct udevice *dev) return ret; } - host->clk = clk_get_rate(&sh_mmcif_clk); + host->clk = clk_set_rate(&sh_mmcif_clk, 97500000); plat->cfg.name = dev->name; plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; From c453fe3a0513f758c7d0b580307909637eb31c9f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2019 23:43:10 +0100 Subject: [PATCH 6/6] mmc: tmio: Clamp SD_SECCNT to 16bit values on 16bit IP On 16bit variants of the TMIO SD IP, the SECCNT register can only be programmed to 16bit values, while on the 32bit and 64bit variants it can be programmed to 32bit values. The SECCNT register indicates the maximum number of blocks in a continuous transfer. Hence, limit the maximum continuous transfer block count to 65535 blocks on 16bit variants of the TMIO IP and to BIT(32)-1 blocks on 32bit and 64bit variants. Signed-off-by: Marek Vasut Cc: Masahiro Yamada --- drivers/mmc/tmio-common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 01d8c2b925..812205a21f 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -783,7 +783,10 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks) plat->cfg.f_min = mclk / (priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512); plat->cfg.f_max = mclk; - plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */ + if (quirks & TMIO_SD_CAP_16BIT) + plat->cfg.b_max = U16_MAX; /* max value of TMIO_SD_SECCNT */ + else + plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */ upriv->mmc = &plat->mmc;