#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;
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)
{
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;
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);
(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,
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;
}
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,
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;
.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)