rockchip: clk: rk3399: update driver for spl

Add ddr clock setting, add rockchip_get_pmucru API,
and enable of-platdata support.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Added rockchip tag and fix pmuclk_init() build warning:
Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Kever Yang 2017-02-13 17:38:56 +08:00 committed by Simon Glass
parent fa72de1045
commit 5ae2fd9724
5 changed files with 125 additions and 15 deletions

View File

@ -63,6 +63,13 @@ static inline u32 clk_get_divisor(ulong input_rate, uint output_rate)
*/ */
void *rockchip_get_cru(void); void *rockchip_get_cru(void);
/**
* rockchip_get_pmucru() - get a pointer to the clock/reset unit registers
*
* @return pointer to registers, or -ve error on error
*/
void *rockchip_get_pmucru(void);
struct rk3288_cru; struct rk3288_cru;
struct rk3288_grf; struct rk3288_grf;

View File

@ -15,6 +15,11 @@ struct rk3399_clk_priv {
ulong rate; ulong rate;
}; };
struct rk3399_pmuclk_priv {
struct rk3399_pmucru *pmucru;
ulong rate;
};
struct rk3399_pmucru { struct rk3399_pmucru {
u32 ppll_con[6]; u32 ppll_con[6];
u32 reserved[0x1a]; u32 reserved[0x1a];

View File

@ -31,3 +31,24 @@ void *rockchip_get_cru(void)
return priv->cru; return priv->cru;
} }
static int rockchip_get_pmucruclk(struct udevice **devp)
{
return uclass_get_device_by_driver(UCLASS_CLK,
DM_GET_DRIVER(rockchip_rk3399_pmuclk), devp);
}
void *rockchip_get_pmucru(void)
{
struct rk3399_pmuclk_priv *priv;
struct udevice *dev;
int ret;
ret = rockchip_get_pmucruclk(&dev);
if (ret)
return ERR_PTR(ret);
priv = dev_get_priv(dev);
return priv->pmucru;
}

View File

@ -7,7 +7,9 @@
#include <common.h> #include <common.h>
#include <clk-uclass.h> #include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <dt-structs.h>
#include <errno.h> #include <errno.h>
#include <mapmem.h>
#include <syscon.h> #include <syscon.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/clock.h> #include <asm/arch/clock.h>
@ -18,10 +20,16 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
struct rk3399_pmuclk_priv { #if CONFIG_IS_ENABLED(OF_PLATDATA)
struct rk3399_pmucru *pmucru; struct rk3399_clk_plat {
struct dtd_rockchip_rk3399_cru dtd;
}; };
struct rk3399_pmuclk_plat {
struct dtd_rockchip_rk3399_pmucru dtd;
};
#endif
struct pll_div { struct pll_div {
u32 refdiv; u32 refdiv;
u32 fbdiv; u32 fbdiv;
@ -381,6 +389,7 @@ static int pll_para_config(u32 freq_hz, struct pll_div *div)
return 0; return 0;
} }
#ifdef CONFIG_SPL_BUILD
static void rkclk_init(struct rk3399_cru *cru) static void rkclk_init(struct rk3399_cru *cru)
{ {
u32 aclk_div; u32 aclk_div;
@ -456,6 +465,7 @@ static void rkclk_init(struct rk3399_cru *cru)
hclk_div << HCLK_PERILP1_DIV_CON_SHIFT | hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT); HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT);
} }
#endif
void rk3399_configure_cpu(struct rk3399_cru *cru, void rk3399_configure_cpu(struct rk3399_cru *cru,
enum apll_l_frequencies apll_l_freq) 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); 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) static ulong rk3399_clk_get_rate(struct clk *clk)
{ {
struct rk3399_clk_priv *priv = dev_get_priv(clk->dev); 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: case DCLK_VOP1:
ret = rk3399_vop_set_clk(priv->cru, clk->id, rate); ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
break; break;
case SCLK_DDRCLK:
ret = rk3399_ddr_set_clk(priv->cru, rate);
break;
default: default:
return -ENOENT; return -ENOENT;
} }
@ -777,19 +828,26 @@ static struct clk_ops rk3399_clk_ops = {
static int rk3399_clk_probe(struct udevice *dev) static int rk3399_clk_probe(struct udevice *dev)
{ {
#ifdef CONFIG_SPL_BUILD
struct rk3399_clk_priv *priv = dev_get_priv(dev); 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; return 0;
} }
static int rk3399_clk_ofdata_to_platdata(struct udevice *dev) 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); struct rk3399_clk_priv *priv = dev_get_priv(dev);
priv->cru = (struct rk3399_cru *)dev_get_addr(dev); priv->cru = (struct rk3399_cru *)dev_get_addr(dev);
#endif
return 0; return 0;
} }
@ -811,7 +869,7 @@ static const struct udevice_id rk3399_clk_ids[] = {
}; };
U_BOOT_DRIVER(clk_rk3399) = { U_BOOT_DRIVER(clk_rk3399) = {
.name = "clk_rk3399", .name = "rockchip_rk3399_cru",
.id = UCLASS_CLK, .id = UCLASS_CLK,
.of_match = rk3399_clk_ids, .of_match = rk3399_clk_ids,
.priv_auto_alloc_size = sizeof(struct rk3399_clk_priv), .priv_auto_alloc_size = sizeof(struct rk3399_clk_priv),
@ -819,6 +877,9 @@ U_BOOT_DRIVER(clk_rk3399) = {
.ops = &rk3399_clk_ops, .ops = &rk3399_clk_ops,
.bind = rk3399_clk_bind, .bind = rk3399_clk_bind,
.probe = rk3399_clk_probe, .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) 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, .set_rate = rk3399_pmuclk_set_rate,
}; };
#ifndef CONFIG_SPL_BUILD
static void pmuclk_init(struct rk3399_pmucru *pmucru) static void pmuclk_init(struct rk3399_pmucru *pmucru)
{ {
u32 pclk_div; u32 pclk_div;
@ -939,27 +1001,35 @@ static void pmuclk_init(struct rk3399_pmucru *pmucru)
/* configure pmu pclk */ /* configure pmu pclk */
pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1; 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], rk_clrsetreg(&pmucru->pmucru_clksel[0],
PMU_PCLK_DIV_CON_MASK, PMU_PCLK_DIV_CON_MASK,
pclk_div << PMU_PCLK_DIV_CON_SHIFT); pclk_div << PMU_PCLK_DIV_CON_SHIFT);
} }
#endif
static int rk3399_pmuclk_probe(struct udevice *dev) static int rk3399_pmuclk_probe(struct udevice *dev)
{ {
struct rk3399_pmuclk_priv *priv = dev_get_priv(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; return 0;
} }
static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev) 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); struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev); priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev);
#endif
return 0; return 0;
} }
@ -969,11 +1039,14 @@ static const struct udevice_id rk3399_pmuclk_ids[] = {
}; };
U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = { U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = {
.name = "pmuclk_rk3399", .name = "rockchip_rk3399_pmucru",
.id = UCLASS_CLK, .id = UCLASS_CLK,
.of_match = rk3399_pmuclk_ids, .of_match = rk3399_pmuclk_ids,
.priv_auto_alloc_size = sizeof(struct rk3399_pmuclk_priv), .priv_auto_alloc_size = sizeof(struct rk3399_pmuclk_priv),
.ofdata_to_platdata = rk3399_pmuclk_ofdata_to_platdata, .ofdata_to_platdata = rk3399_pmuclk_ofdata_to_platdata,
.ops = &rk3399_pmuclk_ops, .ops = &rk3399_pmuclk_ops,
.probe = rk3399_pmuclk_probe, .probe = rk3399_pmuclk_probe,
#if CONFIG_IS_ENABLED(OF_PLATDATA)
.platdata_auto_alloc_size = sizeof(struct rk3399_pmuclk_plat),
#endif
}; };

