]> git.sur5r.net Git - u-boot/blobdiff - drivers/clk/clk_rk3288.c
rockchip: clk: Make rkclk_get_clk() SoC-specific
[u-boot] / drivers / clk / clk_rk3288.c
index e410e7d171056d1582b234086f45394f60a61a24..5a8f175e4b062d33811011fb98c9f913361fe4b6 100644 (file)
@@ -15,7 +15,9 @@
 #include <asm/arch/grf_rk3288.h>
 #include <asm/arch/hardware.h>
 #include <dt-bindings/clock/rk3288-cru.h>
+#include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/uclass-internal.h>
 
 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)