X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fclk%2Fclk_rk3288.c;h=5a8f175e4b062d33811011fb98c9f913361fe4b6;hb=5ddf5d7705d2c2b59282ebd37aa2018460274e89;hp=e410e7d171056d1582b234086f45394f60a61a24;hpb=898d64395c6f8889fc9fd09a0a4dc6a6f018598f;p=u-boot diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c index e410e7d171..5a8f175e4b 100644 --- a/drivers/clk/clk_rk3288.c +++ b/drivers/clk/clk_rk3288.c @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -139,6 +141,37 @@ static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 1); static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2); static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2); +int rkclk_get_clk(enum rk_clk_id clk_id, struct udevice **devp) +{ + struct udevice *dev; + + for (uclass_find_first_device(UCLASS_CLK, &dev); + dev; + uclass_find_next_device(&dev)) { + struct rk3288_clk_plat *plat = dev_get_platdata(dev); + + if (plat->clk_id == clk_id) { + *devp = dev; + return device_probe(dev); + } + } + + return -ENODEV; +} + +void *rockchip_get_cru(void) +{ + struct rk3288_clk_priv *priv; + struct udevice *dev; + int ret; + + ret = rkclk_get_clk(CLK_GENERAL, &dev); + if (ret) + return ERR_PTR(ret); + priv = dev_get_priv(dev); + return priv->cru; +} + static int rkclk_set_pll(struct rk3288_cru *cru, enum rk_clk_id clk_id, const struct pll_div *div) { @@ -363,7 +396,7 @@ static ulong rk3288_clk_set_rate(struct udevice *dev, ulong rate) return 0; } -static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint clk_general_rate, +static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint gclk_rate, int periph) { uint src_rate; @@ -390,18 +423,18 @@ static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint clk_general_rate, return -EINVAL; } - src_rate = mux == EMMC_PLL_SELECT_24MHZ ? OSC_HZ : clk_general_rate; + src_rate = mux == EMMC_PLL_SELECT_24MHZ ? OSC_HZ : gclk_rate; return DIV_TO_RATE(src_rate, div); } -static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint clk_general_rate, +static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint gclk_rate, int periph, uint freq) { int src_clk_div; int mux; - debug("%s: clk_general_rate=%u\n", __func__, clk_general_rate); - src_clk_div = RATE_TO_DIV(clk_general_rate, freq); + debug("%s: gclk_rate=%u\n", __func__, gclk_rate); + src_clk_div = RATE_TO_DIV(gclk_rate, freq); if (src_clk_div > 0x3f) { src_clk_div = RATE_TO_DIV(OSC_HZ, freq); @@ -439,10 +472,10 @@ static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint clk_general_rate, return -EINVAL; } - return rockchip_mmc_get_clk(cru, clk_general_rate, periph); + return rockchip_mmc_get_clk(cru, gclk_rate, periph); } -static ulong rockchip_spi_get_clk(struct rk3288_cru *cru, uint clk_general_rate, +static ulong rockchip_spi_get_clk(struct rk3288_cru *cru, uint gclk_rate, int periph) { uint div, mux; @@ -469,16 +502,16 @@ static ulong rockchip_spi_get_clk(struct rk3288_cru *cru, uint clk_general_rate, } assert(mux == SPI0_PLL_SELECT_GENERAL); - return DIV_TO_RATE(clk_general_rate, div); + return DIV_TO_RATE(gclk_rate, div); } -static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint clk_general_rate, +static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint gclk_rate, int periph, uint freq) { int src_clk_div; - debug("%s: clk_general_rate=%u\n", __func__, clk_general_rate); - src_clk_div = RATE_TO_DIV(clk_general_rate, freq); + debug("%s: clk_general_rate=%u\n", __func__, gclk_rate); + src_clk_div = RATE_TO_DIV(gclk_rate, freq); switch (periph) { case SCLK_SPI0: rk_clrsetreg(&cru->cru_clksel_con[25], @@ -505,7 +538,43 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint clk_general_rate, return -EINVAL; } - return rockchip_spi_get_clk(cru, clk_general_rate, periph); + return rockchip_spi_get_clk(cru, gclk_rate, periph); +} + +static ulong rk3288_get_periph_rate(struct udevice *dev, int periph) +{ + struct rk3288_clk_priv *priv = dev_get_priv(dev); + struct udevice *gclk; + ulong new_rate, gclk_rate; + int ret; + + ret = rkclk_get_clk(CLK_GENERAL, &gclk); + if (ret) + return ret; + gclk_rate = clk_get_rate(gclk); + switch (periph) { + case HCLK_EMMC: + case HCLK_SDMMC: + case HCLK_SDIO0: + new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, periph); + break; + case SCLK_SPI0: + case SCLK_SPI1: + case SCLK_SPI2: + new_rate = rockchip_spi_get_clk(priv->cru, gclk_rate, periph); + break; + case PCLK_I2C0: + case PCLK_I2C1: + case PCLK_I2C2: + case PCLK_I2C3: + case PCLK_I2C4: + case PCLK_I2C5: + return gclk_rate; + default: + return -ENOENT; + } + + return new_rate; } static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate) @@ -515,7 +584,7 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate) ulong new_rate, gclk_rate; int ret; - ret = uclass_get_device(UCLASS_CLK, CLK_GENERAL, &gclk); + ret = rkclk_get_clk(CLK_GENERAL, &gclk); if (ret) return ret; gclk_rate = clk_get_rate(gclk); @@ -543,6 +612,7 @@ static struct clk_ops rk3288_clk_ops = { .get_rate = rk3288_clk_get_rate, .set_rate = rk3288_clk_set_rate, .set_periph_rate = rk3288_set_periph_rate, + .get_periph_rate = rk3288_get_periph_rate, }; static int rk3288_clk_probe(struct udevice *dev)