diff options
-rw-r--r-- | arch/arm/mach-exynos/exynos.c | 21 | ||||
-rw-r--r-- | drivers/clk/clk.c | 3 | ||||
-rw-r--r-- | drivers/clk/samsung/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-cpu.c | 349 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-cpu.h | 73 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos4.c | 24 | ||||
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 11 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 1 | ||||
-rw-r--r-- | drivers/cpufreq/exynos-cpufreq.c | 5 | ||||
-rw-r--r-- | drivers/cpufreq/exynos-cpufreq.h | 9 | ||||
-rw-r--r-- | drivers/cpufreq/exynos4210-cpufreq.c | 184 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 1 |
12 files changed, 471 insertions, 212 deletions
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 5917a30eee33..9cb17ff1e152 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c | |||
@@ -224,6 +224,25 @@ static void __init exynos_init_irq(void) | |||
224 | exynos_map_pmu(); | 224 | exynos_map_pmu(); |
225 | } | 225 | } |
226 | 226 | ||
227 | static const struct of_device_id exynos_cpufreq_matches[] = { | ||
228 | { .compatible = "samsung,exynos4210", .data = "cpufreq-dt" }, | ||
229 | { /* sentinel */ } | ||
230 | }; | ||
231 | |||
232 | static void __init exynos_cpufreq_init(void) | ||
233 | { | ||
234 | struct device_node *root = of_find_node_by_path("/"); | ||
235 | const struct of_device_id *match; | ||
236 | |||
237 | match = of_match_node(exynos_cpufreq_matches, root); | ||
238 | if (!match) { | ||
239 | platform_device_register_simple("exynos-cpufreq", -1, NULL, 0); | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | platform_device_register_simple(match->data, -1, NULL, 0); | ||
244 | } | ||
245 | |||
227 | static void __init exynos_dt_machine_init(void) | 246 | static void __init exynos_dt_machine_init(void) |
228 | { | 247 | { |
229 | /* | 248 | /* |
@@ -245,7 +264,7 @@ static void __init exynos_dt_machine_init(void) | |||
245 | of_machine_is_compatible("samsung,exynos5250")) | 264 | of_machine_is_compatible("samsung,exynos5250")) |
246 | platform_device_register(&exynos_cpuidle); | 265 | platform_device_register(&exynos_cpuidle); |
247 | 266 | ||
248 | platform_device_register_simple("exynos-cpufreq", -1, NULL, 0); | 267 | exynos_cpufreq_init(); |
249 | 268 | ||
250 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | 269 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
251 | } | 270 | } |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 1cf479b9f3b4..059e5d25c9ba 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -1417,6 +1417,9 @@ static void clk_change_rate(struct clk_core *core) | |||
1417 | if (core->notifier_count && old_rate != core->rate) | 1417 | if (core->notifier_count && old_rate != core->rate) |
1418 | __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate); | 1418 | __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate); |
1419 | 1419 | ||
1420 | if (core->flags & CLK_RECALC_NEW_RATES) | ||
1421 | (void)clk_calc_new_rates(core, core->new_rate); | ||
1422 | |||
1420 | /* | 1423 | /* |
1421 | * Use safe iteration, as change_rate can actually swap parents | 1424 | * Use safe iteration, as change_rate can actually swap parents |
1422 | * for certain clock types. | 1425 | * for certain clock types. |
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index a17683b2cf27..5f6833ea355d 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Samsung Clock specific Makefile | 2 | # Samsung Clock specific Makefile |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o | 5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o |
6 | obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o | 6 | obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o |
7 | obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o | 7 | obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o |
8 | obj-$(CONFIG_SOC_EXYNOS4415) += clk-exynos4415.o | 8 | obj-$(CONFIG_SOC_EXYNOS4415) += clk-exynos4415.o |
diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c new file mode 100644 index 000000000000..3a1fe07cfe9e --- /dev/null +++ b/drivers/clk/samsung/clk-cpu.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
3 | * Author: Thomas Abraham <thomas.ab@samsung.com> | ||
4 | * | ||
5 | * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
6 | * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> | ||
7 | * | ||
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. | ||
11 | * | ||
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. | ||
20 | * | ||
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 | ||
26 | * clocks. | ||
27 | * | ||
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. | ||
33 | */ | ||
34 | |||
35 | #include <linux/errno.h> | ||
36 | #include "clk-cpu.h" | ||
37 | |||
38 | #define E4210_SRC_CPU 0x0 | ||
39 | #define E4210_STAT_CPU 0x200 | ||
40 | #define E4210_DIV_CPU0 0x300 | ||
41 | #define E4210_DIV_CPU1 0x304 | ||
42 | #define E4210_DIV_STAT_CPU0 0x400 | ||
43 | #define E4210_DIV_STAT_CPU1 0x404 | ||
44 | |||
45 | #define E4210_DIV0_RATIO0_MASK 0x7 | ||
46 | #define E4210_DIV1_HPM_MASK (0x7 << 4) | ||
47 | #define E4210_DIV1_COPY_MASK (0x7 << 0) | ||
48 | #define E4210_MUX_HPM_MASK (1 << 20) | ||
49 | #define E4210_DIV0_ATB_SHIFT 16 | ||
50 | #define E4210_DIV0_ATB_MASK (DIV_MASK << E4210_DIV0_ATB_SHIFT) | ||
51 | |||
52 | #define MAX_DIV 8 | ||
53 | #define DIV_MASK 7 | ||
54 | #define DIV_MASK_ALL 0xffffffff | ||
55 | #define MUX_MASK 7 | ||
56 | |||
57 | /* | ||
58 | * Helper function to wait until divider(s) have stabilized after the divider | ||
59 | * value has changed. | ||
60 | */ | ||
61 | static void wait_until_divider_stable(void __iomem *div_reg, unsigned long mask) | ||
62 | { | ||
63 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
64 | |||
65 | do { | ||
66 | if (!(readl(div_reg) & mask)) | ||
67 | return; | ||
68 | } while (time_before(jiffies, timeout)); | ||
69 | |||
70 | if (!(readl(div_reg) & mask)) | ||
71 | return; | ||
72 | |||
73 | pr_err("%s: timeout in divider stablization\n", __func__); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Helper function to wait until mux has stabilized after the mux selection | ||
78 | * value was changed. | ||
79 | */ | ||
80 | static void wait_until_mux_stable(void __iomem *mux_reg, u32 mux_pos, | ||
81 | unsigned long mux_value) | ||
82 | { | ||
83 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
84 | |||
85 | do { | ||
86 | if (((readl(mux_reg) >> mux_pos) & MUX_MASK) == mux_value) | ||
87 | return; | ||
88 | } while (time_before(jiffies, timeout)); | ||
89 | |||
90 | if (((readl(mux_reg) >> mux_pos) & MUX_MASK) == mux_value) | ||
91 | return; | ||
92 | |||
93 | pr_err("%s: re-parenting mux timed-out\n", __func__); | ||
94 | } | ||
95 | |||
96 | /* common round rate callback useable for all types of CPU clocks */ | ||
97 | static long exynos_cpuclk_round_rate(struct clk_hw *hw, | ||
98 | unsigned long drate, unsigned long *prate) | ||
99 | { | ||
100 | struct clk *parent = __clk_get_parent(hw->clk); | ||
101 | *prate = __clk_round_rate(parent, drate); | ||
102 | return *prate; | ||
103 | } | ||
104 | |||
105 | /* common recalc rate callback useable for all types of CPU clocks */ | ||
106 | static unsigned long exynos_cpuclk_recalc_rate(struct clk_hw *hw, | ||
107 | unsigned long parent_rate) | ||
108 | { | ||
109 | /* | ||
110 | * The CPU clock output (armclk) rate is the same as its parent | ||
111 | * rate. Although there exist certain dividers inside the CPU | ||
112 | * clock block that could be used to divide the parent clock, | ||
113 | * the driver does not make use of them currently, except during | ||
114 | * frequency transitions. | ||
115 | */ | ||
116 | return parent_rate; | ||
117 | } | ||
118 | |||
119 | static const struct clk_ops exynos_cpuclk_clk_ops = { | ||
120 | .recalc_rate = exynos_cpuclk_recalc_rate, | ||
121 | .round_rate = exynos_cpuclk_round_rate, | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * Helper function to set the 'safe' dividers for the CPU clock. The parameters | ||
126 | * div and mask contain the divider value and the register bit mask of the | ||
127 | * dividers to be programmed. | ||
128 | */ | ||
129 | static void exynos_set_safe_div(void __iomem *base, unsigned long div, | ||
130 | unsigned long mask) | ||
131 | { | ||
132 | unsigned long div0; | ||
133 | |||
134 | div0 = readl(base + E4210_DIV_CPU0); | ||
135 | div0 = (div0 & ~mask) | (div & mask); | ||
136 | writel(div0, base + E4210_DIV_CPU0); | ||
137 | wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, mask); | ||
138 | } | ||
139 | |||
140 | /* handler for pre-rate change notification from parent clock */ | ||
141 | static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata, | ||
142 | struct exynos_cpuclk *cpuclk, void __iomem *base) | ||
143 | { | ||
144 | const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg; | ||
145 | unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent); | ||
146 | unsigned long alt_div = 0, alt_div_mask = DIV_MASK; | ||
147 | unsigned long div0, div1 = 0, mux_reg; | ||
148 | |||
149 | /* find out the divider values to use for clock data */ | ||
150 | while ((cfg_data->prate * 1000) != ndata->new_rate) { | ||
151 | if (cfg_data->prate == 0) | ||
152 | return -EINVAL; | ||
153 | cfg_data++; | ||
154 | } | ||
155 | |||
156 | spin_lock(cpuclk->lock); | ||
157 | |||
158 | /* | ||
159 | * For the selected PLL clock frequency, get the pre-defined divider | ||
160 | * values. If the clock for sclk_hpm is not sourced from apll, then | ||
161 | * the values for DIV_COPY and DIV_HPM dividers need not be set. | ||
162 | */ | ||
163 | div0 = cfg_data->div0; | ||
164 | if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) { | ||
165 | div1 = cfg_data->div1; | ||
166 | if (readl(base + E4210_SRC_CPU) & E4210_MUX_HPM_MASK) | ||
167 | div1 = readl(base + E4210_DIV_CPU1) & | ||
168 | (E4210_DIV1_HPM_MASK | E4210_DIV1_COPY_MASK); | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * If the old parent clock speed is less than the clock speed of | ||
173 | * the alternate parent, then it should be ensured that at no point | ||
174 | * the armclk speed is more than the old_prate until the dividers are | ||
175 | * set. Also workaround the issue of the dividers being set to lower | ||
176 | * values before the parent clock speed is set to new lower speed | ||
177 | * (this can result in too high speed of armclk output clocks). | ||
178 | */ | ||
179 | if (alt_prate > ndata->old_rate || ndata->old_rate > ndata->new_rate) { | ||
180 | unsigned long tmp_rate = min(ndata->old_rate, ndata->new_rate); | ||
181 | |||
182 | alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1; | ||
183 | WARN_ON(alt_div >= MAX_DIV); | ||
184 | |||
185 | if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) { | ||
186 | /* | ||
187 | * In Exynos4210, ATB clock parent is also mout_core. So | ||
188 | * ATB clock also needs to be mantained at safe speed. | ||
189 | */ | ||
190 | alt_div |= E4210_DIV0_ATB_MASK; | ||
191 | alt_div_mask |= E4210_DIV0_ATB_MASK; | ||
192 | } | ||
193 | exynos_set_safe_div(base, alt_div, alt_div_mask); | ||
194 | div0 |= alt_div; | ||
195 | } | ||
196 | |||
197 | /* select sclk_mpll as the alternate parent */ | ||
198 | mux_reg = readl(base + E4210_SRC_CPU); | ||
199 | writel(mux_reg | (1 << 16), base + E4210_SRC_CPU); | ||
200 | wait_until_mux_stable(base + E4210_STAT_CPU, 16, 2); | ||
201 | |||
202 | /* alternate parent is active now. set the dividers */ | ||
203 | writel(div0, base + E4210_DIV_CPU0); | ||
204 | wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, DIV_MASK_ALL); | ||
205 | |||
206 | if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) { | ||
207 | writel(div1, base + E4210_DIV_CPU1); | ||
208 | wait_until_divider_stable(base + E4210_DIV_STAT_CPU1, | ||
209 | DIV_MASK_ALL); | ||
210 | } | ||
211 | |||
212 | spin_unlock(cpuclk->lock); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | /* handler for post-rate change notification from parent clock */ | ||
217 | static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata, | ||
218 | struct exynos_cpuclk *cpuclk, void __iomem *base) | ||
219 | { | ||
220 | const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg; | ||
221 | unsigned long div = 0, div_mask = DIV_MASK; | ||
222 | unsigned long mux_reg; | ||
223 | |||
224 | /* find out the divider values to use for clock data */ | ||
225 | if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) { | ||
226 | while ((cfg_data->prate * 1000) != ndata->new_rate) { | ||
227 | if (cfg_data->prate == 0) | ||
228 | return -EINVAL; | ||
229 | cfg_data++; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | spin_lock(cpuclk->lock); | ||
234 | |||
235 | /* select mout_apll as the alternate parent */ | ||
236 | mux_reg = readl(base + E4210_SRC_CPU); | ||
237 | writel(mux_reg & ~(1 << 16), base + E4210_SRC_CPU); | ||
238 | wait_until_mux_stable(base + E4210_STAT_CPU, 16, 1); | ||
239 | |||
240 | if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) { | ||
241 | div |= (cfg_data->div0 & E4210_DIV0_ATB_MASK); | ||
242 | div_mask |= E4210_DIV0_ATB_MASK; | ||
243 | } | ||
244 | |||
245 | exynos_set_safe_div(base, div, div_mask); | ||
246 | spin_unlock(cpuclk->lock); | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * This notifier function is called for the pre-rate and post-rate change | ||
252 | * notifications of the parent clock of cpuclk. | ||
253 | */ | ||
254 | static int exynos_cpuclk_notifier_cb(struct notifier_block *nb, | ||
255 | unsigned long event, void *data) | ||
256 | { | ||
257 | struct clk_notifier_data *ndata = data; | ||
258 | struct exynos_cpuclk *cpuclk; | ||
259 | void __iomem *base; | ||
260 | int err = 0; | ||
261 | |||
262 | cpuclk = container_of(nb, struct exynos_cpuclk, clk_nb); | ||
263 | base = cpuclk->ctrl_base; | ||
264 | |||
265 | if (event == PRE_RATE_CHANGE) | ||
266 | err = exynos_cpuclk_pre_rate_change(ndata, cpuclk, base); | ||
267 | else if (event == POST_RATE_CHANGE) | ||
268 | err = exynos_cpuclk_post_rate_change(ndata, cpuclk, base); | ||
269 | |||
270 | return notifier_from_errno(err); | ||
271 | } | ||
272 | |||
273 | /* helper function to register a CPU clock */ | ||
274 | int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, | ||
275 | unsigned int lookup_id, const char *name, const char *parent, | ||
276 | const char *alt_parent, unsigned long offset, | ||
277 | const struct exynos_cpuclk_cfg_data *cfg, | ||
278 | unsigned long num_cfgs, unsigned long flags) | ||
279 | { | ||
280 | struct exynos_cpuclk *cpuclk; | ||
281 | struct clk_init_data init; | ||
282 | struct clk *clk; | ||
283 | int ret = 0; | ||
284 | |||
285 | cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL); | ||
286 | if (!cpuclk) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | init.name = name; | ||
290 | init.flags = CLK_SET_RATE_PARENT; | ||
291 | init.parent_names = &parent; | ||
292 | init.num_parents = 1; | ||
293 | init.ops = &exynos_cpuclk_clk_ops; | ||
294 | |||
295 | cpuclk->hw.init = &init; | ||
296 | cpuclk->ctrl_base = ctx->reg_base + offset; | ||
297 | cpuclk->lock = &ctx->lock; | ||
298 | cpuclk->flags = flags; | ||
299 | cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb; | ||
300 | |||
301 | cpuclk->alt_parent = __clk_lookup(alt_parent); | ||
302 | if (!cpuclk->alt_parent) { | ||
303 | pr_err("%s: could not lookup alternate parent %s\n", | ||
304 | __func__, alt_parent); | ||
305 | ret = -EINVAL; | ||
306 | goto free_cpuclk; | ||
307 | } | ||
308 | |||
309 | clk = __clk_lookup(parent); | ||
310 | if (!clk) { | ||
311 | pr_err("%s: could not lookup parent clock %s\n", | ||
312 | __func__, parent); | ||
313 | ret = -EINVAL; | ||
314 | goto free_cpuclk; | ||
315 | } | ||
316 | |||
317 | ret = clk_notifier_register(clk, &cpuclk->clk_nb); | ||
318 | if (ret) { | ||
319 | pr_err("%s: failed to register clock notifier for %s\n", | ||
320 | __func__, name); | ||
321 | goto free_cpuclk; | ||
322 | } | ||
323 | |||
324 | cpuclk->cfg = kmemdup(cfg, sizeof(*cfg) * num_cfgs, GFP_KERNEL); | ||
325 | if (!cpuclk->cfg) { | ||
326 | pr_err("%s: could not allocate memory for cpuclk data\n", | ||
327 | __func__); | ||
328 | ret = -ENOMEM; | ||
329 | goto unregister_clk_nb; | ||
330 | } | ||
331 | |||
332 | clk = clk_register(NULL, &cpuclk->hw); | ||
333 | if (IS_ERR(clk)) { | ||
334 | pr_err("%s: could not register cpuclk %s\n", __func__, name); | ||
335 | ret = PTR_ERR(clk); | ||
336 | goto free_cpuclk_data; | ||
337 | } | ||
338 | |||
339 | samsung_clk_add_lookup(ctx, clk, lookup_id); | ||
340 | return 0; | ||
341 | |||
342 | free_cpuclk_data: | ||
343 | kfree(cpuclk->cfg); | ||
344 | unregister_clk_nb: | ||
345 | clk_notifier_unregister(__clk_lookup(parent), &cpuclk->clk_nb); | ||
346 | free_cpuclk: | ||
347 | kfree(cpuclk); | ||
348 | return ret; | ||
349 | } | ||
diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h new file mode 100644 index 000000000000..37874d3c3165 --- /dev/null +++ b/drivers/clk/samsung/clk-cpu.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Common Clock Framework support for all PLL's in Samsung platforms | ||
9 | */ | ||
10 | |||
11 | #ifndef __SAMSUNG_CLK_CPU_H | ||
12 | #define __SAMSUNG_CLK_CPU_H | ||
13 | |||
14 | #include "clk.h" | ||
15 | |||
16 | /** | ||
17 | * struct exynos_cpuclk_data: config data to setup cpu clocks. | ||
18 | * @prate: frequency of the primary parent clock (in KHz). | ||
19 | * @div0: value to be programmed in the div_cpu0 register. | ||
20 | * @div1: value to be programmed in the div_cpu1 register. | ||
21 | * | ||
22 | * This structure holds the divider configuration data for dividers in the CPU | ||
23 | * clock domain. The parent frequency at which these divider values are valid is | ||
24 | * specified in @prate. The @prate is the frequency of the primary parent clock. | ||
25 | * For CPU clock domains that do not have a DIV1 register, the @div1 member | ||
26 | * value is not used. | ||
27 | */ | ||
28 | struct exynos_cpuclk_cfg_data { | ||
29 | unsigned long prate; | ||
30 | unsigned long div0; | ||
31 | unsigned long div1; | ||
32 | }; | ||
33 | |||
34 | /** | ||
35 | * struct exynos_cpuclk: information about clock supplied to a CPU core. | ||
36 | * @hw: handle between CCF and CPU clock. | ||
37 | * @alt_parent: alternate parent clock to use when switching the speed | ||
38 | * of the primary parent clock. | ||
39 | * @ctrl_base: base address of the clock controller. | ||
40 | * @lock: cpu clock domain register access lock. | ||
41 | * @cfg: cpu clock rate configuration data. | ||
42 | * @num_cfgs: number of array elements in @cfg array. | ||
43 | * @clk_nb: clock notifier registered for changes in clock speed of the | ||
44 | * primary parent clock. | ||
45 | * @flags: configuration flags for the CPU clock. | ||
46 | * | ||
47 | * This structure holds information required for programming the CPU clock for | ||
48 | * various clock speeds. | ||
49 | */ | ||
50 | struct exynos_cpuclk { | ||
51 | struct clk_hw hw; | ||
52 | struct clk *alt_parent; | ||
53 | void __iomem *ctrl_base; | ||
54 | spinlock_t *lock; | ||
55 | const struct exynos_cpuclk_cfg_data *cfg; | ||
56 | const unsigned long num_cfgs; | ||
57 | struct notifier_block clk_nb; | ||
58 | unsigned long flags; | ||
59 | |||
60 | /* The CPU clock registers has DIV1 configuration register */ | ||
61 | #define CLK_CPU_HAS_DIV1 (1 << 0) | ||
62 | /* When ALT parent is active, debug clocks need safe divider values */ | ||
63 | #define CLK_CPU_NEEDS_DEBUG_ALT_DIV (1 << 1) | ||
64 | }; | ||
65 | |||
66 | extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, | ||
67 | unsigned int lookup_id, const char *name, | ||
68 | const char *parent, const char *alt_parent, | ||
69 | unsigned long offset, | ||
70 | const struct exynos_cpuclk_cfg_data *cfg, | ||
71 | unsigned long num_cfgs, unsigned long flags); | ||
72 | |||
73 | #endif /* __SAMSUNG_CLK_CPU_H */ | ||
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 714d6ba782c8..cae2c048488d 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/syscore_ops.h> | 19 | #include <linux/syscore_ops.h> |
20 | 20 | ||
21 | #include "clk.h" | 21 | #include "clk.h" |
22 | #include "clk-cpu.h" | ||
22 | 23 | ||
23 | /* Exynos4 clock controller register offsets */ | 24 | /* Exynos4 clock controller register offsets */ |
24 | #define SRC_LEFTBUS 0x4200 | 25 | #define SRC_LEFTBUS 0x4200 |
@@ -534,7 +535,8 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda | |||
534 | /* list of mux clocks supported in all exynos4 soc's */ | 535 | /* list of mux clocks supported in all exynos4 soc's */ |
535 | static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { | 536 | static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { |
536 | MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, | 537 | MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, |
537 | CLK_SET_RATE_PARENT, 0, "mout_apll"), | 538 | CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0, |
539 | "mout_apll"), | ||
538 | MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), | 540 | MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), |
539 | MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1), | 541 | MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1), |
540 | MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), | 542 | MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), |
@@ -1378,6 +1380,22 @@ static void __init exynos4x12_core_down_clock(void) | |||
1378 | __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2); | 1380 | __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2); |
1379 | } | 1381 | } |
1380 | 1382 | ||
1383 | #define E4210_CPU_DIV0(apll, pclk_dbg, atb, periph, corem1, corem0) \ | ||
1384 | (((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \ | ||
1385 | ((periph) << 12) | ((corem1) << 8) | ((corem0) << 4)) | ||
1386 | #define E4210_CPU_DIV1(hpm, copy) \ | ||
1387 | (((hpm) << 4) | ((copy) << 0)) | ||
1388 | |||
1389 | static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = { | ||
1390 | { 1200000, E4210_CPU_DIV0(7, 1, 4, 3, 7, 3), E4210_CPU_DIV1(0, 5), }, | ||
1391 | { 1000000, E4210_CPU_DIV0(7, 1, 4, 3, 7, 3), E4210_CPU_DIV1(0, 4), }, | ||
1392 | { 800000, E4210_CPU_DIV0(7, 1, 3, 3, 7, 3), E4210_CPU_DIV1(0, 3), }, | ||
1393 | { 500000, E4210_CPU_DIV0(7, 1, 3, 3, 7, 3), E4210_CPU_DIV1(0, 3), }, | ||
1394 | { 400000, E4210_CPU_DIV0(7, 1, 3, 3, 7, 3), E4210_CPU_DIV1(0, 3), }, | ||
1395 | { 200000, E4210_CPU_DIV0(0, 1, 1, 1, 3, 1), E4210_CPU_DIV1(0, 3), }, | ||
1396 | { 0 }, | ||
1397 | }; | ||
1398 | |||
1381 | /* register exynos4 clocks */ | 1399 | /* register exynos4 clocks */ |
1382 | static void __init exynos4_clk_init(struct device_node *np, | 1400 | static void __init exynos4_clk_init(struct device_node *np, |
1383 | enum exynos4_soc soc) | 1401 | enum exynos4_soc soc) |
@@ -1455,6 +1473,10 @@ static void __init exynos4_clk_init(struct device_node *np, | |||
1455 | samsung_clk_register_fixed_factor(ctx, | 1473 | samsung_clk_register_fixed_factor(ctx, |
1456 | exynos4210_fixed_factor_clks, | 1474 | exynos4210_fixed_factor_clks, |
1457 | ARRAY_SIZE(exynos4210_fixed_factor_clks)); | 1475 | ARRAY_SIZE(exynos4210_fixed_factor_clks)); |
1476 | exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", | ||
1477 | mout_core_p4210[0], mout_core_p4210[1], 0x14200, | ||
1478 | e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d), | ||
1479 | CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); | ||
1458 | } else { | 1480 | } else { |
1459 | samsung_clk_register_mux(ctx, exynos4x12_mux_clks, | 1481 | samsung_clk_register_mux(ctx, exynos4x12_mux_clks, |
1460 | ARRAY_SIZE(exynos4x12_mux_clks)); | 1482 | ARRAY_SIZE(exynos4x12_mux_clks)); |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 4f3dbc8cf729..a86a196e32f6 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -36,17 +36,6 @@ config ARM_EXYNOS_CPUFREQ | |||
36 | 36 | ||
37 | If in doubt, say N. | 37 | If in doubt, say N. |
38 | 38 | ||
39 | config ARM_EXYNOS4210_CPUFREQ | ||
40 | bool "SAMSUNG EXYNOS4210" | ||
41 | depends on CPU_EXYNOS4210 | ||
42 | depends on ARM_EXYNOS_CPUFREQ | ||
43 | default y | ||
44 | help | ||
45 | This adds the CPUFreq driver for Samsung EXYNOS4210 | ||
46 | SoC (S5PV310 or S5PC210). | ||
47 | |||
48 | If in doubt, say N. | ||
49 | |||
50 | config ARM_EXYNOS4X12_CPUFREQ | 39 | config ARM_EXYNOS4X12_CPUFREQ |
51 | bool "SAMSUNG EXYNOS4x12" | 40 | bool "SAMSUNG EXYNOS4x12" |
52 | depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 | 41 | depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index cdce92ae2e8b..2169bf792db7 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
@@ -54,7 +54,6 @@ obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o | |||
54 | obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o | 54 | obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o |
55 | obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += arm-exynos-cpufreq.o | 55 | obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += arm-exynos-cpufreq.o |
56 | arm-exynos-cpufreq-y := exynos-cpufreq.o | 56 | arm-exynos-cpufreq-y := exynos-cpufreq.o |
57 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o | ||
58 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o | 57 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o |
59 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o | 58 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o |
60 | obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o | 59 | obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o |
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 82d2fbb20f7e..fb24aaf4adcf 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c | |||
@@ -168,10 +168,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) | |||
168 | 168 | ||
169 | exynos_info->dev = &pdev->dev; | 169 | exynos_info->dev = &pdev->dev; |
170 | 170 | ||
171 | if (of_machine_is_compatible("samsung,exynos4210")) { | 171 | if (of_machine_is_compatible("samsung,exynos4212")) { |
172 | exynos_info->type = EXYNOS_SOC_4210; | ||
173 | ret = exynos4210_cpufreq_init(exynos_info); | ||
174 | } else if (of_machine_is_compatible("samsung,exynos4212")) { | ||
175 | exynos_info->type = EXYNOS_SOC_4212; | 172 | exynos_info->type = EXYNOS_SOC_4212; |
176 | ret = exynos4x12_cpufreq_init(exynos_info); | 173 | ret = exynos4x12_cpufreq_init(exynos_info); |
177 | } else if (of_machine_is_compatible("samsung,exynos4412")) { | 174 | } else if (of_machine_is_compatible("samsung,exynos4412")) { |
diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h index 9f2062a7cc02..a3855e4d913d 100644 --- a/drivers/cpufreq/exynos-cpufreq.h +++ b/drivers/cpufreq/exynos-cpufreq.h | |||
@@ -18,7 +18,6 @@ enum cpufreq_level_index { | |||
18 | }; | 18 | }; |
19 | 19 | ||
20 | enum exynos_soc_type { | 20 | enum exynos_soc_type { |
21 | EXYNOS_SOC_4210, | ||
22 | EXYNOS_SOC_4212, | 21 | EXYNOS_SOC_4212, |
23 | EXYNOS_SOC_4412, | 22 | EXYNOS_SOC_4412, |
24 | EXYNOS_SOC_5250, | 23 | EXYNOS_SOC_5250, |
@@ -53,14 +52,6 @@ struct exynos_dvfs_info { | |||
53 | void __iomem *cmu_regs; | 52 | void __iomem *cmu_regs; |
54 | }; | 53 | }; |
55 | 54 | ||
56 | #ifdef CONFIG_ARM_EXYNOS4210_CPUFREQ | ||
57 | extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *); | ||
58 | #else | ||
59 | static inline int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) | ||
60 | { | ||
61 | return -EOPNOTSUPP; | ||
62 | } | ||
63 | #endif | ||
64 | #ifdef CONFIG_ARM_EXYNOS4X12_CPUFREQ | 55 | #ifdef CONFIG_ARM_EXYNOS4X12_CPUFREQ |
65 | extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *); | 56 | extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *); |
66 | #else | 57 | #else |
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c deleted file mode 100644 index 843ec824fd91..000000000000 --- a/drivers/cpufreq/exynos4210-cpufreq.c +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
3 | * http://www.samsung.com | ||
4 | * | ||
5 | * EXYNOS4210 - CPU frequency scaling support | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/cpufreq.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
21 | |||
22 | #include "exynos-cpufreq.h" | ||
23 | |||
24 | static struct clk *cpu_clk; | ||
25 | static struct clk *moutcore; | ||
26 | static struct clk *mout_mpll; | ||
27 | static struct clk *mout_apll; | ||
28 | static struct exynos_dvfs_info *cpufreq; | ||
29 | |||
30 | static unsigned int exynos4210_volt_table[] = { | ||
31 | 1250000, 1150000, 1050000, 975000, 950000, | ||
32 | }; | ||
33 | |||
34 | static struct cpufreq_frequency_table exynos4210_freq_table[] = { | ||
35 | {0, L0, 1200 * 1000}, | ||
36 | {0, L1, 1000 * 1000}, | ||
37 | {0, L2, 800 * 1000}, | ||
38 | {0, L3, 500 * 1000}, | ||
39 | {0, L4, 200 * 1000}, | ||
40 | {0, 0, CPUFREQ_TABLE_END}, | ||
41 | }; | ||
42 | |||
43 | static struct apll_freq apll_freq_4210[] = { | ||
44 | /* | ||
45 | * values: | ||
46 | * freq | ||
47 | * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, RESERVED | ||
48 | * clock divider for COPY, HPM, RESERVED | ||
49 | * PLL M, P, S | ||
50 | */ | ||
51 | APLL_FREQ(1200, 0, 3, 7, 3, 4, 1, 7, 0, 5, 0, 0, 150, 3, 1), | ||
52 | APLL_FREQ(1000, 0, 3, 7, 3, 4, 1, 7, 0, 4, 0, 0, 250, 6, 1), | ||
53 | APLL_FREQ(800, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 200, 6, 1), | ||
54 | APLL_FREQ(500, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 250, 6, 2), | ||
55 | APLL_FREQ(200, 0, 1, 3, 1, 3, 1, 0, 0, 3, 0, 0, 200, 6, 3), | ||
56 | }; | ||
57 | |||
58 | static void exynos4210_set_clkdiv(unsigned int div_index) | ||
59 | { | ||
60 | unsigned int tmp; | ||
61 | |||
62 | /* Change Divider - CPU0 */ | ||
63 | |||
64 | tmp = apll_freq_4210[div_index].clk_div_cpu0; | ||
65 | |||
66 | __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU); | ||
67 | |||
68 | do { | ||
69 | tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU); | ||
70 | } while (tmp & 0x1111111); | ||
71 | |||
72 | /* Change Divider - CPU1 */ | ||
73 | |||
74 | tmp = apll_freq_4210[div_index].clk_div_cpu1; | ||
75 | |||
76 | __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU1); | ||
77 | |||
78 | do { | ||
79 | tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU1); | ||
80 | } while (tmp & 0x11); | ||
81 | } | ||
82 | |||
83 | static void exynos4210_set_apll(unsigned int index) | ||
84 | { | ||
85 | unsigned int tmp, freq = apll_freq_4210[index].freq; | ||
86 | |||
87 | /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ | ||
88 | clk_set_parent(moutcore, mout_mpll); | ||
89 | |||
90 | do { | ||
91 | tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU) | ||
92 | >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT); | ||
93 | tmp &= 0x7; | ||
94 | } while (tmp != 0x2); | ||
95 | |||
96 | clk_set_rate(mout_apll, freq * 1000); | ||
97 | |||
98 | /* MUX_CORE_SEL = APLL */ | ||
99 | clk_set_parent(moutcore, mout_apll); | ||
100 | |||
101 | do { | ||
102 | tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU); | ||
103 | tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK; | ||
104 | } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); | ||
105 | } | ||
106 | |||
107 | static void exynos4210_set_frequency(unsigned int old_index, | ||
108 | unsigned int new_index) | ||
109 | { | ||
110 | if (old_index > new_index) { | ||
111 | exynos4210_set_clkdiv(new_index); | ||
112 | exynos4210_set_apll(new_index); | ||
113 | } else if (old_index < new_index) { | ||
114 | exynos4210_set_apll(new_index); | ||
115 | exynos4210_set_clkdiv(new_index); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) | ||
120 | { | ||
121 | struct device_node *np; | ||
122 | unsigned long rate; | ||
123 | |||
124 | /* | ||
125 | * HACK: This is a temporary workaround to get access to clock | ||
126 | * controller registers directly and remove static mappings and | ||
127 | * dependencies on platform headers. It is necessary to enable | ||
128 | * Exynos multi-platform support and will be removed together with | ||
129 | * this whole driver as soon as Exynos gets migrated to use | ||
130 | * cpufreq-dt driver. | ||
131 | */ | ||
132 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-clock"); | ||
133 | if (!np) { | ||
134 | pr_err("%s: failed to find clock controller DT node\n", | ||
135 | __func__); | ||
136 | return -ENODEV; | ||
137 | } | ||
138 | |||
139 | info->cmu_regs = of_iomap(np, 0); | ||
140 | if (!info->cmu_regs) { | ||
141 | pr_err("%s: failed to map CMU registers\n", __func__); | ||
142 | return -EFAULT; | ||
143 | } | ||
144 | |||
145 | cpu_clk = clk_get(NULL, "armclk"); | ||
146 | if (IS_ERR(cpu_clk)) | ||
147 | return PTR_ERR(cpu_clk); | ||
148 | |||
149 | moutcore = clk_get(NULL, "moutcore"); | ||
150 | if (IS_ERR(moutcore)) | ||
151 | goto err_moutcore; | ||
152 | |||
153 | mout_mpll = clk_get(NULL, "mout_mpll"); | ||
154 | if (IS_ERR(mout_mpll)) | ||
155 | goto err_mout_mpll; | ||
156 | |||
157 | rate = clk_get_rate(mout_mpll) / 1000; | ||
158 | |||
159 | mout_apll = clk_get(NULL, "mout_apll"); | ||
160 | if (IS_ERR(mout_apll)) | ||
161 | goto err_mout_apll; | ||
162 | |||
163 | info->mpll_freq_khz = rate; | ||
164 | /* 800Mhz */ | ||
165 | info->pll_safe_idx = L2; | ||
166 | info->cpu_clk = cpu_clk; | ||
167 | info->volt_table = exynos4210_volt_table; | ||
168 | info->freq_table = exynos4210_freq_table; | ||
169 | info->set_freq = exynos4210_set_frequency; | ||
170 | |||
171 | cpufreq = info; | ||
172 | |||
173 | return 0; | ||
174 | |||
175 | err_mout_apll: | ||
176 | clk_put(mout_mpll); | ||
177 | err_mout_mpll: | ||
178 | clk_put(moutcore); | ||
179 | err_moutcore: | ||
180 | clk_put(cpu_clk); | ||
181 | |||
182 | pr_debug("%s: failed initialization\n", __func__); | ||
183 | return -EINVAL; | ||
184 | } | ||
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4a943d13625b..6a24df64b0a0 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ | 31 | #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ |
32 | #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ | 32 | #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ |
33 | #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ | 33 | #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ |
34 | #define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ | ||
34 | 35 | ||
35 | struct clk_hw; | 36 | struct clk_hw; |
36 | struct clk_core; | 37 | struct clk_core; |