clk: rockchip: rv1126: Add support restore emmc/sfc/nandc frequency

Change-Id: Iaa62eead12156d284a6ee315dfbaf92e786a0920
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
Finley Xiao 2020-02-27 11:16:28 +08:00
parent 57ae0852b1
commit f96f01225f
1 changed files with 62 additions and 25 deletions

View File

@ -93,6 +93,9 @@ static const struct rv1126_clk_info clks_dump[] = {
}; };
#endif #endif
static ulong rv1126_gpll_set_rate(struct rv1126_clk_priv *priv,
struct rv1126_pmuclk_priv *pmu_priv,
ulong rate);
/* /*
* *
* rational_best_approximation(31415, 10000, * rational_best_approximation(31415, 10000,
@ -150,20 +153,26 @@ static ulong rv1126_gpll_get_pmuclk(struct rv1126_pmuclk_priv *priv)
priv->pmucru, GPLL); priv->pmucru, GPLL);
} }
static ulong rv1126_gpll_set_pmuclk(struct rv1126_pmuclk_priv *priv, ulong rate) static ulong rv1126_gpll_set_pmuclk(struct rv1126_pmuclk_priv *pmu_priv, ulong rate)
{ {
struct udevice *cru_dev;
struct rv1126_clk_priv *priv;
int ret; int ret;
/* ret = uclass_get_device_by_driver(UCLASS_CLK,
* the child div is big enough for gpll 1188MHz, DM_GET_DRIVER(rockchip_rv1126_cru),
* even maskrom has change some clocks. &cru_dev);
*/ if (ret) {
ret = rockchip_pll_set_rate(&rv1126_pll_clks[GPLL], printf("%s: could not find cru device\n", __func__);
priv->pmucru, GPLL, rate); return ret;
if (!ret) }
priv->gpll_hz = rate; priv = dev_get_priv(cru_dev);
return ret; if (rv1126_gpll_set_rate(priv, pmu_priv, rate)) {
printf("%s: failed to set gpll rate %lu\n", __func__, rate);
return -EINVAL;
}
return 0;
} }
static ulong rv1126_rtc32k_get_pmuclk(struct rv1126_pmuclk_priv *priv) static ulong rv1126_rtc32k_get_pmuclk(struct rv1126_pmuclk_priv *priv)
@ -1025,7 +1034,7 @@ static ulong rv1126_mmc_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
return -ENOENT; return -ENOENT;
} }
static ulong rv1126_emmc_set_clk(struct rv1126_clk_priv *priv, ulong clk_id, static ulong rv1126_mmc_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
ulong rate) ulong rate)
{ {
struct rv1126_cru *cru = priv->cru; struct rv1126_cru *cru = priv->cru;
@ -1377,7 +1386,7 @@ static ulong rv1126_clk_set_rate(struct clk *clk, ulong rate)
case HCLK_SDIO: case HCLK_SDIO:
case CLK_EMMC: case CLK_EMMC:
case HCLK_EMMC: case HCLK_EMMC:
ret = rv1126_emmc_set_clk(priv, clk->id, rate); ret = rv1126_mmc_set_clk(priv, clk->id, rate);
break; break;
case SCLK_SFC: case SCLK_SFC:
ret = rv1126_sfc_set_clk(priv, rate); ret = rv1126_sfc_set_clk(priv, rate);
@ -1599,10 +1608,40 @@ static struct clk_ops rv1126_clk_ops = {
#endif #endif
}; };
static int rv1126_gpll_set_clk(ulong rate) static ulong rv1126_gpll_set_rate(struct rv1126_clk_priv *priv,
struct rv1126_pmuclk_priv *pmu_priv,
ulong rate)
{
ulong emmc_rate, sfc_rate, nandc_rate;
int ret;
emmc_rate = rv1126_mmc_get_clk(priv, CLK_EMMC);
sfc_rate = rv1126_sfc_get_clk(priv);
nandc_rate = rv1126_nand_get_clk(priv);
debug("%s emmc=%lu, sdmmc=%lu, nandc=%lu\n", __func__,
emmc_rate, sfc_rate, nandc_rate);
/*
* the child div is big enough for gpll 1188MHz,
* even maskrom has change some clocks.
*/
if (rockchip_pll_set_rate(&rv1126_pll_clks[GPLL],
pmu_priv->pmucru, GPLL, rate))
return -EINVAL;
pmu_priv->gpll_hz = rate;
priv->gpll_hz = rate;
rv1126_mmc_set_clk(priv, CLK_EMMC, emmc_rate);
rv1126_sfc_set_clk(priv, sfc_rate);
rv1126_nand_set_clk(priv, nandc_rate);
return ret;
}
static int rv1126_gpll_set_clk(struct rv1126_clk_priv *priv, ulong rate)
{ {
struct udevice *pmucru_dev; struct udevice *pmucru_dev;
struct rv1126_pmuclk_priv *priv; struct rv1126_pmuclk_priv *pmu_priv;
int ret; int ret;
ret = uclass_get_device_by_driver(UCLASS_CLK, ret = uclass_get_device_by_driver(UCLASS_CLK,
@ -1612,16 +1651,16 @@ static int rv1126_gpll_set_clk(ulong rate)
printf("%s: could not find pmucru device\n", __func__); printf("%s: could not find pmucru device\n", __func__);
return ret; return ret;
} }
priv = dev_get_priv(pmucru_dev); pmu_priv = dev_get_priv(pmucru_dev);
ret = rv1126_gpll_set_pmuclk(priv, rate); if (rv1126_gpll_set_rate(priv, pmu_priv, rate)) {
if (ret) {
printf("%s: failed to set gpll rate %lu\n", __func__, rate); printf("%s: failed to set gpll rate %lu\n", __func__, rate);
return ret; return -EINVAL;
} }
rv1126_pdpmu_set_pmuclk(priv, PCLK_PDPMU_HZ);
return ret; rv1126_pdpmu_set_pmuclk(pmu_priv, PCLK_PDPMU_HZ);
return 0;
} }
static void rv1126_clk_init(struct rv1126_clk_priv *priv) static void rv1126_clk_init(struct rv1126_clk_priv *priv)
@ -1641,11 +1680,9 @@ static void rv1126_clk_init(struct rv1126_clk_priv *priv)
if (!ret) if (!ret)
priv->armclk_init_hz = APLL_HZ; priv->armclk_init_hz = APLL_HZ;
} }
if (priv->gpll_hz != GPLL_HZ) { if (priv->gpll_hz != GPLL_HZ)
ret = rv1126_gpll_set_clk(GPLL_HZ); rv1126_gpll_set_clk(priv, GPLL_HZ);
if (!ret)
priv->gpll_hz = GPLL_HZ;
}
if (priv->cpll_hz != CPLL_HZ) { if (priv->cpll_hz != CPLL_HZ) {
ret = rockchip_pll_set_rate(&rv1126_pll_clks[CPLL], priv->cru, ret = rockchip_pll_set_rate(&rv1126_pll_clks[CPLL], priv->cru,
CPLL, CPLL_HZ); CPLL, CPLL_HZ);