2 * Copyright 2013 Emilio López
4 * Emilio López <emilio@elopez.com.ar>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/clk-provider.h>
18 #include <linux/clkdev.h>
19 #include <linux/clk/sunxi.h>
21 #include <linux/of_address.h>
23 #include "clk-factors.h"
25 static DEFINE_SPINLOCK(clk_lock
);
28 * sunxi_osc_clk_setup() - Setup function for gatable oscillator
31 #define SUNXI_OSC24M_GATE 0
33 static void __init
sunxi_osc_clk_setup(struct device_node
*node
)
36 const char *clk_name
= node
->name
;
40 reg
= of_iomap(node
, 0);
42 parent
= of_clk_get_parent_name(node
, 0);
44 clk
= clk_register_gate(NULL
, clk_name
, parent
, 0, reg
,
45 SUNXI_OSC24M_GATE
, 0, &clk_lock
);
48 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
49 clk_register_clkdev(clk
, clk_name
, NULL
);
56 * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1
57 * PLL1 rate is calculated as follows
58 * rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
59 * parent_rate is always 24Mhz
62 static void sunxi_get_pll1_factors(u32
*freq
, u32 parent_rate
,
63 u8
*n
, u8
*k
, u8
*m
, u8
*p
)
67 /* Normalize value to a 6M multiple */
68 div
= *freq
/ 6000000;
69 *freq
= 6000000 * div
;
71 /* we were called to round the frequency, we can now return */
75 /* m is always zero for pll1 */
78 /* k is 1 only on these cases */
79 if (*freq
>= 768000000 || *freq
== 42000000 || *freq
== 54000000)
84 /* p will be 3 for divs under 10 */
88 /* p will be 2 for divs between 10 - 20 and odd divs under 32 */
89 else if (div
< 20 || (div
< 32 && (div
& 1)))
92 /* p will be 1 for even divs under 32, divs under 40 and odd pairs
93 * of divs between 40-62 */
94 else if (div
< 40 || (div
< 64 && (div
& 2)))
97 /* any other entries have p = 0 */
101 /* calculate a suitable n based on k and p */
110 * sunxi_get_apb1_factors() - calculates m, p factors for APB1
111 * APB1 rate is calculated as follows
112 * rate = (parent_rate >> p) / (m + 1);
115 static void sunxi_get_apb1_factors(u32
*freq
, u32 parent_rate
,
116 u8
*n
, u8
*k
, u8
*m
, u8
*p
)
120 if (parent_rate
< *freq
)
123 parent_rate
= (parent_rate
+ (*freq
- 1)) / *freq
;
126 if (parent_rate
> 32)
129 if (parent_rate
<= 4)
131 else if (parent_rate
<= 8)
133 else if (parent_rate
<= 16)
138 calcm
= (parent_rate
>> calcp
) - 1;
140 *freq
= (parent_rate
>> calcp
) / (calcm
+ 1);
142 /* we were called to round the frequency, we can now return */
153 * sunxi_factors_clk_setup() - Setup function for factor clocks
156 struct factors_data
{
157 struct clk_factors_config
*table
;
158 void (*getter
) (u32
*rate
, u32 parent_rate
, u8
*n
, u8
*k
, u8
*m
, u8
*p
);
161 static struct clk_factors_config pll1_config
= {
172 static struct clk_factors_config apb1_config
= {
179 static const __initconst
struct factors_data pll1_data
= {
180 .table
= &pll1_config
,
181 .getter
= sunxi_get_pll1_factors
,
184 static const __initconst
struct factors_data apb1_data
= {
185 .table
= &apb1_config
,
186 .getter
= sunxi_get_apb1_factors
,
189 static void __init
sunxi_factors_clk_setup(struct device_node
*node
,
190 struct factors_data
*data
)
193 const char *clk_name
= node
->name
;
197 reg
= of_iomap(node
, 0);
199 parent
= of_clk_get_parent_name(node
, 0);
201 clk
= clk_register_factors(NULL
, clk_name
, parent
, 0, reg
,
202 data
->table
, data
->getter
, &clk_lock
);
205 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
206 clk_register_clkdev(clk
, clk_name
, NULL
);
213 * sunxi_mux_clk_setup() - Setup function for muxes
216 #define SUNXI_MUX_GATE_WIDTH 2
222 static const __initconst
struct mux_data cpu_data
= {
226 static const __initconst
struct mux_data apb1_mux_data
= {
230 static void __init
sunxi_mux_clk_setup(struct device_node
*node
,
231 struct mux_data
*data
)
234 const char *clk_name
= node
->name
;
235 const char *parents
[5];
239 reg
= of_iomap(node
, 0);
241 while (i
< 5 && (parents
[i
] = of_clk_get_parent_name(node
, i
)) != NULL
)
244 clk
= clk_register_mux(NULL
, clk_name
, parents
, i
, 0, reg
,
245 data
->shift
, SUNXI_MUX_GATE_WIDTH
,
249 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
250 clk_register_clkdev(clk
, clk_name
, NULL
);
257 * sunxi_divider_clk_setup() - Setup function for simple divider clocks
260 #define SUNXI_DIVISOR_WIDTH 2
267 static const __initconst
struct div_data axi_data
= {
272 static const __initconst
struct div_data ahb_data
= {
277 static const __initconst
struct div_data apb0_data
= {
282 static void __init
sunxi_divider_clk_setup(struct device_node
*node
,
283 struct div_data
*data
)
286 const char *clk_name
= node
->name
;
287 const char *clk_parent
;
290 reg
= of_iomap(node
, 0);
292 clk_parent
= of_clk_get_parent_name(node
, 0);
294 clk
= clk_register_divider(NULL
, clk_name
, clk_parent
, 0,
295 reg
, data
->shift
, SUNXI_DIVISOR_WIDTH
,
296 data
->pow
? CLK_DIVIDER_POWER_OF_TWO
: 0,
299 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
300 clk_register_clkdev(clk
, clk_name
, NULL
);
307 * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
310 #define SUNXI_GATES_MAX_SIZE 64
313 DECLARE_BITMAP(mask
, SUNXI_GATES_MAX_SIZE
);
316 static const __initconst
struct gates_data axi_gates_data
= {
320 static const __initconst
struct gates_data ahb_gates_data
= {
321 .mask
= {0x7F77FFF, 0x14FB3F},
324 static const __initconst
struct gates_data apb0_gates_data
= {
328 static const __initconst
struct gates_data apb1_gates_data
= {
332 static void __init
sunxi_gates_clk_setup(struct device_node
*node
,
333 struct gates_data
*data
)
335 struct clk_onecell_data
*clk_data
;
336 const char *clk_parent
;
337 const char *clk_name
;
344 reg
= of_iomap(node
, 0);
346 clk_parent
= of_clk_get_parent_name(node
, 0);
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
);
353 clk_data
->clks
= kzalloc((qty
+1) * sizeof(struct clk
*), GFP_KERNEL
);
354 if (!clk_data
->clks
) {
359 for_each_set_bit(i
, data
->mask
, SUNXI_GATES_MAX_SIZE
) {
360 of_property_read_string_index(node
, "clock-output-names",
363 /* No driver claims this clock, but it should remain gated */
364 ignore
= !strcmp("ahb_sdram", clk_name
) ? CLK_IGNORE_UNUSED
: 0;
366 clk_data
->clks
[i
] = clk_register_gate(NULL
, clk_name
,
368 reg
+ 4 * (i
/32), i
% 32,
370 WARN_ON(IS_ERR(clk_data
->clks
[i
]));
375 /* Adjust to the real max */
376 clk_data
->clk_num
= i
;
378 of_clk_add_provider(node
, of_clk_src_onecell_get
, clk_data
);
381 /* Matches for of_clk_init */
382 static const __initconst
struct of_device_id clk_match
[] = {
383 {.compatible
= "fixed-clock", .data
= of_fixed_clk_setup
,},
384 {.compatible
= "allwinner,sun4i-osc-clk", .data
= sunxi_osc_clk_setup
,},
388 /* Matches for factors clocks */
389 static const __initconst
struct of_device_id clk_factors_match
[] = {
390 {.compatible
= "allwinner,sun4i-pll1-clk", .data
= &pll1_data
,},
391 {.compatible
= "allwinner,sun4i-apb1-clk", .data
= &apb1_data
,},
395 /* Matches for divider clocks */
396 static const __initconst
struct of_device_id clk_div_match
[] = {
397 {.compatible
= "allwinner,sun4i-axi-clk", .data
= &axi_data
,},
398 {.compatible
= "allwinner,sun4i-ahb-clk", .data
= &ahb_data
,},
399 {.compatible
= "allwinner,sun4i-apb0-clk", .data
= &apb0_data
,},
403 /* Matches for mux clocks */
404 static const __initconst
struct of_device_id clk_mux_match
[] = {
405 {.compatible
= "allwinner,sun4i-cpu-clk", .data
= &cpu_data
,},
406 {.compatible
= "allwinner,sun4i-apb1-mux-clk", .data
= &apb1_mux_data
,},
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
,},
419 static void __init
of_sunxi_table_clock_setup(const struct of_device_id
*clk_match
,
422 struct device_node
*np
;
423 const struct div_data
*data
;
424 const struct of_device_id
*match
;
425 void (*setup_function
)(struct device_node
*, const void *) = function
;
427 for_each_matching_node(np
, clk_match
) {
428 match
= of_match_node(clk_match
, np
);
430 setup_function(np
, data
);
434 void __init
sunxi_init_clocks(void)
436 /* Register all the simple sunxi clocks on DT */
437 of_clk_init(clk_match
);
439 /* Register factor clocks */
440 of_sunxi_table_clock_setup(clk_factors_match
, sunxi_factors_clk_setup
);
442 /* Register divider clocks */
443 of_sunxi_table_clock_setup(clk_div_match
, sunxi_divider_clk_setup
);
445 /* Register mux clocks */
446 of_sunxi_table_clock_setup(clk_mux_match
, sunxi_mux_clk_setup
);
448 /* Register gate clocks */
449 of_sunxi_table_clock_setup(clk_gates_match
, sunxi_gates_clk_setup
);