|
|
|
@ -7,7 +7,9 @@ |
|
|
|
|
#include <common.h> |
|
|
|
|
#include <clk-uclass.h> |
|
|
|
|
#include <dm.h> |
|
|
|
|
#include <dt-structs.h> |
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <mapmem.h> |
|
|
|
|
#include <syscon.h> |
|
|
|
|
#include <asm/io.h> |
|
|
|
|
#include <asm/arch/clock.h> |
|
|
|
@ -18,10 +20,16 @@ |
|
|
|
|
|
|
|
|
|
DECLARE_GLOBAL_DATA_PTR; |
|
|
|
|
|
|
|
|
|
struct rk3399_pmuclk_priv { |
|
|
|
|
struct rk3399_pmucru *pmucru; |
|
|
|
|
#if CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
struct rk3399_clk_plat { |
|
|
|
|
struct dtd_rockchip_rk3399_cru dtd; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct rk3399_pmuclk_plat { |
|
|
|
|
struct dtd_rockchip_rk3399_pmucru dtd; |
|
|
|
|
}; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
struct pll_div { |
|
|
|
|
u32 refdiv; |
|
|
|
|
u32 fbdiv; |
|
|
|
@ -381,6 +389,7 @@ static int pll_para_config(u32 freq_hz, struct pll_div *div) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_SPL_BUILD |
|
|
|
|
static void rkclk_init(struct rk3399_cru *cru) |
|
|
|
|
{ |
|
|
|
|
u32 aclk_div; |
|
|
|
@ -456,6 +465,7 @@ static void rkclk_init(struct rk3399_cru *cru) |
|
|
|
|
hclk_div << HCLK_PERILP1_DIV_CON_SHIFT | |
|
|
|
|
HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
void rk3399_configure_cpu(struct rk3399_cru *cru, |
|
|
|
|
enum apll_l_frequencies apll_l_freq) |
|
|
|
@ -709,6 +719,44 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru, |
|
|
|
|
return rk3399_mmc_get_clk(cru, clk_id); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define PMUSGRF_DDR_RGN_CON16 0xff330040 |
|
|
|
|
static ulong rk3399_ddr_set_clk(struct rk3399_cru *cru, |
|
|
|
|
ulong set_rate) |
|
|
|
|
{ |
|
|
|
|
struct pll_div dpll_cfg; |
|
|
|
|
|
|
|
|
|
/* IC ECO bug, need to set this register */ |
|
|
|
|
writel(0xc000c000, PMUSGRF_DDR_RGN_CON16); |
|
|
|
|
|
|
|
|
|
/* clk_ddrc == DPLL = 24MHz / refdiv * fbdiv / postdiv1 / postdiv2 */ |
|
|
|
|
switch (set_rate) { |
|
|
|
|
case 200*MHz: |
|
|
|
|
dpll_cfg = (struct pll_div) |
|
|
|
|
{.refdiv = 1, .fbdiv = 50, .postdiv1 = 6, .postdiv2 = 1}; |
|
|
|
|
break; |
|
|
|
|
case 300*MHz: |
|
|
|
|
dpll_cfg = (struct pll_div) |
|
|
|
|
{.refdiv = 2, .fbdiv = 100, .postdiv1 = 4, .postdiv2 = 1}; |
|
|
|
|
break; |
|
|
|
|
case 666*MHz: |
|
|
|
|
dpll_cfg = (struct pll_div) |
|
|
|
|
{.refdiv = 2, .fbdiv = 111, .postdiv1 = 2, .postdiv2 = 1}; |
|
|
|
|
break; |
|
|
|
|
case 800*MHz: |
|
|
|
|
dpll_cfg = (struct pll_div) |
|
|
|
|
{.refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1}; |
|
|
|
|
break; |
|
|
|
|
case 933*MHz: |
|
|
|
|
dpll_cfg = (struct pll_div) |
|
|
|
|
{.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1}; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
error("Unsupported SDRAM frequency!,%ld\n", set_rate); |
|
|
|
|
} |
|
|
|
|
rkclk_set_pll(&cru->dpll_con[0], &dpll_cfg); |
|
|
|
|
|
|
|
|
|
return set_rate; |
|
|
|
|
} |
|
|
|
|
static ulong rk3399_clk_get_rate(struct clk *clk) |
|
|
|
|
{ |
|
|
|
|
struct rk3399_clk_priv *priv = dev_get_priv(clk->dev); |
|
|
|
@ -763,6 +811,9 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate) |
|
|
|
|
case DCLK_VOP1: |
|
|
|
|
ret = rk3399_vop_set_clk(priv->cru, clk->id, rate); |
|
|
|
|
break; |
|
|
|
|
case SCLK_DDRCLK: |
|
|
|
|
ret = rk3399_ddr_set_clk(priv->cru, rate); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return -ENOENT; |
|
|
|
|
} |
|
|
|
@ -777,19 +828,26 @@ static struct clk_ops rk3399_clk_ops = { |
|
|
|
|
|
|
|
|
|
static int rk3399_clk_probe(struct udevice *dev) |
|
|
|
|
{ |
|
|
|
|
#ifdef CONFIG_SPL_BUILD |
|
|
|
|
struct rk3399_clk_priv *priv = dev_get_priv(dev); |
|
|
|
|
|
|
|
|
|
rkclk_init(priv->cru); |
|
|
|
|
#if CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
struct rk3399_clk_plat *plat = dev_get_platdata(dev); |
|
|
|
|
|
|
|
|
|
priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); |
|
|
|
|
#endif |
|
|
|
|
rkclk_init(priv->cru); |
|
|
|
|
#endif |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int rk3399_clk_ofdata_to_platdata(struct udevice *dev) |
|
|
|
|
{ |
|
|
|
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
struct rk3399_clk_priv *priv = dev_get_priv(dev); |
|
|
|
|
|
|
|
|
|
priv->cru = (struct rk3399_cru *)dev_get_addr(dev); |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -811,7 +869,7 @@ static const struct udevice_id rk3399_clk_ids[] = { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
U_BOOT_DRIVER(clk_rk3399) = { |
|
|
|
|
.name = "clk_rk3399", |
|
|
|
|
.name = "rockchip_rk3399_cru", |
|
|
|
|
.id = UCLASS_CLK, |
|
|
|
|
.of_match = rk3399_clk_ids, |
|
|
|
|
.priv_auto_alloc_size = sizeof(struct rk3399_clk_priv), |
|
|
|
@ -819,6 +877,9 @@ U_BOOT_DRIVER(clk_rk3399) = { |
|
|
|
|
.ops = &rk3399_clk_ops, |
|
|
|
|
.bind = rk3399_clk_bind, |
|
|
|
|
.probe = rk3399_clk_probe, |
|
|
|
|
#if CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
.platdata_auto_alloc_size = sizeof(struct rk3399_clk_plat), |
|
|
|
|
#endif |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static ulong rk3399_i2c_get_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id) |
|
|
|
@ -930,6 +991,7 @@ static struct clk_ops rk3399_pmuclk_ops = { |
|
|
|
|
.set_rate = rk3399_pmuclk_set_rate, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#ifndef CONFIG_SPL_BUILD |
|
|
|
|
static void pmuclk_init(struct rk3399_pmucru *pmucru) |
|
|
|
|
{ |
|
|
|
|
u32 pclk_div; |
|
|
|
@ -939,27 +1001,35 @@ static void pmuclk_init(struct rk3399_pmucru *pmucru) |
|
|
|
|
|
|
|
|
|
/* 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); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static int rk3399_pmuclk_probe(struct udevice *dev) |
|
|
|
|
{ |
|
|
|
|
struct rk3399_pmuclk_priv *priv = dev_get_priv(dev); |
|
|
|
|
|
|
|
|
|
pmuclk_init(priv->pmucru); |
|
|
|
|
#if CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
struct rk3399_pmuclk_plat *plat = dev_get_platdata(dev); |
|
|
|
|
|
|
|
|
|
priv->pmucru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifndef CONFIG_SPL_BUILD |
|
|
|
|
pmuclk_init(priv->pmucru); |
|
|
|
|
#endif |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev) |
|
|
|
|
{ |
|
|
|
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
struct rk3399_pmuclk_priv *priv = dev_get_priv(dev); |
|
|
|
|
|
|
|
|
|
priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev); |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -969,11 +1039,14 @@ static const struct udevice_id rk3399_pmuclk_ids[] = { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = { |
|
|
|
|
.name = "pmuclk_rk3399", |
|
|
|
|
.name = "rockchip_rk3399_pmucru", |
|
|
|
|
.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, |
|
|
|
|
#if CONFIG_IS_ENABLED(OF_PLATDATA) |
|
|
|
|
.platdata_auto_alloc_size = sizeof(struct rk3399_pmuclk_plat), |
|
|
|
|
#endif |
|
|
|
|
}; |
|
|
|
|