aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/sunxi
diff options
context:
space:
mode:
authorEmilio López <emilio@elopez.com.ar>2013-03-27 17:20:37 -0400
committerMike Turquette <mturquette@linaro.org>2013-04-04 16:51:35 -0400
commit13569a709ad12aef4d9c2b352c92e95ab7dd201f (patch)
tree82c1411a3a64b0d1988c17eb93443a8864765f48 /drivers/clk/sunxi
parent056b205316cc3dcf8a67cf813a26ff8a72bf3cb9 (diff)
clk: sunxi: Add support for AXI, AHB, APB0 and APB1 gates
This patchset adds DT support for all the AXI, AHB, APB0 and APB1 gates present on sunxi SoCs. Signed-off-by: Emilio López <emilio@elopez.com.ar> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/sunxi')
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index d528a2496690..244de90d5360 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -302,6 +302,82 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
302} 302}
303 303
304 304
305
306/**
307 * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
308 */
309
310#define SUNXI_GATES_MAX_SIZE 64
311
312struct gates_data {
313 DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
314};
315
316static const __initconst struct gates_data axi_gates_data = {
317 .mask = {1},
318};
319
320static const __initconst struct gates_data ahb_gates_data = {
321 .mask = {0x7F77FFF, 0x14FB3F},
322};
323
324static const __initconst struct gates_data apb0_gates_data = {
325 .mask = {0x4EF},
326};
327
328static const __initconst struct gates_data apb1_gates_data = {
329 .mask = {0xFF00F7},
330};
331
332static void __init sunxi_gates_clk_setup(struct device_node *node,
333 struct gates_data *data)
334{
335 struct clk_onecell_data *clk_data;
336 const char *clk_parent;
337 const char *clk_name;
338 void *reg;
339 int qty;
340 int i = 0;
341 int j = 0;
342 int ignore;
343
344 reg = of_iomap(node, 0);
345
346 clk_parent = of_clk_get_parent_name(node, 0);
347
348 /* Worst-case size approximation and memory allocation */
349 qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
350 clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
351 if (!clk_data)
352 return;
353 clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
354 if (!clk_data->clks) {
355 kfree(clk_data);
356 return;
357 }
358
359 for_each_set_bit(i, data->mask, SUNXI_GATES_MAX_SIZE) {
360 of_property_read_string_index(node, "clock-output-names",
361 j, &clk_name);
362
363 /* No driver claims this clock, but it should remain gated */
364 ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0;
365
366 clk_data->clks[i] = clk_register_gate(NULL, clk_name,
367 clk_parent, ignore,
368 reg + 4 * (i/32), i % 32,
369 0, &clk_lock);
370 WARN_ON(IS_ERR(clk_data->clks[i]));
371
372 j++;
373 }
374
375 /* Adjust to the real max */
376 clk_data->clk_num = i;
377
378 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
379}
380
305/* Matches for of_clk_init */ 381/* Matches for of_clk_init */
306static const __initconst struct of_device_id clk_match[] = { 382static const __initconst struct of_device_id clk_match[] = {
307 {.compatible = "fixed-clock", .data = of_fixed_clk_setup,}, 383 {.compatible = "fixed-clock", .data = of_fixed_clk_setup,},
@@ -331,6 +407,15 @@ static const __initconst struct of_device_id clk_mux_match[] = {
331 {} 407 {}
332}; 408};
333 409
410/* Matches for gate clocks */
411static const __initconst struct of_device_id clk_gates_match[] = {
412 {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &axi_gates_data,},
413 {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &ahb_gates_data,},
414 {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &apb0_gates_data,},
415 {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &apb1_gates_data,},
416 {}
417};
418
334static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match, 419static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match,
335 void *function) 420 void *function)
336{ 421{
@@ -359,4 +444,7 @@ void __init sunxi_init_clocks(void)
359 444
360 /* Register mux clocks */ 445 /* Register mux clocks */
361 of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); 446 of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
447
448 /* Register gate clocks */
449 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
362} 450}