Commit | Line | Data |
---|---|---|
df791b3e PW |
1 | /* |
2 | * clkt_clksel.c - OMAP2/3/4 clksel clock functions | |
3 | * | |
4 | * Copyright (C) 2005-2008 Texas Instruments, Inc. | |
5 | * Copyright (C) 2004-2010 Nokia Corporation | |
6 | * | |
7 | * Contacts: | |
8 | * Richard Woodruff <r-woodruff2@ti.com> | |
9 | * Paul Walmsley | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License version 2 as | |
13 | * published by the Free Software Foundation. | |
14 | * | |
435699db PW |
15 | * |
16 | * clksel clocks are clocks that do not have a fixed parent, or that | |
17 | * can divide their parent's rate, or possibly both at the same time, based | |
18 | * on the contents of a hardware register bitfield. | |
19 | * | |
20 | * All of the various mux and divider settings can be encoded into | |
21 | * struct clksel* data structures, and then these can be autogenerated | |
22 | * from some hardware database for each new chip generation. This | |
23 | * should avoid the need to write, review, and validate a lot of new | |
24 | * clock code for each new chip, since it can be exported from the SoC | |
25 | * design flow. This is now done on OMAP4. | |
26 | * | |
27 | * The fusion of mux and divider clocks is a software creation. In | |
28 | * hardware reality, the multiplexer (parent selection) and the | |
29 | * divider exist separately. XXX At some point these clksel clocks | |
30 | * should be split into "divider" clocks and "mux" clocks to better | |
31 | * match the hardware. | |
32 | * | |
33 | * (The name "clksel" comes from the name of the corresponding | |
34 | * register field in the OMAP2/3 family of SoCs.) | |
df791b3e PW |
35 | * |
36 | * XXX Currently these clocks are only used in the OMAP2/3/4 code, but | |
37 | * many of the OMAP1 clocks should be convertible to use this | |
38 | * mechanism. | |
39 | */ | |
40 | #undef DEBUG | |
41 | ||
42 | #include <linux/kernel.h> | |
43 | #include <linux/errno.h> | |
44 | #include <linux/clk.h> | |
45 | #include <linux/io.h> | |
d9a5f4dd | 46 | #include <linux/bug.h> |
df791b3e PW |
47 | |
48 | #include <plat/clock.h> | |
49 | ||
50 | #include "clock.h" | |
df791b3e PW |
51 | |
52 | /* Private functions */ | |
53 | ||
54 | /** | |
435699db | 55 | * _get_clksel_by_parent() - return clksel struct for a given clk & parent |
df791b3e PW |
56 | * @clk: OMAP struct clk ptr to inspect |
57 | * @src_clk: OMAP struct clk ptr of the parent clk to search for | |
58 | * | |
59 | * Scan the struct clksel array associated with the clock to find | |
60 | * the element associated with the supplied parent clock address. | |
61 | * Returns a pointer to the struct clksel on success or NULL on error. | |
62 | */ | |
435699db PW |
63 | static const struct clksel *_get_clksel_by_parent(struct clk *clk, |
64 | struct clk *src_clk) | |
df791b3e PW |
65 | { |
66 | const struct clksel *clks; | |
67 | ||
435699db | 68 | for (clks = clk->clksel; clks->parent; clks++) |
df791b3e PW |
69 | if (clks->parent == src_clk) |
70 | break; /* Found the requested parent */ | |
df791b3e PW |
71 | |
72 | if (!clks->parent) { | |
435699db PW |
73 | /* This indicates a data problem */ |
74 | WARN(1, "clock: Could not find parent clock %s in clksel array " | |
75 | "of clock %s\n", src_clk->name, clk->name); | |
df791b3e PW |
76 | return NULL; |
77 | } | |
78 | ||
79 | return clks; | |
80 | } | |
81 | ||
d74b4949 | 82 | /** |
435699db | 83 | * _get_div_and_fieldval() - find the new clksel divisor and field value to use |
d74b4949 PW |
84 | * @src_clk: planned new parent struct clk * |
85 | * @clk: struct clk * that is being reparented | |
86 | * @field_val: pointer to a u32 to contain the register data for the divisor | |
87 | * | |
88 | * Given an intended new parent struct clk * @src_clk, and the struct | |
89 | * clk * @clk to the clock that is being reparented, find the | |
90 | * appropriate rate divisor for the new clock (returned as the return | |
91 | * value), and the corresponding register bitfield data to program to | |
92 | * reach that divisor (returned in the u32 pointed to by @field_val). | |
93 | * Returns 0 on error, or returns the newly-selected divisor upon | |
94 | * success (in this latter case, the corresponding register bitfield | |
95 | * value is passed back in the variable pointed to by @field_val) | |
df791b3e | 96 | */ |
435699db PW |
97 | static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk, |
98 | u32 *field_val) | |
df791b3e PW |
99 | { |
100 | const struct clksel *clks; | |
405505c2 | 101 | const struct clksel_rate *clkr, *max_clkr = NULL; |
d74b4949 | 102 | u8 max_div = 0; |
df791b3e | 103 | |
435699db | 104 | clks = _get_clksel_by_parent(clk, src_clk); |
df791b3e PW |
105 | if (!clks) |
106 | return 0; | |
107 | ||
d74b4949 PW |
108 | /* |
109 | * Find the highest divisor (e.g., the one resulting in the | |
110 | * lowest rate) to use as the default. This should avoid | |
111 | * clock rates that are too high for the device. XXX A better | |
112 | * solution here would be to try to determine if there is a | |
113 | * divisor matching the original clock rate before the parent | |
114 | * switch, and if it cannot be found, to fall back to the | |
115 | * highest divisor. | |
116 | */ | |
df791b3e | 117 | for (clkr = clks->rates; clkr->div; clkr++) { |
d74b4949 PW |
118 | if (!(clkr->flags & cpu_mask)) |
119 | continue; | |
120 | ||
121 | if (clkr->div > max_div) { | |
122 | max_div = clkr->div; | |
123 | max_clkr = clkr; | |
124 | } | |
df791b3e PW |
125 | } |
126 | ||
d74b4949 | 127 | if (max_div == 0) { |
435699db PW |
128 | /* This indicates an error in the clksel data */ |
129 | WARN(1, "clock: Could not find divisor for clock %s parent %s" | |
130 | "\n", clk->name, src_clk->parent->name); | |
df791b3e PW |
131 | return 0; |
132 | } | |
133 | ||
d74b4949 | 134 | *field_val = max_clkr->val; |
df791b3e | 135 | |
d74b4949 | 136 | return max_div; |
df791b3e PW |
137 | } |
138 | ||
435699db PW |
139 | /** |
140 | * _write_clksel_reg() - program a clock's clksel register in hardware | |
141 | * @clk: struct clk * to program | |
142 | * @v: clksel bitfield value to program (with LSB at bit 0) | |
143 | * | |
144 | * Shift the clksel register bitfield value @v to its appropriate | |
145 | * location in the clksel register and write it in. This function | |
146 | * will ensure that the write to the clksel_reg reaches its | |
147 | * destination before returning -- important since PRM and CM register | |
148 | * accesses can be quite slow compared to ARM cycles -- but does not | |
149 | * take into account any time the hardware might take to switch the | |
150 | * clock source. | |
151 | */ | |
152 | static void _write_clksel_reg(struct clk *clk, u32 field_val) | |
153 | { | |
154 | u32 v; | |
df791b3e | 155 | |
435699db PW |
156 | v = __raw_readl(clk->clksel_reg); |
157 | v &= ~clk->clksel_mask; | |
158 | v |= field_val << __ffs(clk->clksel_mask); | |
159 | __raw_writel(v, clk->clksel_reg); | |
160 | ||
161 | v = __raw_readl(clk->clksel_reg); /* OCP barrier */ | |
162 | } | |
df791b3e PW |
163 | |
164 | /** | |
435699db PW |
165 | * _clksel_to_divisor() - turn clksel field value into integer divider |
166 | * @clk: OMAP struct clk to use | |
167 | * @field_val: register field value to find | |
df791b3e | 168 | * |
435699db PW |
169 | * Given a struct clk of a rate-selectable clksel clock, and a register field |
170 | * value to search for, find the corresponding clock divisor. The register | |
171 | * field value should be pre-masked and shifted down so the LSB is at bit 0 | |
172 | * before calling. Returns 0 on error or returns the actual integer divisor | |
173 | * upon success. | |
df791b3e | 174 | */ |
435699db | 175 | static u32 _clksel_to_divisor(struct clk *clk, u32 field_val) |
df791b3e PW |
176 | { |
177 | const struct clksel *clks; | |
178 | const struct clksel_rate *clkr; | |
df791b3e | 179 | |
435699db PW |
180 | clks = _get_clksel_by_parent(clk, clk->parent); |
181 | if (!clks) | |
182 | return 0; | |
df791b3e | 183 | |
435699db PW |
184 | for (clkr = clks->rates; clkr->div; clkr++) { |
185 | if (!(clkr->flags & cpu_mask)) | |
186 | continue; | |
df791b3e | 187 | |
435699db PW |
188 | if (clkr->val == field_val) |
189 | break; | |
df791b3e PW |
190 | } |
191 | ||
435699db PW |
192 | if (!clkr->div) { |
193 | /* This indicates a data error */ | |
194 | WARN(1, "clock: Could not find fieldval %d for clock %s parent " | |
195 | "%s\n", field_val, clk->name, clk->parent->name); | |
196 | return 0; | |
197 | } | |
df791b3e | 198 | |
435699db | 199 | return clkr->div; |
df791b3e PW |
200 | } |
201 | ||
435699db PW |
202 | /** |
203 | * _divisor_to_clksel() - turn clksel integer divisor into a field value | |
204 | * @clk: OMAP struct clk to use | |
205 | * @div: integer divisor to search for | |
206 | * | |
207 | * Given a struct clk of a rate-selectable clksel clock, and a clock | |
208 | * divisor, find the corresponding register field value. Returns the | |
209 | * register field value _before_ left-shifting (i.e., LSB is at bit | |
210 | * 0); or returns 0xFFFFFFFF (~0) upon error. | |
df791b3e | 211 | */ |
435699db | 212 | static u32 _divisor_to_clksel(struct clk *clk, u32 div) |
df791b3e | 213 | { |
435699db PW |
214 | const struct clksel *clks; |
215 | const struct clksel_rate *clkr; | |
df791b3e | 216 | |
435699db PW |
217 | /* should never happen */ |
218 | WARN_ON(div == 0); | |
df791b3e | 219 | |
435699db PW |
220 | clks = _get_clksel_by_parent(clk, clk->parent); |
221 | if (!clks) | |
222 | return ~0; | |
df791b3e | 223 | |
435699db PW |
224 | for (clkr = clks->rates; clkr->div; clkr++) { |
225 | if (!(clkr->flags & cpu_mask)) | |
226 | continue; | |
df791b3e | 227 | |
435699db PW |
228 | if (clkr->div == div) |
229 | break; | |
230 | } | |
df791b3e | 231 | |
435699db PW |
232 | if (!clkr->div) { |
233 | pr_err("clock: Could not find divisor %d for clock %s parent " | |
234 | "%s\n", div, clk->name, clk->parent->name); | |
235 | return ~0; | |
236 | } | |
237 | ||
238 | return clkr->val; | |
df791b3e PW |
239 | } |
240 | ||
241 | /** | |
435699db PW |
242 | * _read_divisor() - get current divisor applied to parent clock (from hdwr) |
243 | * @clk: OMAP struct clk to use. | |
244 | * | |
245 | * Read the current divisor register value for @clk that is programmed | |
246 | * into the hardware, convert it into the actual divisor value, and | |
247 | * return it; or return 0 on error. | |
248 | */ | |
249 | static u32 _read_divisor(struct clk *clk) | |
250 | { | |
251 | u32 v; | |
252 | ||
253 | if (!clk->clksel || !clk->clksel_mask) | |
254 | return 0; | |
255 | ||
256 | v = __raw_readl(clk->clksel_reg); | |
257 | v &= clk->clksel_mask; | |
258 | v >>= __ffs(clk->clksel_mask); | |
259 | ||
260 | return _clksel_to_divisor(clk, v); | |
261 | } | |
262 | ||
263 | /* Public functions */ | |
264 | ||
265 | /** | |
266 | * omap2_clksel_round_rate_div() - find divisor for the given clock and rate | |
df791b3e PW |
267 | * @clk: OMAP struct clk to use |
268 | * @target_rate: desired clock rate | |
269 | * @new_div: ptr to where we should store the divisor | |
270 | * | |
271 | * Finds 'best' divider value in an array based on the source and target | |
272 | * rates. The divider array must be sorted with smallest divider first. | |
435699db | 273 | * This function is also used by the DPLL3 M2 divider code. |
df791b3e PW |
274 | * |
275 | * Returns the rounded clock rate or returns 0xffffffff on error. | |
276 | */ | |
277 | u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate, | |
278 | u32 *new_div) | |
279 | { | |
280 | unsigned long test_rate; | |
281 | const struct clksel *clks; | |
282 | const struct clksel_rate *clkr; | |
283 | u32 last_div = 0; | |
284 | ||
435699db PW |
285 | if (!clk->clksel || !clk->clksel_mask) |
286 | return ~0; | |
287 | ||
df791b3e PW |
288 | pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n", |
289 | clk->name, target_rate); | |
290 | ||
291 | *new_div = 1; | |
292 | ||
435699db | 293 | clks = _get_clksel_by_parent(clk, clk->parent); |
df791b3e PW |
294 | if (!clks) |
295 | return ~0; | |
296 | ||
297 | for (clkr = clks->rates; clkr->div; clkr++) { | |
298 | if (!(clkr->flags & cpu_mask)) | |
299 | continue; | |
300 | ||
301 | /* Sanity check */ | |
302 | if (clkr->div <= last_div) | |
303 | pr_err("clock: clksel_rate table not sorted " | |
304 | "for clock %s", clk->name); | |
305 | ||
306 | last_div = clkr->div; | |
307 | ||
308 | test_rate = clk->parent->rate / clkr->div; | |
309 | ||
310 | if (test_rate <= target_rate) | |
311 | break; /* found it */ | |
312 | } | |
313 | ||
314 | if (!clkr->div) { | |
315 | pr_err("clock: Could not find divisor for target " | |
316 | "rate %ld for clock %s parent %s\n", target_rate, | |
317 | clk->name, clk->parent->name); | |
318 | return ~0; | |
319 | } | |
320 | ||
321 | *new_div = clkr->div; | |
322 | ||
323 | pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div, | |
324 | (clk->parent->rate / clkr->div)); | |
325 | ||
326 | return clk->parent->rate / clkr->div; | |
327 | } | |
328 | ||
435699db PW |
329 | /* |
330 | * Clocktype interface functions to the OMAP clock code | |
331 | * (i.e., those used in struct clk field function pointers, etc.) | |
df791b3e | 332 | */ |
df791b3e PW |
333 | |
334 | /** | |
435699db PW |
335 | * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr |
336 | * @clk: OMAP clock struct ptr to use | |
df791b3e | 337 | * |
435699db PW |
338 | * Given a pointer @clk to a source-selectable struct clk, read the |
339 | * hardware register and determine what its parent is currently set | |
340 | * to. Update @clk's .parent field with the appropriate clk ptr. No | |
341 | * return value. | |
df791b3e | 342 | */ |
435699db | 343 | void omap2_init_clksel_parent(struct clk *clk) |
df791b3e PW |
344 | { |
345 | const struct clksel *clks; | |
346 | const struct clksel_rate *clkr; | |
435699db | 347 | u32 r, found = 0; |
df791b3e | 348 | |
435699db PW |
349 | if (!clk->clksel || !clk->clksel_mask) |
350 | return; | |
df791b3e | 351 | |
435699db PW |
352 | r = __raw_readl(clk->clksel_reg) & clk->clksel_mask; |
353 | r >>= __ffs(clk->clksel_mask); | |
df791b3e | 354 | |
435699db PW |
355 | for (clks = clk->clksel; clks->parent && !found; clks++) { |
356 | for (clkr = clks->rates; clkr->div && !found; clkr++) { | |
357 | if (!(clkr->flags & cpu_mask)) | |
358 | continue; | |
359 | ||
360 | if (clkr->val == r) { | |
361 | if (clk->parent != clks->parent) { | |
362 | pr_debug("clock: inited %s parent " | |
363 | "to %s (was %s)\n", | |
364 | clk->name, clks->parent->name, | |
365 | ((clk->parent) ? | |
366 | clk->parent->name : "NULL")); | |
367 | clk_reparent(clk, clks->parent); | |
368 | }; | |
369 | found = 1; | |
370 | } | |
371 | } | |
df791b3e PW |
372 | } |
373 | ||
435699db PW |
374 | /* This indicates a data error */ |
375 | WARN(!found, "clock: %s: init parent: could not find regval %0x\n", | |
376 | clk->name, r); | |
377 | ||
378 | return; | |
df791b3e PW |
379 | } |
380 | ||
381 | /** | |
435699db PW |
382 | * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field |
383 | * @clk: struct clk * | |
df791b3e | 384 | * |
435699db PW |
385 | * This function is intended to be called only by the clock framework. |
386 | * Each clksel clock should have its struct clk .recalc field set to this | |
387 | * function. Returns the clock's current rate, based on its parent's rate | |
388 | * and its current divisor setting in the hardware. | |
df791b3e | 389 | */ |
435699db | 390 | unsigned long omap2_clksel_recalc(struct clk *clk) |
df791b3e | 391 | { |
435699db PW |
392 | unsigned long rate; |
393 | u32 div = 0; | |
df791b3e | 394 | |
435699db PW |
395 | div = _read_divisor(clk); |
396 | if (div == 0) | |
397 | return clk->rate; | |
df791b3e | 398 | |
435699db | 399 | rate = clk->parent->rate / div; |
df791b3e | 400 | |
435699db PW |
401 | pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n", clk->name, |
402 | rate, div); | |
df791b3e | 403 | |
435699db | 404 | return rate; |
df791b3e PW |
405 | } |
406 | ||
407 | /** | |
435699db PW |
408 | * omap2_clksel_round_rate() - find rounded rate for the given clock and rate |
409 | * @clk: OMAP struct clk to use | |
410 | * @target_rate: desired clock rate | |
411 | * | |
412 | * This function is intended to be called only by the clock framework. | |
413 | * Finds best target rate based on the source clock and possible dividers. | |
414 | * rates. The divider array must be sorted with smallest divider first. | |
df791b3e | 415 | * |
435699db | 416 | * Returns the rounded clock rate or returns 0xffffffff on error. |
df791b3e | 417 | */ |
435699db | 418 | long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate) |
df791b3e | 419 | { |
435699db | 420 | u32 new_div; |
df791b3e | 421 | |
435699db | 422 | return omap2_clksel_round_rate_div(clk, target_rate, &new_div); |
df791b3e PW |
423 | } |
424 | ||
435699db PW |
425 | /** |
426 | * omap2_clksel_set_rate() - program clock rate in hardware | |
427 | * @clk: struct clk * to program rate | |
428 | * @rate: target rate to program | |
429 | * | |
430 | * This function is intended to be called only by the clock framework. | |
431 | * Program @clk's rate to @rate in the hardware. The clock can be | |
432 | * either enabled or disabled when this happens, although if the clock | |
433 | * is enabled, some downstream devices may glitch or behave | |
434 | * unpredictably when the clock rate is changed - this depends on the | |
435 | * hardware. This function does not currently check the usecount of | |
436 | * the clock, so if multiple drivers are using the clock, and the rate | |
437 | * is changed, they will all be affected without any notification. | |
438 | * Returns -EINVAL upon error, or 0 upon success. | |
439 | */ | |
df791b3e PW |
440 | int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) |
441 | { | |
435699db | 442 | u32 field_val, validrate, new_div = 0; |
df791b3e | 443 | |
435699db | 444 | if (!clk->clksel || !clk->clksel_mask) |
df791b3e PW |
445 | return -EINVAL; |
446 | ||
447 | validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); | |
448 | if (validrate != rate) | |
449 | return -EINVAL; | |
450 | ||
435699db | 451 | field_val = _divisor_to_clksel(clk, new_div); |
df791b3e PW |
452 | if (field_val == ~0) |
453 | return -EINVAL; | |
454 | ||
435699db | 455 | _write_clksel_reg(clk, field_val); |
df791b3e PW |
456 | |
457 | clk->rate = clk->parent->rate / new_div; | |
458 | ||
435699db PW |
459 | pr_debug("clock: %s: set rate to %ld\n", clk->name, clk->rate); |
460 | ||
df791b3e PW |
461 | return 0; |
462 | } | |
463 | ||
435699db PW |
464 | /* |
465 | * Clksel parent setting function - not passed in struct clk function | |
466 | * pointer - instead, the OMAP clock code currently assumes that any | |
467 | * parent-setting clock is a clksel clock, and calls | |
468 | * omap2_clksel_set_parent() by default | |
469 | */ | |
470 | ||
471 | /** | |
472 | * omap2_clksel_set_parent() - change a clock's parent clock | |
473 | * @clk: struct clk * of the child clock | |
474 | * @new_parent: struct clk * of the new parent clock | |
475 | * | |
476 | * This function is intended to be called only by the clock framework. | |
477 | * Change the parent clock of clock @clk to @new_parent. This is | |
478 | * intended to be used while @clk is disabled. This function does not | |
479 | * currently check the usecount of the clock, so if multiple drivers | |
480 | * are using the clock, and the parent is changed, they will all be | |
481 | * affected without any notification. Returns -EINVAL upon error, or | |
482 | * 0 upon success. | |
483 | */ | |
df791b3e PW |
484 | int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent) |
485 | { | |
435699db PW |
486 | u32 field_val = 0; |
487 | u32 parent_div; | |
df791b3e | 488 | |
d74b4949 | 489 | if (!clk->clksel || !clk->clksel_mask) |
df791b3e PW |
490 | return -EINVAL; |
491 | ||
435699db | 492 | parent_div = _get_div_and_fieldval(new_parent, clk, &field_val); |
df791b3e PW |
493 | if (!parent_div) |
494 | return -EINVAL; | |
495 | ||
435699db | 496 | _write_clksel_reg(clk, field_val); |
df791b3e | 497 | |
df791b3e PW |
498 | clk_reparent(clk, new_parent); |
499 | ||
500 | /* CLKSEL clocks follow their parents' rates, divided by a divisor */ | |
501 | clk->rate = new_parent->rate; | |
502 | ||
503 | if (parent_div > 0) | |
504 | clk->rate /= parent_div; | |
505 | ||
435699db | 506 | pr_debug("clock: %s: set parent to %s (new rate %ld)\n", |
df791b3e PW |
507 | clk->name, clk->parent->name, clk->rate); |
508 | ||
509 | return 0; | |
510 | } |