diff options
author | Tero Kristo <t-kristo@ti.com> | 2014-12-16 11:20:50 -0500 |
---|---|---|
committer | Michael Turquette <mturquette@linaro.org> | 2015-01-30 13:55:05 -0500 |
commit | d96f774b25386a7a71c799bbf55b69c27129e454 (patch) | |
tree | cc32d394bd7ec907c0c5fede7a9a546dd74be27c | |
parent | 06524fa4289797deb9a66c1a3e681052eed0d83d (diff) |
clk: ti: divider: add support for legacy divider init
Legacy clock data is initialized slightly differently compared to
DT clocks, thus add support for this.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
-rw-r--r-- | drivers/clk/ti/clk.c | 3 | ||||
-rw-r--r-- | drivers/clk/ti/clock.h | 2 | ||||
-rw-r--r-- | drivers/clk/ti/divider.c | 132 |
3 files changed, 136 insertions, 1 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c index 676dbf170b31..a0475e23881d 100644 --- a/drivers/clk/ti/clk.c +++ b/drivers/clk/ti/clk.c | |||
@@ -214,6 +214,9 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup) | |||
214 | case TI_CLK_MUX: | 214 | case TI_CLK_MUX: |
215 | clk = ti_clk_register_mux(setup); | 215 | clk = ti_clk_register_mux(setup); |
216 | break; | 216 | break; |
217 | case TI_CLK_DIVIDER: | ||
218 | clk = ti_clk_register_divider(setup); | ||
219 | break; | ||
217 | case TI_CLK_FIXED_FACTOR: | 220 | case TI_CLK_FIXED_FACTOR: |
218 | fixed_factor = setup->data; | 221 | fixed_factor = setup->data; |
219 | 222 | ||
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index 9430dc614d3c..fe709412514c 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h | |||
@@ -156,7 +156,9 @@ struct ti_clk_dpll { | |||
156 | struct clk *ti_clk_register_gate(struct ti_clk *setup); | 156 | struct clk *ti_clk_register_gate(struct ti_clk *setup); |
157 | struct clk *ti_clk_register_interface(struct ti_clk *setup); | 157 | struct clk *ti_clk_register_interface(struct ti_clk *setup); |
158 | struct clk *ti_clk_register_mux(struct ti_clk *setup); | 158 | struct clk *ti_clk_register_mux(struct ti_clk *setup); |
159 | struct clk *ti_clk_register_divider(struct ti_clk *setup); | ||
159 | 160 | ||
161 | struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup); | ||
160 | struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup); | 162 | struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup); |
161 | struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup); | 163 | struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup); |
162 | 164 | ||
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index bff2b5b8ff59..6211893c0980 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
23 | #include <linux/clk/ti.h> | 23 | #include <linux/clk/ti.h> |
24 | #include "clock.h" | ||
24 | 25 | ||
25 | #undef pr_fmt | 26 | #undef pr_fmt |
26 | #define pr_fmt(fmt) "%s: " fmt, __func__ | 27 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
@@ -301,6 +302,134 @@ static struct clk *_register_divider(struct device *dev, const char *name, | |||
301 | } | 302 | } |
302 | 303 | ||
303 | static struct clk_div_table * | 304 | static struct clk_div_table * |
305 | _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width) | ||
306 | { | ||
307 | int valid_div = 0; | ||
308 | struct clk_div_table *table; | ||
309 | int i; | ||
310 | int div; | ||
311 | u32 val; | ||
312 | u8 flags; | ||
313 | |||
314 | if (!setup->num_dividers) { | ||
315 | /* Clk divider table not provided, determine min/max divs */ | ||
316 | flags = setup->flags; | ||
317 | |||
318 | if (flags & CLKF_INDEX_STARTS_AT_ONE) | ||
319 | val = 1; | ||
320 | else | ||
321 | val = 0; | ||
322 | |||
323 | div = 1; | ||
324 | |||
325 | while (div < setup->max_div) { | ||
326 | if (flags & CLKF_INDEX_POWER_OF_TWO) | ||
327 | div <<= 1; | ||
328 | else | ||
329 | div++; | ||
330 | val++; | ||
331 | } | ||
332 | |||
333 | *width = fls(val); | ||
334 | |||
335 | return NULL; | ||
336 | } | ||
337 | |||
338 | for (i = 0; i < setup->num_dividers; i++) | ||
339 | if (setup->dividers[i]) | ||
340 | valid_div++; | ||
341 | |||
342 | table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL); | ||
343 | if (!table) | ||
344 | return ERR_PTR(-ENOMEM); | ||
345 | |||
346 | valid_div = 0; | ||
347 | *width = 0; | ||
348 | |||
349 | for (i = 0; i < setup->num_dividers; i++) | ||
350 | if (setup->dividers[i]) { | ||
351 | table[valid_div].div = setup->dividers[i]; | ||
352 | table[valid_div].val = i; | ||
353 | valid_div++; | ||
354 | *width = i; | ||
355 | } | ||
356 | |||
357 | *width = fls(*width); | ||
358 | |||
359 | return table; | ||
360 | } | ||
361 | |||
362 | struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup) | ||
363 | { | ||
364 | struct clk_divider *div; | ||
365 | struct clk_omap_reg *reg; | ||
366 | |||
367 | if (!setup) | ||
368 | return NULL; | ||
369 | |||
370 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
371 | if (!div) | ||
372 | return ERR_PTR(-ENOMEM); | ||
373 | |||
374 | reg = (struct clk_omap_reg *)&div->reg; | ||
375 | reg->index = setup->module; | ||
376 | reg->offset = setup->reg; | ||
377 | |||
378 | if (setup->flags & CLKF_INDEX_STARTS_AT_ONE) | ||
379 | div->flags |= CLK_DIVIDER_ONE_BASED; | ||
380 | |||
381 | if (setup->flags & CLKF_INDEX_POWER_OF_TWO) | ||
382 | div->flags |= CLK_DIVIDER_POWER_OF_TWO; | ||
383 | |||
384 | div->table = _get_div_table_from_setup(setup, &div->width); | ||
385 | |||
386 | div->shift = setup->bit_shift; | ||
387 | |||
388 | return &div->hw; | ||
389 | } | ||
390 | |||
391 | struct clk *ti_clk_register_divider(struct ti_clk *setup) | ||
392 | { | ||
393 | struct ti_clk_divider *div; | ||
394 | struct clk_omap_reg *reg_setup; | ||
395 | u32 reg; | ||
396 | u8 width; | ||
397 | u32 flags = 0; | ||
398 | u8 div_flags = 0; | ||
399 | struct clk_div_table *table; | ||
400 | struct clk *clk; | ||
401 | |||
402 | div = setup->data; | ||
403 | |||
404 | reg_setup = (struct clk_omap_reg *)® | ||
405 | |||
406 | reg_setup->index = div->module; | ||
407 | reg_setup->offset = div->reg; | ||
408 | |||
409 | if (div->flags & CLKF_INDEX_STARTS_AT_ONE) | ||
410 | div_flags |= CLK_DIVIDER_ONE_BASED; | ||
411 | |||
412 | if (div->flags & CLKF_INDEX_POWER_OF_TWO) | ||
413 | div_flags |= CLK_DIVIDER_POWER_OF_TWO; | ||
414 | |||
415 | if (div->flags & CLKF_SET_RATE_PARENT) | ||
416 | flags |= CLK_SET_RATE_PARENT; | ||
417 | |||
418 | table = _get_div_table_from_setup(div, &width); | ||
419 | if (IS_ERR(table)) | ||
420 | return (struct clk *)table; | ||
421 | |||
422 | clk = _register_divider(NULL, setup->name, div->parent, | ||
423 | flags, (void __iomem *)reg, div->bit_shift, | ||
424 | width, div_flags, table, NULL); | ||
425 | |||
426 | if (IS_ERR(clk)) | ||
427 | kfree(table); | ||
428 | |||
429 | return clk; | ||
430 | } | ||
431 | |||
432 | static struct clk_div_table * | ||
304 | __init ti_clk_get_div_table(struct device_node *node) | 433 | __init ti_clk_get_div_table(struct device_node *node) |
305 | { | 434 | { |
306 | struct clk_div_table *table; | 435 | struct clk_div_table *table; |
@@ -455,7 +584,8 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) | |||
455 | goto cleanup; | 584 | goto cleanup; |
456 | 585 | ||
457 | clk = _register_divider(NULL, node->name, parent_name, flags, reg, | 586 | clk = _register_divider(NULL, node->name, parent_name, flags, reg, |
458 | shift, width, clk_divider_flags, table, NULL); | 587 | shift, width, clk_divider_flags, table, |
588 | NULL); | ||
459 | 589 | ||
460 | if (!IS_ERR(clk)) { | 590 | if (!IS_ERR(clk)) { |
461 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 591 | of_clk_add_provider(node, of_clk_src_simple_get, clk); |