Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
555eae97 TY |
2 | /* |
3 | * Copyright 2013 Freescale Semiconductor, Inc. | |
fa4dd53e | 4 | * Copyright 2021 NXP |
555eae97 | 5 | * |
93a17c05 | 6 | * clock driver for Freescale QorIQ SoCs. |
555eae97 | 7 | */ |
c88b2b66 EM |
8 | |
9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | ||
4cb15934 | 11 | #include <dt-bindings/clock/fsl,qoriq-clockgen.h> |
0dfc86b3 | 12 | #include <linux/clk.h> |
555eae97 | 13 | #include <linux/clk-provider.h> |
45899dc5 | 14 | #include <linux/clkdev.h> |
0dfc86b3 | 15 | #include <linux/fsl/guts.h> |
555eae97 TY |
16 | #include <linux/io.h> |
17 | #include <linux/kernel.h> | |
18 | #include <linux/module.h> | |
c11eede6 | 19 | #include <linux/of_address.h> |
555eae97 TY |
20 | #include <linux/of_platform.h> |
21 | #include <linux/of.h> | |
22 | #include <linux/slab.h> | |
23 | ||
0dfc86b3 SW |
24 | #define PLL_DIV1 0 |
25 | #define PLL_DIV2 1 | |
26 | #define PLL_DIV3 2 | |
27 | #define PLL_DIV4 3 | |
28 | ||
29 | #define PLATFORM_PLL 0 | |
30 | #define CGA_PLL1 1 | |
31 | #define CGA_PLL2 2 | |
32 | #define CGA_PLL3 3 | |
33 | #define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */ | |
34 | #define CGB_PLL1 4 | |
35 | #define CGB_PLL2 5 | |
e9501b97 | 36 | #define MAX_PLL_DIV 32 |
0dfc86b3 SW |
37 | |
38 | struct clockgen_pll_div { | |
39 | struct clk *clk; | |
40 | char name[32]; | |
41 | }; | |
42 | ||
43 | struct clockgen_pll { | |
cc61ab9b | 44 | struct clockgen_pll_div div[MAX_PLL_DIV]; |
0dfc86b3 SW |
45 | }; |
46 | ||
47 | #define CLKSEL_VALID 1 | |
48 | #define CLKSEL_80PCT 2 /* Only allowed if PLL <= 80% of max cpu freq */ | |
49 | ||
50 | struct clockgen_sourceinfo { | |
51 | u32 flags; /* CLKSEL_xxx */ | |
52 | int pll; /* CGx_PLLn */ | |
53 | int div; /* PLL_DIVn */ | |
54 | }; | |
55 | ||
56 | #define NUM_MUX_PARENTS 16 | |
57 | ||
58 | struct clockgen_muxinfo { | |
59 | struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS]; | |
60 | }; | |
61 | ||
62 | #define NUM_HWACCEL 5 | |
63 | #define NUM_CMUX 8 | |
64 | ||
65 | struct clockgen; | |
66 | ||
67 | /* | |
68 | * cmux freq must be >= platform pll. | |
69 | * If not set, cmux freq must be >= platform pll/2 | |
70 | */ | |
71 | #define CG_CMUX_GE_PLAT 1 | |
9e19ca2f | 72 | |
0dfc86b3 | 73 | #define CG_PLL_8BIT 2 /* PLLCnGSR[CFG] is 8 bits, not 6 */ |
9e19ca2f SW |
74 | #define CG_VER3 4 /* version 3 cg: reg layout different */ |
75 | #define CG_LITTLE_ENDIAN 8 | |
0dfc86b3 SW |
76 | |
77 | struct clockgen_chipinfo { | |
78 | const char *compat, *guts_compat; | |
79 | const struct clockgen_muxinfo *cmux_groups[2]; | |
80 | const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL]; | |
81 | void (*init_periph)(struct clockgen *cg); | |
42614b5b | 82 | int cmux_to_group[NUM_CMUX + 1]; /* array should be -1 terminated */ |
0dfc86b3 SW |
83 | u32 pll_mask; /* 1 << n bit set if PLL n is valid */ |
84 | u32 flags; /* CG_xxx */ | |
85 | }; | |
86 | ||
87 | struct clockgen { | |
88 | struct device_node *node; | |
89 | void __iomem *regs; | |
90 | struct clockgen_chipinfo info; /* mutable copy */ | |
80b4ae7a | 91 | struct clk *sysclk, *coreclk; |
0dfc86b3 SW |
92 | struct clockgen_pll pll[6]; |
93 | struct clk *cmux[NUM_CMUX]; | |
94 | struct clk *hwaccel[NUM_HWACCEL]; | |
95 | struct clk *fman[2]; | |
96 | struct ccsr_guts __iomem *guts; | |
97 | }; | |
98 | ||
99 | static struct clockgen clockgen; | |
cf1e0449 | 100 | static bool add_cpufreq_dev __initdata; |
0dfc86b3 | 101 | |
9e19ca2f SW |
102 | static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg) |
103 | { | |
104 | if (cg->info.flags & CG_LITTLE_ENDIAN) | |
105 | iowrite32(val, reg); | |
106 | else | |
107 | iowrite32be(val, reg); | |
108 | } | |
109 | ||
110 | static u32 cg_in(struct clockgen *cg, u32 __iomem *reg) | |
111 | { | |
112 | u32 val; | |
113 | ||
114 | if (cg->info.flags & CG_LITTLE_ENDIAN) | |
115 | val = ioread32(reg); | |
116 | else | |
117 | val = ioread32be(reg); | |
118 | ||
119 | return val; | |
120 | } | |
121 | ||
0dfc86b3 SW |
122 | static const struct clockgen_muxinfo p2041_cmux_grp1 = { |
123 | { | |
124 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
125 | [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
126 | [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
127 | } | |
128 | }; | |
129 | ||
130 | static const struct clockgen_muxinfo p2041_cmux_grp2 = { | |
131 | { | |
132 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
2c7693e0 SW |
133 | [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, |
134 | [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
0dfc86b3 SW |
135 | } |
136 | }; | |
137 | ||
138 | static const struct clockgen_muxinfo p5020_cmux_grp1 = { | |
139 | { | |
140 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
141 | [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
142 | [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 }, | |
143 | } | |
144 | }; | |
145 | ||
146 | static const struct clockgen_muxinfo p5020_cmux_grp2 = { | |
147 | { | |
148 | [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 }, | |
149 | [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
150 | [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
151 | } | |
152 | }; | |
153 | ||
154 | static const struct clockgen_muxinfo p5040_cmux_grp1 = { | |
155 | { | |
156 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
157 | [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
158 | [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 }, | |
159 | [5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 }, | |
160 | } | |
161 | }; | |
162 | ||
163 | static const struct clockgen_muxinfo p5040_cmux_grp2 = { | |
164 | { | |
165 | [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 }, | |
166 | [1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 }, | |
167 | [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
168 | [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
169 | } | |
170 | }; | |
171 | ||
172 | static const struct clockgen_muxinfo p4080_cmux_grp1 = { | |
173 | { | |
174 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
175 | [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
176 | [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
177 | [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
178 | [8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 }, | |
179 | } | |
180 | }; | |
181 | ||
182 | static const struct clockgen_muxinfo p4080_cmux_grp2 = { | |
183 | { | |
184 | [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 }, | |
185 | [8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 }, | |
186 | [9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 }, | |
187 | [12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 }, | |
188 | [13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 }, | |
189 | } | |
190 | }; | |
191 | ||
192 | static const struct clockgen_muxinfo t1023_cmux = { | |
193 | { | |
194 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
195 | [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
196 | } | |
197 | }; | |
198 | ||
199 | static const struct clockgen_muxinfo t1040_cmux = { | |
200 | { | |
201 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
202 | [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
203 | [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
204 | [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
205 | } | |
206 | }; | |
207 | ||
208 | ||
209 | static const struct clockgen_muxinfo clockgen2_cmux_cga = { | |
210 | { | |
211 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
212 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
213 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
214 | {}, | |
215 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
216 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
217 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, | |
218 | {}, | |
219 | { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 }, | |
220 | { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 }, | |
221 | { CLKSEL_VALID, CGA_PLL3, PLL_DIV4 }, | |
222 | }, | |
223 | }; | |
224 | ||
225 | static const struct clockgen_muxinfo clockgen2_cmux_cga12 = { | |
226 | { | |
227 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
228 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
229 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
230 | {}, | |
231 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
232 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
233 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, | |
234 | }, | |
235 | }; | |
236 | ||
237 | static const struct clockgen_muxinfo clockgen2_cmux_cgb = { | |
238 | { | |
239 | { CLKSEL_VALID, CGB_PLL1, PLL_DIV1 }, | |
240 | { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 }, | |
241 | { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 }, | |
242 | {}, | |
243 | { CLKSEL_VALID, CGB_PLL2, PLL_DIV1 }, | |
244 | { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 }, | |
245 | { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 }, | |
246 | }, | |
247 | }; | |
248 | ||
92df3a9b MK |
249 | static const struct clockgen_muxinfo ls1021a_cmux = { |
250 | { | |
251 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
252 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
253 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
254 | } | |
255 | }; | |
256 | ||
95089f6a YT |
257 | static const struct clockgen_muxinfo ls1028a_hwa1 = { |
258 | { | |
259 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
260 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
261 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
262 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
263 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
264 | {}, | |
265 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
266 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
267 | }, | |
268 | }; | |
269 | ||
270 | static const struct clockgen_muxinfo ls1028a_hwa2 = { | |
271 | { | |
272 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
273 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
274 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
275 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
276 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, | |
277 | {}, | |
278 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
279 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
280 | }, | |
281 | }; | |
282 | ||
283 | static const struct clockgen_muxinfo ls1028a_hwa3 = { | |
284 | { | |
285 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
286 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
287 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
288 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
289 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
290 | {}, | |
291 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
292 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
293 | }, | |
294 | }; | |
295 | ||
296 | static const struct clockgen_muxinfo ls1028a_hwa4 = { | |
297 | { | |
298 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
299 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
300 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
301 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
302 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, | |
303 | {}, | |
304 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
305 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
306 | }, | |
307 | }; | |
308 | ||
e994412c HZ |
309 | static const struct clockgen_muxinfo ls1043a_hwa1 = { |
310 | { | |
311 | {}, | |
312 | {}, | |
313 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
314 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
315 | {}, | |
316 | {}, | |
317 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
318 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
319 | }, | |
320 | }; | |
321 | ||
322 | static const struct clockgen_muxinfo ls1043a_hwa2 = { | |
323 | { | |
324 | {}, | |
325 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
326 | {}, | |
327 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
328 | }, | |
329 | }; | |
330 | ||
80e52198 MH |
331 | static const struct clockgen_muxinfo ls1046a_hwa1 = { |
332 | { | |
333 | {}, | |
334 | {}, | |
335 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
336 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
337 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
338 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
339 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
340 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
341 | }, | |
342 | }; | |
343 | ||
344 | static const struct clockgen_muxinfo ls1046a_hwa2 = { | |
345 | { | |
346 | {}, | |
347 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
348 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
349 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
350 | {}, | |
351 | {}, | |
352 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
353 | }, | |
354 | }; | |
355 | ||
a932872f YL |
356 | static const struct clockgen_muxinfo ls1088a_hwa1 = { |
357 | { | |
358 | {}, | |
359 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
360 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
361 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
362 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
363 | {}, | |
364 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
365 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
366 | }, | |
367 | }; | |
368 | ||
369 | static const struct clockgen_muxinfo ls1088a_hwa2 = { | |
370 | { | |
371 | {}, | |
372 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
373 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
374 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
375 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, | |
376 | {}, | |
377 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
378 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
379 | }, | |
380 | }; | |
381 | ||
44709358 TY |
382 | static const struct clockgen_muxinfo ls1012a_cmux = { |
383 | { | |
384 | [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
385 | {}, | |
386 | [2] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
387 | } | |
388 | }; | |
389 | ||
0dfc86b3 SW |
390 | static const struct clockgen_muxinfo t1023_hwa1 = { |
391 | { | |
392 | {}, | |
393 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
394 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
395 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
396 | }, | |
397 | }; | |
398 | ||
399 | static const struct clockgen_muxinfo t1023_hwa2 = { | |
400 | { | |
401 | [6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
402 | }, | |
403 | }; | |
404 | ||
405 | static const struct clockgen_muxinfo t2080_hwa1 = { | |
406 | { | |
407 | {}, | |
408 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
409 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
410 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
411 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
412 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
413 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
414 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
415 | }, | |
416 | }; | |
417 | ||
418 | static const struct clockgen_muxinfo t2080_hwa2 = { | |
419 | { | |
420 | {}, | |
421 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, | |
422 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
423 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
424 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, | |
425 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
426 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
427 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
428 | }, | |
429 | }; | |
430 | ||
431 | static const struct clockgen_muxinfo t4240_hwa1 = { | |
432 | { | |
433 | { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 }, | |
434 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, | |
435 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, | |
436 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, | |
437 | { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, | |
438 | {}, | |
439 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, | |
440 | { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, | |
441 | }, | |
442 | }; | |
443 | ||
444 | static const struct clockgen_muxinfo t4240_hwa4 = { | |
445 | { | |
446 | [2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 }, | |
447 | [3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 }, | |
448 | [4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 }, | |
449 | [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
450 | [6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 }, | |
451 | }, | |
452 | }; | |
453 | ||
454 | static const struct clockgen_muxinfo t4240_hwa5 = { | |
455 | { | |
456 | [2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 }, | |
457 | [3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 }, | |
458 | [4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 }, | |
459 | [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, | |
460 | [6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 }, | |
461 | [7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 }, | |
462 | }, | |
463 | }; | |
464 | ||
465 | #define RCWSR7_FM1_CLK_SEL 0x40000000 | |
466 | #define RCWSR7_FM2_CLK_SEL 0x20000000 | |
467 | #define RCWSR7_HWA_ASYNC_DIV 0x04000000 | |
468 | ||
469 | static void __init p2041_init_periph(struct clockgen *cg) | |
470 | { | |
471 | u32 reg; | |
472 | ||
473 | reg = ioread32be(&cg->guts->rcwsr[7]); | |
474 | ||
475 | if (reg & RCWSR7_FM1_CLK_SEL) | |
476 | cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk; | |
477 | else | |
478 | cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; | |
479 | } | |
480 | ||
481 | static void __init p4080_init_periph(struct clockgen *cg) | |
482 | { | |
483 | u32 reg; | |
484 | ||
485 | reg = ioread32be(&cg->guts->rcwsr[7]); | |
486 | ||
487 | if (reg & RCWSR7_FM1_CLK_SEL) | |
488 | cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk; | |
489 | else | |
490 | cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; | |
491 | ||
492 | if (reg & RCWSR7_FM2_CLK_SEL) | |
493 | cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk; | |
494 | else | |
495 | cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; | |
496 | } | |
497 | ||
498 | static void __init p5020_init_periph(struct clockgen *cg) | |
499 | { | |
500 | u32 reg; | |
501 | int div = PLL_DIV2; | |
502 | ||
503 | reg = ioread32be(&cg->guts->rcwsr[7]); | |
504 | if (reg & RCWSR7_HWA_ASYNC_DIV) | |
505 | div = PLL_DIV4; | |
506 | ||
507 | if (reg & RCWSR7_FM1_CLK_SEL) | |
508 | cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk; | |
509 | else | |
510 | cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; | |
511 | } | |
512 | ||
513 | static void __init p5040_init_periph(struct clockgen *cg) | |
514 | { | |
515 | u32 reg; | |
516 | int div = PLL_DIV2; | |
517 | ||
518 | reg = ioread32be(&cg->guts->rcwsr[7]); | |
519 | if (reg & RCWSR7_HWA_ASYNC_DIV) | |
520 | div = PLL_DIV4; | |
521 | ||
522 | if (reg & RCWSR7_FM1_CLK_SEL) | |
523 | cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk; | |
524 | else | |
525 | cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; | |
526 | ||
527 | if (reg & RCWSR7_FM2_CLK_SEL) | |
528 | cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk; | |
529 | else | |
530 | cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; | |
531 | } | |
532 | ||
533 | static void __init t1023_init_periph(struct clockgen *cg) | |
534 | { | |
535 | cg->fman[0] = cg->hwaccel[1]; | |
536 | } | |
537 | ||
538 | static void __init t1040_init_periph(struct clockgen *cg) | |
539 | { | |
540 | cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk; | |
541 | } | |
542 | ||
543 | static void __init t2080_init_periph(struct clockgen *cg) | |
544 | { | |
545 | cg->fman[0] = cg->hwaccel[0]; | |
546 | } | |
547 | ||
548 | static void __init t4240_init_periph(struct clockgen *cg) | |
549 | { | |
550 | cg->fman[0] = cg->hwaccel[3]; | |
551 | cg->fman[1] = cg->hwaccel[4]; | |
552 | } | |
553 | ||
554 | static const struct clockgen_chipinfo chipinfo[] = { | |
555 | { | |
556 | .compat = "fsl,b4420-clockgen", | |
557 | .guts_compat = "fsl,b4860-device-config", | |
558 | .init_periph = t2080_init_periph, | |
559 | .cmux_groups = { | |
560 | &clockgen2_cmux_cga12, &clockgen2_cmux_cgb | |
561 | }, | |
562 | .hwaccel = { | |
563 | &t2080_hwa1 | |
564 | }, | |
565 | .cmux_to_group = { | |
566 | 0, 1, 1, 1, -1 | |
567 | }, | |
fa4dd53e WK |
568 | .pll_mask = BIT(PLATFORM_PLL) | |
569 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | | |
570 | BIT(CGB_PLL1) | BIT(CGB_PLL2), | |
0dfc86b3 SW |
571 | .flags = CG_PLL_8BIT, |
572 | }, | |
573 | { | |
574 | .compat = "fsl,b4860-clockgen", | |
575 | .guts_compat = "fsl,b4860-device-config", | |
576 | .init_periph = t2080_init_periph, | |
577 | .cmux_groups = { | |
578 | &clockgen2_cmux_cga12, &clockgen2_cmux_cgb | |
579 | }, | |
580 | .hwaccel = { | |
581 | &t2080_hwa1 | |
582 | }, | |
583 | .cmux_to_group = { | |
584 | 0, 1, 1, 1, -1 | |
585 | }, | |
fa4dd53e WK |
586 | .pll_mask = BIT(PLATFORM_PLL) | |
587 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | | |
588 | BIT(CGB_PLL1) | BIT(CGB_PLL2), | |
0dfc86b3 SW |
589 | .flags = CG_PLL_8BIT, |
590 | }, | |
591 | { | |
592 | .compat = "fsl,ls1021a-clockgen", | |
593 | .cmux_groups = { | |
92df3a9b | 594 | &ls1021a_cmux |
0dfc86b3 SW |
595 | }, |
596 | .cmux_to_group = { | |
597 | 0, -1 | |
598 | }, | |
fa4dd53e WK |
599 | .pll_mask = BIT(PLATFORM_PLL) | |
600 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
0dfc86b3 | 601 | }, |
95089f6a YT |
602 | { |
603 | .compat = "fsl,ls1028a-clockgen", | |
604 | .cmux_groups = { | |
605 | &clockgen2_cmux_cga12 | |
606 | }, | |
607 | .hwaccel = { | |
608 | &ls1028a_hwa1, &ls1028a_hwa2, | |
609 | &ls1028a_hwa3, &ls1028a_hwa4 | |
610 | }, | |
611 | .cmux_to_group = { | |
612 | 0, 0, 0, 0, -1 | |
613 | }, | |
fa4dd53e WK |
614 | .pll_mask = BIT(PLATFORM_PLL) | |
615 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
95089f6a YT |
616 | .flags = CG_VER3 | CG_LITTLE_ENDIAN, |
617 | }, | |
e994412c HZ |
618 | { |
619 | .compat = "fsl,ls1043a-clockgen", | |
620 | .init_periph = t2080_init_periph, | |
621 | .cmux_groups = { | |
622 | &t1040_cmux | |
623 | }, | |
624 | .hwaccel = { | |
625 | &ls1043a_hwa1, &ls1043a_hwa2 | |
626 | }, | |
627 | .cmux_to_group = { | |
628 | 0, -1 | |
629 | }, | |
fa4dd53e WK |
630 | .pll_mask = BIT(PLATFORM_PLL) | |
631 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
e994412c HZ |
632 | .flags = CG_PLL_8BIT, |
633 | }, | |
80e52198 MH |
634 | { |
635 | .compat = "fsl,ls1046a-clockgen", | |
636 | .init_periph = t2080_init_periph, | |
637 | .cmux_groups = { | |
638 | &t1040_cmux | |
639 | }, | |
640 | .hwaccel = { | |
641 | &ls1046a_hwa1, &ls1046a_hwa2 | |
642 | }, | |
643 | .cmux_to_group = { | |
644 | 0, -1 | |
645 | }, | |
fa4dd53e WK |
646 | .pll_mask = BIT(PLATFORM_PLL) | |
647 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
80e52198 MH |
648 | .flags = CG_PLL_8BIT, |
649 | }, | |
e0c888c4 YT |
650 | { |
651 | .compat = "fsl,ls1088a-clockgen", | |
652 | .cmux_groups = { | |
653 | &clockgen2_cmux_cga12 | |
654 | }, | |
a932872f YL |
655 | .hwaccel = { |
656 | &ls1088a_hwa1, &ls1088a_hwa2 | |
657 | }, | |
e0c888c4 YT |
658 | .cmux_to_group = { |
659 | 0, 0, -1 | |
660 | }, | |
fa4dd53e WK |
661 | .pll_mask = BIT(PLATFORM_PLL) | |
662 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
e0c888c4 YT |
663 | .flags = CG_VER3 | CG_LITTLE_ENDIAN, |
664 | }, | |
44709358 TY |
665 | { |
666 | .compat = "fsl,ls1012a-clockgen", | |
667 | .cmux_groups = { | |
668 | &ls1012a_cmux | |
669 | }, | |
670 | .cmux_to_group = { | |
671 | 0, -1 | |
672 | }, | |
fa4dd53e | 673 | .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1), |
44709358 | 674 | }, |
9e19ca2f SW |
675 | { |
676 | .compat = "fsl,ls2080a-clockgen", | |
677 | .cmux_groups = { | |
678 | &clockgen2_cmux_cga12, &clockgen2_cmux_cgb | |
679 | }, | |
680 | .cmux_to_group = { | |
681 | 0, 0, 1, 1, -1 | |
682 | }, | |
fa4dd53e WK |
683 | .pll_mask = BIT(PLATFORM_PLL) | |
684 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | | |
685 | BIT(CGB_PLL1) | BIT(CGB_PLL2), | |
9e19ca2f SW |
686 | .flags = CG_VER3 | CG_LITTLE_ENDIAN, |
687 | }, | |
78a5ba8f VS |
688 | { |
689 | .compat = "fsl,lx2160a-clockgen", | |
690 | .cmux_groups = { | |
691 | &clockgen2_cmux_cga12, &clockgen2_cmux_cgb | |
692 | }, | |
693 | .cmux_to_group = { | |
694 | 0, 0, 0, 0, 1, 1, 1, 1, -1 | |
695 | }, | |
fa4dd53e WK |
696 | .pll_mask = BIT(PLATFORM_PLL) | |
697 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | | |
698 | BIT(CGB_PLL1) | BIT(CGB_PLL2), | |
78a5ba8f VS |
699 | .flags = CG_VER3 | CG_LITTLE_ENDIAN, |
700 | }, | |
0dfc86b3 SW |
701 | { |
702 | .compat = "fsl,p2041-clockgen", | |
703 | .guts_compat = "fsl,qoriq-device-config-1.0", | |
704 | .init_periph = p2041_init_periph, | |
705 | .cmux_groups = { | |
706 | &p2041_cmux_grp1, &p2041_cmux_grp2 | |
707 | }, | |
708 | .cmux_to_group = { | |
709 | 0, 0, 1, 1, -1 | |
710 | }, | |
fa4dd53e WK |
711 | .pll_mask = BIT(PLATFORM_PLL) | |
712 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
0dfc86b3 SW |
713 | }, |
714 | { | |
715 | .compat = "fsl,p3041-clockgen", | |
716 | .guts_compat = "fsl,qoriq-device-config-1.0", | |
717 | .init_periph = p2041_init_periph, | |
718 | .cmux_groups = { | |
719 | &p2041_cmux_grp1, &p2041_cmux_grp2 | |
720 | }, | |
721 | .cmux_to_group = { | |
722 | 0, 0, 1, 1, -1 | |
723 | }, | |
fa4dd53e WK |
724 | .pll_mask = BIT(PLATFORM_PLL) | |
725 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
0dfc86b3 SW |
726 | }, |
727 | { | |
728 | .compat = "fsl,p4080-clockgen", | |
729 | .guts_compat = "fsl,qoriq-device-config-1.0", | |
730 | .init_periph = p4080_init_periph, | |
731 | .cmux_groups = { | |
732 | &p4080_cmux_grp1, &p4080_cmux_grp2 | |
733 | }, | |
734 | .cmux_to_group = { | |
42614b5b | 735 | 0, 0, 0, 0, 1, 1, 1, 1, -1 |
0dfc86b3 | 736 | }, |
fa4dd53e WK |
737 | .pll_mask = BIT(PLATFORM_PLL) | |
738 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | | |
739 | BIT(CGA_PLL3) | BIT(CGA_PLL4), | |
0dfc86b3 SW |
740 | }, |
741 | { | |
742 | .compat = "fsl,p5020-clockgen", | |
743 | .guts_compat = "fsl,qoriq-device-config-1.0", | |
744 | .init_periph = p5020_init_periph, | |
745 | .cmux_groups = { | |
a95fb581 | 746 | &p5020_cmux_grp1, &p5020_cmux_grp2 |
0dfc86b3 SW |
747 | }, |
748 | .cmux_to_group = { | |
749 | 0, 1, -1 | |
750 | }, | |
fa4dd53e WK |
751 | .pll_mask = BIT(PLATFORM_PLL) | |
752 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
0dfc86b3 SW |
753 | }, |
754 | { | |
755 | .compat = "fsl,p5040-clockgen", | |
756 | .guts_compat = "fsl,p5040-device-config", | |
757 | .init_periph = p5040_init_periph, | |
758 | .cmux_groups = { | |
759 | &p5040_cmux_grp1, &p5040_cmux_grp2 | |
760 | }, | |
761 | .cmux_to_group = { | |
762 | 0, 0, 1, 1, -1 | |
763 | }, | |
fa4dd53e WK |
764 | .pll_mask = BIT(PLATFORM_PLL) | |
765 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3), | |
0dfc86b3 SW |
766 | }, |
767 | { | |
768 | .compat = "fsl,t1023-clockgen", | |
769 | .guts_compat = "fsl,t1023-device-config", | |
770 | .init_periph = t1023_init_periph, | |
771 | .cmux_groups = { | |
772 | &t1023_cmux | |
773 | }, | |
774 | .hwaccel = { | |
775 | &t1023_hwa1, &t1023_hwa2 | |
776 | }, | |
777 | .cmux_to_group = { | |
778 | 0, 0, -1 | |
779 | }, | |
fa4dd53e | 780 | .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1), |
0dfc86b3 SW |
781 | .flags = CG_PLL_8BIT, |
782 | }, | |
783 | { | |
784 | .compat = "fsl,t1040-clockgen", | |
785 | .guts_compat = "fsl,t1040-device-config", | |
786 | .init_periph = t1040_init_periph, | |
787 | .cmux_groups = { | |
788 | &t1040_cmux | |
789 | }, | |
790 | .cmux_to_group = { | |
791 | 0, 0, 0, 0, -1 | |
792 | }, | |
fa4dd53e WK |
793 | .pll_mask = BIT(PLATFORM_PLL) | |
794 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
0dfc86b3 SW |
795 | .flags = CG_PLL_8BIT, |
796 | }, | |
797 | { | |
798 | .compat = "fsl,t2080-clockgen", | |
799 | .guts_compat = "fsl,t2080-device-config", | |
800 | .init_periph = t2080_init_periph, | |
801 | .cmux_groups = { | |
802 | &clockgen2_cmux_cga12 | |
803 | }, | |
804 | .hwaccel = { | |
805 | &t2080_hwa1, &t2080_hwa2 | |
806 | }, | |
807 | .cmux_to_group = { | |
808 | 0, -1 | |
809 | }, | |
fa4dd53e WK |
810 | .pll_mask = BIT(PLATFORM_PLL) | |
811 | BIT(CGA_PLL1) | BIT(CGA_PLL2), | |
0dfc86b3 SW |
812 | .flags = CG_PLL_8BIT, |
813 | }, | |
814 | { | |
815 | .compat = "fsl,t4240-clockgen", | |
816 | .guts_compat = "fsl,t4240-device-config", | |
817 | .init_periph = t4240_init_periph, | |
818 | .cmux_groups = { | |
819 | &clockgen2_cmux_cga, &clockgen2_cmux_cgb | |
820 | }, | |
821 | .hwaccel = { | |
822 | &t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5 | |
823 | }, | |
824 | .cmux_to_group = { | |
825 | 0, 0, 1, -1 | |
826 | }, | |
fa4dd53e WK |
827 | .pll_mask = BIT(PLATFORM_PLL) | |
828 | BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | | |
829 | BIT(CGB_PLL1) | BIT(CGB_PLL2), | |
0dfc86b3 SW |
830 | .flags = CG_PLL_8BIT, |
831 | }, | |
832 | {}, | |
833 | }; | |
834 | ||
835 | struct mux_hwclock { | |
555eae97 | 836 | struct clk_hw hw; |
0dfc86b3 SW |
837 | struct clockgen *cg; |
838 | const struct clockgen_muxinfo *info; | |
839 | u32 __iomem *reg; | |
840 | u8 parent_to_clksel[NUM_MUX_PARENTS]; | |
841 | s8 clksel_to_parent[NUM_MUX_PARENTS]; | |
842 | int num_parents; | |
555eae97 TY |
843 | }; |
844 | ||
0dfc86b3 SW |
845 | #define to_mux_hwclock(p) container_of(p, struct mux_hwclock, hw) |
846 | #define CLKSEL_MASK 0x78000000 | |
555eae97 | 847 | #define CLKSEL_SHIFT 27 |
555eae97 | 848 | |
0dfc86b3 | 849 | static int mux_set_parent(struct clk_hw *hw, u8 idx) |
555eae97 | 850 | { |
0dfc86b3 | 851 | struct mux_hwclock *hwc = to_mux_hwclock(hw); |
555eae97 TY |
852 | u32 clksel; |
853 | ||
0dfc86b3 SW |
854 | if (idx >= hwc->num_parents) |
855 | return -EINVAL; | |
856 | ||
857 | clksel = hwc->parent_to_clksel[idx]; | |
9e19ca2f | 858 | cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg); |
555eae97 TY |
859 | |
860 | return 0; | |
861 | } | |
862 | ||
0dfc86b3 | 863 | static u8 mux_get_parent(struct clk_hw *hw) |
555eae97 | 864 | { |
0dfc86b3 | 865 | struct mux_hwclock *hwc = to_mux_hwclock(hw); |
555eae97 | 866 | u32 clksel; |
0dfc86b3 | 867 | s8 ret; |
555eae97 | 868 | |
9e19ca2f | 869 | clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; |
555eae97 | 870 | |
0dfc86b3 SW |
871 | ret = hwc->clksel_to_parent[clksel]; |
872 | if (ret < 0) { | |
873 | pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg); | |
874 | return 0; | |
875 | } | |
876 | ||
877 | return ret; | |
555eae97 TY |
878 | } |
879 | ||
334680dd | 880 | static const struct clk_ops cmux_ops = { |
0dfc86b3 SW |
881 | .get_parent = mux_get_parent, |
882 | .set_parent = mux_set_parent, | |
555eae97 TY |
883 | }; |
884 | ||
0dfc86b3 SW |
885 | /* |
886 | * Don't allow setting for now, as the clock options haven't been | |
887 | * sanitized for additional restrictions. | |
888 | */ | |
889 | static const struct clk_ops hwaccel_ops = { | |
890 | .get_parent = mux_get_parent, | |
891 | }; | |
892 | ||
893 | static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg, | |
894 | struct mux_hwclock *hwc, | |
895 | int idx) | |
555eae97 | 896 | { |
0dfc86b3 | 897 | int pll, div; |
555eae97 | 898 | |
0dfc86b3 SW |
899 | if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID)) |
900 | return NULL; | |
555eae97 | 901 | |
0dfc86b3 SW |
902 | pll = hwc->info->clksel[idx].pll; |
903 | div = hwc->info->clksel[idx].div; | |
555eae97 | 904 | |
0dfc86b3 SW |
905 | return &cg->pll[pll].div[div]; |
906 | } | |
555eae97 | 907 | |
0dfc86b3 SW |
908 | static struct clk * __init create_mux_common(struct clockgen *cg, |
909 | struct mux_hwclock *hwc, | |
910 | const struct clk_ops *ops, | |
911 | unsigned long min_rate, | |
7c1c5413 | 912 | unsigned long max_rate, |
0dfc86b3 SW |
913 | unsigned long pct80_rate, |
914 | const char *fmt, int idx) | |
915 | { | |
916 | struct clk_init_data init = {}; | |
917 | struct clk *clk; | |
918 | const struct clockgen_pll_div *div; | |
919 | const char *parent_names[NUM_MUX_PARENTS]; | |
920 | char name[32]; | |
921 | int i, j; | |
8002cab6 | 922 | |
0dfc86b3 | 923 | snprintf(name, sizeof(name), fmt, idx); |
555eae97 | 924 | |
0dfc86b3 SW |
925 | for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) { |
926 | unsigned long rate; | |
57bfd7ee | 927 | |
0dfc86b3 | 928 | hwc->clksel_to_parent[i] = -1; |
57bfd7ee | 929 | |
0dfc86b3 SW |
930 | div = get_pll_div(cg, hwc, i); |
931 | if (!div) | |
932 | continue; | |
555eae97 | 933 | |
0dfc86b3 SW |
934 | rate = clk_get_rate(div->clk); |
935 | ||
936 | if (hwc->info->clksel[i].flags & CLKSEL_80PCT && | |
937 | rate > pct80_rate) | |
938 | continue; | |
939 | if (rate < min_rate) | |
940 | continue; | |
7c1c5413 SW |
941 | if (rate > max_rate) |
942 | continue; | |
0dfc86b3 SW |
943 | |
944 | parent_names[j] = div->name; | |
945 | hwc->parent_to_clksel[j] = i; | |
946 | hwc->clksel_to_parent[i] = j; | |
947 | j++; | |
555eae97 TY |
948 | } |
949 | ||
0dfc86b3 SW |
950 | init.name = name; |
951 | init.ops = ops; | |
555eae97 | 952 | init.parent_names = parent_names; |
0dfc86b3 | 953 | init.num_parents = hwc->num_parents = j; |
555eae97 | 954 | init.flags = 0; |
0dfc86b3 SW |
955 | hwc->hw.init = &init; |
956 | hwc->cg = cg; | |
555eae97 | 957 | |
0dfc86b3 | 958 | clk = clk_register(NULL, &hwc->hw); |
555eae97 | 959 | if (IS_ERR(clk)) { |
0dfc86b3 SW |
960 | pr_err("%s: Couldn't register %s: %ld\n", __func__, name, |
961 | PTR_ERR(clk)); | |
962 | kfree(hwc); | |
963 | return NULL; | |
964 | } | |
965 | ||
966 | return clk; | |
967 | } | |
968 | ||
969 | static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) | |
970 | { | |
971 | struct mux_hwclock *hwc; | |
972 | const struct clockgen_pll_div *div; | |
973 | unsigned long plat_rate, min_rate; | |
7c1c5413 | 974 | u64 max_rate, pct80_rate; |
0dfc86b3 SW |
975 | u32 clksel; |
976 | ||
977 | hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); | |
978 | if (!hwc) | |
979 | return NULL; | |
980 | ||
8964193f TY |
981 | if (cg->info.flags & CG_VER3) |
982 | hwc->reg = cg->regs + 0x70000 + 0x20 * idx; | |
983 | else | |
984 | hwc->reg = cg->regs + 0x20 * idx; | |
985 | ||
0dfc86b3 SW |
986 | hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]]; |
987 | ||
988 | /* | |
989 | * Find the rate for the default clksel, and treat it as the | |
990 | * maximum rated core frequency. If this is an incorrect | |
991 | * assumption, certain clock options (possibly including the | |
992 | * default clksel) may be inappropriately excluded on certain | |
993 | * chips. | |
994 | */ | |
9e19ca2f | 995 | clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; |
0dfc86b3 | 996 | div = get_pll_div(cg, hwc, clksel); |
279104e3 SM |
997 | if (!div) { |
998 | kfree(hwc); | |
0dfc86b3 | 999 | return NULL; |
279104e3 | 1000 | } |
0dfc86b3 | 1001 | |
7c1c5413 SW |
1002 | max_rate = clk_get_rate(div->clk); |
1003 | pct80_rate = max_rate * 8; | |
0dfc86b3 SW |
1004 | do_div(pct80_rate, 10); |
1005 | ||
1006 | plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk); | |
1007 | ||
1008 | if (cg->info.flags & CG_CMUX_GE_PLAT) | |
1009 | min_rate = plat_rate; | |
1010 | else | |
1011 | min_rate = plat_rate / 2; | |
1012 | ||
7c1c5413 | 1013 | return create_mux_common(cg, hwc, &cmux_ops, min_rate, max_rate, |
0dfc86b3 SW |
1014 | pct80_rate, "cg-cmux%d", idx); |
1015 | } | |
1016 | ||
1017 | static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx) | |
1018 | { | |
1019 | struct mux_hwclock *hwc; | |
1020 | ||
1021 | hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); | |
1022 | if (!hwc) | |
1023 | return NULL; | |
1024 | ||
1025 | hwc->reg = cg->regs + 0x20 * idx + 0x10; | |
1026 | hwc->info = cg->info.hwaccel[idx]; | |
1027 | ||
7c1c5413 | 1028 | return create_mux_common(cg, hwc, &hwaccel_ops, 0, ULONG_MAX, 0, |
0dfc86b3 SW |
1029 | "cg-hwaccel%d", idx); |
1030 | } | |
1031 | ||
1032 | static void __init create_muxes(struct clockgen *cg) | |
1033 | { | |
1034 | int i; | |
1035 | ||
1036 | for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) { | |
1037 | if (cg->info.cmux_to_group[i] < 0) | |
1038 | break; | |
1039 | if (cg->info.cmux_to_group[i] >= | |
1040 | ARRAY_SIZE(cg->info.cmux_groups)) { | |
1041 | WARN_ON_ONCE(1); | |
1042 | continue; | |
1043 | } | |
1044 | ||
1045 | cg->cmux[i] = create_one_cmux(cg, i); | |
555eae97 TY |
1046 | } |
1047 | ||
0dfc86b3 SW |
1048 | for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) { |
1049 | if (!cg->info.hwaccel[i]) | |
1050 | continue; | |
1051 | ||
1052 | cg->hwaccel[i] = create_one_hwaccel(cg, i); | |
1053 | } | |
1054 | } | |
1055 | ||
cf1e0449 | 1056 | static void __init _clockgen_init(struct device_node *np, bool legacy); |
0dfc86b3 | 1057 | |
80b4ae7a SW |
1058 | /* |
1059 | * Legacy nodes may get probed before the parent clockgen node. | |
1060 | * It is assumed that device trees with legacy nodes will not | |
1061 | * contain a "clocks" property -- otherwise the input clocks may | |
1062 | * not be initialized at this point. | |
1063 | */ | |
0dfc86b3 SW |
1064 | static void __init legacy_init_clockgen(struct device_node *np) |
1065 | { | |
1066 | if (!clockgen.node) | |
cf1e0449 | 1067 | _clockgen_init(of_get_parent(np), true); |
0dfc86b3 SW |
1068 | } |
1069 | ||
1070 | /* Legacy node */ | |
1071 | static void __init core_mux_init(struct device_node *np) | |
1072 | { | |
1073 | struct clk *clk; | |
1074 | struct resource res; | |
1075 | int idx, rc; | |
1076 | ||
1077 | legacy_init_clockgen(np); | |
1078 | ||
1079 | if (of_address_to_resource(np, 0, &res)) | |
1080 | return; | |
1081 | ||
1082 | idx = (res.start & 0xf0) >> 5; | |
1083 | clk = clockgen.cmux[idx]; | |
1084 | ||
555eae97 TY |
1085 | rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); |
1086 | if (rc) { | |
e665f029 RH |
1087 | pr_err("%s: Couldn't register clk provider for node %pOFn: %d\n", |
1088 | __func__, np, rc); | |
0dfc86b3 | 1089 | return; |
555eae97 | 1090 | } |
0dfc86b3 | 1091 | } |
555eae97 | 1092 | |
3432a2e3 JL |
1093 | static struct clk __init |
1094 | *sysclk_from_fixed(struct device_node *node, const char *name) | |
0dfc86b3 SW |
1095 | { |
1096 | u32 rate; | |
1097 | ||
1098 | if (of_property_read_u32(node, "clock-frequency", &rate)) | |
1099 | return ERR_PTR(-ENODEV); | |
1100 | ||
ec3f2fcb | 1101 | return clk_register_fixed_rate(NULL, name, NULL, 0, rate); |
555eae97 TY |
1102 | } |
1103 | ||
80b4ae7a | 1104 | static struct clk __init *input_clock(const char *name, struct clk *clk) |
0dfc86b3 | 1105 | { |
80b4ae7a | 1106 | const char *input_name; |
0dfc86b3 SW |
1107 | |
1108 | /* Register the input clock under the desired name. */ | |
80b4ae7a SW |
1109 | input_name = __clk_get_name(clk); |
1110 | clk = clk_register_fixed_factor(NULL, name, input_name, | |
0dfc86b3 SW |
1111 | 0, 1, 1); |
1112 | if (IS_ERR(clk)) | |
1113 | pr_err("%s: Couldn't register %s: %ld\n", __func__, name, | |
1114 | PTR_ERR(clk)); | |
1115 | ||
1116 | return clk; | |
1117 | } | |
1118 | ||
80b4ae7a SW |
1119 | static struct clk __init *input_clock_by_name(const char *name, |
1120 | const char *dtname) | |
1121 | { | |
1122 | struct clk *clk; | |
1123 | ||
1124 | clk = of_clk_get_by_name(clockgen.node, dtname); | |
1125 | if (IS_ERR(clk)) | |
1126 | return clk; | |
1127 | ||
1128 | return input_clock(name, clk); | |
1129 | } | |
1130 | ||
1131 | static struct clk __init *input_clock_by_index(const char *name, int idx) | |
1132 | { | |
1133 | struct clk *clk; | |
1134 | ||
1135 | clk = of_clk_get(clockgen.node, 0); | |
1136 | if (IS_ERR(clk)) | |
1137 | return clk; | |
1138 | ||
1139 | return input_clock(name, clk); | |
1140 | } | |
1141 | ||
0dfc86b3 SW |
1142 | static struct clk * __init create_sysclk(const char *name) |
1143 | { | |
1144 | struct device_node *sysclk; | |
1145 | struct clk *clk; | |
1146 | ||
1147 | clk = sysclk_from_fixed(clockgen.node, name); | |
1148 | if (!IS_ERR(clk)) | |
1149 | return clk; | |
1150 | ||
80b4ae7a SW |
1151 | clk = input_clock_by_name(name, "sysclk"); |
1152 | if (!IS_ERR(clk)) | |
1153 | return clk; | |
1154 | ||
1155 | clk = input_clock_by_index(name, 0); | |
0dfc86b3 SW |
1156 | if (!IS_ERR(clk)) |
1157 | return clk; | |
1158 | ||
1159 | sysclk = of_get_child_by_name(clockgen.node, "sysclk"); | |
1160 | if (sysclk) { | |
1161 | clk = sysclk_from_fixed(sysclk, name); | |
1162 | if (!IS_ERR(clk)) | |
1163 | return clk; | |
1164 | } | |
1165 | ||
80b4ae7a SW |
1166 | pr_err("%s: No input sysclk\n", __func__); |
1167 | return NULL; | |
1168 | } | |
1169 | ||
1170 | static struct clk * __init create_coreclk(const char *name) | |
1171 | { | |
1172 | struct clk *clk; | |
1173 | ||
1174 | clk = input_clock_by_name(name, "coreclk"); | |
1175 | if (!IS_ERR(clk)) | |
1176 | return clk; | |
1177 | ||
1178 | /* | |
1179 | * This indicates a mix of legacy nodes with the new coreclk | |
1180 | * mechanism, which should never happen. If this error occurs, | |
1181 | * don't use the wrong input clock just because coreclk isn't | |
1182 | * ready yet. | |
1183 | */ | |
1184 | if (WARN_ON(PTR_ERR(clk) == -EPROBE_DEFER)) | |
1185 | return clk; | |
1186 | ||
0dfc86b3 SW |
1187 | return NULL; |
1188 | } | |
1189 | ||
1190 | /* Legacy node */ | |
1191 | static void __init sysclk_init(struct device_node *node) | |
1192 | { | |
1193 | struct clk *clk; | |
1194 | ||
1195 | legacy_init_clockgen(node); | |
1196 | ||
1197 | clk = clockgen.sysclk; | |
1198 | if (clk) | |
1199 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | |
1200 | } | |
1201 | ||
1202 | #define PLL_KILL BIT(31) | |
1203 | ||
1204 | static void __init create_one_pll(struct clockgen *cg, int idx) | |
555eae97 | 1205 | { |
0dfc86b3 | 1206 | u32 __iomem *reg; |
00fa6e5d | 1207 | u32 mult; |
0dfc86b3 | 1208 | struct clockgen_pll *pll = &cg->pll[idx]; |
80b4ae7a | 1209 | const char *input = "cg-sysclk"; |
0dfc86b3 | 1210 | int i; |
555eae97 | 1211 | |
0dfc86b3 | 1212 | if (!(cg->info.pll_mask & (1 << idx))) |
555eae97 | 1213 | return; |
555eae97 | 1214 | |
80b4ae7a SW |
1215 | if (cg->coreclk && idx != PLATFORM_PLL) { |
1216 | if (IS_ERR(cg->coreclk)) | |
1217 | return; | |
1218 | ||
1219 | input = "cg-coreclk"; | |
1220 | } | |
1221 | ||
9e19ca2f SW |
1222 | if (cg->info.flags & CG_VER3) { |
1223 | switch (idx) { | |
1224 | case PLATFORM_PLL: | |
1225 | reg = cg->regs + 0x60080; | |
1226 | break; | |
1227 | case CGA_PLL1: | |
1228 | reg = cg->regs + 0x80; | |
1229 | break; | |
1230 | case CGA_PLL2: | |
1231 | reg = cg->regs + 0xa0; | |
1232 | break; | |
1233 | case CGB_PLL1: | |
1234 | reg = cg->regs + 0x10080; | |
1235 | break; | |
1236 | case CGB_PLL2: | |
1237 | reg = cg->regs + 0x100a0; | |
1238 | break; | |
1239 | default: | |
1240 | WARN_ONCE(1, "index %d\n", idx); | |
1241 | return; | |
1242 | } | |
1243 | } else { | |
1244 | if (idx == PLATFORM_PLL) | |
1245 | reg = cg->regs + 0xc00; | |
1246 | else | |
1247 | reg = cg->regs + 0x800 + 0x20 * (idx - 1); | |
1248 | } | |
555eae97 | 1249 | |
0dfc86b3 | 1250 | /* Get the multiple of PLL */ |
9e19ca2f | 1251 | mult = cg_in(cg, reg); |
0dfc86b3 SW |
1252 | |
1253 | /* Check if this PLL is disabled */ | |
555eae97 | 1254 | if (mult & PLL_KILL) { |
0dfc86b3 SW |
1255 | pr_debug("%s(): pll %p disabled\n", __func__, reg); |
1256 | return; | |
555eae97 | 1257 | } |
555eae97 | 1258 | |
9e19ca2f SW |
1259 | if ((cg->info.flags & CG_VER3) || |
1260 | ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)) | |
0dfc86b3 SW |
1261 | mult = (mult & GENMASK(8, 1)) >> 1; |
1262 | else | |
1263 | mult = (mult & GENMASK(6, 1)) >> 1; | |
1264 | ||
1265 | for (i = 0; i < ARRAY_SIZE(pll->div); i++) { | |
1266 | struct clk *clk; | |
45899dc5 | 1267 | int ret; |
0dfc86b3 | 1268 | |
36ab0467 | 1269 | /* |
cc61ab9b | 1270 | * For platform PLL, there are MAX_PLL_DIV divider clocks. |
36ab0467 YT |
1271 | * For core PLL, there are 4 divider clocks at most. |
1272 | */ | |
1273 | if (idx != PLATFORM_PLL && i >= 4) | |
1274 | break; | |
1275 | ||
0dfc86b3 SW |
1276 | snprintf(pll->div[i].name, sizeof(pll->div[i].name), |
1277 | "cg-pll%d-div%d", idx, i + 1); | |
1278 | ||
1279 | clk = clk_register_fixed_factor(NULL, | |
80b4ae7a | 1280 | pll->div[i].name, input, 0, mult, i + 1); |
0dfc86b3 SW |
1281 | if (IS_ERR(clk)) { |
1282 | pr_err("%s: %s: register failed %ld\n", | |
1283 | __func__, pll->div[i].name, PTR_ERR(clk)); | |
1284 | continue; | |
1285 | } | |
1286 | ||
1287 | pll->div[i].clk = clk; | |
45899dc5 YT |
1288 | ret = clk_register_clkdev(clk, pll->div[i].name, NULL); |
1289 | if (ret != 0) | |
8f99f5ea DC |
1290 | pr_err("%s: %s: register to lookup table failed %d\n", |
1291 | __func__, pll->div[i].name, ret); | |
45899dc5 | 1292 | |
555eae97 | 1293 | } |
0dfc86b3 SW |
1294 | } |
1295 | ||
1296 | static void __init create_plls(struct clockgen *cg) | |
1297 | { | |
1298 | int i; | |
1299 | ||
1300 | for (i = 0; i < ARRAY_SIZE(cg->pll); i++) | |
1301 | create_one_pll(cg, i); | |
1302 | } | |
555eae97 | 1303 | |
0dfc86b3 SW |
1304 | static void __init legacy_pll_init(struct device_node *np, int idx) |
1305 | { | |
1306 | struct clockgen_pll *pll; | |
1307 | struct clk_onecell_data *onecell_data; | |
1308 | struct clk **subclks; | |
1309 | int count, rc; | |
1310 | ||
1311 | legacy_init_clockgen(np); | |
1312 | ||
1313 | pll = &clockgen.pll[idx]; | |
555eae97 | 1314 | count = of_property_count_strings(np, "clock-output-names"); |
555eae97 | 1315 | |
0dfc86b3 SW |
1316 | BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4); |
1317 | subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL); | |
8002cab6 | 1318 | if (!subclks) |
0dfc86b3 | 1319 | return; |
555eae97 | 1320 | |
6ef1ccac | 1321 | onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL); |
8002cab6 | 1322 | if (!onecell_data) |
555eae97 | 1323 | goto err_clks; |
555eae97 | 1324 | |
0dfc86b3 SW |
1325 | if (count <= 3) { |
1326 | subclks[0] = pll->div[0].clk; | |
1327 | subclks[1] = pll->div[1].clk; | |
1328 | subclks[2] = pll->div[3].clk; | |
1329 | } else { | |
1330 | subclks[0] = pll->div[0].clk; | |
1331 | subclks[1] = pll->div[1].clk; | |
1332 | subclks[2] = pll->div[2].clk; | |
1333 | subclks[3] = pll->div[3].clk; | |
555eae97 TY |
1334 | } |
1335 | ||
1336 | onecell_data->clks = subclks; | |
1337 | onecell_data->clk_num = count; | |
1338 | ||
1339 | rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data); | |
1340 | if (rc) { | |
e665f029 RH |
1341 | pr_err("%s: Couldn't register clk provider for node %pOFn: %d\n", |
1342 | __func__, np, rc); | |
555eae97 TY |
1343 | goto err_cell; |
1344 | } | |
1345 | ||
1346 | return; | |
1347 | err_cell: | |
1348 | kfree(onecell_data); | |
1349 | err_clks: | |
1350 | kfree(subclks); | |
00fa6e5d TY |
1351 | } |
1352 | ||
0dfc86b3 SW |
1353 | /* Legacy node */ |
1354 | static void __init pltfrm_pll_init(struct device_node *np) | |
00fa6e5d | 1355 | { |
0dfc86b3 SW |
1356 | legacy_pll_init(np, PLATFORM_PLL); |
1357 | } | |
00fa6e5d | 1358 | |
0dfc86b3 SW |
1359 | /* Legacy node */ |
1360 | static void __init core_pll_init(struct device_node *np) | |
1361 | { | |
1362 | struct resource res; | |
1363 | int idx; | |
1364 | ||
1365 | if (of_address_to_resource(np, 0, &res)) | |
00fa6e5d | 1366 | return; |
0dfc86b3 SW |
1367 | |
1368 | if ((res.start & 0xfff) == 0xc00) { | |
1369 | /* | |
1370 | * ls1021a devtree labels the platform PLL | |
1371 | * with the core PLL compatible | |
1372 | */ | |
1373 | pltfrm_pll_init(np); | |
1374 | } else { | |
1375 | idx = (res.start & 0xf0) >> 5; | |
1376 | legacy_pll_init(np, CGA_PLL1 + idx); | |
00fa6e5d | 1377 | } |
0dfc86b3 | 1378 | } |
00fa6e5d | 1379 | |
0dfc86b3 SW |
1380 | static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data) |
1381 | { | |
1382 | struct clockgen *cg = data; | |
1383 | struct clk *clk; | |
1384 | struct clockgen_pll *pll; | |
1385 | u32 type, idx; | |
1386 | ||
1387 | if (clkspec->args_count < 2) { | |
1388 | pr_err("%s: insufficient phandle args\n", __func__); | |
1389 | return ERR_PTR(-EINVAL); | |
00fa6e5d TY |
1390 | } |
1391 | ||
0dfc86b3 SW |
1392 | type = clkspec->args[0]; |
1393 | idx = clkspec->args[1]; | |
00fa6e5d | 1394 | |
0dfc86b3 | 1395 | switch (type) { |
4cb15934 | 1396 | case QORIQ_CLK_SYSCLK: |
0dfc86b3 SW |
1397 | if (idx != 0) |
1398 | goto bad_args; | |
1399 | clk = cg->sysclk; | |
1400 | break; | |
4cb15934 | 1401 | case QORIQ_CLK_CMUX: |
0dfc86b3 SW |
1402 | if (idx >= ARRAY_SIZE(cg->cmux)) |
1403 | goto bad_args; | |
1404 | clk = cg->cmux[idx]; | |
1405 | break; | |
4cb15934 | 1406 | case QORIQ_CLK_HWACCEL: |
0dfc86b3 SW |
1407 | if (idx >= ARRAY_SIZE(cg->hwaccel)) |
1408 | goto bad_args; | |
1409 | clk = cg->hwaccel[idx]; | |
1410 | break; | |
4cb15934 | 1411 | case QORIQ_CLK_FMAN: |
0dfc86b3 SW |
1412 | if (idx >= ARRAY_SIZE(cg->fman)) |
1413 | goto bad_args; | |
1414 | clk = cg->fman[idx]; | |
1415 | break; | |
4cb15934 | 1416 | case QORIQ_CLK_PLATFORM_PLL: |
0dfc86b3 SW |
1417 | pll = &cg->pll[PLATFORM_PLL]; |
1418 | if (idx >= ARRAY_SIZE(pll->div)) | |
1419 | goto bad_args; | |
1420 | clk = pll->div[idx].clk; | |
1421 | break; | |
4cb15934 | 1422 | case QORIQ_CLK_CORECLK: |
80b4ae7a SW |
1423 | if (idx != 0) |
1424 | goto bad_args; | |
1425 | clk = cg->coreclk; | |
1426 | if (IS_ERR(clk)) | |
1427 | clk = NULL; | |
1428 | break; | |
0dfc86b3 SW |
1429 | default: |
1430 | goto bad_args; | |
1431 | } | |
1432 | ||
1433 | if (!clk) | |
1434 | return ERR_PTR(-ENOENT); | |
1435 | return clk; | |
1436 | ||
1437 | bad_args: | |
1438 | pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx); | |
1439 | return ERR_PTR(-EINVAL); | |
555eae97 | 1440 | } |
a513b72c | 1441 | |
0dfc86b3 SW |
1442 | #ifdef CONFIG_PPC |
1443 | #include <asm/mpc85xx.h> | |
1444 | ||
1445 | static const u32 a4510_svrs[] __initconst = { | |
1446 | (SVR_P2040 << 8) | 0x10, /* P2040 1.0 */ | |
1447 | (SVR_P2040 << 8) | 0x11, /* P2040 1.1 */ | |
1448 | (SVR_P2041 << 8) | 0x10, /* P2041 1.0 */ | |
1449 | (SVR_P2041 << 8) | 0x11, /* P2041 1.1 */ | |
1450 | (SVR_P3041 << 8) | 0x10, /* P3041 1.0 */ | |
1451 | (SVR_P3041 << 8) | 0x11, /* P3041 1.1 */ | |
1452 | (SVR_P4040 << 8) | 0x20, /* P4040 2.0 */ | |
1453 | (SVR_P4080 << 8) | 0x20, /* P4080 2.0 */ | |
1454 | (SVR_P5010 << 8) | 0x10, /* P5010 1.0 */ | |
1455 | (SVR_P5010 << 8) | 0x20, /* P5010 2.0 */ | |
1456 | (SVR_P5020 << 8) | 0x10, /* P5020 1.0 */ | |
1457 | (SVR_P5021 << 8) | 0x10, /* P5021 1.0 */ | |
1458 | (SVR_P5040 << 8) | 0x10, /* P5040 1.0 */ | |
1459 | }; | |
1460 | ||
1461 | #define SVR_SECURITY 0x80000 /* The Security (E) bit */ | |
1462 | ||
1463 | static bool __init has_erratum_a4510(void) | |
a513b72c | 1464 | { |
0dfc86b3 SW |
1465 | u32 svr = mfspr(SPRN_SVR); |
1466 | int i; | |
1467 | ||
1468 | svr &= ~SVR_SECURITY; | |
1469 | ||
1470 | for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) { | |
1471 | if (svr == a4510_svrs[i]) | |
1472 | return true; | |
a513b72c EM |
1473 | } |
1474 | ||
0dfc86b3 SW |
1475 | return false; |
1476 | } | |
1477 | #else | |
1478 | static bool __init has_erratum_a4510(void) | |
1479 | { | |
1480 | return false; | |
1481 | } | |
1482 | #endif | |
a513b72c | 1483 | |
cf1e0449 | 1484 | static void __init _clockgen_init(struct device_node *np, bool legacy) |
0dfc86b3 SW |
1485 | { |
1486 | int i, ret; | |
1487 | bool is_old_ls1021a = false; | |
a513b72c | 1488 | |
0dfc86b3 SW |
1489 | /* May have already been called by a legacy probe */ |
1490 | if (clockgen.node) | |
a513b72c | 1491 | return; |
a513b72c | 1492 | |
0dfc86b3 SW |
1493 | clockgen.node = np; |
1494 | clockgen.regs = of_iomap(np, 0); | |
1495 | if (!clockgen.regs && | |
1496 | of_device_is_compatible(of_root, "fsl,ls1021a")) { | |
1497 | /* Compatibility hack for old, broken device trees */ | |
1498 | clockgen.regs = ioremap(0x1ee1000, 0x1000); | |
1499 | is_old_ls1021a = true; | |
1500 | } | |
1501 | if (!clockgen.regs) { | |
e665f029 | 1502 | pr_err("%s(): %pOFn: of_iomap() failed\n", __func__, np); |
a513b72c EM |
1503 | return; |
1504 | } | |
1505 | ||
0dfc86b3 SW |
1506 | for (i = 0; i < ARRAY_SIZE(chipinfo); i++) { |
1507 | if (of_device_is_compatible(np, chipinfo[i].compat)) | |
1508 | break; | |
1509 | if (is_old_ls1021a && | |
1510 | !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen")) | |
1511 | break; | |
a513b72c EM |
1512 | } |
1513 | ||
0dfc86b3 | 1514 | if (i == ARRAY_SIZE(chipinfo)) { |
16673931 | 1515 | pr_err("%s: unknown clockgen node %pOF\n", __func__, np); |
0dfc86b3 SW |
1516 | goto err; |
1517 | } | |
1518 | clockgen.info = chipinfo[i]; | |
1519 | ||
1520 | if (clockgen.info.guts_compat) { | |
1521 | struct device_node *guts; | |
a513b72c | 1522 | |
0dfc86b3 SW |
1523 | guts = of_find_compatible_node(NULL, NULL, |
1524 | clockgen.info.guts_compat); | |
1525 | if (guts) { | |
1526 | clockgen.guts = of_iomap(guts, 0); | |
1527 | if (!clockgen.guts) { | |
16673931 RH |
1528 | pr_err("%s: Couldn't map %pOF regs\n", __func__, |
1529 | guts); | |
0dfc86b3 | 1530 | } |
70af6c5b | 1531 | of_node_put(guts); |
a513b72c | 1532 | } |
0dfc86b3 | 1533 | |
a513b72c EM |
1534 | } |
1535 | ||
0dfc86b3 SW |
1536 | if (has_erratum_a4510()) |
1537 | clockgen.info.flags |= CG_CMUX_GE_PLAT; | |
1538 | ||
1539 | clockgen.sysclk = create_sysclk("cg-sysclk"); | |
80b4ae7a | 1540 | clockgen.coreclk = create_coreclk("cg-coreclk"); |
0dfc86b3 SW |
1541 | create_plls(&clockgen); |
1542 | create_muxes(&clockgen); | |
1543 | ||
1544 | if (clockgen.info.init_periph) | |
1545 | clockgen.info.init_periph(&clockgen); | |
1546 | ||
1547 | ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen); | |
1548 | if (ret) { | |
e665f029 RH |
1549 | pr_err("%s: Couldn't register clk provider for node %pOFn: %d\n", |
1550 | __func__, np, ret); | |
a513b72c EM |
1551 | } |
1552 | ||
cf1e0449 MYK |
1553 | /* Don't create cpufreq device for legacy clockgen blocks */ |
1554 | add_cpufreq_dev = !legacy; | |
1555 | ||
a513b72c | 1556 | return; |
0dfc86b3 SW |
1557 | err: |
1558 | iounmap(clockgen.regs); | |
1559 | clockgen.regs = NULL; | |
a513b72c EM |
1560 | } |
1561 | ||
cf1e0449 MYK |
1562 | static void __init clockgen_init(struct device_node *np) |
1563 | { | |
1564 | _clockgen_init(np, false); | |
1565 | } | |
1566 | ||
1567 | static int __init clockgen_cpufreq_init(void) | |
1568 | { | |
1569 | struct platform_device *pdev; | |
1570 | ||
1571 | if (add_cpufreq_dev) { | |
1572 | pdev = platform_device_register_simple("qoriq-cpufreq", -1, | |
1573 | NULL, 0); | |
1574 | if (IS_ERR(pdev)) | |
1575 | pr_err("Couldn't register qoriq-cpufreq err=%ld\n", | |
1576 | PTR_ERR(pdev)); | |
1577 | } | |
1578 | return 0; | |
1579 | } | |
1580 | device_initcall(clockgen_cpufreq_init); | |
1581 | ||
0dfc86b3 SW |
1582 | CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init); |
1583 | CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init); | |
b8b211ca YT |
1584 | CLK_OF_DECLARE(qoriq_clockgen_b4420, "fsl,b4420-clockgen", clockgen_init); |
1585 | CLK_OF_DECLARE(qoriq_clockgen_b4860, "fsl,b4860-clockgen", clockgen_init); | |
44709358 | 1586 | CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init); |
0dfc86b3 | 1587 | CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); |
95089f6a | 1588 | CLK_OF_DECLARE(qoriq_clockgen_ls1028a, "fsl,ls1028a-clockgen", clockgen_init); |
e994412c | 1589 | CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init); |
80e52198 | 1590 | CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init); |
e0c888c4 | 1591 | CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init); |
9e19ca2f | 1592 | CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); |
78a5ba8f | 1593 | CLK_OF_DECLARE(qoriq_clockgen_lx2160a, "fsl,lx2160a-clockgen", clockgen_init); |
b8b211ca YT |
1594 | CLK_OF_DECLARE(qoriq_clockgen_p2041, "fsl,p2041-clockgen", clockgen_init); |
1595 | CLK_OF_DECLARE(qoriq_clockgen_p3041, "fsl,p3041-clockgen", clockgen_init); | |
1596 | CLK_OF_DECLARE(qoriq_clockgen_p4080, "fsl,p4080-clockgen", clockgen_init); | |
1597 | CLK_OF_DECLARE(qoriq_clockgen_p5020, "fsl,p5020-clockgen", clockgen_init); | |
1598 | CLK_OF_DECLARE(qoriq_clockgen_p5040, "fsl,p5040-clockgen", clockgen_init); | |
1599 | CLK_OF_DECLARE(qoriq_clockgen_t1023, "fsl,t1023-clockgen", clockgen_init); | |
1600 | CLK_OF_DECLARE(qoriq_clockgen_t1040, "fsl,t1040-clockgen", clockgen_init); | |
1601 | CLK_OF_DECLARE(qoriq_clockgen_t2080, "fsl,t2080-clockgen", clockgen_init); | |
1602 | CLK_OF_DECLARE(qoriq_clockgen_t4240, "fsl,t4240-clockgen", clockgen_init); | |
0dfc86b3 SW |
1603 | |
1604 | /* Legacy nodes */ | |
66619ac5 KH |
1605 | CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init); |
1606 | CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init); | |
1607 | CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init); | |
1608 | CLK_OF_DECLARE(qoriq_core_pll_2, "fsl,qoriq-core-pll-2.0", core_pll_init); | |
1609 | CLK_OF_DECLARE(qoriq_core_mux_1, "fsl,qoriq-core-mux-1.0", core_mux_init); | |
1610 | CLK_OF_DECLARE(qoriq_core_mux_2, "fsl,qoriq-core-mux-2.0", core_mux_init); | |
a513b72c EM |
1611 | CLK_OF_DECLARE(qoriq_pltfrm_pll_1, "fsl,qoriq-platform-pll-1.0", pltfrm_pll_init); |
1612 | CLK_OF_DECLARE(qoriq_pltfrm_pll_2, "fsl,qoriq-platform-pll-2.0", pltfrm_pll_init); |