]> 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 0172ad13bb7038ecf89ca40494fd30f87cb8b1dd..5a8f175e4b062d33811011fb98c9f913361fe4b6 100644 (file)
 #include <asm/arch/cru_rk3288.h>
 #include <asm/arch/grf_rk3288.h>
 #include <asm/arch/hardware.h>
-#include <asm/arch/periph.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,25 +396,25 @@ 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,
-                                 enum periph_id periph)
+static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint gclk_rate,
+                                 int periph)
 {
        uint src_rate;
        uint div, mux;
        u32 con;
 
        switch (periph) {
-       case PERIPH_ID_EMMC:
+       case HCLK_EMMC:
                con = readl(&cru->cru_clksel_con[12]);
                mux = (con >> EMMC_PLL_SHIFT) & EMMC_PLL_MASK;
                div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
                break;
-       case PERIPH_ID_SDCARD:
-               con = readl(&cru->cru_clksel_con[12]);
+       case HCLK_SDMMC:
+               con = readl(&cru->cru_clksel_con[11]);
                mux = (con >> MMC0_PLL_SHIFT) & MMC0_PLL_MASK;
                div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
                break;
-       case PERIPH_ID_SDMMC2:
+       case HCLK_SDIO0:
                con = readl(&cru->cru_clksel_con[12]);
                mux = (con >> SDIO0_PLL_SHIFT) & SDIO0_PLL_MASK;
                div = (con >> SDIO0_DIV_SHIFT) & SDIO0_DIV_MASK;
@@ -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,
-                                 enum periph_id periph, uint freq)
+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);
@@ -414,21 +447,21 @@ static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint clk_general_rate,
                       (int)MMC0_PLL_SELECT_GENERAL);
        }
        switch (periph) {
-       case PERIPH_ID_EMMC:
+       case HCLK_EMMC:
                rk_clrsetreg(&cru->cru_clksel_con[12],
                             EMMC_PLL_MASK << EMMC_PLL_SHIFT |
                             EMMC_DIV_MASK << EMMC_DIV_SHIFT,
                             mux << EMMC_PLL_SHIFT |
                             (src_clk_div - 1) << EMMC_DIV_SHIFT);
                break;
-       case PERIPH_ID_SDCARD:
+       case HCLK_SDMMC:
                rk_clrsetreg(&cru->cru_clksel_con[11],
                             MMC0_PLL_MASK << MMC0_PLL_SHIFT |
                             MMC0_DIV_MASK << MMC0_DIV_SHIFT,
                             mux << MMC0_PLL_SHIFT |
                             (src_clk_div - 1) << MMC0_DIV_SHIFT);
                break;
-       case PERIPH_ID_SDMMC2:
+       case HCLK_SDIO0:
                rk_clrsetreg(&cru->cru_clksel_con[12],
                             SDIO0_PLL_MASK << SDIO0_PLL_SHIFT |
                             SDIO0_DIV_MASK << SDIO0_DIV_SHIFT,
@@ -439,27 +472,27 @@ 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,
-                                 enum periph_id periph)
+static ulong rockchip_spi_get_clk(struct rk3288_cru *cru, uint gclk_rate,
+                                 int periph)
 {
        uint div, mux;
        u32 con;
 
        switch (periph) {
-       case PERIPH_ID_SPI0:
+       case SCLK_SPI0:
                con = readl(&cru->cru_clksel_con[25]);
                mux = (con >> SPI0_PLL_SHIFT) & SPI0_PLL_MASK;
                div = (con >> SPI0_DIV_SHIFT) & SPI0_DIV_MASK;
                break;
-       case PERIPH_ID_SPI1:
+       case SCLK_SPI1:
                con = readl(&cru->cru_clksel_con[25]);
                mux = (con >> SPI1_PLL_SHIFT) & SPI1_PLL_MASK;
                div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK;
                break;
-       case PERIPH_ID_SPI2:
+       case SCLK_SPI2:
                con = readl(&cru->cru_clksel_con[39]);
                mux = (con >> SPI2_PLL_SHIFT) & SPI2_PLL_MASK;
                div = (con >> SPI2_DIV_SHIFT) & SPI2_DIV_MASK;
@@ -469,32 +502,32 @@ 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,
-                                 enum periph_id periph, uint freq)
+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 PERIPH_ID_SPI0:
+       case SCLK_SPI0:
                rk_clrsetreg(&cru->cru_clksel_con[25],
                             SPI0_PLL_MASK << SPI0_PLL_SHIFT |
                             SPI0_DIV_MASK << SPI0_DIV_SHIFT,
                             SPI0_PLL_SELECT_GENERAL << SPI0_PLL_SHIFT |
                             src_clk_div << SPI0_DIV_SHIFT);
                break;
-       case PERIPH_ID_SPI1:
+       case SCLK_SPI1:
                rk_clrsetreg(&cru->cru_clksel_con[25],
                             SPI1_PLL_MASK << SPI1_PLL_SHIFT |
                             SPI1_DIV_MASK << SPI1_DIV_SHIFT,
                             SPI1_PLL_SELECT_GENERAL << SPI1_PLL_SHIFT |
                             src_clk_div << SPI1_DIV_SHIFT);
                break;
-       case PERIPH_ID_SPI2:
+       case SCLK_SPI2:
                rk_clrsetreg(&cru->cru_clksel_con[39],
                             SPI2_PLL_MASK << SPI2_PLL_SHIFT |
                             SPI2_DIV_MASK << SPI2_DIV_SHIFT,
@@ -505,25 +538,68 @@ 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)
 {
        struct rk3288_clk_priv *priv = dev_get_priv(dev);
-       ulong new_rate;
+       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 PERIPH_ID_EMMC:
-       case PERIPH_ID_SDCARD:
-               new_rate = rockchip_mmc_set_clk(priv->cru, clk_get_rate(dev),
-                                               periph, rate);
+       case HCLK_EMMC:
+       case HCLK_SDMMC:
+       case HCLK_SDIO0:
+               new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate, periph,
+                                               rate);
                break;
-       case PERIPH_ID_SPI0:
-       case PERIPH_ID_SPI1:
-       case PERIPH_ID_SPI2:
-               new_rate = rockchip_spi_set_clk(priv->cru, clk_get_rate(dev),
-                                               periph, rate);
+       case SCLK_SPI0:
+       case SCLK_SPI1:
+       case SCLK_SPI2:
+               new_rate = rockchip_spi_set_clk(priv->cru, gclk_rate, periph,
+                                               rate);
                break;
        default:
                return -ENOENT;
@@ -536,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)