diff options
author | Emilio López <emilio@elopez.com.ar> | 2013-03-27 17:20:37 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2013-04-04 16:51:35 -0400 |
commit | 13569a709ad12aef4d9c2b352c92e95ab7dd201f (patch) | |
tree | 82c1411a3a64b0d1988c17eb93443a8864765f48 | |
parent | 056b205316cc3dcf8a67cf813a26ff8a72bf3cb9 (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>
-rw-r--r-- | Documentation/devicetree/bindings/clock/sunxi.txt | 109 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 88 |
2 files changed, 196 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 20b8479c2760..729f52426fe1 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
@@ -10,15 +10,23 @@ Required properties: | |||
10 | "allwinner,sun4i-pll1-clk" - for the main PLL clock | 10 | "allwinner,sun4i-pll1-clk" - for the main PLL clock |
11 | "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock | 11 | "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock |
12 | "allwinner,sun4i-axi-clk" - for the AXI clock | 12 | "allwinner,sun4i-axi-clk" - for the AXI clock |
13 | "allwinner,sun4i-axi-gates-clk" - for the AXI gates | ||
13 | "allwinner,sun4i-ahb-clk" - for the AHB clock | 14 | "allwinner,sun4i-ahb-clk" - for the AHB clock |
15 | "allwinner,sun4i-ahb-gates-clk" - for the AHB gates | ||
14 | "allwinner,sun4i-apb0-clk" - for the APB0 clock | 16 | "allwinner,sun4i-apb0-clk" - for the APB0 clock |
17 | "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates | ||
15 | "allwinner,sun4i-apb1-clk" - for the APB1 clock | 18 | "allwinner,sun4i-apb1-clk" - for the APB1 clock |
16 | "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing | 19 | "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing |
20 | "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates | ||
17 | 21 | ||
18 | Required properties for all clocks: | 22 | Required properties for all clocks: |
19 | - reg : shall be the control register address for the clock. | 23 | - reg : shall be the control register address for the clock. |
20 | - clocks : shall be the input parent clock(s) phandle for the clock | 24 | - clocks : shall be the input parent clock(s) phandle for the clock |
21 | - #clock-cells : from common clock binding; shall be set to 0. | 25 | - #clock-cells : from common clock binding; shall be set to 0 except for |
26 | "allwinner,sun4i-*-gates-clk" where it shall be set to 1 | ||
27 | |||
28 | Additionally, "allwinner,sun4i-*-gates-clk" clocks require: | ||
29 | - clock-output-names : the corresponding gate names that the clock controls | ||
22 | 30 | ||
23 | For example: | 31 | For example: |
24 | 32 | ||
@@ -42,3 +50,102 @@ cpu: cpu@01c20054 { | |||
42 | reg = <0x01c20054 0x4>; | 50 | reg = <0x01c20054 0x4>; |
43 | clocks = <&osc32k>, <&osc24M>, <&pll1>; | 51 | clocks = <&osc32k>, <&osc24M>, <&pll1>; |
44 | }; | 52 | }; |
53 | |||
54 | |||
55 | |||
56 | Gate clock outputs | ||
57 | |||
58 | The "allwinner,sun4i-*-gates-clk" clocks provide several gatable outputs; | ||
59 | their corresponding offsets as present on sun4i are listed below. Note that | ||
60 | some of these gates are not present on sun5i. | ||
61 | |||
62 | * AXI gates ("allwinner,sun4i-axi-gates-clk") | ||
63 | |||
64 | DRAM 0 | ||
65 | |||
66 | * AHB gates ("allwinner,sun4i-ahb-gates-clk") | ||
67 | |||
68 | USB0 0 | ||
69 | EHCI0 1 | ||
70 | OHCI0 2* | ||
71 | EHCI1 3 | ||
72 | OHCI1 4* | ||
73 | SS 5 | ||
74 | DMA 6 | ||
75 | BIST 7 | ||
76 | MMC0 8 | ||
77 | MMC1 9 | ||
78 | MMC2 10 | ||
79 | MMC3 11 | ||
80 | MS 12** | ||
81 | NAND 13 | ||
82 | SDRAM 14 | ||
83 | |||
84 | ACE 16 | ||
85 | EMAC 17 | ||
86 | TS 18 | ||
87 | |||
88 | SPI0 20 | ||
89 | SPI1 21 | ||
90 | SPI2 22 | ||
91 | SPI3 23 | ||
92 | PATA 24 | ||
93 | SATA 25** | ||
94 | GPS 26* | ||
95 | |||
96 | VE 32 | ||
97 | TVD 33 | ||
98 | TVE0 34 | ||
99 | TVE1 35 | ||
100 | LCD0 36 | ||
101 | LCD1 37 | ||
102 | |||
103 | CSI0 40 | ||
104 | CSI1 41 | ||
105 | |||
106 | HDMI 43 | ||
107 | DE_BE0 44 | ||
108 | DE_BE1 45 | ||
109 | DE_FE0 46 | ||
110 | DE_FE1 47 | ||
111 | |||
112 | MP 50 | ||
113 | |||
114 | MALI400 52 | ||
115 | |||
116 | * APB0 gates ("allwinner,sun4i-apb0-gates-clk") | ||
117 | |||
118 | CODEC 0 | ||
119 | SPDIF 1* | ||
120 | AC97 2 | ||
121 | IIS 3 | ||
122 | |||
123 | PIO 5 | ||
124 | IR0 6 | ||
125 | IR1 7 | ||
126 | |||
127 | KEYPAD 10 | ||
128 | |||
129 | * APB1 gates ("allwinner,sun4i-apb1-gates-clk") | ||
130 | |||
131 | I2C0 0 | ||
132 | I2C1 1 | ||
133 | I2C2 2 | ||
134 | |||
135 | CAN 4 | ||
136 | SCR 5 | ||
137 | PS20 6 | ||
138 | PS21 7 | ||
139 | |||
140 | UART0 16 | ||
141 | UART1 17 | ||
142 | UART2 18 | ||
143 | UART3 19 | ||
144 | UART4 20 | ||
145 | UART5 21 | ||
146 | UART6 22 | ||
147 | UART7 23 | ||
148 | |||
149 | Notation: | ||
150 | [*]: The datasheet didn't mention these, but they are present on AW code | ||
151 | [**]: The datasheet had this marked as "NC" but they are used on AW code | ||
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 | |||
312 | struct gates_data { | ||
313 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); | ||
314 | }; | ||
315 | |||
316 | static const __initconst struct gates_data axi_gates_data = { | ||
317 | .mask = {1}, | ||
318 | }; | ||
319 | |||
320 | static const __initconst struct gates_data ahb_gates_data = { | ||
321 | .mask = {0x7F77FFF, 0x14FB3F}, | ||
322 | }; | ||
323 | |||
324 | static const __initconst struct gates_data apb0_gates_data = { | ||
325 | .mask = {0x4EF}, | ||
326 | }; | ||
327 | |||
328 | static const __initconst struct gates_data apb1_gates_data = { | ||
329 | .mask = {0xFF00F7}, | ||
330 | }; | ||
331 | |||
332 | static 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 */ |
306 | static const __initconst struct of_device_id clk_match[] = { | 382 | static 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 */ | ||
411 | static 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 | |||
334 | static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match, | 419 | static 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 | } |