summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-09-22 16:51:19 -0400
committerTom Rini <trini@konsulko.com>2016-09-22 16:51:19 -0400
commit201c9d884dcadb4e76981c30e9915f73de2d09b5 (patch)
treeaf1030f3a441f1538085eaa586e0e8392f2429ab /drivers/clk
parent82f5279b0cd99a9163d34cfe926d0316d9dc0d37 (diff)
parent4f0b8efa50a543efd407fb8b2e9ad0de49467a15 (diff)
Merge git://git.denx.de/u-boot-rockchip
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/rockchip/clk_rk3288.c2
-rw-r--r--drivers/clk/rockchip/clk_rk3399.c177
2 files changed, 175 insertions, 4 deletions
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index c07203d84b..bd71a96927 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -695,6 +695,8 @@ static ulong rk3288_clk_get_rate(struct clk *clk)
case PCLK_I2C4:
case PCLK_I2C5:
return gclk_rate;
+ case PCLK_PWM:
+ return PD_BUS_PCLK_HZ;
default:
return -ENOENT;
}
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 0b4ea828f6..ea0ce2aab1 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -23,6 +23,10 @@ struct rk3399_clk_priv {
ulong rate;
};
+struct rk3399_pmuclk_priv {
+ struct rk3399_pmucru *pmucru;
+};
+
struct pll_div {
u32 refdiv;
u32 fbdiv;
@@ -95,11 +99,11 @@ enum {
/* PMUCRU_CLKSEL_CON2 */
I2C_DIV_CON_MASK = 0x7f,
- I2C8_DIV_CON_SHIFT = 8,
- I2C0_DIV_CON_SHIFT = 0,
+ CLK_I2C8_DIV_CON_SHIFT = 8,
+ CLK_I2C0_DIV_CON_SHIFT = 0,
/* PMUCRU_CLKSEL_CON3 */
- I2C4_DIV_CON_SHIFT = 0,
+ CLK_I2C4_DIV_CON_SHIFT = 0,
/* CLKSEL_CON0 */
ACLKM_CORE_L_DIV_CON_SHIFT = 8,
@@ -507,6 +511,14 @@ void rk3399_configure_cpu(struct rk3399_cru *cru,
(con >> CLK_I2C ##bus## _DIV_CON_SHIFT) & \
I2C_DIV_CON_MASK;
+#define I2C_PMUCLK_REG_MASK(bus) \
+ (I2C_DIV_CON_MASK << \
+ CLK_I2C ##bus## _DIV_CON_SHIFT)
+
+#define I2C_PMUCLK_REG_VALUE(bus, clk_div) \
+ ((clk_div - 1) << \
+ CLK_I2C ##bus## _DIV_CON_SHIFT)
+
static ulong rk3399_i2c_get_clk(struct rk3399_cru *cru, ulong clk_id)
{
u32 div, con;
@@ -754,7 +766,7 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
break;
case DCLK_VOP0:
case DCLK_VOP1:
- rate = rk3399_vop_set_clk(priv->cru, clk->id, rate);
+ ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
break;
default:
return -ENOENT;
@@ -830,3 +842,160 @@ U_BOOT_DRIVER(clk_rk3399) = {
.bind = rk3399_clk_bind,
.probe = rk3399_clk_probe,
};
+
+static ulong rk3399_i2c_get_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id)
+{
+ u32 div, con;
+
+ switch (clk_id) {
+ case SCLK_I2C0_PMU:
+ con = readl(&pmucru->pmucru_clksel[2]);
+ div = I2C_CLK_DIV_VALUE(con, 0);
+ break;
+ case SCLK_I2C4_PMU:
+ con = readl(&pmucru->pmucru_clksel[3]);
+ div = I2C_CLK_DIV_VALUE(con, 4);
+ break;
+ case SCLK_I2C8_PMU:
+ con = readl(&pmucru->pmucru_clksel[2]);
+ div = I2C_CLK_DIV_VALUE(con, 8);
+ break;
+ default:
+ printf("do not support this i2c bus\n");
+ return -EINVAL;
+ }
+
+ return DIV_TO_RATE(PPLL_HZ, div);
+}
+
+static ulong rk3399_i2c_set_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id,
+ uint hz)
+{
+ int src_clk_div;
+
+ src_clk_div = PPLL_HZ / hz;
+ assert(src_clk_div - 1 < 127);
+
+ switch (clk_id) {
+ case SCLK_I2C0_PMU:
+ rk_clrsetreg(&pmucru->pmucru_clksel[2], I2C_PMUCLK_REG_MASK(0),
+ I2C_PMUCLK_REG_VALUE(0, src_clk_div));
+ break;
+ case SCLK_I2C4_PMU:
+ rk_clrsetreg(&pmucru->pmucru_clksel[3], I2C_PMUCLK_REG_MASK(4),
+ I2C_PMUCLK_REG_VALUE(4, src_clk_div));
+ break;
+ case SCLK_I2C8_PMU:
+ rk_clrsetreg(&pmucru->pmucru_clksel[2], I2C_PMUCLK_REG_MASK(8),
+ I2C_PMUCLK_REG_VALUE(8, src_clk_div));
+ break;
+ default:
+ printf("do not support this i2c bus\n");
+ return -EINVAL;
+ }
+
+ return DIV_TO_RATE(PPLL_HZ, src_clk_div);
+}
+
+static ulong rk3399_pwm_get_clk(struct rk3399_pmucru *pmucru)
+{
+ u32 div, con;
+
+ /* PWM closk rate is same as pclk_pmu */
+ con = readl(&pmucru->pmucru_clksel[0]);
+ div = con & PMU_PCLK_DIV_CON_MASK;
+
+ return DIV_TO_RATE(PPLL_HZ, div);
+}
+
+static ulong rk3399_pmuclk_get_rate(struct clk *clk)
+{
+ struct rk3399_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ switch (clk->id) {
+ case PCLK_RKPWM_PMU:
+ rate = rk3399_pwm_get_clk(priv->pmucru);
+ break;
+ case SCLK_I2C0_PMU:
+ case SCLK_I2C4_PMU:
+ case SCLK_I2C8_PMU:
+ rate = rk3399_i2c_get_pmuclk(priv->pmucru, clk->id);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+}
+
+static ulong rk3399_pmuclk_set_rate(struct clk *clk, ulong rate)
+{
+ struct rk3399_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ switch (clk->id) {
+ case SCLK_I2C0_PMU:
+ case SCLK_I2C4_PMU:
+ case SCLK_I2C8_PMU:
+ ret = rk3399_i2c_set_pmuclk(priv->pmucru, clk->id, rate);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return ret;
+}
+
+static struct clk_ops rk3399_pmuclk_ops = {
+ .get_rate = rk3399_pmuclk_get_rate,
+ .set_rate = rk3399_pmuclk_set_rate,
+};
+
+static void pmuclk_init(struct rk3399_pmucru *pmucru)
+{
+ u32 pclk_div;
+
+ /* configure pmu pll(ppll) */
+ rkclk_set_pll(&pmucru->ppll_con[0], &ppll_init_cfg);
+
+ /* configure pmu pclk */
+ pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
+ assert((pclk_div + 1) * PMU_PCLK_HZ == PPLL_HZ && pclk_div < 0x1f);
+ rk_clrsetreg(&pmucru->pmucru_clksel[0],
+ PMU_PCLK_DIV_CON_MASK,
+ pclk_div << PMU_PCLK_DIV_CON_SHIFT);
+}
+
+static int rk3399_pmuclk_probe(struct udevice *dev)
+{
+ struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
+
+ pmuclk_init(priv->pmucru);
+
+ return 0;
+}
+
+static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev)
+{
+ struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
+
+ priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev);
+
+ return 0;
+}
+
+static const struct udevice_id rk3399_pmuclk_ids[] = {
+ { .compatible = "rockchip,rk3399-pmucru" },
+ { }
+};
+
+U_BOOT_DRIVER(pmuclk_rk3399) = {
+ .name = "pmuclk_rk3399",
+ .id = UCLASS_CLK,
+ .of_match = rk3399_pmuclk_ids,
+ .priv_auto_alloc_size = sizeof(struct rk3399_pmuclk_priv),
+ .ofdata_to_platdata = rk3399_pmuclk_ofdata_to_platdata,
+ .ops = &rk3399_pmuclk_ops,
+ .probe = rk3399_pmuclk_probe,
+};