aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/ti
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2015-01-13 17:51:27 -0500
committerMichael Turquette <mturquette@linaro.org>2015-01-20 13:09:07 -0500
commit163152cbbe32177154cb6a2832b5c15324669bc1 (patch)
treee2f3c0cd132e3df6b19554e5fd7b6b82dd020b87 /drivers/clk/ti
parent4526e7b857076ba613cc7199fc7fd17d60e86ede (diff)
clk: ti: Add support for FAPLL on dm816x
On dm816x the clocks are sourced from a FAPLL (Flying Adder PLL) that does not seem to be used on the other omap variants. There are four instances of the FAPLL on dm816x that each have three to seven child synthesizers. I've set up the FAPLL as a single fapll.c driver. Later on we could potentially have the PLL code generic. To do that, we would have to consider the following: 1. Setting the PLL to bypass mode also sets the child synthesizers into bypass mode. As the bypass rate can also be generated by the PLL in regular mode, there's no way for the child synthesizers to detect the bypass mode based on the parent clock rate. 2. The PLL registers control the power for each of the child syntheriser. Note that the clocks are currently still missing the set_rate implementation so things are still running based on the bootloader values. That's OK for now as most of the outputs have dividers and those can be set using the existing TI component clock code. I have verified that the extclk rates are correct for a few clocks, so adding the set_rate support should be fairly trivial later on. This code is partially based on the TI81XX-LINUX-PSP-04.04.00.02 patches published at: http://downloads.ti.com/dsps/dsps_public_sw/psp/LinuxPSP/TI81XX_04_04/04_04_00_02/index_FDS.html Cc: Brian Hutchinson <b.hutchman@gmail.com> Cc: Paul Walmsley <paul@pwsan.com> Cc: Tero Kristo <t-kristo@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Michael Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r--drivers/clk/ti/Makefile1
-rw-r--r--drivers/clk/ti/fapll.c410
2 files changed, 411 insertions, 0 deletions
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index ed4d0aaf8916..e55438c41c31 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -3,6 +3,7 @@ obj-y += clk.o autoidle.o clockdomain.o
3clk-common = dpll.o composite.o divider.o gate.o \ 3clk-common = dpll.o composite.o divider.o gate.o \
4 fixed-factor.o mux.o apll.o 4 fixed-factor.o mux.o apll.o
5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o 5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o
6obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o
6obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o 7obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
7obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o 8obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o
8obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o 9obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
new file mode 100644
index 000000000000..6ef89639a9f6
--- /dev/null
+++ b/drivers/clk/ti/fapll.c
@@ -0,0 +1,410 @@
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
52struct 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
62struct 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
72static 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
82static 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
87 v |= (1 << FAPLL_MAIN_PLLEN);
88 writel_relaxed(v, fd->base);
89
90 return 0;
91}
92
93static 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
98 v &= ~(1 << FAPLL_MAIN_PLLEN);
99 writel_relaxed(v, fd->base);
100}
101
102static 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
107 return v & (1 << FAPLL_MAIN_PLLEN);
108}
109
110static 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
134static 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
144static 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
152static 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
163static 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
172static 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 */
183static 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
228static 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
235static 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
269free:
270 kfree(synth);
271 kfree(init);
272
273 return ERR_PTR(-ENOMEM);
274}
275
276static 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
398unmap:
399 iounmap(fd->base);
400free:
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
410CLK_OF_DECLARE(ti_fapll_clock, "ti,dm816-fapll-clock", ti_fapll_setup);