upgrade 3.13 targets to 3.13.2, refresh patches
[openwrt.git] / target / linux / sunxi / patches-3.13 / 118-clk-sunxi-add-pll5-pll6.patch
1 From 655893a197a5134a371a5c6b579f1bbce03ab413 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
3 Date: Mon, 23 Dec 2013 00:32:37 -0300
4 Subject: [PATCH] clk: sunxi: add PLL5 and PLL6 support
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 This commit implements PLL5 and PLL6 support on the sunxi clock driver.
10 These PLLs use a similar factor clock, but differ on their outputs.
11
12 Signed-off-by: Emilio López <emilio@elopez.com.ar>
13 Acked-by: Mike Turquette <mturquette@linaro.org>
14 ---
15  Documentation/devicetree/bindings/clock/sunxi.txt |   2 +
16  drivers/clk/sunxi/clk-sunxi.c                     | 230 ++++++++++++++++++++++
17  2 files changed, 232 insertions(+)
18
19 --- a/Documentation/devicetree/bindings/clock/sunxi.txt
20 +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
21 @@ -9,6 +9,8 @@ Required properties:
22         "allwinner,sun4i-osc-clk" - for a gatable oscillator
23         "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
24         "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
25 +       "allwinner,sun4i-pll5-clk" - for the PLL5 clock
26 +       "allwinner,sun4i-pll6-clk" - for the PLL6 clock
27         "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
28         "allwinner,sun4i-axi-clk" - for the AXI clock
29         "allwinner,sun4i-axi-gates-clk" - for the AXI gates
30 --- a/drivers/clk/sunxi/clk-sunxi.c
31 +++ b/drivers/clk/sunxi/clk-sunxi.c
32 @@ -218,6 +218,40 @@ static void sun6i_a31_get_pll1_factors(u
33  }
34  
35  /**
36 + * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
37 + * PLL5 rate is calculated as follows
38 + * rate = parent_rate * n * (k + 1)
39 + * parent_rate is always 24Mhz
40 + */
41 +
42 +static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
43 +                                  u8 *n, u8 *k, u8 *m, u8 *p)
44 +{
45 +       u8 div;
46 +
47 +       /* Normalize value to a parent_rate multiple (24M) */
48 +       div = *freq / parent_rate;
49 +       *freq = parent_rate * div;
50 +
51 +       /* we were called to round the frequency, we can now return */
52 +       if (n == NULL)
53 +               return;
54 +
55 +       if (div < 31)
56 +               *k = 0;
57 +       else if (div / 2 < 31)
58 +               *k = 1;
59 +       else if (div / 3 < 31)
60 +               *k = 2;
61 +       else
62 +               *k = 3;
63 +
64 +       *n = DIV_ROUND_UP(div, (*k+1));
65 +}
66 +
67 +
68 +
69 +/**
70   * sun4i_get_apb1_factors() - calculates m, p factors for APB1
71   * APB1 rate is calculated as follows
72   * rate = (parent_rate >> p) / (m + 1);
73 @@ -293,6 +327,13 @@ static struct clk_factors_config sun6i_a
74         .mwidth = 2,
75  };
76  
77 +static struct clk_factors_config sun4i_pll5_config = {
78 +       .nshift = 8,
79 +       .nwidth = 5,
80 +       .kshift = 4,
81 +       .kwidth = 2,
82 +};
83 +
84  static struct clk_factors_config sun4i_apb1_config = {
85         .mshift = 0,
86         .mwidth = 5,
87 @@ -312,6 +353,12 @@ static const struct factors_data sun6i_a
88         .getter = sun6i_a31_get_pll1_factors,
89  };
90  
91 +static const struct factors_data sun4i_pll5_data __initconst = {
92 +       .enable = 31,
93 +       .table = &sun4i_pll5_config,
94 +       .getter = sun4i_get_pll5_factors,
95 +};
96 +
97  static const struct factors_data sun4i_apb1_data __initconst = {
98         .table = &sun4i_apb1_config,
99         .getter = sun4i_get_apb1_factors,
100 @@ -627,6 +674,179 @@ static void __init sunxi_gates_clk_setup
101         of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
102  }
103  
104 +
105 +
106 +/**
107 + * sunxi_divs_clk_setup() helper data
108 + */
109 +
110 +#define SUNXI_DIVS_MAX_QTY     2
111 +#define SUNXI_DIVISOR_WIDTH    2
112 +
113 +struct divs_data {
114 +       const struct factors_data *factors; /* data for the factor clock */
115 +       struct {
116 +               u8 fixed; /* is it a fixed divisor? if not... */
117 +               struct clk_div_table *table; /* is it a table based divisor? */
118 +               u8 shift; /* otherwise it's a normal divisor with this shift */
119 +               u8 pow;   /* is it power-of-two based? */
120 +               u8 gate;  /* is it independently gateable? */
121 +       } div[SUNXI_DIVS_MAX_QTY];
122 +};
123 +
124 +static struct clk_div_table pll6_sata_tbl[] = {
125 +       { .val = 0, .div = 6, },
126 +       { .val = 1, .div = 12, },
127 +       { .val = 2, .div = 18, },
128 +       { .val = 3, .div = 24, },
129 +       { } /* sentinel */
130 +};
131 +
132 +static const struct divs_data pll5_divs_data __initconst = {
133 +       .factors = &sun4i_pll5_data,
134 +       .div = {
135 +               { .shift = 0, .pow = 0, }, /* M, DDR */
136 +               { .shift = 16, .pow = 1, }, /* P, other */
137 +       }
138 +};
139 +
140 +static const struct divs_data pll6_divs_data __initconst = {
141 +       .factors = &sun4i_pll5_data,
142 +       .div = {
143 +               { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
144 +               { .fixed = 2 }, /* P, other */
145 +       }
146 +};
147 +
148 +/**
149 + * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
150 + *
151 + * These clocks look something like this
152 + *            ________________________
153 + *           |         ___divisor 1---|----> to consumer
154 + * parent >--|  pll___/___divisor 2---|----> to consumer
155 + *           |        \_______________|____> to consumer
156 + *           |________________________|
157 + */
158 +
159 +static void __init sunxi_divs_clk_setup(struct device_node *node,
160 +                                       struct divs_data *data)
161 +{
162 +       struct clk_onecell_data *clk_data;
163 +       const char *parent  = node->name;
164 +       const char *clk_name;
165 +       struct clk **clks, *pclk;
166 +       struct clk_hw *gate_hw, *rate_hw;
167 +       const struct clk_ops *rate_ops;
168 +       struct clk_gate *gate = NULL;
169 +       struct clk_fixed_factor *fix_factor;
170 +       struct clk_divider *divider;
171 +       void *reg;
172 +       int i = 0;
173 +       int flags, clkflags;
174 +
175 +       /* Set up factor clock that we will be dividing */
176 +       pclk = sunxi_factors_clk_setup(node, data->factors);
177 +
178 +       reg = of_iomap(node, 0);
179 +
180 +       clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
181 +       if (!clk_data)
182 +               return;
183 +
184 +       clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
185 +       if (!clks)
186 +               goto free_clkdata;
187 +
188 +       clk_data->clks = clks;
189 +
190 +       /* It's not a good idea to have automatic reparenting changing
191 +        * our RAM clock! */
192 +       clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
193 +
194 +       for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
195 +               if (of_property_read_string_index(node, "clock-output-names",
196 +                                                 i, &clk_name) != 0)
197 +                       break;
198 +
199 +               gate_hw = NULL;
200 +               rate_hw = NULL;
201 +               rate_ops = NULL;
202 +
203 +               /* If this leaf clock can be gated, create a gate */
204 +               if (data->div[i].gate) {
205 +                       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
206 +                       if (!gate)
207 +                               goto free_clks;
208 +
209 +                       gate->reg = reg;
210 +                       gate->bit_idx = data->div[i].gate;
211 +                       gate->lock = &clk_lock;
212 +
213 +                       gate_hw = &gate->hw;
214 +               }
215 +
216 +               /* Leaves can be fixed or configurable divisors */
217 +               if (data->div[i].fixed) {
218 +                       fix_factor = kzalloc(sizeof(*fix_factor), GFP_KERNEL);
219 +                       if (!fix_factor)
220 +                               goto free_gate;
221 +
222 +                       fix_factor->mult = 1;
223 +                       fix_factor->div = data->div[i].fixed;
224 +
225 +                       rate_hw = &fix_factor->hw;
226 +                       rate_ops = &clk_fixed_factor_ops;
227 +               } else {
228 +                       divider = kzalloc(sizeof(*divider), GFP_KERNEL);
229 +                       if (!divider)
230 +                               goto free_gate;
231 +
232 +                       flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
233 +
234 +                       divider->reg = reg;
235 +                       divider->shift = data->div[i].shift;
236 +                       divider->width = SUNXI_DIVISOR_WIDTH;
237 +                       divider->flags = flags;
238 +                       divider->lock = &clk_lock;
239 +                       divider->table = data->div[i].table;
240 +
241 +                       rate_hw = &divider->hw;
242 +                       rate_ops = &clk_divider_ops;
243 +               }
244 +
245 +               /* Wrap the (potential) gate and the divisor on a composite
246 +                * clock to unify them */
247 +               clks[i] = clk_register_composite(NULL, clk_name, &parent, 1,
248 +                                                NULL, NULL,
249 +                                                rate_hw, rate_ops,
250 +                                                gate_hw, &clk_gate_ops,
251 +                                                clkflags);
252 +
253 +               WARN_ON(IS_ERR(clk_data->clks[i]));
254 +               clk_register_clkdev(clks[i], clk_name, NULL);
255 +       }
256 +
257 +       /* The last clock available on the getter is the parent */
258 +       clks[i++] = pclk;
259 +
260 +       /* Adjust to the real max */
261 +       clk_data->clk_num = i;
262 +
263 +       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
264 +
265 +       return;
266 +
267 +free_gate:
268 +       kfree(gate);
269 +free_clks:
270 +       kfree(clks);
271 +free_clkdata:
272 +       kfree(clk_data);
273 +}
274 +
275 +
276 +
277  /* Matches for factors clocks */
278  static const struct of_device_id clk_factors_match[] __initconst = {
279         {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
280 @@ -644,6 +864,13 @@ static const struct of_device_id clk_div
281         {}
282  };
283  
284 +/* Matches for divided outputs */
285 +static const struct of_device_id clk_divs_match[] __initconst = {
286 +       {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
287 +       {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
288 +       {}
289 +};
290 +
291  /* Matches for mux clocks */
292  static const struct of_device_id clk_mux_match[] __initconst = {
293         {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
294 @@ -721,6 +948,9 @@ static void __init sunxi_init_clocks(str
295         /* Register divider clocks */
296         of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
297  
298 +       /* Register divided output clocks */
299 +       of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
300 +
301         /* Register mux clocks */
302         of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
303