aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2014-12-16 11:20:50 -0500
committerMichael Turquette <mturquette@linaro.org>2015-01-30 13:55:05 -0500
commitd96f774b25386a7a71c799bbf55b69c27129e454 (patch)
treecc32d394bd7ec907c0c5fede7a9a546dd74be27c
parent06524fa4289797deb9a66c1a3e681052eed0d83d (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.c3
-rw-r--r--drivers/clk/ti/clock.h2
-rw-r--r--drivers/clk/ti/divider.c132
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 {
156struct clk *ti_clk_register_gate(struct ti_clk *setup); 156struct clk *ti_clk_register_gate(struct ti_clk *setup);
157struct clk *ti_clk_register_interface(struct ti_clk *setup); 157struct clk *ti_clk_register_interface(struct ti_clk *setup);
158struct clk *ti_clk_register_mux(struct ti_clk *setup); 158struct clk *ti_clk_register_mux(struct ti_clk *setup);
159struct clk *ti_clk_register_divider(struct ti_clk *setup);
159 160
161struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup);
160struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup); 162struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
161struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup); 163struct 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
303static struct clk_div_table * 304static 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
362struct 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
391struct 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 *)&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
432static 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);