mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-29 08:01:08 +00:00
clk: rk3399: add pmucru controller support
pmucru is a module like cru which is a clock controller manage some PLL and module clocks. Signed-off-by: Kever Yang <kever.yang@rock-chips.com> Acked-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
4a79ececeb
commit
5e79f44355
1 changed files with 173 additions and 4 deletions
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue