Blame view

drivers/clk/clk-qoriq.c 28.7 KB
555eae973   Tang Yuantian   clk: add PowerPC ...
1
2
3
4
5
6
7
  /*
   * Copyright 2013 Freescale Semiconductor, Inc.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
93a17c058   Tang Yuantian   clk: ppc-corenet:...
8
   * clock driver for Freescale QorIQ SoCs.
555eae973   Tang Yuantian   clk: add PowerPC ...
9
   */
c88b2b662   Emil Medve   clk: qoriq: Use p...
10
11
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0dfc86b31   Scott Wood   clk: qoriq: Move ...
12
  #include <linux/clk.h>
555eae973   Tang Yuantian   clk: add PowerPC ...
13
  #include <linux/clk-provider.h>
0dfc86b31   Scott Wood   clk: qoriq: Move ...
14
  #include <linux/fsl/guts.h>
555eae973   Tang Yuantian   clk: add PowerPC ...
15
16
17
  #include <linux/io.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
c11eede69   Rob Herring   powerpc: add miss...
18
  #include <linux/of_address.h>
555eae973   Tang Yuantian   clk: add PowerPC ...
19
20
21
  #include <linux/of_platform.h>
  #include <linux/of.h>
  #include <linux/slab.h>
0dfc86b31   Scott Wood   clk: qoriq: Move ...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  #define PLL_DIV1	0
  #define PLL_DIV2	1
  #define PLL_DIV3	2
  #define PLL_DIV4	3
  
  #define PLATFORM_PLL	0
  #define CGA_PLL1	1
  #define CGA_PLL2	2
  #define CGA_PLL3	3
  #define CGA_PLL4	4	/* only on clockgen-1.0, which lacks CGB */
  #define CGB_PLL1	4
  #define CGB_PLL2	5
  
  struct clockgen_pll_div {
  	struct clk *clk;
  	char name[32];
  };
  
  struct clockgen_pll {
  	struct clockgen_pll_div div[4];
  };
  
  #define CLKSEL_VALID	1
  #define CLKSEL_80PCT	2	/* Only allowed if PLL <= 80% of max cpu freq */
  
  struct clockgen_sourceinfo {
  	u32 flags;	/* CLKSEL_xxx */
  	int pll;	/* CGx_PLLn */
  	int div;	/* PLL_DIVn */
  };
  
  #define NUM_MUX_PARENTS	16
  
  struct clockgen_muxinfo {
  	struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
  };
  
  #define NUM_HWACCEL	5
  #define NUM_CMUX	8
  
  struct clockgen;
  
  /*
   * cmux freq must be >= platform pll.
   * If not set, cmux freq must be >= platform pll/2
   */
  #define CG_CMUX_GE_PLAT		1
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
69

0dfc86b31   Scott Wood   clk: qoriq: Move ...
70
  #define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
71
72
  #define CG_VER3			4	/* version 3 cg: reg layout different */
  #define CG_LITTLE_ENDIAN	8
0dfc86b31   Scott Wood   clk: qoriq: Move ...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  
  struct clockgen_chipinfo {
  	const char *compat, *guts_compat;
  	const struct clockgen_muxinfo *cmux_groups[2];
  	const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
  	void (*init_periph)(struct clockgen *cg);
  	int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
  	u32 pll_mask;	/* 1 << n bit set if PLL n is valid */
  	u32 flags;	/* CG_xxx */
  };
  
  struct clockgen {
  	struct device_node *node;
  	void __iomem *regs;
  	struct clockgen_chipinfo info; /* mutable copy */
  	struct clk *sysclk;
  	struct clockgen_pll pll[6];
  	struct clk *cmux[NUM_CMUX];
  	struct clk *hwaccel[NUM_HWACCEL];
  	struct clk *fman[2];
  	struct ccsr_guts __iomem *guts;
  };
  
  static struct clockgen clockgen;
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
  {
  	if (cg->info.flags & CG_LITTLE_ENDIAN)
  		iowrite32(val, reg);
  	else
  		iowrite32be(val, reg);
  }
  
  static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
  {
  	u32 val;
  
  	if (cg->info.flags & CG_LITTLE_ENDIAN)
  		val = ioread32(reg);
  	else
  		val = ioread32be(reg);
  
  	return val;
  }
0dfc86b31   Scott Wood   clk: qoriq: Move ...
116
117
118
119
120
121
122
123
124
125
126
  static const struct clockgen_muxinfo p2041_cmux_grp1 = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  	}
  };
  
  static const struct clockgen_muxinfo p2041_cmux_grp2 = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
2c7693e08   Scott Wood   clk: qoriq: Fix w...
127
128
  		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
0dfc86b31   Scott Wood   clk: qoriq: Move ...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  	}
  };
  
  static const struct clockgen_muxinfo p5020_cmux_grp1 = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
  	}
  };
  
  static const struct clockgen_muxinfo p5020_cmux_grp2 = {
  	{
  		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
  		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  	}
  };
  
  static const struct clockgen_muxinfo p5040_cmux_grp1 = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
  		[5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
  	}
  };
  
  static const struct clockgen_muxinfo p5040_cmux_grp2 = {
  	{
  		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
  		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  	}
  };
  
  static const struct clockgen_muxinfo p4080_cmux_grp1 = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		[8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
  	}
  };
  
  static const struct clockgen_muxinfo p4080_cmux_grp2 = {
  	{
  		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
  		[8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
  		[9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
  		[12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
  		[13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
  	}
  };
  
  static const struct clockgen_muxinfo t1023_cmux = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  	}
  };
  
  static const struct clockgen_muxinfo t1040_cmux = {
  	{
  		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  	}
  };
  
  
  static const struct clockgen_muxinfo clockgen2_cmux_cga = {
  	{
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
  		{},
  		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
  	},
  };
  
  static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
  	{
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
  	},
  };
  
  static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
  	{
  		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
  		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
  		{},
  		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
  		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
  	},
  };
