From: Takeshi Saito <takeshi.saito.xv@xxxxxxxxxxx> In HS400 timing mode selection, SD clock is switched like: 1) HS200 (200MHz) for tuning 2) High Speed (<= 52MHz) for select HS400 mode (card) 3) HS400 (200MHz) The SDHI controller needs its internal SCC component for HS400 and other modes which need tuning. However, SCC gets only fed a clock when the module clk is > 100MHz. Make sure the SCC is always active with tuning by enforcing at least 100MHz. Note that we only change the module clock. An internal divider ensures that we will still talk to the card at 52MHz. Signed-off-by: Takeshi Saito <takeshi.saito.xv@xxxxxxxxxxx> [wsa: don't overwrite 'new_freq', use 'mmc_doing_retune', improve docs] Signed-off-by: Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx> --- Shimoda-san: can you forward this patch to the BSP team to have a look, too? I needed to change their version of checking various MMC_TIMING_* constants because this approach did not work with current mainline for me. After some testing and researching, I think the solution with 'mmc_doing_retune' is not only working again, but also more future proof, in general. drivers/mmc/host/renesas_sdhi.h | 2 ++ drivers/mmc/host/renesas_sdhi_core.c | 8 +++++++- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index c0504aa90857..33a1acc67cb4 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -27,6 +27,7 @@ struct renesas_sdhi_of_data { dma_addr_t dma_rx_offset; unsigned int bus_shift; int scc_offset; + unsigned int scc_base_f_min; struct renesas_sdhi_scc *taps; int taps_num; unsigned int max_blk_count; @@ -49,6 +50,7 @@ struct renesas_sdhi { struct pinctrl *pinctrl; struct pinctrl_state *pins_default, *pins_uhs; void __iomem *scc_ctl; + unsigned int scc_base_f_min; u32 scc_tappos; u32 scc_tappos_hs400; }; diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 4a2872f49a60..82a492567016 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -120,16 +120,21 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host) } static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host, - unsigned int new_clock) + unsigned int req_clock) { struct renesas_sdhi *priv = host_to_priv(host); unsigned int freq, diff, best_freq = 0, diff_min = ~0; + unsigned int new_clock = req_clock; int i, ret; /* tested only on R-Car Gen2+ currently; may work for others */ if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2)) return clk_get_rate(priv->clk); + /* When SCC is needed, make sure it gets a proper clock */ + if (mmc_doing_retune(host->mmc) && new_clock < priv->scc_base_f_min) + new_clock = priv->scc_base_f_min; + /* * We want the bus clock to be as close as possible to, but no * greater than, new_clock. As we can divide by 1 << i for @@ -709,6 +714,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, mmc_data->max_segs = of_data->max_segs; dma_priv->dma_buswidth = of_data->dma_buswidth; host->bus_shift = of_data->bus_shift; + priv->scc_base_f_min = of_data->scc_base_f_min; } host->write16_hook = renesas_sdhi_write16_hook; diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 751fe91c7571..7010c524b180 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -109,6 +109,8 @@ static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT, .bus_shift = 2, .scc_offset = 0x1000, + /* SCC module clock (SDnH) is enabled at 100MHz or more */ + .scc_base_f_min = 100000000, .taps = rcar_gen3_scc_taps, .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps), /* DMAC can handle 32bit blk count but only 1 segment */ -- 2.20.1