aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakeshi Saito <takeshi.saito.xv@renesas.com>2019-03-01 17:23:46 +0900
committerRyo Kataoka <ryo.kataoka.wt@renesas.com>2019-03-22 20:50:20 +0900
commitaddfe9203290e3c274bca15e64e3f11638649e66 (patch)
tree170d4105af041f3a3f9a70d9072ec126c6457eb3
parent6d483c3415d3e3c7daa3c0a1adfe8e84a401f4a2 (diff)
downloadrenesas-bsp-addfe9203290e3c274bca15e64e3f11638649e66.tar.gz
mmc: renesas_sdhi: Fix hang up in HS400 timing mode selection
In HS400 timing mode selection, SD clock is switched the following. 1) HS200 (200MHz) for tuning 2) High Speed (<= 52MHz) for select HS400 mode (card) 3) HS400 (200MHz) In R-Car Gen3 SDHI, internal SCC modules uses SDnH clock. It is controlled by SDnCKCR.STPnHCK bit in CPG. When SD clock is less than High Speed, SDnH clock is stopped. And SDnH clock is supplied with 100MHz or more in Clock divider table of CPG in R-Car Gen3. It is the recommended setting of H/W. Therefore, when bus timing is SDR104/HS200/HS400 mode, minimum frequency of SDHI clock is 100MHz. Signed-off-by: Takeshi Saito <takeshi.saito.xv@renesas.com>
-rw-r--r--drivers/mmc/host/renesas_sdhi.h2
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c8
-rw-r--r--drivers/mmc/host/renesas_sdhi_internal_dmac.c2
3 files changed, 12 insertions, 0 deletions
diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index b5db61a449e19..14e64336aef60 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -30,6 +30,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;
@@ -55,6 +56,7 @@ struct renesas_sdhi {
u32 scc_tappos;
u32 scc_tappos_hs400;
int scc_offset;
+ unsigned int scc_base_f_min;
u32 adjust_hs400_offset;
u32 adjust_hs400_calibrate;
};
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index bd54028ad807e..f8345aafec733 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -128,6 +128,13 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
return clk_get_rate(priv->clk);
+ /* In SDR104/HS200/HS400 mode, SDnH clock must supply for SCC */
+ if (new_clock < priv->scc_base_f_min &&
+ (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 ||
+ host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
+ host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
+ 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
@@ -850,6 +857,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
dma_priv->dma_buswidth = of_data->dma_buswidth;
host->bus_shift = of_data->bus_shift;
priv->scc_offset = of_data->scc_offset;
+ 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 173be0742191e..2291b55599df9 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -94,6 +94,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 0xffffffff blk count but only 1 segment */