diff options
author | Hai Pham <hai.pham.ud@renesas.com> | 2023-01-29 02:50:22 +0100 |
---|---|---|
committer | Marek Vasut <marek.vasut+renesas@gmail.com> | 2023-02-02 01:49:20 +0100 |
commit | 4dbbc3f37387e6a7248ec057b617690bf7ff9a7d (patch) | |
tree | 6db0d5b93ea3524b554cd26c275b1293488e1367 /drivers/mmc/renesas-sdhi.c | |
parent | c287c184aea435ef17ff5d11c3e06540dd2db0d7 (diff) |
clk: renesas: Switch to new SD clock handling
The old SD handling code was huge and could not handle all the details
which showed up on R-Car Gen3 SoCs meanwhile. It is time to switch to
another design. Have SDnH a separate clock, use the existing divider
clocks and move the errata handling from the clock driver to the SDHI
driver where it belongs.
Based on Linux series by Wolfram Sang, commit bb6d3fa98a41 ("clk:
renesas: rcar-gen3: Switch to new SD clock handling") and commit
e5f7e81ee430a ("mmc: renesas_sdhi: Parse DT for SDnH")
Signed-off-by: Hai Pham <hai.pham.ud@renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Marek: - Add rcar_clk_* prefix to all functions
- Fix missing ~ in GENMASK(a, b), use clrsetbits_le32 instead
- Use DIV_ROUND_CLOSEST, else if parent clock = 199999992 and
rate = 200000000, the divider would be 0 and table lookup
would fail.
- Turn rcar_clk_get_table_val into signed integer, so it can
return 0 as a valid value and negative values as errors.
- Make the code operate on correct clock and add comment
which explains the reasoning behind it.
- Rebase on changes to
clk: renesas: Introduce and use rcar_clk_get_rate64_div_table function
Diffstat (limited to 'drivers/mmc/renesas-sdhi.c')
-rw-r--r-- | drivers/mmc/renesas-sdhi.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f30d7847bf..4a1accebfc 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -358,13 +358,21 @@ static int renesas_sdhi_hs400(struct udevice *dev) struct mmc *mmc = mmc_get_mmc_dev(dev); bool hs400 = (mmc->selected_mode == MMC_HS_400); int ret, taps = hs400 ? priv->nrtaps : 8; + const u32 sdn_rate = 200000000; + u32 sdnh_rate = 800000000; unsigned long new_tap; u32 reg; - if (taps == 4) /* HS400 on 4tap SoC needs different clock */ - ret = clk_set_rate(&priv->clk, 400000000); - else - ret = clk_set_rate(&priv->clk, 200000000); + if (clk_valid(&priv->clkh) && !priv->needs_clkh_fallback) { + /* HS400 on 4tap SoC => SDnH=400 MHz, SDn=200 MHz */ + if (taps == 4) + sdnh_rate /= 2; + ret = clk_set_rate(&priv->clkh, sdnh_rate); + if (ret < 0) + return ret; + } + + ret = clk_set_rate(&priv->clk, sdn_rate); if (ret < 0) return ret; @@ -967,6 +975,11 @@ static int renesas_sdhi_probe(struct udevice *dev) return ret; } + /* optional SDnH clock */ + ret = clk_get_by_name(dev, "clkh", &priv->clkh); + if (ret < 0) + dev_dbg(dev, "failed to get clkh\n"); + /* set to max rate */ ret = clk_set_rate(&priv->clk, 200000000); if (ret < 0) { |