diff options
Diffstat (limited to 'drivers/clk/rockchip')
-rw-r--r-- | drivers/clk/rockchip/clk-pll.c | 50 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.h | 6 |
2 files changed, 56 insertions, 0 deletions
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 1bb68910a76b..f8d3baf275b2 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c | |||
@@ -258,6 +258,55 @@ static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw) | |||
258 | return !(pllcon & RK3066_PLLCON3_PWRDOWN); | 258 | return !(pllcon & RK3066_PLLCON3_PWRDOWN); |
259 | } | 259 | } |
260 | 260 | ||
261 | static void rockchip_rk3066_pll_init(struct clk_hw *hw) | ||
262 | { | ||
263 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
264 | const struct rockchip_pll_rate_table *rate; | ||
265 | unsigned int nf, nr, no, bwadj; | ||
266 | unsigned long drate; | ||
267 | u32 pllcon; | ||
268 | |||
269 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) | ||
270 | return; | ||
271 | |||
272 | drate = __clk_get_rate(hw->clk); | ||
273 | rate = rockchip_get_pll_settings(pll, drate); | ||
274 | |||
275 | /* when no rate setting for the current rate, rely on clk_set_rate */ | ||
276 | if (!rate) | ||
277 | return; | ||
278 | |||
279 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0)); | ||
280 | nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1; | ||
281 | no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1; | ||
282 | |||
283 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1)); | ||
284 | nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1; | ||
285 | |||
286 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2)); | ||
287 | bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK; | ||
288 | |||
289 | pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n", | ||
290 | __func__, __clk_get_name(hw->clk), drate, rate->nr, nr, | ||
291 | rate->no, no, rate->nf, nf, rate->bwadj, bwadj); | ||
292 | if (rate->nr != nr || rate->no != no || rate->nf != nf | ||
293 | || rate->bwadj != bwadj) { | ||
294 | struct clk *parent = __clk_get_parent(hw->clk); | ||
295 | unsigned long prate; | ||
296 | |||
297 | if (!parent) { | ||
298 | pr_warn("%s: parent of %s not available\n", | ||
299 | __func__, __clk_get_name(hw->clk)); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", | ||
304 | __func__, __clk_get_name(hw->clk)); | ||
305 | prate = __clk_get_rate(parent); | ||
306 | rockchip_rk3066_pll_set_rate(hw, drate, prate); | ||
307 | } | ||
308 | } | ||
309 | |||
261 | static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { | 310 | static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { |
262 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, | 311 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, |
263 | .enable = rockchip_rk3066_pll_enable, | 312 | .enable = rockchip_rk3066_pll_enable, |
@@ -272,6 +321,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { | |||
272 | .enable = rockchip_rk3066_pll_enable, | 321 | .enable = rockchip_rk3066_pll_enable, |
273 | .disable = rockchip_rk3066_pll_disable, | 322 | .disable = rockchip_rk3066_pll_disable, |
274 | .is_enabled = rockchip_rk3066_pll_is_enabled, | 323 | .is_enabled = rockchip_rk3066_pll_is_enabled, |
324 | .init = rockchip_rk3066_pll_init, | ||
275 | }; | 325 | }; |
276 | 326 | ||
277 | /* | 327 | /* |
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index eefd39a3820b..dc9468132ef1 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h | |||
@@ -92,6 +92,10 @@ struct rockchip_pll_rate_table { | |||
92 | * @type: Type of PLL to be registered. | 92 | * @type: Type of PLL to be registered. |
93 | * @pll_flags: hardware-specific flags | 93 | * @pll_flags: hardware-specific flags |
94 | * @rate_table: Table of usable pll rates | 94 | * @rate_table: Table of usable pll rates |
95 | * | ||
96 | * Flags: | ||
97 | * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the | ||
98 | * rate_table parameters and ajust them if necessary. | ||
95 | */ | 99 | */ |
96 | struct rockchip_pll_clock { | 100 | struct rockchip_pll_clock { |
97 | unsigned int id; | 101 | unsigned int id; |
@@ -108,6 +112,8 @@ struct rockchip_pll_clock { | |||
108 | struct rockchip_pll_rate_table *rate_table; | 112 | struct rockchip_pll_rate_table *rate_table; |
109 | }; | 113 | }; |
110 | 114 | ||
115 | #define ROCKCHIP_PLL_SYNC_RATE BIT(0) | ||
116 | |||
111 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ | 117 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ |
112 | _lshift, _pflags, _rtable) \ | 118 | _lshift, _pflags, _rtable) \ |
113 | { \ | 119 | { \ |