Commit | Line | Data |
---|---|---|
163152cb TL |
1 | /* |
2 | * This program is free software; you can redistribute it and/or | |
3 | * modify it under the terms of the GNU General Public License as | |
4 | * published by the Free Software Foundation version 2. | |
5 | * | |
6 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
7 | * kind, whether express or implied; without even the implied warranty | |
8 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
9 | * GNU General Public License for more details. | |
10 | */ | |
11 | ||
12 | #include <linux/clk-provider.h> | |
13 | #include <linux/delay.h> | |
14 | #include <linux/slab.h> | |
15 | #include <linux/err.h> | |
16 | #include <linux/of.h> | |
17 | #include <linux/of_address.h> | |
18 | #include <linux/clk/ti.h> | |
19 | #include <asm/div64.h> | |
20 | ||
21 | /* FAPLL Control Register PLL_CTRL */ | |
22 | #define FAPLL_MAIN_LOCK BIT(7) | |
23 | #define FAPLL_MAIN_PLLEN BIT(3) | |
24 | #define FAPLL_MAIN_BP BIT(2) | |
25 | #define FAPLL_MAIN_LOC_CTL BIT(0) | |
26 | ||
27 | /* FAPLL powerdown register PWD */ | |
28 | #define FAPLL_PWD_OFFSET 4 | |
29 | ||
30 | #define MAX_FAPLL_OUTPUTS 7 | |
31 | #define FAPLL_MAX_RETRIES 1000 | |
32 | ||
33 | #define to_fapll(_hw) container_of(_hw, struct fapll_data, hw) | |
34 | #define to_synth(_hw) container_of(_hw, struct fapll_synth, hw) | |
35 | ||
36 | /* The bypass bit is inverted on the ddr_pll.. */ | |
37 | #define fapll_is_ddr_pll(va) (((u32)(va) & 0xffff) == 0x0440) | |
38 | ||
39 | /* | |
40 | * The audio_pll_clk1 input is hard wired to the 27MHz bypass clock, | |
41 | * and the audio_pll_clk1 synthesizer is hardwared to 32KiHz output. | |
42 | */ | |
43 | #define is_ddr_pll_clk1(va) (((u32)(va) & 0xffff) == 0x044c) | |
44 | #define is_audio_pll_clk1(va) (((u32)(va) & 0xffff) == 0x04a8) | |
45 | ||
46 | /* Synthesizer divider register */ | |
47 | #define SYNTH_LDMDIV1 BIT(8) | |
48 | ||
49 | /* Synthesizer frequency register */ | |
50 | #define SYNTH_LDFREQ BIT(31) | |
51 | ||
52 | struct fapll_data { | |
53 | struct clk_hw hw; | |
54 | void __iomem *base; | |
55 | const char *name; | |
56 | struct clk *clk_ref; | |
57 | struct clk *clk_bypass; | |
58 | struct clk_onecell_data outputs; | |
59 | bool bypass_bit_inverted; | |
60 | }; | |
61 | ||
62 | struct fapll_synth { | |
63 | struct clk_hw hw; | |
64 | struct fapll_data *fd; | |
65 | int index; | |
66 | void __iomem *freq; | |
67 | void __iomem *div; | |
68 | const char *name; | |
69 | struct clk *clk_pll; | |
70 | }; | |
71 | ||
72 | static bool ti_fapll_clock_is_bypass(struct fapll_data *fd) | |
73 | { | |
74 | u32 v = readl_relaxed(fd->base); | |
75 | ||
76 | if (fd->bypass_bit_inverted) | |
77 | return !(v & FAPLL_MAIN_BP); | |
78 | else | |
79 | return !!(v & FAPLL_MAIN_BP); | |
80 | } | |
81 | ||
82 | static int ti_fapll_enable(struct clk_hw *hw) | |
83 | { | |
84 | struct fapll_data *fd = to_fapll(hw); | |
85 | u32 v = readl_relaxed(fd->base); | |
86 | ||
03208cc6 | 87 | v |= FAPLL_MAIN_PLLEN; |
163152cb TL |
88 | writel_relaxed(v, fd->base); |
89 | ||
90 | return 0; | |
91 | } | |
92 | ||
93 | static void ti_fapll_disable(struct clk_hw *hw) | |
94 | { | |
95 | struct fapll_data *fd = to_fapll(hw); | |
96 | u32 v = readl_relaxed(fd->base); | |
97 | ||
03208cc6 | 98 | v &= ~FAPLL_MAIN_PLLEN; |
163152cb TL |
99 | writel_relaxed(v, fd->base); |
100 | } | |
101 | ||
102 | static int ti_fapll_is_enabled(struct clk_hw *hw) | |
103 | { | |
104 | struct fapll_data *fd = to_fapll(hw); | |
105 | u32 v = readl_relaxed(fd->base); | |
106 | ||
03208cc6 | 107 | return v & FAPLL_MAIN_PLLEN; |
163152cb TL |
108 | } |
109 | ||
110 | static unsigned long ti_fapll_recalc_rate(struct clk_hw *hw, | |
111 | unsigned long parent_rate) | |
112 | { | |
113 | struct fapll_data *fd = to_fapll(hw); | |
114 | u32 fapll_n, fapll_p, v; | |
115 | long long rate; | |
116 | ||
117 | if (ti_fapll_clock_is_bypass(fd)) | |
118 | return parent_rate; | |
119 | ||
120 | rate = parent_rate; | |
121 | ||
122 | /* PLL pre-divider is P and multiplier is N */ | |
123 | v = readl_relaxed(fd->base); | |
124 | fapll_p = (v >> 8) & 0xff; | |
125 | if (fapll_p) | |
126 | do_div(rate, fapll_p); | |
127 | fapll_n = v >> 16; | |
128 | if (fapll_n) | |
129 | rate *= fapll_n; | |
130 | ||
131 | return rate; | |
132 | } | |
133 | ||
134 | static u8 ti_fapll_get_parent(struct clk_hw *hw) | |
135 | { | |
136 | struct fapll_data *fd = to_fapll(hw); | |
137 | ||
138 | if (ti_fapll_clock_is_bypass(fd)) | |
139 | return 1; | |
140 | ||
141 | return 0; | |
142 | } | |
143 | ||
144 | static struct clk_ops ti_fapll_ops = { | |
145 | .enable = ti_fapll_enable, | |
146 | .disable = ti_fapll_disable, | |
147 | .is_enabled = ti_fapll_is_enabled, | |
148 | .recalc_rate = ti_fapll_recalc_rate, | |
149 | .get_parent = ti_fapll_get_parent, | |
150 | }; | |
151 | ||
152 | static int ti_fapll_synth_enable(struct clk_hw *hw) | |
153 | { | |
154 | struct fapll_synth *synth = to_synth(hw); | |
155 | u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET); | |
156 | ||
157 | v &= ~(1 << synth->index); | |
158 | writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET); | |
159 | ||
160 | return 0; | |
161 | } | |
162 | ||
163 | static void ti_fapll_synth_disable(struct clk_hw *hw) | |
164 | { | |
165 | struct fapll_synth *synth = to_synth(hw); | |
166 | u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET); | |
167 | ||
168 | v |= 1 << synth->index; | |
169 | writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET); | |
170 | } | |
171 | ||
172 | static int ti_fapll_synth_is_enabled(struct clk_hw *hw) | |
173 | { | |
174 | struct fapll_synth *synth = to_synth(hw); | |
175 | u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET); | |
176 | ||
177 | return !(v & (1 << synth->index)); | |
178 | } | |
179 | ||
180 | /* | |
181 | * See dm816x TRM chapter 1.10.3 Flying Adder PLL fore more info | |
182 | */ | |
183 | static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw, | |
184 | unsigned long parent_rate) | |
185 | { | |
186 | struct fapll_synth *synth = to_synth(hw); | |
187 | u32 synth_div_m; | |
188 | long long rate; | |
189 | ||
190 | /* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */ | |
191 | if (!synth->div) | |
192 | return 32768; | |
193 | ||
194 | /* | |
195 | * PLL in bypass sets the synths in bypass mode too. The PLL rate | |
196 | * can be also be set to 27MHz, so we can't use parent_rate to | |
197 | * check for bypass mode. | |
198 | */ | |
199 | if (ti_fapll_clock_is_bypass(synth->fd)) | |
200 | return parent_rate; | |
201 | ||
202 | rate = parent_rate; | |
203 | ||
204 | /* | |
205 | * Synth frequency integer and fractional divider. | |
206 | * Note that the phase output K is 8, so the result needs | |
207 | * to be multiplied by 8. | |
208 | */ | |
209 | if (synth->freq) { | |
210 | u32 v, synth_int_div, synth_frac_div, synth_div_freq; | |
211 | ||
212 | v = readl_relaxed(synth->freq); | |
213 | synth_int_div = (v >> 24) & 0xf; | |
214 | synth_frac_div = v & 0xffffff; | |
215 | synth_div_freq = (synth_int_div * 10000000) + synth_frac_div; | |
216 | rate *= 10000000; | |
217 | do_div(rate, synth_div_freq); | |
218 | rate *= 8; | |
219 | } | |
220 | ||
221 | /* Synth ost-divider M */ | |
222 | synth_div_m = readl_relaxed(synth->div) & 0xff; | |
223 | do_div(rate, synth_div_m); | |
224 | ||
225 | return rate; | |
226 | } | |
227 | ||
228 | static struct clk_ops ti_fapll_synt_ops = { | |
229 | .enable = ti_fapll_synth_enable, | |
230 | .disable = ti_fapll_synth_disable, | |
231 | .is_enabled = ti_fapll_synth_is_enabled, | |
232 | .recalc_rate = ti_fapll_synth_recalc_rate, | |
233 | }; | |
234 | ||
235 | static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, | |
236 | void __iomem *freq, | |
237 | void __iomem *div, | |
238 | int index, | |
239 | const char *name, | |
240 | const char *parent, | |
241 | struct clk *pll_clk) | |
242 | { | |
243 | struct clk_init_data *init; | |
244 | struct fapll_synth *synth; | |
245 | ||
246 | init = kzalloc(sizeof(*init), GFP_KERNEL); | |
247 | if (!init) | |
248 | return ERR_PTR(-ENOMEM); | |
249 | ||
250 | init->ops = &ti_fapll_synt_ops; | |
251 | init->name = name; | |
252 | init->parent_names = &parent; | |
253 | init->num_parents = 1; | |
254 | ||
255 | synth = kzalloc(sizeof(*synth), GFP_KERNEL); | |
256 | if (!synth) | |
257 | goto free; | |
258 | ||
259 | synth->fd = fd; | |
260 | synth->index = index; | |
261 | synth->freq = freq; | |
262 | synth->div = div; | |
263 | synth->name = name; | |
264 | synth->hw.init = init; | |
265 | synth->clk_pll = pll_clk; | |
266 | ||
267 | return clk_register(NULL, &synth->hw); | |
268 | ||
269 | free: | |
270 | kfree(synth); | |
271 | kfree(init); | |
272 | ||
273 | return ERR_PTR(-ENOMEM); | |
274 | } | |
275 | ||
276 | static void __init ti_fapll_setup(struct device_node *node) | |
277 | { | |
278 | struct fapll_data *fd; | |
279 | struct clk_init_data *init = NULL; | |
280 | const char *parent_name[2]; | |
281 | struct clk *pll_clk; | |
282 | int i; | |
283 | ||
284 | fd = kzalloc(sizeof(*fd), GFP_KERNEL); | |
285 | if (!fd) | |
286 | return; | |
287 | ||
288 | fd->outputs.clks = kzalloc(sizeof(struct clk *) * | |
289 | MAX_FAPLL_OUTPUTS + 1, | |
290 | GFP_KERNEL); | |
291 | if (!fd->outputs.clks) | |
292 | goto free; | |
293 | ||
294 | init = kzalloc(sizeof(*init), GFP_KERNEL); | |
295 | if (!init) | |
296 | goto free; | |
297 | ||
298 | init->ops = &ti_fapll_ops; | |
299 | init->name = node->name; | |
300 | ||
301 | init->num_parents = of_clk_get_parent_count(node); | |
302 | if (init->num_parents != 2) { | |
303 | pr_err("%s must have two parents\n", node->name); | |
304 | goto free; | |
305 | } | |
306 | ||
307 | parent_name[0] = of_clk_get_parent_name(node, 0); | |
308 | parent_name[1] = of_clk_get_parent_name(node, 1); | |
309 | init->parent_names = parent_name; | |
310 | ||
311 | fd->clk_ref = of_clk_get(node, 0); | |
312 | if (IS_ERR(fd->clk_ref)) { | |
313 | pr_err("%s could not get clk_ref\n", node->name); | |
314 | goto free; | |
315 | } | |
316 | ||
317 | fd->clk_bypass = of_clk_get(node, 1); | |
318 | if (IS_ERR(fd->clk_bypass)) { | |
319 | pr_err("%s could not get clk_bypass\n", node->name); | |
320 | goto free; | |
321 | } | |
322 | ||
323 | fd->base = of_iomap(node, 0); | |
324 | if (!fd->base) { | |
325 | pr_err("%s could not get IO base\n", node->name); | |
326 | goto free; | |
327 | } | |
328 | ||
329 | if (fapll_is_ddr_pll(fd->base)) | |
330 | fd->bypass_bit_inverted = true; | |
331 | ||
332 | fd->name = node->name; | |
333 | fd->hw.init = init; | |
334 | ||
335 | /* Register the parent PLL */ | |
336 | pll_clk = clk_register(NULL, &fd->hw); | |
337 | if (IS_ERR(pll_clk)) | |
338 | goto unmap; | |
339 | ||
340 | fd->outputs.clks[0] = pll_clk; | |
341 | fd->outputs.clk_num++; | |
342 | ||
343 | /* | |
344 | * Set up the child synthesizers starting at index 1 as the | |
345 | * PLL output is at index 0. We need to check the clock-indices | |
346 | * for numbering in case there are holes in the synth mapping, | |
347 | * and then probe the synth register to see if it has a FREQ | |
348 | * register available. | |
349 | */ | |
350 | for (i = 0; i < MAX_FAPLL_OUTPUTS; i++) { | |
351 | const char *output_name; | |
352 | void __iomem *freq, *div; | |
353 | struct clk *synth_clk; | |
354 | int output_instance; | |
355 | u32 v; | |
356 | ||
357 | if (of_property_read_string_index(node, "clock-output-names", | |
358 | i, &output_name)) | |
359 | continue; | |
360 | ||
361 | if (of_property_read_u32_index(node, "clock-indices", i, | |
362 | &output_instance)) | |
363 | output_instance = i; | |
364 | ||
365 | freq = fd->base + (output_instance * 8); | |
366 | div = freq + 4; | |
367 | ||
368 | /* Check for hardwired audio_pll_clk1 */ | |
369 | if (is_audio_pll_clk1(freq)) { | |
370 | freq = 0; | |
371 | div = 0; | |
372 | } else { | |
373 | /* Does the synthesizer have a FREQ register? */ | |
374 | v = readl_relaxed(freq); | |
375 | if (!v) | |
376 | freq = 0; | |
377 | } | |
378 | synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance, | |
379 | output_name, node->name, | |
380 | pll_clk); | |
381 | if (IS_ERR(synth_clk)) | |
382 | continue; | |
383 | ||
384 | fd->outputs.clks[output_instance] = synth_clk; | |
385 | fd->outputs.clk_num++; | |
386 | ||
387 | clk_register_clkdev(synth_clk, output_name, NULL); | |
388 | } | |
389 | ||
390 | /* Register the child synthesizers as the FAPLL outputs */ | |
391 | of_clk_add_provider(node, of_clk_src_onecell_get, &fd->outputs); | |
392 | /* Add clock alias for the outputs */ | |
393 | ||
394 | kfree(init); | |
395 | ||
396 | return; | |
397 | ||
398 | unmap: | |
399 | iounmap(fd->base); | |
400 | free: | |
401 | if (fd->clk_bypass) | |
402 | clk_put(fd->clk_bypass); | |
403 | if (fd->clk_ref) | |
404 | clk_put(fd->clk_ref); | |
405 | kfree(fd->outputs.clks); | |
406 | kfree(fd); | |
407 | kfree(init); | |
408 | } | |
409 | ||
410 | CLK_OF_DECLARE(ti_fapll_clock, "ti,dm816-fapll-clock", ti_fapll_setup); |