blob: 07985a57ae726140d1f5604978da0908c26661b8 [file] [log] [blame]
Tang Yuantian555eae92013-04-09 16:46:26 +08001/*
2 * Copyright 2013 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
Tang Yuantian93a17c02015-01-15 14:03:41 +08008 * clock driver for Freescale QorIQ SoCs.
Tang Yuantian555eae92013-04-09 16:46:26 +08009 */
Emil Medvec88b2b62015-01-21 04:03:29 -060010
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
Scott Wood0dfc86b2015-09-19 23:29:54 -050013#include <linux/clk.h>
Tang Yuantian555eae92013-04-09 16:46:26 +080014#include <linux/clk-provider.h>
Scott Wood0dfc86b2015-09-19 23:29:54 -050015#include <linux/fsl/guts.h>
Tang Yuantian555eae92013-04-09 16:46:26 +080016#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
Rob Herringc11eede2013-11-10 23:19:08 -060019#include <linux/of_address.h>
Tang Yuantian555eae92013-04-09 16:46:26 +080020#include <linux/of_platform.h>
21#include <linux/of.h>
22#include <linux/slab.h>
23
Scott Wood0dfc86b2015-09-19 23:29:54 -050024#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
36
37struct clockgen_pll_div {
38 struct clk *clk;
39 char name[32];
Tang Yuantian555eae92013-04-09 16:46:26 +080040};
41
Scott Wood0dfc86b2015-09-19 23:29:54 -050042struct clockgen_pll {
43 struct clockgen_pll_div div[4];
44};
Tang Yuantian555eae92013-04-09 16:46:26 +080045
Scott Wood0dfc86b2015-09-19 23:29:54 -050046#define CLKSEL_VALID 1
47#define CLKSEL_80PCT 2 /* Only allowed if PLL <= 80% of max cpu freq */
48
49struct clockgen_sourceinfo {
50 u32 flags; /* CLKSEL_xxx */
51 int pll; /* CGx_PLLn */
52 int div; /* PLL_DIVn */
53};
54
55#define NUM_MUX_PARENTS 16
56
57struct clockgen_muxinfo {
58 struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
59};
60
61#define NUM_HWACCEL 5
62#define NUM_CMUX 8
63
64struct clockgen;
65
66/*
67 * cmux freq must be >= platform pll.
68 * If not set, cmux freq must be >= platform pll/2
69 */
70#define CG_CMUX_GE_PLAT 1
Scott Wood9e19ca22015-09-19 23:29:55 -050071
Scott Wood0dfc86b2015-09-19 23:29:54 -050072#define CG_PLL_8BIT 2 /* PLLCnGSR[CFG] is 8 bits, not 6 */
Scott Wood9e19ca22015-09-19 23:29:55 -050073#define CG_VER3 4 /* version 3 cg: reg layout different */
74#define CG_LITTLE_ENDIAN 8
Scott Wood0dfc86b2015-09-19 23:29:54 -050075
76struct clockgen_chipinfo {
77 const char *compat, *guts_compat;
78 const struct clockgen_muxinfo *cmux_groups[2];
79 const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
80 void (*init_periph)(struct clockgen *cg);
81 int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
82 u32 pll_mask; /* 1 << n bit set if PLL n is valid */
83 u32 flags; /* CG_xxx */
84};
85
86struct clockgen {
87 struct device_node *node;
88 void __iomem *regs;
89 struct clockgen_chipinfo info; /* mutable copy */
90 struct clk *sysclk;
91 struct clockgen_pll pll[6];
92 struct clk *cmux[NUM_CMUX];
93 struct clk *hwaccel[NUM_HWACCEL];
94 struct clk *fman[2];
95 struct ccsr_guts __iomem *guts;
96};
97
98static struct clockgen clockgen;
99
Scott Wood9e19ca22015-09-19 23:29:55 -0500100static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
101{
102 if (cg->info.flags & CG_LITTLE_ENDIAN)
103 iowrite32(val, reg);
104 else
105 iowrite32be(val, reg);
106}
107
108static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
109{
110 u32 val;
111
112 if (cg->info.flags & CG_LITTLE_ENDIAN)
113 val = ioread32(reg);
114 else
115 val = ioread32be(reg);
116
117 return val;
118}
119
Scott Wood0dfc86b2015-09-19 23:29:54 -0500120static const struct clockgen_muxinfo p2041_cmux_grp1 = {
121 {
122 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
123 [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
124 [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
125 }
126};
127
128static const struct clockgen_muxinfo p2041_cmux_grp2 = {
129 {
130 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
Scott Wood2c7693e2015-10-22 23:21:46 -0500131 [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
132 [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
Scott Wood0dfc86b2015-09-19 23:29:54 -0500133 }
134};
135
136static const struct clockgen_muxinfo p5020_cmux_grp1 = {
137 {
138 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
139 [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
140 [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
141 }
142};
143
144static const struct clockgen_muxinfo p5020_cmux_grp2 = {
145 {
146 [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
147 [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
148 [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
149 }
150};
151
152static const struct clockgen_muxinfo p5040_cmux_grp1 = {
153 {
154 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
155 [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
156 [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
157 [5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
158 }
159};
160
161static const struct clockgen_muxinfo p5040_cmux_grp2 = {
162 {
163 [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
164 [1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
165 [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
166 [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
167 }
168};
169
170static const struct clockgen_muxinfo p4080_cmux_grp1 = {
171 {
172 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
173 [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
174 [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
175 [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
176 [8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
177 }
178};
179
180static const struct clockgen_muxinfo p4080_cmux_grp2 = {
181 {
182 [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
183 [8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
184 [9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
185 [12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
186 [13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
187 }
188};
189
190static const struct clockgen_muxinfo t1023_cmux = {
191 {
192 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
193 [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
194 }
195};
196
197static const struct clockgen_muxinfo t1040_cmux = {
198 {
199 [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
200 [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
201 [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
202 [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
203 }
204};
205
206
207static const struct clockgen_muxinfo clockgen2_cmux_cga = {
208 {
209 { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
210 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
211 { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
212 {},
213 { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
214 { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
215 { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
216 {},
217 { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
218 { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
219 { CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
220 },
221};
222
223static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
224 {
225 { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
226 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
227 { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
228 {},
229 { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
230 { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
231 { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
232 },
233};
234
235static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
236 {
237 { CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
238 { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
239 { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
240 {},
241 { CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
242 { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
243 { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
244 },
245};
246
247static const struct clockgen_muxinfo t1023_hwa1 = {
248 {
249 {},
250 { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
251 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
252 { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
253 },
254};
255
256static const struct clockgen_muxinfo t1023_hwa2 = {
257 {
258 [6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
259 },
260};
261
262static const struct clockgen_muxinfo t2080_hwa1 = {
263 {
264 {},
265 { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
266 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
267 { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
268 { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
269 { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
270 { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
271 { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
272 },
273};
274
275static const struct clockgen_muxinfo t2080_hwa2 = {
276 {
277 {},
278 { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
279 { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
280 { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
281 { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
282 { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
283 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
284 { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
285 },
286};
287
288static const struct clockgen_muxinfo t4240_hwa1 = {
289 {
290 { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
291 { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
292 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
293 { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
294 { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
295 {},
296 { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
297 { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
298 },
299};
300
301static const struct clockgen_muxinfo t4240_hwa4 = {
302 {
303 [2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
304 [3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
305 [4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
306 [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
307 [6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
308 },
309};
310
311static const struct clockgen_muxinfo t4240_hwa5 = {
312 {
313 [2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
314 [3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
315 [4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
316 [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
317 [6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
318 [7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
319 },
320};
321
322#define RCWSR7_FM1_CLK_SEL 0x40000000
323#define RCWSR7_FM2_CLK_SEL 0x20000000
324#define RCWSR7_HWA_ASYNC_DIV 0x04000000
325
326static void __init p2041_init_periph(struct clockgen *cg)
Tang Yuantian555eae92013-04-09 16:46:26 +0800327{
Scott Wood0dfc86b2015-09-19 23:29:54 -0500328 u32 reg;
329
330 reg = ioread32be(&cg->guts->rcwsr[7]);
331
332 if (reg & RCWSR7_FM1_CLK_SEL)
333 cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
334 else
335 cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
336}
337
338static void __init p4080_init_periph(struct clockgen *cg)
339{
340 u32 reg;
341
342 reg = ioread32be(&cg->guts->rcwsr[7]);
343
344 if (reg & RCWSR7_FM1_CLK_SEL)
345 cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
346 else
347 cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
348
349 if (reg & RCWSR7_FM2_CLK_SEL)
350 cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
351 else
352 cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
353}
354
355static void __init p5020_init_periph(struct clockgen *cg)
356{
357 u32 reg;
358 int div = PLL_DIV2;
359
360 reg = ioread32be(&cg->guts->rcwsr[7]);
361 if (reg & RCWSR7_HWA_ASYNC_DIV)
362 div = PLL_DIV4;
363
364 if (reg & RCWSR7_FM1_CLK_SEL)
365 cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
366 else
367 cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
368}
369
370static void __init p5040_init_periph(struct clockgen *cg)
371{
372 u32 reg;
373 int div = PLL_DIV2;
374
375 reg = ioread32be(&cg->guts->rcwsr[7]);
376 if (reg & RCWSR7_HWA_ASYNC_DIV)
377 div = PLL_DIV4;
378
379 if (reg & RCWSR7_FM1_CLK_SEL)
380 cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
381 else
382 cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
383
384 if (reg & RCWSR7_FM2_CLK_SEL)
385 cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
386 else
387 cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
388}
389
390static void __init t1023_init_periph(struct clockgen *cg)
391{
392 cg->fman[0] = cg->hwaccel[1];
393}
394
395static void __init t1040_init_periph(struct clockgen *cg)
396{
397 cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
398}
399
400static void __init t2080_init_periph(struct clockgen *cg)
401{
402 cg->fman[0] = cg->hwaccel[0];
403}
404
405static void __init t4240_init_periph(struct clockgen *cg)
406{
407 cg->fman[0] = cg->hwaccel[3];
408 cg->fman[1] = cg->hwaccel[4];
409}
410
411static const struct clockgen_chipinfo chipinfo[] = {
412 {
413 .compat = "fsl,b4420-clockgen",
414 .guts_compat = "fsl,b4860-device-config",
415 .init_periph = t2080_init_periph,
416 .cmux_groups = {
417 &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
418 },
419 .hwaccel = {
420 &t2080_hwa1
421 },
422 .cmux_to_group = {
423 0, 1, 1, 1, -1
424 },
425 .pll_mask = 0x3f,
426 .flags = CG_PLL_8BIT,
427 },
428 {
429 .compat = "fsl,b4860-clockgen",
430 .guts_compat = "fsl,b4860-device-config",
431 .init_periph = t2080_init_periph,
432 .cmux_groups = {
433 &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
434 },
435 .hwaccel = {
436 &t2080_hwa1
437 },
438 .cmux_to_group = {
439 0, 1, 1, 1, -1
440 },
441 .pll_mask = 0x3f,
442 .flags = CG_PLL_8BIT,
443 },
444 {
445 .compat = "fsl,ls1021a-clockgen",
446 .cmux_groups = {
447 &t1023_cmux
448 },
449 .cmux_to_group = {
450 0, -1
451 },
452 .pll_mask = 0x03,
453 },
454 {
Scott Wood9e19ca22015-09-19 23:29:55 -0500455 .compat = "fsl,ls2080a-clockgen",
456 .cmux_groups = {
457 &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
458 },
459 .cmux_to_group = {
460 0, 0, 1, 1, -1
461 },
462 .pll_mask = 0x37,
463 .flags = CG_VER3 | CG_LITTLE_ENDIAN,
464 },
465 {
Scott Wood0dfc86b2015-09-19 23:29:54 -0500466 .compat = "fsl,p2041-clockgen",
467 .guts_compat = "fsl,qoriq-device-config-1.0",
468 .init_periph = p2041_init_periph,
469 .cmux_groups = {
470 &p2041_cmux_grp1, &p2041_cmux_grp2
471 },
472 .cmux_to_group = {
473 0, 0, 1, 1, -1
474 },
475 .pll_mask = 0x07,
476 },
477 {
478 .compat = "fsl,p3041-clockgen",
479 .guts_compat = "fsl,qoriq-device-config-1.0",
480 .init_periph = p2041_init_periph,
481 .cmux_groups = {
482 &p2041_cmux_grp1, &p2041_cmux_grp2
483 },
484 .cmux_to_group = {
485 0, 0, 1, 1, -1
486 },
487 .pll_mask = 0x07,
488 },
489 {
490 .compat = "fsl,p4080-clockgen",
491 .guts_compat = "fsl,qoriq-device-config-1.0",
492 .init_periph = p4080_init_periph,
493 .cmux_groups = {
494 &p4080_cmux_grp1, &p4080_cmux_grp2
495 },
496 .cmux_to_group = {
497 0, 0, 0, 0, 1, 1, 1, 1
498 },
499 .pll_mask = 0x1f,
500 },
501 {
502 .compat = "fsl,p5020-clockgen",
503 .guts_compat = "fsl,qoriq-device-config-1.0",
504 .init_periph = p5020_init_periph,
505 .cmux_groups = {
506 &p2041_cmux_grp1, &p2041_cmux_grp2
507 },
508 .cmux_to_group = {
509 0, 1, -1
510 },
511 .pll_mask = 0x07,
512 },
513 {
514 .compat = "fsl,p5040-clockgen",
515 .guts_compat = "fsl,p5040-device-config",
516 .init_periph = p5040_init_periph,
517 .cmux_groups = {
518 &p5040_cmux_grp1, &p5040_cmux_grp2
519 },
520 .cmux_to_group = {
521 0, 0, 1, 1, -1
522 },
523 .pll_mask = 0x0f,
524 },
525 {
526 .compat = "fsl,t1023-clockgen",
527 .guts_compat = "fsl,t1023-device-config",
528 .init_periph = t1023_init_periph,
529 .cmux_groups = {
530 &t1023_cmux
531 },
532 .hwaccel = {
533 &t1023_hwa1, &t1023_hwa2
534 },
535 .cmux_to_group = {
536 0, 0, -1
537 },
538 .pll_mask = 0x03,
539 .flags = CG_PLL_8BIT,
540 },
541 {
542 .compat = "fsl,t1040-clockgen",
543 .guts_compat = "fsl,t1040-device-config",
544 .init_periph = t1040_init_periph,
545 .cmux_groups = {
546 &t1040_cmux
547 },
548 .cmux_to_group = {
549 0, 0, 0, 0, -1
550 },
551 .pll_mask = 0x07,
552 .flags = CG_PLL_8BIT,
553 },
554 {
555 .compat = "fsl,t2080-clockgen",
556 .guts_compat = "fsl,t2080-device-config",
557 .init_periph = t2080_init_periph,
558 .cmux_groups = {
559 &clockgen2_cmux_cga12
560 },
561 .hwaccel = {
562 &t2080_hwa1, &t2080_hwa2
563 },
564 .cmux_to_group = {
565 0, -1
566 },
567 .pll_mask = 0x07,
568 .flags = CG_PLL_8BIT,
569 },
570 {
571 .compat = "fsl,t4240-clockgen",
572 .guts_compat = "fsl,t4240-device-config",
573 .init_periph = t4240_init_periph,
574 .cmux_groups = {
575 &clockgen2_cmux_cga, &clockgen2_cmux_cgb
576 },
577 .hwaccel = {
578 &t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
579 },
580 .cmux_to_group = {
581 0, 0, 1, -1
582 },
583 .pll_mask = 0x3f,
584 .flags = CG_PLL_8BIT,
585 },
586 {},
587};
588
589struct mux_hwclock {
590 struct clk_hw hw;
591 struct clockgen *cg;
592 const struct clockgen_muxinfo *info;
593 u32 __iomem *reg;
594 u8 parent_to_clksel[NUM_MUX_PARENTS];
595 s8 clksel_to_parent[NUM_MUX_PARENTS];
596 int num_parents;
597};
598
599#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, hw)
600#define CLKSEL_MASK 0x78000000
601#define CLKSEL_SHIFT 27
602
603static int mux_set_parent(struct clk_hw *hw, u8 idx)
604{
605 struct mux_hwclock *hwc = to_mux_hwclock(hw);
Tang Yuantian555eae92013-04-09 16:46:26 +0800606 u32 clksel;
607
Scott Wood0dfc86b2015-09-19 23:29:54 -0500608 if (idx >= hwc->num_parents)
609 return -EINVAL;
610
611 clksel = hwc->parent_to_clksel[idx];
Scott Wood9e19ca22015-09-19 23:29:55 -0500612 cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
Tang Yuantian555eae92013-04-09 16:46:26 +0800613
614 return 0;
615}
616
Scott Wood0dfc86b2015-09-19 23:29:54 -0500617static u8 mux_get_parent(struct clk_hw *hw)
Tang Yuantian555eae92013-04-09 16:46:26 +0800618{
Scott Wood0dfc86b2015-09-19 23:29:54 -0500619 struct mux_hwclock *hwc = to_mux_hwclock(hw);
Tang Yuantian555eae92013-04-09 16:46:26 +0800620 u32 clksel;
Scott Wood0dfc86b2015-09-19 23:29:54 -0500621 s8 ret;
Tang Yuantian555eae92013-04-09 16:46:26 +0800622
Scott Wood9e19ca22015-09-19 23:29:55 -0500623 clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
Tang Yuantian555eae92013-04-09 16:46:26 +0800624
Scott Wood0dfc86b2015-09-19 23:29:54 -0500625 ret = hwc->clksel_to_parent[clksel];
626 if (ret < 0) {
627 pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg);
628 return 0;
629 }
630
631 return ret;
Tang Yuantian555eae92013-04-09 16:46:26 +0800632}
633
Emil Medve334680d2015-01-21 04:03:27 -0600634static const struct clk_ops cmux_ops = {
Scott Wood0dfc86b2015-09-19 23:29:54 -0500635 .get_parent = mux_get_parent,
636 .set_parent = mux_set_parent,
Tang Yuantian555eae92013-04-09 16:46:26 +0800637};
638
Scott Wood0dfc86b2015-09-19 23:29:54 -0500639/*
640 * Don't allow setting for now, as the clock options haven't been
641 * sanitized for additional restrictions.
642 */
643static const struct clk_ops hwaccel_ops = {
644 .get_parent = mux_get_parent,
645};
646
647static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
648 struct mux_hwclock *hwc,
649 int idx)
650{
651 int pll, div;
652
653 if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
654 return NULL;
655
656 pll = hwc->info->clksel[idx].pll;
657 div = hwc->info->clksel[idx].div;
658
659 return &cg->pll[pll].div[div];
660}
661
662static struct clk * __init create_mux_common(struct clockgen *cg,
663 struct mux_hwclock *hwc,
664 const struct clk_ops *ops,
665 unsigned long min_rate,
666 unsigned long pct80_rate,
667 const char *fmt, int idx)
668{
669 struct clk_init_data init = {};
670 struct clk *clk;
671 const struct clockgen_pll_div *div;
672 const char *parent_names[NUM_MUX_PARENTS];
673 char name[32];
674 int i, j;
675
676 snprintf(name, sizeof(name), fmt, idx);
677
678 for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
679 unsigned long rate;
680
681 hwc->clksel_to_parent[i] = -1;
682
683 div = get_pll_div(cg, hwc, i);
684 if (!div)
685 continue;
686
687 rate = clk_get_rate(div->clk);
688
689 if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
690 rate > pct80_rate)
691 continue;
692 if (rate < min_rate)
693 continue;
694
695 parent_names[j] = div->name;
696 hwc->parent_to_clksel[j] = i;
697 hwc->clksel_to_parent[i] = j;
698 j++;
699 }
700
701 init.name = name;
702 init.ops = ops;
703 init.parent_names = parent_names;
704 init.num_parents = hwc->num_parents = j;
705 init.flags = 0;
706 hwc->hw.init = &init;
707 hwc->cg = cg;
708
709 clk = clk_register(NULL, &hwc->hw);
710 if (IS_ERR(clk)) {
711 pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
712 PTR_ERR(clk));
713 kfree(hwc);
714 return NULL;
715 }
716
717 return clk;
718}
719
720static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
721{
722 struct mux_hwclock *hwc;
723 const struct clockgen_pll_div *div;
724 unsigned long plat_rate, min_rate;
725 u64 pct80_rate;
726 u32 clksel;
727
728 hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
729 if (!hwc)
730 return NULL;
731
732 hwc->reg = cg->regs + 0x20 * idx;
733 hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
734
735 /*
736 * Find the rate for the default clksel, and treat it as the
737 * maximum rated core frequency. If this is an incorrect
738 * assumption, certain clock options (possibly including the
739 * default clksel) may be inappropriately excluded on certain
740 * chips.
741 */
Scott Wood9e19ca22015-09-19 23:29:55 -0500742 clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
Scott Wood0dfc86b2015-09-19 23:29:54 -0500743 div = get_pll_div(cg, hwc, clksel);
744 if (!div)
745 return NULL;
746
747 pct80_rate = clk_get_rate(div->clk);
748 pct80_rate *= 8;
749 do_div(pct80_rate, 10);
750
751 plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
752
753 if (cg->info.flags & CG_CMUX_GE_PLAT)
754 min_rate = plat_rate;
755 else
756 min_rate = plat_rate / 2;
757
758 return create_mux_common(cg, hwc, &cmux_ops, min_rate,
759 pct80_rate, "cg-cmux%d", idx);
760}
761
762static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
763{
764 struct mux_hwclock *hwc;
765
766 hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
767 if (!hwc)
768 return NULL;
769
770 hwc->reg = cg->regs + 0x20 * idx + 0x10;
771 hwc->info = cg->info.hwaccel[idx];
772
773 return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
774 "cg-hwaccel%d", idx);
775}
776
777static void __init create_muxes(struct clockgen *cg)
778{
779 int i;
780
781 for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
782 if (cg->info.cmux_to_group[i] < 0)
783 break;
784 if (cg->info.cmux_to_group[i] >=
785 ARRAY_SIZE(cg->info.cmux_groups)) {
786 WARN_ON_ONCE(1);
787 continue;
788 }
789
790 cg->cmux[i] = create_one_cmux(cg, i);
791 }
792
793 for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
794 if (!cg->info.hwaccel[i])
795 continue;
796
797 cg->hwaccel[i] = create_one_hwaccel(cg, i);
798 }
799}
800
801static void __init clockgen_init(struct device_node *np);
802
803/* Legacy nodes may get probed before the parent clockgen node */
804static void __init legacy_init_clockgen(struct device_node *np)
805{
806 if (!clockgen.node)
807 clockgen_init(of_get_parent(np));
808}
809
810/* Legacy node */
Tang Yuantian555eae92013-04-09 16:46:26 +0800811static void __init core_mux_init(struct device_node *np)
812{
813 struct clk *clk;
Scott Wood0dfc86b2015-09-19 23:29:54 -0500814 struct resource res;
815 int idx, rc;
Tang Yuantian555eae92013-04-09 16:46:26 +0800816
Scott Wood0dfc86b2015-09-19 23:29:54 -0500817 legacy_init_clockgen(np);
Tang Yuantian555eae92013-04-09 16:46:26 +0800818
Scott Wood0dfc86b2015-09-19 23:29:54 -0500819 if (of_address_to_resource(np, 0, &res))
Tang Yuantian555eae92013-04-09 16:46:26 +0800820 return;
Tang Yuantian555eae92013-04-09 16:46:26 +0800821
Scott Wood0dfc86b2015-09-19 23:29:54 -0500822 idx = (res.start & 0xf0) >> 5;
823 clk = clockgen.cmux[idx];
Tang Yuantian555eae92013-04-09 16:46:26 +0800824
825 rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
826 if (rc) {
Scott Wood0dfc86b2015-09-19 23:29:54 -0500827 pr_err("%s: Couldn't register clk provider for node %s: %d\n",
828 __func__, np->name, rc);
829 return;
Tang Yuantian555eae92013-04-09 16:46:26 +0800830 }
Tang Yuantian555eae92013-04-09 16:46:26 +0800831}
832
Scott Wood0dfc86b2015-09-19 23:29:54 -0500833static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
Tang Yuantian555eae92013-04-09 16:46:26 +0800834{
Scott Wood0dfc86b2015-09-19 23:29:54 -0500835 u32 rate;
Tang Yuantian555eae92013-04-09 16:46:26 +0800836
Scott Wood0dfc86b2015-09-19 23:29:54 -0500837 if (of_property_read_u32(node, "clock-frequency", &rate))
838 return ERR_PTR(-ENODEV);
839
840 return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
841}
842
843static struct clk *sysclk_from_parent(const char *name)
844{
845 struct clk *clk;
846 const char *parent_name;
847
848 clk = of_clk_get(clockgen.node, 0);
849 if (IS_ERR(clk))
850 return clk;
851
852 /* Register the input clock under the desired name. */
853 parent_name = __clk_get_name(clk);
854 clk = clk_register_fixed_factor(NULL, name, parent_name,
855 0, 1, 1);
856 if (IS_ERR(clk))
857 pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
858 PTR_ERR(clk));
859
860 return clk;
861}
862
863static struct clk * __init create_sysclk(const char *name)
864{
865 struct device_node *sysclk;
866 struct clk *clk;
867
868 clk = sysclk_from_fixed(clockgen.node, name);
869 if (!IS_ERR(clk))
870 return clk;
871
872 clk = sysclk_from_parent(name);
873 if (!IS_ERR(clk))
874 return clk;
875
876 sysclk = of_get_child_by_name(clockgen.node, "sysclk");
877 if (sysclk) {
878 clk = sysclk_from_fixed(sysclk, name);
879 if (!IS_ERR(clk))
880 return clk;
881 }
882
883 pr_err("%s: No input clock\n", __func__);
884 return NULL;
885}
886
887/* Legacy node */
888static void __init sysclk_init(struct device_node *node)
889{
890 struct clk *clk;
891
892 legacy_init_clockgen(node);
893
894 clk = clockgen.sysclk;
895 if (clk)
896 of_clk_add_provider(node, of_clk_src_simple_get, clk);
897}
898
899#define PLL_KILL BIT(31)
900
901static void __init create_one_pll(struct clockgen *cg, int idx)
902{
903 u32 __iomem *reg;
904 u32 mult;
905 struct clockgen_pll *pll = &cg->pll[idx];
906 int i;
907
908 if (!(cg->info.pll_mask & (1 << idx)))
909 return;
910
Scott Wood9e19ca22015-09-19 23:29:55 -0500911 if (cg->info.flags & CG_VER3) {
912 switch (idx) {
913 case PLATFORM_PLL:
914 reg = cg->regs + 0x60080;
915 break;
916 case CGA_PLL1:
917 reg = cg->regs + 0x80;
918 break;
919 case CGA_PLL2:
920 reg = cg->regs + 0xa0;
921 break;
922 case CGB_PLL1:
923 reg = cg->regs + 0x10080;
924 break;
925 case CGB_PLL2:
926 reg = cg->regs + 0x100a0;
927 break;
928 default:
929 WARN_ONCE(1, "index %d\n", idx);
930 return;
931 }
932 } else {
933 if (idx == PLATFORM_PLL)
934 reg = cg->regs + 0xc00;
935 else
936 reg = cg->regs + 0x800 + 0x20 * (idx - 1);
937 }
Scott Wood0dfc86b2015-09-19 23:29:54 -0500938
939 /* Get the multiple of PLL */
Scott Wood9e19ca22015-09-19 23:29:55 -0500940 mult = cg_in(cg, reg);
Scott Wood0dfc86b2015-09-19 23:29:54 -0500941
942 /* Check if this PLL is disabled */
943 if (mult & PLL_KILL) {
944 pr_debug("%s(): pll %p disabled\n", __func__, reg);
Tang Yuantian555eae92013-04-09 16:46:26 +0800945 return;
946 }
947
Scott Wood9e19ca22015-09-19 23:29:55 -0500948 if ((cg->info.flags & CG_VER3) ||
949 ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
Scott Wood0dfc86b2015-09-19 23:29:54 -0500950 mult = (mult & GENMASK(8, 1)) >> 1;
951 else
952 mult = (mult & GENMASK(6, 1)) >> 1;
Tang Yuantian555eae92013-04-09 16:46:26 +0800953
Scott Wood0dfc86b2015-09-19 23:29:54 -0500954 for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
955 struct clk *clk;
956
957 snprintf(pll->div[i].name, sizeof(pll->div[i].name),
958 "cg-pll%d-div%d", idx, i + 1);
959
960 clk = clk_register_fixed_factor(NULL,
961 pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
962 if (IS_ERR(clk)) {
963 pr_err("%s: %s: register failed %ld\n",
964 __func__, pll->div[i].name, PTR_ERR(clk));
965 continue;
966 }
967
968 pll->div[i].clk = clk;
Tang Yuantian555eae92013-04-09 16:46:26 +0800969 }
Scott Wood0dfc86b2015-09-19 23:29:54 -0500970}
Tang Yuantian555eae92013-04-09 16:46:26 +0800971
Scott Wood0dfc86b2015-09-19 23:29:54 -0500972static void __init create_plls(struct clockgen *cg)
973{
974 int i;
Tang Yuantian555eae92013-04-09 16:46:26 +0800975
Scott Wood0dfc86b2015-09-19 23:29:54 -0500976 for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
977 create_one_pll(cg, i);
978}
979
980static void __init legacy_pll_init(struct device_node *np, int idx)
981{
982 struct clockgen_pll *pll;
983 struct clk_onecell_data *onecell_data;
984 struct clk **subclks;
985 int count, rc;
986
987 legacy_init_clockgen(np);
988
989 pll = &clockgen.pll[idx];
Tang Yuantian555eae92013-04-09 16:46:26 +0800990 count = of_property_count_strings(np, "clock-output-names");
Tang Yuantian555eae92013-04-09 16:46:26 +0800991
Scott Wood0dfc86b2015-09-19 23:29:54 -0500992 BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
993 subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
Emil Medve8002cab2015-01-21 04:03:26 -0600994 if (!subclks)
Scott Wood0dfc86b2015-09-19 23:29:54 -0500995 return;
Tang Yuantian555eae92013-04-09 16:46:26 +0800996
Emil Medve6ef1cca2015-01-21 04:03:28 -0600997 onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
Emil Medve8002cab2015-01-21 04:03:26 -0600998 if (!onecell_data)
Tang Yuantian555eae92013-04-09 16:46:26 +0800999 goto err_clks;
Tang Yuantian555eae92013-04-09 16:46:26 +08001000
Scott Wood0dfc86b2015-09-19 23:29:54 -05001001 if (count <= 3) {
1002 subclks[0] = pll->div[0].clk;
1003 subclks[1] = pll->div[1].clk;
1004 subclks[2] = pll->div[3].clk;
1005 } else {
1006 subclks[0] = pll->div[0].clk;
1007 subclks[1] = pll->div[1].clk;
1008 subclks[2] = pll->div[2].clk;
1009 subclks[3] = pll->div[3].clk;
Tang Yuantian555eae92013-04-09 16:46:26 +08001010 }
1011
1012 onecell_data->clks = subclks;
1013 onecell_data->clk_num = count;
1014
1015 rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
1016 if (rc) {
Scott Wood0dfc86b2015-09-19 23:29:54 -05001017 pr_err("%s: Couldn't register clk provider for node %s: %d\n",
1018 __func__, np->name, rc);
Tang Yuantian555eae92013-04-09 16:46:26 +08001019 goto err_cell;
1020 }
1021
1022 return;
1023err_cell:
1024 kfree(onecell_data);
1025err_clks:
1026 kfree(subclks);
Tang Yuantian00fa6e52014-01-21 09:32:45 +08001027}
1028
Scott Wood0dfc86b2015-09-19 23:29:54 -05001029/* Legacy node */
Emil Medvea513b722015-01-21 04:03:31 -06001030static void __init pltfrm_pll_init(struct device_node *np)
1031{
Scott Wood0dfc86b2015-09-19 23:29:54 -05001032 legacy_pll_init(np, PLATFORM_PLL);
1033}
Emil Medvea513b722015-01-21 04:03:31 -06001034
Scott Wood0dfc86b2015-09-19 23:29:54 -05001035/* Legacy node */
1036static void __init core_pll_init(struct device_node *np)
1037{
1038 struct resource res;
1039 int idx;
1040
1041 if (of_address_to_resource(np, 0, &res))
1042 return;
1043
1044 if ((res.start & 0xfff) == 0xc00) {
1045 /*
1046 * ls1021a devtree labels the platform PLL
1047 * with the core PLL compatible
1048 */
1049 pltfrm_pll_init(np);
1050 } else {
1051 idx = (res.start & 0xf0) >> 5;
1052 legacy_pll_init(np, CGA_PLL1 + idx);
1053 }
1054}
1055
1056static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
1057{
1058 struct clockgen *cg = data;
1059 struct clk *clk;
1060 struct clockgen_pll *pll;
1061 u32 type, idx;
1062
1063 if (clkspec->args_count < 2) {
1064 pr_err("%s: insufficient phandle args\n", __func__);
1065 return ERR_PTR(-EINVAL);
1066 }
1067
1068 type = clkspec->args[0];
1069 idx = clkspec->args[1];
1070
1071 switch (type) {
1072 case 0:
1073 if (idx != 0)
1074 goto bad_args;
1075 clk = cg->sysclk;
1076 break;
1077 case 1:
1078 if (idx >= ARRAY_SIZE(cg->cmux))
1079 goto bad_args;
1080 clk = cg->cmux[idx];
1081 break;
1082 case 2:
1083 if (idx >= ARRAY_SIZE(cg->hwaccel))
1084 goto bad_args;
1085 clk = cg->hwaccel[idx];
1086 break;
1087 case 3:
1088 if (idx >= ARRAY_SIZE(cg->fman))
1089 goto bad_args;
1090 clk = cg->fman[idx];
1091 break;
1092 case 4:
1093 pll = &cg->pll[PLATFORM_PLL];
1094 if (idx >= ARRAY_SIZE(pll->div))
1095 goto bad_args;
1096 clk = pll->div[idx].clk;
1097 break;
1098 default:
1099 goto bad_args;
1100 }
1101
1102 if (!clk)
1103 return ERR_PTR(-ENOENT);
1104 return clk;
1105
1106bad_args:
1107 pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx);
1108 return ERR_PTR(-EINVAL);
1109}
1110
1111#ifdef CONFIG_PPC
1112#include <asm/mpc85xx.h>
1113
1114static const u32 a4510_svrs[] __initconst = {
1115 (SVR_P2040 << 8) | 0x10, /* P2040 1.0 */
1116 (SVR_P2040 << 8) | 0x11, /* P2040 1.1 */
1117 (SVR_P2041 << 8) | 0x10, /* P2041 1.0 */
1118 (SVR_P2041 << 8) | 0x11, /* P2041 1.1 */
1119 (SVR_P3041 << 8) | 0x10, /* P3041 1.0 */
1120 (SVR_P3041 << 8) | 0x11, /* P3041 1.1 */
1121 (SVR_P4040 << 8) | 0x20, /* P4040 2.0 */
1122 (SVR_P4080 << 8) | 0x20, /* P4080 2.0 */
1123 (SVR_P5010 << 8) | 0x10, /* P5010 1.0 */
1124 (SVR_P5010 << 8) | 0x20, /* P5010 2.0 */
1125 (SVR_P5020 << 8) | 0x10, /* P5020 1.0 */
1126 (SVR_P5021 << 8) | 0x10, /* P5021 1.0 */
1127 (SVR_P5040 << 8) | 0x10, /* P5040 1.0 */
1128};
1129
1130#define SVR_SECURITY 0x80000 /* The Security (E) bit */
1131
1132static bool __init has_erratum_a4510(void)
1133{
1134 u32 svr = mfspr(SPRN_SVR);
1135 int i;
1136
1137 svr &= ~SVR_SECURITY;
1138
1139 for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
1140 if (svr == a4510_svrs[i])
1141 return true;
1142 }
1143
1144 return false;
1145}
1146#else
1147static bool __init has_erratum_a4510(void)
1148{
1149 return false;
1150}
1151#endif
1152
1153static void __init clockgen_init(struct device_node *np)
1154{
1155 int i, ret;
1156 bool is_old_ls1021a = false;
1157
1158 /* May have already been called by a legacy probe */
1159 if (clockgen.node)
1160 return;
1161
1162 clockgen.node = np;
1163 clockgen.regs = of_iomap(np, 0);
1164 if (!clockgen.regs &&
1165 of_device_is_compatible(of_root, "fsl,ls1021a")) {
1166 /* Compatibility hack for old, broken device trees */
1167 clockgen.regs = ioremap(0x1ee1000, 0x1000);
1168 is_old_ls1021a = true;
1169 }
1170 if (!clockgen.regs) {
Emil Medvea513b722015-01-21 04:03:31 -06001171 pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
1172 return;
1173 }
1174
Scott Wood0dfc86b2015-09-19 23:29:54 -05001175 for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
1176 if (of_device_is_compatible(np, chipinfo[i].compat))
1177 break;
1178 if (is_old_ls1021a &&
1179 !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
1180 break;
Emil Medvea513b722015-01-21 04:03:31 -06001181 }
1182
Scott Wood0dfc86b2015-09-19 23:29:54 -05001183 if (i == ARRAY_SIZE(chipinfo)) {
1184 pr_err("%s: unknown clockgen node %s\n", __func__,
1185 np->full_name);
1186 goto err;
Emil Medvea513b722015-01-21 04:03:31 -06001187 }
Scott Wood0dfc86b2015-09-19 23:29:54 -05001188 clockgen.info = chipinfo[i];
Emil Medvea513b722015-01-21 04:03:31 -06001189
Scott Wood0dfc86b2015-09-19 23:29:54 -05001190 if (clockgen.info.guts_compat) {
1191 struct device_node *guts;
Emil Medvea513b722015-01-21 04:03:31 -06001192
Scott Wood0dfc86b2015-09-19 23:29:54 -05001193 guts = of_find_compatible_node(NULL, NULL,
1194 clockgen.info.guts_compat);
1195 if (guts) {
1196 clockgen.guts = of_iomap(guts, 0);
1197 if (!clockgen.guts) {
1198 pr_err("%s: Couldn't map %s regs\n", __func__,
1199 guts->full_name);
1200 }
Emil Medvea513b722015-01-21 04:03:31 -06001201 }
1202
Emil Medvea513b722015-01-21 04:03:31 -06001203 }
1204
Scott Wood0dfc86b2015-09-19 23:29:54 -05001205 if (has_erratum_a4510())
1206 clockgen.info.flags |= CG_CMUX_GE_PLAT;
1207
1208 clockgen.sysclk = create_sysclk("cg-sysclk");
1209 create_plls(&clockgen);
1210 create_muxes(&clockgen);
1211
1212 if (clockgen.info.init_periph)
1213 clockgen.info.init_periph(&clockgen);
1214
1215 ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
1216 if (ret) {
1217 pr_err("%s: Couldn't register clk provider for node %s: %d\n",
1218 __func__, np->name, ret);
Emil Medvea513b722015-01-21 04:03:31 -06001219 }
1220
1221 return;
Scott Wood0dfc86b2015-09-19 23:29:54 -05001222err:
1223 iounmap(clockgen.regs);
1224 clockgen.regs = NULL;
Emil Medvea513b722015-01-21 04:03:31 -06001225}
1226
Scott Wood0dfc86b2015-09-19 23:29:54 -05001227CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
1228CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
1229CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
Scott Wood9e19ca22015-09-19 23:29:55 -05001230CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
Scott Wood0dfc86b2015-09-19 23:29:54 -05001231
1232/* Legacy nodes */
Kevin Hao66619ac2014-12-03 16:53:53 +08001233CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
1234CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
1235CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
1236CLK_OF_DECLARE(qoriq_core_pll_2, "fsl,qoriq-core-pll-2.0", core_pll_init);
1237CLK_OF_DECLARE(qoriq_core_mux_1, "fsl,qoriq-core-mux-1.0", core_mux_init);
1238CLK_OF_DECLARE(qoriq_core_mux_2, "fsl,qoriq-core-mux-2.0", core_mux_init);
Emil Medvea513b722015-01-21 04:03:31 -06001239CLK_OF_DECLARE(qoriq_pltfrm_pll_1, "fsl,qoriq-platform-pll-1.0", pltfrm_pll_init);
1240CLK_OF_DECLARE(qoriq_pltfrm_pll_2, "fsl,qoriq-platform-pll-2.0", pltfrm_pll_init);