View File

@ -122,6 +122,10 @@
#define SCLK_DPHY_RX0_CFG 165 #define SCLK_DPHY_RX0_CFG 165
#define SCLK_RMII_SRC 166 #define SCLK_RMII_SRC 166
#define SCLK_PCIEPHY_REF100M 167 #define SCLK_PCIEPHY_REF100M 167
#define SCLK_USBPHY0_480M_SRC 168
#define SCLK_USBPHY1_480M_SRC 169
#define SCLK_DDRCLK 170
#define SCLK_TESTOUT2 171
#define DCLK_VOP0 180 #define DCLK_VOP0 180
#define DCLK_VOP1 181 #define DCLK_VOP1 181
@ -589,13 +593,13 @@
#define SRST_P_SPI0 214 #define SRST_P_SPI0 214
#define SRST_P_SPI1 215 #define SRST_P_SPI1 215
#define SRST_P_SPI2 216 #define SRST_P_SPI2 216
#define SRST_P_SPI3 217 #define SRST_P_SPI4 217
#define SRST_P_SPI4 218 #define SRST_P_SPI5 218
#define SRST_SPI0 219 #define SRST_SPI0 219
#define SRST_SPI1 220 #define SRST_SPI1 220
#define SRST_SPI2 221 #define SRST_SPI2 221
#define SRST_SPI3 222 #define SRST_SPI4 222
#define SRST_SPI4 223 #define SRST_SPI5 223
/* cru_softrst_con14 */ /* cru_softrst_con14 */
#define SRST_I2S0_8CH 224 #define SRST_I2S0_8CH 224
@ -717,8 +721,8 @@
#define SRST_H_CM0S_NOC 3 #define SRST_H_CM0S_NOC 3
#define SRST_DBG_CM0S 4 #define SRST_DBG_CM0S 4
#define SRST_PO_CM0S 5 #define SRST_PO_CM0S 5
#define SRST_P_SPI6 6 #define SRST_P_SPI3 6
#define SRST_SPI6 7 #define SRST_SPI3 7
#define SRST_P_TIMER_0_1 8 #define SRST_P_TIMER_0_1 8
#define SRST_P_TIMER_0 9 #define SRST_P_TIMER_0 9
#define SRST_P_TIMER_1 10 #define SRST_P_TIMER_1 10