2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * Author: Thomas Abraham <thomas.ab@samsung.com>
5 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6 * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This file contains the utility function to register CPU clock for Samsung
13 * Exynos platforms. A CPU clock is defined as a clock supplied to a CPU or a
14 * group of CPUs. The CPU clock is typically derived from a hierarchy of clock
15 * blocks which includes mux and divider blocks. There are a number of other
16 * auxiliary clocks supplied to the CPU domain such as the debug blocks and AXI
17 * clock for CPU domain. The rates of these auxiliary clocks are related to the
18 * CPU clock rate and this relation is usually specified in the hardware manual
19 * of the SoC or supplied after the SoC characterization.
21 * The below implementation of the CPU clock allows the rate changes of the CPU
22 * clock and the corresponding rate changes of the auxillary clocks of the CPU
23 * domain. The platform clock driver provides a clock register configuration
24 * for each configurable rate which is then used to program the clock hardware
25 * registers to acheive a fast co-oridinated rate change for all the CPU domain
28 * On a rate change request for the CPU clock, the rate change is propagated
29 * upto the PLL supplying the clock to the CPU domain clock blocks. While the
30 * CPU domain PLL is reconfigured, the CPU domain clocks are driven using an
31 * alternate clock source. If required, the alternate clock source is divided
32 * down in order to keep the output clock rate within the previous OPP limits.
35 #include <linux/errno.h>
36 #include <linux/slab.h>
37 #include <linux/clk.h>
38 #include <linux/clk-provider.h>
41 #define E4210_SRC_CPU 0x0
42 #define E4210_STAT_CPU 0x200
43 #define E4210_DIV_CPU0 0x300
44 #define E4210_DIV_CPU1 0x304
45 #define E4210_DIV_STAT_CPU0 0x400
46 #define E4210_DIV_STAT_CPU1 0x404
48 #define E5433_MUX_SEL2 0x008
49 #define E5433_MUX_STAT2 0x208
50 #define E5433_DIV_CPU0 0x400
51 #define E5433_DIV_CPU1 0x404
52 #define E5433_DIV_STAT_CPU0 0x500
53 #define E5433_DIV_STAT_CPU1 0x504
55 #define E4210_DIV0_RATIO0_MASK 0x7
56 #define E4210_DIV1_HPM_MASK (0x7 << 4)
57 #define E4210_DIV1_COPY_MASK (0x7 << 0)
58 #define E4210_MUX_HPM_MASK (1 << 20)
59 #define E4210_DIV0_ATB_SHIFT 16
60 #define E4210_DIV0_ATB_MASK (DIV_MASK << E4210_DIV0_ATB_SHIFT)
64 #define DIV_MASK_ALL 0xffffffff
68 * Helper function to wait until divider(s) have stabilized after the divider
71 static void wait_until_divider_stable(void __iomem
*div_reg
, unsigned long mask
)
73 unsigned long timeout
= jiffies
+ msecs_to_jiffies(10);
76 if (!(readl(div_reg
) & mask
))
78 } while (time_before(jiffies
, timeout
));
80 if (!(readl(div_reg
) & mask
))
83 pr_err("%s: timeout in divider stablization\n", __func__
);
87 * Helper function to wait until mux has stabilized after the mux selection
90 static void wait_until_mux_stable(void __iomem
*mux_reg
, u32 mux_pos
,
91 unsigned long mux_value
)
93 unsigned long timeout
= jiffies
+ msecs_to_jiffies(10);
96 if (((readl(mux_reg
) >> mux_pos
) & MUX_MASK
) == mux_value
)
98 } while (time_before(jiffies
, timeout
));
100 if (((readl(mux_reg
) >> mux_pos
) & MUX_MASK
) == mux_value
)
103 pr_err("%s: re-parenting mux timed-out\n", __func__
);
106 /* common round rate callback useable for all types of CPU clocks */
107 static long exynos_cpuclk_round_rate(struct clk_hw
*hw
,
108 unsigned long drate
, unsigned long *prate
)
110 struct clk_hw
*parent
= clk_hw_get_parent(hw
);
111 *prate
= clk_hw_round_rate(parent
, drate
);
115 /* common recalc rate callback useable for all types of CPU clocks */
116 static unsigned long exynos_cpuclk_recalc_rate(struct clk_hw
*hw
,
117 unsigned long parent_rate
)
120 * The CPU clock output (armclk) rate is the same as its parent
121 * rate. Although there exist certain dividers inside the CPU
122 * clock block that could be used to divide the parent clock,
123 * the driver does not make use of them currently, except during
124 * frequency transitions.
129 static const struct clk_ops exynos_cpuclk_clk_ops
= {
130 .recalc_rate
= exynos_cpuclk_recalc_rate
,
131 .round_rate
= exynos_cpuclk_round_rate
,
135 * Helper function to set the 'safe' dividers for the CPU clock. The parameters
136 * div and mask contain the divider value and the register bit mask of the
137 * dividers to be programmed.
139 static void exynos_set_safe_div(void __iomem
*base
, unsigned long div
,
144 div0
= readl(base
+ E4210_DIV_CPU0
);
145 div0
= (div0
& ~mask
) | (div
& mask
);
146 writel(div0
, base
+ E4210_DIV_CPU0
);
147 wait_until_divider_stable(base
+ E4210_DIV_STAT_CPU0
, mask
);
150 /* handler for pre-rate change notification from parent clock */
151 static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data
*ndata
,
152 struct exynos_cpuclk
*cpuclk
, void __iomem
*base
)
154 const struct exynos_cpuclk_cfg_data
*cfg_data
= cpuclk
->cfg
;
155 unsigned long alt_prate
= clk_get_rate(cpuclk
->alt_parent
);
156 unsigned long alt_div
= 0, alt_div_mask
= DIV_MASK
;
157 unsigned long div0
, div1
= 0, mux_reg
;
160 /* find out the divider values to use for clock data */
161 while ((cfg_data
->prate
* 1000) != ndata
->new_rate
) {
162 if (cfg_data
->prate
== 0)
167 spin_lock_irqsave(cpuclk
->lock
, flags
);
170 * For the selected PLL clock frequency, get the pre-defined divider
171 * values. If the clock for sclk_hpm is not sourced from apll, then
172 * the values for DIV_COPY and DIV_HPM dividers need not be set.
174 div0
= cfg_data
->div0
;
175 if (cpuclk
->flags
& CLK_CPU_HAS_DIV1
) {
176 div1
= cfg_data
->div1
;
177 if (readl(base
+ E4210_SRC_CPU
) & E4210_MUX_HPM_MASK
)
178 div1
= readl(base
+ E4210_DIV_CPU1
) &
179 (E4210_DIV1_HPM_MASK
| E4210_DIV1_COPY_MASK
);
183 * If the old parent clock speed is less than the clock speed of
184 * the alternate parent, then it should be ensured that at no point
185 * the armclk speed is more than the old_prate until the dividers are
186 * set. Also workaround the issue of the dividers being set to lower
187 * values before the parent clock speed is set to new lower speed
188 * (this can result in too high speed of armclk output clocks).
190 if (alt_prate
> ndata
->old_rate
|| ndata
->old_rate
> ndata
->new_rate
) {
191 unsigned long tmp_rate
= min(ndata
->old_rate
, ndata
->new_rate
);
193 alt_div
= DIV_ROUND_UP(alt_prate
, tmp_rate
) - 1;
194 WARN_ON(alt_div
>= MAX_DIV
);
196 if (cpuclk
->flags
& CLK_CPU_NEEDS_DEBUG_ALT_DIV
) {
198 * In Exynos4210, ATB clock parent is also mout_core. So
199 * ATB clock also needs to be mantained at safe speed.
201 alt_div
|= E4210_DIV0_ATB_MASK
;
202 alt_div_mask
|= E4210_DIV0_ATB_MASK
;
204 exynos_set_safe_div(base
, alt_div
, alt_div_mask
);
208 /* select sclk_mpll as the alternate parent */
209 mux_reg
= readl(base
+ E4210_SRC_CPU
);
210 writel(mux_reg
| (1 << 16), base
+ E4210_SRC_CPU
);
211 wait_until_mux_stable(base
+ E4210_STAT_CPU
, 16, 2);
213 /* alternate parent is active now. set the dividers */
214 writel(div0
, base
+ E4210_DIV_CPU0
);
215 wait_until_divider_stable(base
+ E4210_DIV_STAT_CPU0
, DIV_MASK_ALL
);
217 if (cpuclk
->flags
& CLK_CPU_HAS_DIV1
) {
218 writel(div1
, base
+ E4210_DIV_CPU1
);
219 wait_until_divider_stable(base
+ E4210_DIV_STAT_CPU1
,
223 spin_unlock_irqrestore(cpuclk
->lock
, flags
);
227 /* handler for post-rate change notification from parent clock */
228 static int exynos_cpuclk_post_rate_change(struct clk_notifier_data
*ndata
,
229 struct exynos_cpuclk
*cpuclk
, void __iomem
*base
)
231 const struct exynos_cpuclk_cfg_data
*cfg_data
= cpuclk
->cfg
;
232 unsigned long div
= 0, div_mask
= DIV_MASK
;
233 unsigned long mux_reg
;
236 /* find out the divider values to use for clock data */
237 if (cpuclk
->flags
& CLK_CPU_NEEDS_DEBUG_ALT_DIV
) {
238 while ((cfg_data
->prate
* 1000) != ndata
->new_rate
) {
239 if (cfg_data
->prate
== 0)
245 spin_lock_irqsave(cpuclk
->lock
, flags
);
247 /* select mout_apll as the alternate parent */
248 mux_reg
= readl(base
+ E4210_SRC_CPU
);
249 writel(mux_reg
& ~(1 << 16), base
+ E4210_SRC_CPU
);
250 wait_until_mux_stable(base
+ E4210_STAT_CPU
, 16, 1);
252 if (cpuclk
->flags
& CLK_CPU_NEEDS_DEBUG_ALT_DIV
) {
253 div
|= (cfg_data
->div0
& E4210_DIV0_ATB_MASK
);
254 div_mask
|= E4210_DIV0_ATB_MASK
;
257 exynos_set_safe_div(base
, div
, div_mask
);
258 spin_unlock_irqrestore(cpuclk
->lock
, flags
);
263 * Helper function to set the 'safe' dividers for the CPU clock. The parameters
264 * div and mask contain the divider value and the register bit mask of the
265 * dividers to be programmed.
267 static void exynos5433_set_safe_div(void __iomem
*base
, unsigned long div
,
272 div0
= readl(base
+ E5433_DIV_CPU0
);
273 div0
= (div0
& ~mask
) | (div
& mask
);
274 writel(div0
, base
+ E5433_DIV_CPU0
);
275 wait_until_divider_stable(base
+ E5433_DIV_STAT_CPU0
, mask
);
278 /* handler for pre-rate change notification from parent clock */
279 static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data
*ndata
,
280 struct exynos_cpuclk
*cpuclk
, void __iomem
*base
)
282 const struct exynos_cpuclk_cfg_data
*cfg_data
= cpuclk
->cfg
;
283 unsigned long alt_prate
= clk_get_rate(cpuclk
->alt_parent
);
284 unsigned long alt_div
= 0, alt_div_mask
= DIV_MASK
;
285 unsigned long div0
, div1
= 0, mux_reg
;
288 /* find out the divider values to use for clock data */
289 while ((cfg_data
->prate
* 1000) != ndata
->new_rate
) {
290 if (cfg_data
->prate
== 0)
295 spin_lock_irqsave(cpuclk
->lock
, flags
);
298 * For the selected PLL clock frequency, get the pre-defined divider
301 div0
= cfg_data
->div0
;
302 div1
= cfg_data
->div1
;
305 * If the old parent clock speed is less than the clock speed of
306 * the alternate parent, then it should be ensured that at no point
307 * the armclk speed is more than the old_prate until the dividers are
308 * set. Also workaround the issue of the dividers being set to lower
309 * values before the parent clock speed is set to new lower speed
310 * (this can result in too high speed of armclk output clocks).
312 if (alt_prate
> ndata
->old_rate
|| ndata
->old_rate
> ndata
->new_rate
) {
313 unsigned long tmp_rate
= min(ndata
->old_rate
, ndata
->new_rate
);
315 alt_div
= DIV_ROUND_UP(alt_prate
, tmp_rate
) - 1;
316 WARN_ON(alt_div
>= MAX_DIV
);
318 exynos5433_set_safe_div(base
, alt_div
, alt_div_mask
);
322 /* select the alternate parent */
323 mux_reg
= readl(base
+ E5433_MUX_SEL2
);
324 writel(mux_reg
| 1, base
+ E5433_MUX_SEL2
);
325 wait_until_mux_stable(base
+ E5433_MUX_STAT2
, 0, 2);
327 /* alternate parent is active now. set the dividers */
328 writel(div0
, base
+ E5433_DIV_CPU0
);
329 wait_until_divider_stable(base
+ E5433_DIV_STAT_CPU0
, DIV_MASK_ALL
);
331 writel(div1
, base
+ E5433_DIV_CPU1
);
332 wait_until_divider_stable(base
+ E5433_DIV_STAT_CPU1
, DIV_MASK_ALL
);
334 spin_unlock_irqrestore(cpuclk
->lock
, flags
);
338 /* handler for post-rate change notification from parent clock */
339 static int exynos5433_cpuclk_post_rate_change(struct clk_notifier_data
*ndata
,
340 struct exynos_cpuclk
*cpuclk
, void __iomem
*base
)
342 unsigned long div
= 0, div_mask
= DIV_MASK
;
343 unsigned long mux_reg
;
346 spin_lock_irqsave(cpuclk
->lock
, flags
);
348 /* select apll as the alternate parent */
349 mux_reg
= readl(base
+ E5433_MUX_SEL2
);
350 writel(mux_reg
& ~1, base
+ E5433_MUX_SEL2
);
351 wait_until_mux_stable(base
+ E5433_MUX_STAT2
, 0, 1);
353 exynos5433_set_safe_div(base
, div
, div_mask
);
354 spin_unlock_irqrestore(cpuclk
->lock
, flags
);
359 * This notifier function is called for the pre-rate and post-rate change
360 * notifications of the parent clock of cpuclk.
362 static int exynos_cpuclk_notifier_cb(struct notifier_block
*nb
,
363 unsigned long event
, void *data
)
365 struct clk_notifier_data
*ndata
= data
;
366 struct exynos_cpuclk
*cpuclk
;
370 cpuclk
= container_of(nb
, struct exynos_cpuclk
, clk_nb
);
371 base
= cpuclk
->ctrl_base
;
373 if (event
== PRE_RATE_CHANGE
)
374 err
= exynos_cpuclk_pre_rate_change(ndata
, cpuclk
, base
);
375 else if (event
== POST_RATE_CHANGE
)
376 err
= exynos_cpuclk_post_rate_change(ndata
, cpuclk
, base
);
378 return notifier_from_errno(err
);
382 * This notifier function is called for the pre-rate and post-rate change
383 * notifications of the parent clock of cpuclk.
385 static int exynos5433_cpuclk_notifier_cb(struct notifier_block
*nb
,
386 unsigned long event
, void *data
)
388 struct clk_notifier_data
*ndata
= data
;
389 struct exynos_cpuclk
*cpuclk
;
393 cpuclk
= container_of(nb
, struct exynos_cpuclk
, clk_nb
);
394 base
= cpuclk
->ctrl_base
;
396 if (event
== PRE_RATE_CHANGE
)
397 err
= exynos5433_cpuclk_pre_rate_change(ndata
, cpuclk
, base
);
398 else if (event
== POST_RATE_CHANGE
)
399 err
= exynos5433_cpuclk_post_rate_change(ndata
, cpuclk
, base
);
401 return notifier_from_errno(err
);
404 /* helper function to register a CPU clock */
405 int __init
exynos_register_cpu_clock(struct samsung_clk_provider
*ctx
,
406 unsigned int lookup_id
, const char *name
, const char *parent
,
407 const char *alt_parent
, unsigned long offset
,
408 const struct exynos_cpuclk_cfg_data
*cfg
,
409 unsigned long num_cfgs
, unsigned long flags
)
411 struct exynos_cpuclk
*cpuclk
;
412 struct clk_init_data init
;
416 cpuclk
= kzalloc(sizeof(*cpuclk
), GFP_KERNEL
);
421 init
.flags
= CLK_SET_RATE_PARENT
;
422 init
.parent_names
= &parent
;
423 init
.num_parents
= 1;
424 init
.ops
= &exynos_cpuclk_clk_ops
;
426 cpuclk
->hw
.init
= &init
;
427 cpuclk
->ctrl_base
= ctx
->reg_base
+ offset
;
428 cpuclk
->lock
= &ctx
->lock
;
429 cpuclk
->flags
= flags
;
430 if (flags
& CLK_CPU_HAS_E5433_REGS_LAYOUT
)
431 cpuclk
->clk_nb
.notifier_call
= exynos5433_cpuclk_notifier_cb
;
433 cpuclk
->clk_nb
.notifier_call
= exynos_cpuclk_notifier_cb
;
435 cpuclk
->alt_parent
= __clk_lookup(alt_parent
);
436 if (!cpuclk
->alt_parent
) {
437 pr_err("%s: could not lookup alternate parent %s\n",
438 __func__
, alt_parent
);
443 clk
= __clk_lookup(parent
);
445 pr_err("%s: could not lookup parent clock %s\n",
451 ret
= clk_notifier_register(clk
, &cpuclk
->clk_nb
);
453 pr_err("%s: failed to register clock notifier for %s\n",
458 cpuclk
->cfg
= kmemdup(cfg
, sizeof(*cfg
) * num_cfgs
, GFP_KERNEL
);
460 pr_err("%s: could not allocate memory for cpuclk data\n",
463 goto unregister_clk_nb
;
466 clk
= clk_register(NULL
, &cpuclk
->hw
);
468 pr_err("%s: could not register cpuclk %s\n", __func__
, name
);
470 goto free_cpuclk_data
;
473 samsung_clk_add_lookup(ctx
, clk
, lookup_id
);
479 clk_notifier_unregister(__clk_lookup(parent
), &cpuclk
->clk_nb
);