e994412c5   Hou Zhiqiang   clk: qoriq: Add l...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  static const struct clockgen_muxinfo ls1043a_hwa1 = {
  	{
  		{},
  		{},
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
  		{},
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
  	},
  };
  
  static const struct clockgen_muxinfo ls1043a_hwa2 = {
  	{
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
  	},
  };
0dfc86b31   Scott Wood   clk: qoriq: Move ...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
  static const struct clockgen_muxinfo t1023_hwa1 = {
  	{
  		{},
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
  	},
  };
  
  static const struct clockgen_muxinfo t1023_hwa2 = {
  	{
  		[6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  	},
  };
  
  static const struct clockgen_muxinfo t2080_hwa1 = {
  	{
  		{},
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
  		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
  	},
  };
  
  static const struct clockgen_muxinfo t2080_hwa2 = {
  	{
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
  		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
  	},
  };
  
  static const struct clockgen_muxinfo t4240_hwa1 = {
  	{
  		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
  		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
  		{},
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
  		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
  	},
  };
  
  static const struct clockgen_muxinfo t4240_hwa4 = {
  	{
  		[2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
  		[3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
  		[4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
  		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
  		[6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
  	},
  };
  
  static const struct clockgen_muxinfo t4240_hwa5 = {
  	{
  		[2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
  		[3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
  		[4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
  		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
  		[6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
  		[7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
  	},
  };
  
  #define RCWSR7_FM1_CLK_SEL	0x40000000
  #define RCWSR7_FM2_CLK_SEL	0x20000000
  #define RCWSR7_HWA_ASYNC_DIV	0x04000000
  
  static void __init p2041_init_periph(struct clockgen *cg)
  {
  	u32 reg;
  
  	reg = ioread32be(&cg->guts->rcwsr[7]);
  
  	if (reg & RCWSR7_FM1_CLK_SEL)
  		cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
  	else
  		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
  }
  
  static void __init p4080_init_periph(struct clockgen *cg)
  {
  	u32 reg;
  
  	reg = ioread32be(&cg->guts->rcwsr[7]);
  
  	if (reg & RCWSR7_FM1_CLK_SEL)
  		cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
  	else
  		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
  
  	if (reg & RCWSR7_FM2_CLK_SEL)
  		cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
  	else
  		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
  }
  
  static void __init p5020_init_periph(struct clockgen *cg)
  {
  	u32 reg;
  	int div = PLL_DIV2;
  
  	reg = ioread32be(&cg->guts->rcwsr[7]);
  	if (reg & RCWSR7_HWA_ASYNC_DIV)
  		div = PLL_DIV4;
  
  	if (reg & RCWSR7_FM1_CLK_SEL)
  		cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
  	else
  		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
  }
  
  static void __init p5040_init_periph(struct clockgen *cg)
  {
  	u32 reg;
  	int div = PLL_DIV2;
  
  	reg = ioread32be(&cg->guts->rcwsr[7]);
  	if (reg & RCWSR7_HWA_ASYNC_DIV)
  		div = PLL_DIV4;
  
  	if (reg & RCWSR7_FM1_CLK_SEL)
  		cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
  	else
  		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
  
  	if (reg & RCWSR7_FM2_CLK_SEL)
  		cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
  	else
  		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
  }
  
  static void __init t1023_init_periph(struct clockgen *cg)
  {
  	cg->fman[0] = cg->hwaccel[1];
  }
  
  static void __init t1040_init_periph(struct clockgen *cg)
  {
  	cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
  }
  
  static void __init t2080_init_periph(struct clockgen *cg)
  {
  	cg->fman[0] = cg->hwaccel[0];
  }
  
  static void __init t4240_init_periph(struct clockgen *cg)
  {
  	cg->fman[0] = cg->hwaccel[3];
  	cg->fman[1] = cg->hwaccel[4];
  }
  
  static const struct clockgen_chipinfo chipinfo[] = {
  	{
  		.compat = "fsl,b4420-clockgen",
  		.guts_compat = "fsl,b4860-device-config",
  		.init_periph = t2080_init_periph,
  		.cmux_groups = {
  			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
  		},
  		.hwaccel = {
  			&t2080_hwa1
  		},
  		.cmux_to_group = {
  			0, 1, 1, 1, -1
  		},
  		.pll_mask = 0x3f,
  		.flags = CG_PLL_8BIT,
  	},
  	{
  		.compat = "fsl,b4860-clockgen",
  		.guts_compat = "fsl,b4860-device-config",
  		.init_periph = t2080_init_periph,
  		.cmux_groups = {
  			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
  		},
  		.hwaccel = {
  			&t2080_hwa1
  		},
  		.cmux_to_group = {
  			0, 1, 1, 1, -1
  		},
  		.pll_mask = 0x3f,
  		.flags = CG_PLL_8BIT,
  	},
  	{
  		.compat = "fsl,ls1021a-clockgen",
  		.cmux_groups = {
  			&t1023_cmux
  		},
  		.cmux_to_group = {
  			0, -1
  		},
  		.pll_mask = 0x03,
  	},
  	{
e994412c5   Hou Zhiqiang   clk: qoriq: Add l...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  		.compat = "fsl,ls1043a-clockgen",
  		.init_periph = t2080_init_periph,
  		.cmux_groups = {
  			&t1040_cmux
  		},
  		.hwaccel = {
  			&ls1043a_hwa1, &ls1043a_hwa2
  		},
  		.cmux_to_group = {
  			0, -1
  		},
  		.pll_mask = 0x07,
  		.flags = CG_PLL_8BIT,
  	},
  	{
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
486
487
488
489
490
491
492
493
494
495
496
  		.compat = "fsl,ls2080a-clockgen",
  		.cmux_groups = {
  			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
  		},
  		.cmux_to_group = {
  			0, 0, 1, 1, -1
  		},
  		.pll_mask = 0x37,
  		.flags = CG_VER3 | CG_LITTLE_ENDIAN,
  	},
  	{
0dfc86b31   Scott Wood   clk: qoriq: Move ...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  		.compat = "fsl,p2041-clockgen",
  		.guts_compat = "fsl,qoriq-device-config-1.0",
  		.init_periph = p2041_init_periph,
  		.cmux_groups = {
  			&p2041_cmux_grp1, &p2041_cmux_grp2
  		},
  		.cmux_to_group = {
  			0, 0, 1, 1, -1
  		},
  		.pll_mask = 0x07,
  	},
  	{
  		.compat = "fsl,p3041-clockgen",
  		.guts_compat = "fsl,qoriq-device-config-1.0",
  		.init_periph = p2041_init_periph,
  		.cmux_groups = {
  			&p2041_cmux_grp1, &p2041_cmux_grp2
  		},
  		.cmux_to_group = {
  			0, 0, 1, 1, -1
  		},
  		.pll_mask = 0x07,
  	},
  	{
  		.compat = "fsl,p4080-clockgen",
  		.guts_compat = "fsl,qoriq-device-config-1.0",
  		.init_periph = p4080_init_periph,
  		.cmux_groups = {
  			&p4080_cmux_grp1, &p4080_cmux_grp2
  		},
  		.cmux_to_group = {
  			0, 0, 0, 0, 1, 1, 1, 1
  		},
  		.pll_mask = 0x1f,
  	},
  	{
  		.compat = "fsl,p5020-clockgen",
  		.guts_compat = "fsl,qoriq-device-config-1.0",
  		.init_periph = p5020_init_periph,
  		.cmux_groups = {
  			&p2041_cmux_grp1, &p2041_cmux_grp2
  		},
  		.cmux_to_group = {
  			0, 1, -1
  		},
  		.pll_mask = 0x07,
  	},
  	{
  		.compat = "fsl,p5040-clockgen",
  		.guts_compat = "fsl,p5040-device-config",
  		.init_periph = p5040_init_periph,
  		.cmux_groups = {
  			&p5040_cmux_grp1, &p5040_cmux_grp2
  		},
  		.cmux_to_group = {
  			0, 0, 1, 1, -1
  		},
  		.pll_mask = 0x0f,
  	},
  	{
  		.compat = "fsl,t1023-clockgen",
  		.guts_compat = "fsl,t1023-device-config",
  		.init_periph = t1023_init_periph,
  		.cmux_groups = {
  			&t1023_cmux
  		},
  		.hwaccel = {
  			&t1023_hwa1, &t1023_hwa2
  		},
  		.cmux_to_group = {
  			0, 0, -1
  		},
  		.pll_mask = 0x03,
  		.flags = CG_PLL_8BIT,
  	},
  	{
  		.compat = "fsl,t1040-clockgen",
  		.guts_compat = "fsl,t1040-device-config",
  		.init_periph = t1040_init_periph,
  		.cmux_groups = {
  			&t1040_cmux
  		},
  		.cmux_to_group = {
  			0, 0, 0, 0, -1
  		},
  		.pll_mask = 0x07,
  		.flags = CG_PLL_8BIT,
  	},
  	{
  		.compat = "fsl,t2080-clockgen",
  		.guts_compat = "fsl,t2080-device-config",
  		.init_periph = t2080_init_periph,
  		.cmux_groups = {
  			&clockgen2_cmux_cga12
  		},
  		.hwaccel = {
  			&t2080_hwa1, &t2080_hwa2
  		},
  		.cmux_to_group = {
  			0, -1
  		},
  		.pll_mask = 0x07,
  		.flags = CG_PLL_8BIT,
  	},
  	{
  		.compat = "fsl,t4240-clockgen",
  		.guts_compat = "fsl,t4240-device-config",
  		.init_periph = t4240_init_periph,
  		.cmux_groups = {
  			&clockgen2_cmux_cga, &clockgen2_cmux_cgb
  		},
  		.hwaccel = {
  			&t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
  		},
  		.cmux_to_group = {
  			0, 0, 1, -1
  		},
  		.pll_mask = 0x3f,
  		.flags = CG_PLL_8BIT,
  	},
  	{},
  };
  
  struct mux_hwclock {
555eae973   Tang Yuantian   clk: add PowerPC ...
621
  	struct clk_hw hw;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
622
623
624
625
626
627
  	struct clockgen *cg;
  	const struct clockgen_muxinfo *info;
  	u32 __iomem *reg;
  	u8 parent_to_clksel[NUM_MUX_PARENTS];
  	s8 clksel_to_parent[NUM_MUX_PARENTS];
  	int num_parents;
555eae973   Tang Yuantian   clk: add PowerPC ...
628
  };
0dfc86b31   Scott Wood   clk: qoriq: Move ...
629
630
  #define to_mux_hwclock(p)	container_of(p, struct mux_hwclock, hw)
  #define CLKSEL_MASK		0x78000000
555eae973   Tang Yuantian   clk: add PowerPC ...
631
  #define	CLKSEL_SHIFT		27
555eae973   Tang Yuantian   clk: add PowerPC ...
632

0dfc86b31   Scott Wood   clk: qoriq: Move ...
633
  static int mux_set_parent(struct clk_hw *hw, u8 idx)
555eae973   Tang Yuantian   clk: add PowerPC ...
634
  {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
635
  	struct mux_hwclock *hwc = to_mux_hwclock(hw);
555eae973   Tang Yuantian   clk: add PowerPC ...
636
  	u32 clksel;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
637
638
639
640
  	if (idx >= hwc->num_parents)
  		return -EINVAL;
  
  	clksel = hwc->parent_to_clksel[idx];
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
641
  	cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
555eae973   Tang Yuantian   clk: add PowerPC ...
642
643
644
  
  	return 0;
  }
0dfc86b31   Scott Wood   clk: qoriq: Move ...
645
  static u8 mux_get_parent(struct clk_hw *hw)
555eae973   Tang Yuantian   clk: add PowerPC ...
646
  {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
647
  	struct mux_hwclock *hwc = to_mux_hwclock(hw);
555eae973   Tang Yuantian   clk: add PowerPC ...
648
  	u32 clksel;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
649
  	s8 ret;
555eae973   Tang Yuantian   clk: add PowerPC ...
650

9e19ca2f6   Scott Wood   clk: qoriq: Add l...
651
  	clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
555eae973   Tang Yuantian   clk: add PowerPC ...
652

0dfc86b31   Scott Wood   clk: qoriq: Move ...
653
654
655
656
657
658
659
660
  	ret = hwc->clksel_to_parent[clksel];
  	if (ret < 0) {
  		pr_err("%s: mux at %p has bad clksel
  ", __func__, hwc->reg);
  		return 0;
  	}
  
  	return ret;
555eae973   Tang Yuantian   clk: add PowerPC ...
661
  }
334680dd5   Emil Medve   clk: qoriq: Make ...
662
  static const struct clk_ops cmux_ops = {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
663
664
  	.get_parent = mux_get_parent,
  	.set_parent = mux_set_parent,
555eae973   Tang Yuantian   clk: add PowerPC ...
665
  };
0dfc86b31   Scott Wood   clk: qoriq: Move ...
666
667
668
669
670
671
672
673
674
675
676
  /*
   * Don't allow setting for now, as the clock options haven't been
   * sanitized for additional restrictions.
   */
  static const struct clk_ops hwaccel_ops = {
  	.get_parent = mux_get_parent,
  };
  
  static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
  						  struct mux_hwclock *hwc,
  						  int idx)
555eae973   Tang Yuantian   clk: add PowerPC ...
677
  {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
678
  	int pll, div;
555eae973   Tang Yuantian   clk: add PowerPC ...
679

0dfc86b31   Scott Wood   clk: qoriq: Move ...
680
681
  	if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
  		return NULL;
555eae973   Tang Yuantian   clk: add PowerPC ...
682

0dfc86b31   Scott Wood   clk: qoriq: Move ...
683
684
  	pll = hwc->info->clksel[idx].pll;
  	div = hwc->info->clksel[idx].div;
555eae973   Tang Yuantian   clk: add PowerPC ...
685

0dfc86b31   Scott Wood   clk: qoriq: Move ...
686
687
  	return &cg->pll[pll].div[div];
  }
555eae973   Tang Yuantian   clk: add PowerPC ...
688

0dfc86b31   Scott Wood   clk: qoriq: Move ...
689
690
691
692
  static struct clk * __init create_mux_common(struct clockgen *cg,
  					     struct mux_hwclock *hwc,
  					     const struct clk_ops *ops,
  					     unsigned long min_rate,
7c1c5413a   Scott Wood   clk: qoriq: Don't...
693
  					     unsigned long max_rate,
0dfc86b31   Scott Wood   clk: qoriq: Move ...
694
695
696
697
698
699
700
701
702
  					     unsigned long pct80_rate,
  					     const char *fmt, int idx)
  {
  	struct clk_init_data init = {};
  	struct clk *clk;
  	const struct clockgen_pll_div *div;
  	const char *parent_names[NUM_MUX_PARENTS];
  	char name[32];
  	int i, j;
8002cab6b   Emil Medve   clk: qoriq: Fix c...
703

0dfc86b31   Scott Wood   clk: qoriq: Move ...
704
  	snprintf(name, sizeof(name), fmt, idx);
555eae973   Tang Yuantian   clk: add PowerPC ...
705

0dfc86b31   Scott Wood   clk: qoriq: Move ...
706
707
  	for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
  		unsigned long rate;
57bfd7ee6   Tang Yuantian   clock: redefine v...
708

0dfc86b31   Scott Wood   clk: qoriq: Move ...
709
  		hwc->clksel_to_parent[i] = -1;
57bfd7ee6   Tang Yuantian   clock: redefine v...
710

0dfc86b31   Scott Wood   clk: qoriq: Move ...
711
712
713
  		div = get_pll_div(cg, hwc, i);
  		if (!div)
  			continue;
555eae973   Tang Yuantian   clk: add PowerPC ...
714

0dfc86b31   Scott Wood   clk: qoriq: Move ...
715
716
717
718
719
720
721
  		rate = clk_get_rate(div->clk);
  
  		if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
  		    rate > pct80_rate)
  			continue;
  		if (rate < min_rate)
  			continue;
7c1c5413a   Scott Wood   clk: qoriq: Don't...
722
723
  		if (rate > max_rate)
  			continue;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
724
725
726
727
728
  
  		parent_names[j] = div->name;
  		hwc->parent_to_clksel[j] = i;
  		hwc->clksel_to_parent[i] = j;
  		j++;
555eae973   Tang Yuantian   clk: add PowerPC ...
729
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
730
731
  	init.name = name;
  	init.ops = ops;
555eae973   Tang Yuantian   clk: add PowerPC ...
732
  	init.parent_names = parent_names;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
733
  	init.num_parents = hwc->num_parents = j;
555eae973   Tang Yuantian   clk: add PowerPC ...
734
  	init.flags = 0;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
735
736
  	hwc->hw.init = &init;
  	hwc->cg = cg;
555eae973   Tang Yuantian   clk: add PowerPC ...
737

0dfc86b31   Scott Wood   clk: qoriq: Move ...
738
  	clk = clk_register(NULL, &hwc->hw);
555eae973   Tang Yuantian   clk: add PowerPC ...
739
  	if (IS_ERR(clk)) {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  		pr_err("%s: Couldn't register %s: %ld
  ", __func__, name,
  		       PTR_ERR(clk));
  		kfree(hwc);
  		return NULL;
  	}
  
  	return clk;
  }
  
  static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
  {
  	struct mux_hwclock *hwc;
  	const struct clockgen_pll_div *div;
  	unsigned long plat_rate, min_rate;
7c1c5413a   Scott Wood   clk: qoriq: Don't...
755
  	u64 max_rate, pct80_rate;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
756
757
758
759
760
  	u32 clksel;
  
  	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
  	if (!hwc)
  		return NULL;
8964193f6   Tang Yuantian   clk: qoriq: fix a...
761
762
763
764
  	if (cg->info.flags & CG_VER3)
  		hwc->reg = cg->regs + 0x70000 + 0x20 * idx;
  	else
  		hwc->reg = cg->regs + 0x20 * idx;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
765
766
767
768
769
770
771
772
773
  	hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
  
  	/*
  	 * Find the rate for the default clksel, and treat it as the
  	 * maximum rated core frequency.  If this is an incorrect
  	 * assumption, certain clock options (possibly including the
  	 * default clksel) may be inappropriately excluded on certain
  	 * chips.
  	 */
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
774
  	clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
775
  	div = get_pll_div(cg, hwc, clksel);
279104e3a   Sudip Mukherjee   clk: qoriq: fix m...
776
777
  	if (!div) {
  		kfree(hwc);
0dfc86b31   Scott Wood   clk: qoriq: Move ...
778
  		return NULL;
279104e3a   Sudip Mukherjee   clk: qoriq: fix m...
779
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
780

7c1c5413a   Scott Wood   clk: qoriq: Don't...
781
782
  	max_rate = clk_get_rate(div->clk);
  	pct80_rate = max_rate * 8;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
783
784
785
786
787
788
789
790
  	do_div(pct80_rate, 10);
  
  	plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
  
  	if (cg->info.flags & CG_CMUX_GE_PLAT)
  		min_rate = plat_rate;
  	else
  		min_rate = plat_rate / 2;
7c1c5413a   Scott Wood   clk: qoriq: Don't...
791
  	return create_mux_common(cg, hwc, &cmux_ops, min_rate, max_rate,
0dfc86b31   Scott Wood   clk: qoriq: Move ...
792
793
794
795
796
797
798
799
800
801
802
803
804
  				 pct80_rate, "cg-cmux%d", idx);
  }
  
  static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
  {
  	struct mux_hwclock *hwc;
  
  	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
  	if (!hwc)
  		return NULL;
  
  	hwc->reg = cg->regs + 0x20 * idx + 0x10;
  	hwc->info = cg->info.hwaccel[idx];
7c1c5413a   Scott Wood   clk: qoriq: Don't...
805
  	return create_mux_common(cg, hwc, &hwaccel_ops, 0, ULONG_MAX, 0,
0dfc86b31   Scott Wood   clk: qoriq: Move ...
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  				 "cg-hwaccel%d", idx);
  }
  
  static void __init create_muxes(struct clockgen *cg)
  {
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
  		if (cg->info.cmux_to_group[i] < 0)
  			break;
  		if (cg->info.cmux_to_group[i] >=
  		    ARRAY_SIZE(cg->info.cmux_groups)) {
  			WARN_ON_ONCE(1);
  			continue;
  		}
  
  		cg->cmux[i] = create_one_cmux(cg, i);
555eae973   Tang Yuantian   clk: add PowerPC ...
823
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
  	for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
  		if (!cg->info.hwaccel[i])
  			continue;
  
  		cg->hwaccel[i] = create_one_hwaccel(cg, i);
  	}
  }
  
  static void __init clockgen_init(struct device_node *np);
  
  /* Legacy nodes may get probed before the parent clockgen node */
  static void __init legacy_init_clockgen(struct device_node *np)
  {
  	if (!clockgen.node)
  		clockgen_init(of_get_parent(np));
  }
  
  /* Legacy node */
  static void __init core_mux_init(struct device_node *np)
  {
  	struct clk *clk;
  	struct resource res;
  	int idx, rc;
  
  	legacy_init_clockgen(np);
  
  	if (of_address_to_resource(np, 0, &res))
  		return;
  
  	idx = (res.start & 0xf0) >> 5;
  	clk = clockgen.cmux[idx];
555eae973   Tang Yuantian   clk: add PowerPC ...
855
856
  	rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
  	if (rc) {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
857
858
859
860
  		pr_err("%s: Couldn't register clk provider for node %s: %d
  ",
  		       __func__, np->name, rc);
  		return;
555eae973   Tang Yuantian   clk: add PowerPC ...
861
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
862
  }
555eae973   Tang Yuantian   clk: add PowerPC ...
863

3432a2e39   Julia Lawall   clk: qoriq: add _...
864
865
  static struct clk __init
  *sysclk_from_fixed(struct device_node *node, const char *name)
0dfc86b31   Scott Wood   clk: qoriq: Move ...
866
867
868
869
870
  {
  	u32 rate;
  
  	if (of_property_read_u32(node, "clock-frequency", &rate))
  		return ERR_PTR(-ENODEV);
ec3f2fcb3   Stephen Boyd   clk: qoriq: Remov...
871
  	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
555eae973   Tang Yuantian   clk: add PowerPC ...
872
  }
0dfc86b31   Scott Wood   clk: qoriq: Move ...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  static struct clk *sysclk_from_parent(const char *name)
  {
  	struct clk *clk;
  	const char *parent_name;
  
  	clk = of_clk_get(clockgen.node, 0);
  	if (IS_ERR(clk))
  		return clk;
  
  	/* Register the input clock under the desired name. */
  	parent_name = __clk_get_name(clk);
  	clk = clk_register_fixed_factor(NULL, name, parent_name,
  					0, 1, 1);
  	if (IS_ERR(clk))
  		pr_err("%s: Couldn't register %s: %ld
  ", __func__, name,
  		       PTR_ERR(clk));
  
  	return clk;
  }
  
  static struct clk * __init create_sysclk(const char *name)
  {
  	struct device_node *sysclk;
  	struct clk *clk;
  
  	clk = sysclk_from_fixed(clockgen.node, name);
  	if (!IS_ERR(clk))
  		return clk;
  
  	clk = sysclk_from_parent(name);
  	if (!IS_ERR(clk))
  		return clk;
  
  	sysclk = of_get_child_by_name(clockgen.node, "sysclk");
  	if (sysclk) {
  		clk = sysclk_from_fixed(sysclk, name);
  		if (!IS_ERR(clk))
  			return clk;
  	}
  
  	pr_err("%s: No input clock
  ", __func__);
  	return NULL;
  }
  
  /* Legacy node */
  static void __init sysclk_init(struct device_node *node)
  {
  	struct clk *clk;
  
  	legacy_init_clockgen(node);
  
  	clk = clockgen.sysclk;
  	if (clk)
  		of_clk_add_provider(node, of_clk_src_simple_get, clk);
  }
  
  #define PLL_KILL BIT(31)
  
  static void __init create_one_pll(struct clockgen *cg, int idx)
555eae973   Tang Yuantian   clk: add PowerPC ...
934
  {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
935
  	u32 __iomem *reg;
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
936
  	u32 mult;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
937
938
  	struct clockgen_pll *pll = &cg->pll[idx];
  	int i;
555eae973   Tang Yuantian   clk: add PowerPC ...
939

0dfc86b31   Scott Wood   clk: qoriq: Move ...
940
  	if (!(cg->info.pll_mask & (1 << idx)))
555eae973   Tang Yuantian   clk: add PowerPC ...
941
  		return;
555eae973   Tang Yuantian   clk: add PowerPC ...
942

9e19ca2f6   Scott Wood   clk: qoriq: Add l...
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
  	if (cg->info.flags & CG_VER3) {
  		switch (idx) {
  		case PLATFORM_PLL:
  			reg = cg->regs + 0x60080;
  			break;
  		case CGA_PLL1:
  			reg = cg->regs + 0x80;
  			break;
  		case CGA_PLL2:
  			reg = cg->regs + 0xa0;
  			break;
  		case CGB_PLL1:
  			reg = cg->regs + 0x10080;
  			break;
  		case CGB_PLL2:
  			reg = cg->regs + 0x100a0;
  			break;
  		default:
  			WARN_ONCE(1, "index %d
  ", idx);
  			return;
  		}
  	} else {
  		if (idx == PLATFORM_PLL)
  			reg = cg->regs + 0xc00;
  		else
  			reg = cg->regs + 0x800 + 0x20 * (idx - 1);
  	}
555eae973   Tang Yuantian   clk: add PowerPC ...
971

0dfc86b31   Scott Wood   clk: qoriq: Move ...
972
  	/* Get the multiple of PLL */
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
973
  	mult = cg_in(cg, reg);
0dfc86b31   Scott Wood   clk: qoriq: Move ...
974
975
  
  	/* Check if this PLL is disabled */
555eae973   Tang Yuantian   clk: add PowerPC ...
976
  	if (mult & PLL_KILL) {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
977
978
979
  		pr_debug("%s(): pll %p disabled
  ", __func__, reg);
  		return;
555eae973   Tang Yuantian   clk: add PowerPC ...
980
  	}
555eae973   Tang Yuantian   clk: add PowerPC ...
981

9e19ca2f6   Scott Wood   clk: qoriq: Add l...
982
983
  	if ((cg->info.flags & CG_VER3) ||
  	    ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
0dfc86b31   Scott Wood   clk: qoriq: Move ...
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
  		mult = (mult & GENMASK(8, 1)) >> 1;
  	else
  		mult = (mult & GENMASK(6, 1)) >> 1;
  
  	for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
  		struct clk *clk;
  
  		snprintf(pll->div[i].name, sizeof(pll->div[i].name),
  			 "cg-pll%d-div%d", idx, i + 1);
  
  		clk = clk_register_fixed_factor(NULL,
  				pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
  		if (IS_ERR(clk)) {
  			pr_err("%s: %s: register failed %ld
  ",
  			       __func__, pll->div[i].name, PTR_ERR(clk));
  			continue;
  		}
  
  		pll->div[i].clk = clk;
555eae973   Tang Yuantian   clk: add PowerPC ...
1004
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1005
1006
1007
1008
1009
1010
1011
1012
1013
  }
  
  static void __init create_plls(struct clockgen *cg)
  {
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
  		create_one_pll(cg, i);
  }
555eae973   Tang Yuantian   clk: add PowerPC ...
1014

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  static void __init legacy_pll_init(struct device_node *np, int idx)
  {
  	struct clockgen_pll *pll;
  	struct clk_onecell_data *onecell_data;
  	struct clk **subclks;
  	int count, rc;
  
  	legacy_init_clockgen(np);
  
  	pll = &clockgen.pll[idx];
555eae973   Tang Yuantian   clk: add PowerPC ...
1025
  	count = of_property_count_strings(np, "clock-output-names");
555eae973   Tang Yuantian   clk: add PowerPC ...
1026

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1027
1028
  	BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
  	subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
8002cab6b   Emil Medve   clk: qoriq: Fix c...
1029
  	if (!subclks)
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1030
  		return;
555eae973   Tang Yuantian   clk: add PowerPC ...
1031

6ef1ccac5   Emil Medve   clk: qoriq: Repla...
1032
  	onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
8002cab6b   Emil Medve   clk: qoriq: Fix c...
1033
  	if (!onecell_data)
555eae973   Tang Yuantian   clk: add PowerPC ...
1034
  		goto err_clks;
555eae973   Tang Yuantian   clk: add PowerPC ...
1035

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1036
1037
1038
1039
1040
1041
1042
1043
1044
  	if (count <= 3) {
  		subclks[0] = pll->div[0].clk;
  		subclks[1] = pll->div[1].clk;
  		subclks[2] = pll->div[3].clk;
  	} else {
  		subclks[0] = pll->div[0].clk;
  		subclks[1] = pll->div[1].clk;
  		subclks[2] = pll->div[2].clk;
  		subclks[3] = pll->div[3].clk;
555eae973   Tang Yuantian   clk: add PowerPC ...
1045
1046
1047
1048
1049
1050
1051
  	}
  
  	onecell_data->clks = subclks;
  	onecell_data->clk_num = count;
  
  	rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
  	if (rc) {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1052
1053
1054
  		pr_err("%s: Couldn't register clk provider for node %s: %d
  ",
  		       __func__, np->name, rc);
555eae973   Tang Yuantian   clk: add PowerPC ...
1055
1056
1057
1058
1059
1060
1061
1062
  		goto err_cell;
  	}
  
  	return;
  err_cell:
  	kfree(onecell_data);
  err_clks:
  	kfree(subclks);
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1063
  }
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1064
1065
  /* Legacy node */
  static void __init pltfrm_pll_init(struct device_node *np)
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1066
  {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1067
1068
  	legacy_pll_init(np, PLATFORM_PLL);
  }
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1069

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1070
1071
1072
1073
1074
1075
1076
  /* Legacy node */
  static void __init core_pll_init(struct device_node *np)
  {
  	struct resource res;
  	int idx;
  
  	if (of_address_to_resource(np, 0, &res))
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1077
  		return;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
  
  	if ((res.start & 0xfff) == 0xc00) {
  		/*
  		 * ls1021a devtree labels the platform PLL
  		 * with the core PLL compatible
  		 */
  		pltfrm_pll_init(np);
  	} else {
  		idx = (res.start & 0xf0) >> 5;
  		legacy_pll_init(np, CGA_PLL1 + idx);
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1088
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1089
  }
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1090

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
  static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
  {
  	struct clockgen *cg = data;
  	struct clk *clk;
  	struct clockgen_pll *pll;
  	u32 type, idx;
  
  	if (clkspec->args_count < 2) {
  		pr_err("%s: insufficient phandle args
  ", __func__);
  		return ERR_PTR(-EINVAL);
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1102
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1103
1104
  	type = clkspec->args[0];
  	idx = clkspec->args[1];
00fa6e5d1   Tang Yuantian   clk: mpc85xx: Upd...
1105

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
  	switch (type) {
  	case 0:
  		if (idx != 0)
  			goto bad_args;
  		clk = cg->sysclk;
  		break;
  	case 1:
  		if (idx >= ARRAY_SIZE(cg->cmux))
  			goto bad_args;
  		clk = cg->cmux[idx];
  		break;
  	case 2:
  		if (idx >= ARRAY_SIZE(cg->hwaccel))
  			goto bad_args;
  		clk = cg->hwaccel[idx];
  		break;
  	case 3:
  		if (idx >= ARRAY_SIZE(cg->fman))
  			goto bad_args;
  		clk = cg->fman[idx];
  		break;
  	case 4:
  		pll = &cg->pll[PLATFORM_PLL];
  		if (idx >= ARRAY_SIZE(pll->div))
  			goto bad_args;
  		clk = pll->div[idx].clk;
  		break;
  	default:
  		goto bad_args;
  	}
  
  	if (!clk)
  		return ERR_PTR(-ENOENT);
  	return clk;
  
  bad_args:
  	pr_err("%s: Bad phandle args %u %u
  ", __func__, type, idx);
  	return ERR_PTR(-EINVAL);
555eae973   Tang Yuantian   clk: add PowerPC ...
1145
  }
a513b72cc   Emil Medve   clk: qoriq: Add s...
1146

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  #ifdef CONFIG_PPC
  #include <asm/mpc85xx.h>
  
  static const u32 a4510_svrs[] __initconst = {
  	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
  	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
  	(SVR_P2041 << 8) | 0x10,	/* P2041 1.0 */
  	(SVR_P2041 << 8) | 0x11,	/* P2041 1.1 */
  	(SVR_P3041 << 8) | 0x10,	/* P3041 1.0 */
  	(SVR_P3041 << 8) | 0x11,	/* P3041 1.1 */
  	(SVR_P4040 << 8) | 0x20,	/* P4040 2.0 */
  	(SVR_P4080 << 8) | 0x20,	/* P4080 2.0 */
  	(SVR_P5010 << 8) | 0x10,	/* P5010 1.0 */
  	(SVR_P5010 << 8) | 0x20,	/* P5010 2.0 */
  	(SVR_P5020 << 8) | 0x10,	/* P5020 1.0 */
  	(SVR_P5021 << 8) | 0x10,	/* P5021 1.0 */
  	(SVR_P5040 << 8) | 0x10,	/* P5040 1.0 */
  };
  
  #define SVR_SECURITY	0x80000	/* The Security (E) bit */
  
  static bool __init has_erratum_a4510(void)
a513b72cc   Emil Medve   clk: qoriq: Add s...
1169
  {
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1170
1171
1172
1173
1174
1175
1176
1177
  	u32 svr = mfspr(SPRN_SVR);
  	int i;
  
  	svr &= ~SVR_SECURITY;
  
  	for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
  		if (svr == a4510_svrs[i])
  			return true;
a513b72cc   Emil Medve   clk: qoriq: Add s...
1178
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1179
1180
1181
1182
1183
1184
1185
1186
  	return false;
  }
  #else
  static bool __init has_erratum_a4510(void)
  {
  	return false;
  }
  #endif
a513b72cc   Emil Medve   clk: qoriq: Add s...
1187

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1188
1189
1190
1191
  static void __init clockgen_init(struct device_node *np)
  {
  	int i, ret;
  	bool is_old_ls1021a = false;
a513b72cc   Emil Medve   clk: qoriq: Add s...
1192

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1193
1194
  	/* May have already been called by a legacy probe */
  	if (clockgen.node)
a513b72cc   Emil Medve   clk: qoriq: Add s...
1195
  		return;
a513b72cc   Emil Medve   clk: qoriq: Add s...
1196

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
  	clockgen.node = np;
  	clockgen.regs = of_iomap(np, 0);
  	if (!clockgen.regs &&
  	    of_device_is_compatible(of_root, "fsl,ls1021a")) {
  		/* Compatibility hack for old, broken device trees */
  		clockgen.regs = ioremap(0x1ee1000, 0x1000);
  		is_old_ls1021a = true;
  	}
  	if (!clockgen.regs) {
  		pr_err("%s(): %s: of_iomap() failed
  ", __func__, np->name);
a513b72cc   Emil Medve   clk: qoriq: Add s...
1208
1209
  		return;
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1210
1211
1212
1213
1214
1215
  	for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
  		if (of_device_is_compatible(np, chipinfo[i].compat))
  			break;
  		if (is_old_ls1021a &&
  		    !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
  			break;
a513b72cc   Emil Medve   clk: qoriq: Add s...
1216
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
  	if (i == ARRAY_SIZE(chipinfo)) {
  		pr_err("%s: unknown clockgen node %s
  ", __func__,
  		       np->full_name);
  		goto err;
  	}
  	clockgen.info = chipinfo[i];
  
  	if (clockgen.info.guts_compat) {
  		struct device_node *guts;
a513b72cc   Emil Medve   clk: qoriq: Add s...
1227

0dfc86b31   Scott Wood   clk: qoriq: Move ...
1228
1229
1230
1231
1232
1233
1234
1235
1236
  		guts = of_find_compatible_node(NULL, NULL,
  					       clockgen.info.guts_compat);
  		if (guts) {
  			clockgen.guts = of_iomap(guts, 0);
  			if (!clockgen.guts) {
  				pr_err("%s: Couldn't map %s regs
  ", __func__,
  				       guts->full_name);
  			}
a513b72cc   Emil Medve   clk: qoriq: Add s...
1237
  		}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1238

a513b72cc   Emil Medve   clk: qoriq: Add s...
1239
  	}
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
  	if (has_erratum_a4510())
  		clockgen.info.flags |= CG_CMUX_GE_PLAT;
  
  	clockgen.sysclk = create_sysclk("cg-sysclk");
  	create_plls(&clockgen);
  	create_muxes(&clockgen);
  
  	if (clockgen.info.init_periph)
  		clockgen.info.init_periph(&clockgen);
  
  	ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
  	if (ret) {
  		pr_err("%s: Couldn't register clk provider for node %s: %d
  ",
  		       __func__, np->name, ret);
a513b72cc   Emil Medve   clk: qoriq: Add s...
1255
1256
1257
  	}
  
  	return;
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1258
1259
1260
  err:
  	iounmap(clockgen.regs);
  	clockgen.regs = NULL;
a513b72cc   Emil Medve   clk: qoriq: Add s...
1261
  }
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1262
1263
1264
  CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
e994412c5   Hou Zhiqiang   clk: qoriq: Add l...
1265
  CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
9e19ca2f6   Scott Wood   clk: qoriq: Add l...
1266
  CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
0dfc86b31   Scott Wood   clk: qoriq: Move ...
1267
1268
  
  /* Legacy nodes */
66619ac51   Kevin Hao   clk: ppc-corenet:...
1269
1270
1271
1272
1273
1274
  CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
  CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
  CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
  CLK_OF_DECLARE(qoriq_core_pll_2, "fsl,qoriq-core-pll-2.0", core_pll_init);
  CLK_OF_DECLARE(qoriq_core_mux_1, "fsl,qoriq-core-mux-1.0", core_mux_init);
  CLK_OF_DECLARE(qoriq_core_mux_2, "fsl,qoriq-core-mux-2.0", core_mux_init);
a513b72cc   Emil Medve   clk: qoriq: Add s...
1275
1276
  CLK_OF_DECLARE(qoriq_pltfrm_pll_1, "fsl,qoriq-platform-pll-1.0", pltfrm_pll_init);
  CLK_OF_DECLARE(qoriq_pltfrm_pll_2, "fsl,qoriq-platform-pll-2.0", pltfrm_pll_init);