1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/io.h>
8#include <linux/of_address.h>
9#include <linux/platform_device.h>
10
11#include "ccu_common.h"
12#include "ccu_reset.h"
13
14#include "ccu_div.h"
15#include "ccu_gate.h"
16#include "ccu_mp.h"
17#include "ccu_nkmp.h"
18#include "ccu_nm.h"
19#include "ccu_phase.h"
20
21#include "ccu-sun9i-a80.h"
22
23#define CCU_SUN9I_LOCK_REG	0x09c
24
25/*
26 * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
27 * P should only be used for output frequencies lower than 228 MHz.
28 * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
29 *
30 * For now we can just model it as a multiplier clock, and force P to /1.
31 */
32#define SUN9I_A80_PLL_C0CPUX_REG	0x000
33#define SUN9I_A80_PLL_C1CPUX_REG	0x004
34
35static struct ccu_mult pll_c0cpux_clk = {
36	.enable		= BIT(31),
37	.lock		= BIT(0),
38	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
39	.common		= {
40		.reg		= SUN9I_A80_PLL_C0CPUX_REG,
41		.lock_reg	= CCU_SUN9I_LOCK_REG,
42		.features	= CCU_FEATURE_LOCK_REG,
43		.hw.init	= CLK_HW_INIT("pll-c0cpux", "osc24M",
44					      &ccu_mult_ops,
45					      CLK_SET_RATE_UNGATE),
46	},
47};
48
49static struct ccu_mult pll_c1cpux_clk = {
50	.enable		= BIT(31),
51	.lock		= BIT(1),
52	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
53	.common		= {
54		.reg		= SUN9I_A80_PLL_C1CPUX_REG,
55		.lock_reg	= CCU_SUN9I_LOCK_REG,
56		.features	= CCU_FEATURE_LOCK_REG,
57		.hw.init	= CLK_HW_INIT("pll-c1cpux", "osc24M",
58					      &ccu_mult_ops,
59					      CLK_SET_RATE_UNGATE),
60	},
61};
62
63/*
64 * The Audio PLL has d1, d2 dividers in addition to the usual N, M
65 * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
66 * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
67 */
68#define SUN9I_A80_PLL_AUDIO_REG	0x008
69
70static struct ccu_nm pll_audio_clk = {
71	.enable		= BIT(31),
72	.lock		= BIT(2),
73	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
74	.m		= _SUNXI_CCU_DIV_OFFSET(0, 6, 0),
75	.common		= {
76		.reg		= 0x008,
77		.lock_reg	= CCU_SUN9I_LOCK_REG,
78		.features	= CCU_FEATURE_LOCK_REG,
79		.hw.init	= CLK_HW_INIT("pll-audio", "osc24M",
80					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
81	},
82};
83
84/* Some PLLs are input * N / div1 / div2. Model them as NKMP with no K */
85static struct ccu_nkmp pll_periph0_clk = {
86	.enable		= BIT(31),
87	.lock		= BIT(3),
88	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
89	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
90	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
91	.common		= {
92		.reg		= 0x00c,
93		.lock_reg	= CCU_SUN9I_LOCK_REG,
94		.features	= CCU_FEATURE_LOCK_REG,
95		.hw.init	= CLK_HW_INIT("pll-periph0", "osc24M",
96					      &ccu_nkmp_ops,
97					      CLK_SET_RATE_UNGATE),
98	},
99};
100
101static struct ccu_nkmp pll_ve_clk = {
102	.enable		= BIT(31),
103	.lock		= BIT(4),
104	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
105	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
106	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
107	.common		= {
108		.reg		= 0x010,
109		.lock_reg	= CCU_SUN9I_LOCK_REG,
110		.features	= CCU_FEATURE_LOCK_REG,
111		.hw.init	= CLK_HW_INIT("pll-ve", "osc24M",
112					      &ccu_nkmp_ops,
113					      CLK_SET_RATE_UNGATE),
114	},
115};
116
117static struct ccu_nkmp pll_ddr_clk = {
118	.enable		= BIT(31),
119	.lock		= BIT(5),
120	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
121	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
122	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
123	.common		= {
124		.reg		= 0x014,
125		.lock_reg	= CCU_SUN9I_LOCK_REG,
126		.features	= CCU_FEATURE_LOCK_REG,
127		.hw.init	= CLK_HW_INIT("pll-ddr", "osc24M",
128					      &ccu_nkmp_ops,
129					      CLK_SET_RATE_UNGATE),
130	},
131};
132
133static struct ccu_nm pll_video0_clk = {
134	.enable		= BIT(31),
135	.lock		= BIT(6),
136	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
137	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
138	.common		= {
139		.reg		= 0x018,
140		.lock_reg	= CCU_SUN9I_LOCK_REG,
141		.features	= CCU_FEATURE_LOCK_REG,
142		.hw.init	= CLK_HW_INIT("pll-video0", "osc24M",
143					      &ccu_nm_ops,
144					      CLK_SET_RATE_UNGATE),
145	},
146};
147
148static struct ccu_nkmp pll_video1_clk = {
149	.enable		= BIT(31),
150	.lock		= BIT(7),
151	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
152	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
153	.p		= _SUNXI_CCU_DIV(0, 2), /* external divider p */
154	.common		= {
155		.reg		= 0x01c,
156		.lock_reg	= CCU_SUN9I_LOCK_REG,
157		.features	= CCU_FEATURE_LOCK_REG,
158		.hw.init	= CLK_HW_INIT("pll-video1", "osc24M",
159					      &ccu_nkmp_ops,
160					      CLK_SET_RATE_UNGATE),
161	},
162};
163
164static struct ccu_nkmp pll_gpu_clk = {
165	.enable		= BIT(31),
166	.lock		= BIT(8),
167	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
168	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
169	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
170	.common		= {
171		.reg		= 0x020,
172		.lock_reg	= CCU_SUN9I_LOCK_REG,
173		.features	= CCU_FEATURE_LOCK_REG,
174		.hw.init	= CLK_HW_INIT("pll-gpu", "osc24M",
175					      &ccu_nkmp_ops,
176					      CLK_SET_RATE_UNGATE),
177	},
178};
179
180static struct ccu_nkmp pll_de_clk = {
181	.enable		= BIT(31),
182	.lock		= BIT(9),
183	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
184	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
185	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
186	.common		= {
187		.reg		= 0x024,
188		.lock_reg	= CCU_SUN9I_LOCK_REG,
189		.features	= CCU_FEATURE_LOCK_REG,
190		.hw.init	= CLK_HW_INIT("pll-de", "osc24M",
191					      &ccu_nkmp_ops,
192					      CLK_SET_RATE_UNGATE),
193	},
194};
195
196static struct ccu_nkmp pll_isp_clk = {
197	.enable		= BIT(31),
198	.lock		= BIT(10),
199	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
200	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
201	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
202	.common		= {
203		.reg		= 0x028,
204		.lock_reg	= CCU_SUN9I_LOCK_REG,
205		.features	= CCU_FEATURE_LOCK_REG,
206		.hw.init	= CLK_HW_INIT("pll-isp", "osc24M",
207					      &ccu_nkmp_ops,
208					      CLK_SET_RATE_UNGATE),
209	},
210};
211
212static struct ccu_nkmp pll_periph1_clk = {
213	.enable		= BIT(31),
214	.lock		= BIT(11),
215	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
216	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
217	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
218	.common		= {
219		.reg		= 0x028,
220		.lock_reg	= CCU_SUN9I_LOCK_REG,
221		.features	= CCU_FEATURE_LOCK_REG,
222		.hw.init	= CLK_HW_INIT("pll-periph1", "osc24M",
223					      &ccu_nkmp_ops,
224					      CLK_SET_RATE_UNGATE),
225	},
226};
227
228static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };
229static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,
230		     0x50, 0, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
231
232static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };
233static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,
234		     0x50, 8, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
235
236static struct clk_div_table axi_div_table[] = {
237	{ .val = 0, .div = 1 },
238	{ .val = 1, .div = 2 },
239	{ .val = 2, .div = 3 },
240	{ .val = 3, .div = 4 },
241	{ .val = 4, .div = 4 },
242	{ .val = 5, .div = 4 },
243	{ .val = 6, .div = 4 },
244	{ .val = 7, .div = 4 },
245	{ /* Sentinel */ },
246};
247
248static SUNXI_CCU_M(atb0_clk, "atb0", "c0cpux", 0x054, 8, 2, 0);
249
250static SUNXI_CCU_DIV_TABLE(axi0_clk, "axi0", "c0cpux",
251			   0x054, 0, 3, axi_div_table, 0);
252
253static SUNXI_CCU_M(atb1_clk, "atb1", "c1cpux", 0x058, 8, 2, 0);
254
255static SUNXI_CCU_DIV_TABLE(axi1_clk, "axi1", "c1cpux",
256			   0x058, 0, 3, axi_div_table, 0);
257
258static const char * const gtbus_parents[] = { "osc24M", "pll-periph0",
259					      "pll-periph1", "pll-periph1" };
260static SUNXI_CCU_M_WITH_MUX(gtbus_clk, "gtbus", gtbus_parents,
261			    0x05c, 0, 2, 24, 2, CLK_IS_CRITICAL);
262
263static const char * const ahb_parents[] = { "gtbus", "pll-periph0",
264					    "pll-periph1", "pll-periph1" };
265static struct ccu_div ahb0_clk = {
266	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
267	.mux		= _SUNXI_CCU_MUX(24, 2),
268	.common		= {
269		.reg		= 0x060,
270		.hw.init	= CLK_HW_INIT_PARENTS("ahb0",
271						      ahb_parents,
272						      &ccu_div_ops,
273						      0),
274	},
275};
276
277static struct ccu_div ahb1_clk = {
278	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
279	.mux		= _SUNXI_CCU_MUX(24, 2),
280	.common		= {
281		.reg		= 0x064,
282		.hw.init	= CLK_HW_INIT_PARENTS("ahb1",
283						      ahb_parents,
284						      &ccu_div_ops,
285						      0),
286	},
287};
288
289static struct ccu_div ahb2_clk = {
290	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
291	.mux		= _SUNXI_CCU_MUX(24, 2),
292	.common		= {
293		.reg		= 0x068,
294		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
295						      ahb_parents,
296						      &ccu_div_ops,
297						      0),
298	},
299};
300
301static const char * const apb_parents[] = { "osc24M", "pll-periph0" };
302
303static struct ccu_div apb0_clk = {
304	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
305	.mux		= _SUNXI_CCU_MUX(24, 1),
306	.common		= {
307		.reg		= 0x070,
308		.hw.init	= CLK_HW_INIT_PARENTS("apb0",
309						      apb_parents,
310						      &ccu_div_ops,
311						      0),
312	},
313};
314
315static struct ccu_div apb1_clk = {
316	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
317	.mux		= _SUNXI_CCU_MUX(24, 1),
318	.common		= {
319		.reg		= 0x074,
320		.hw.init	= CLK_HW_INIT_PARENTS("apb1",
321						      apb_parents,
322						      &ccu_div_ops,
323						      0),
324	},
325};
326
327static struct ccu_div cci400_clk = {
328	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
329	.mux		= _SUNXI_CCU_MUX(24, 2),
330	.common		= {
331		.reg		= 0x078,
332		.hw.init	= CLK_HW_INIT_PARENTS("cci400",
333						      ahb_parents,
334						      &ccu_div_ops,
335						      CLK_IS_CRITICAL),
336	},
337};
338
339static SUNXI_CCU_M_WITH_MUX_GATE(ats_clk, "ats", apb_parents,
340				 0x080, 0, 3, 24, 2, BIT(31), 0);
341
342static SUNXI_CCU_M_WITH_MUX_GATE(trace_clk, "trace", apb_parents,
343				 0x084, 0, 3, 24, 2, BIT(31), 0);
344
345static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" };
346static const struct ccu_mux_fixed_prediv out_prediv = {
347	.index = 0, .div = 750
348};
349
350static struct ccu_mp out_a_clk = {
351	.enable		= BIT(31),
352	.m		= _SUNXI_CCU_DIV(8, 5),
353	.p		= _SUNXI_CCU_DIV(20, 2),
354	.mux		= {
355		.shift		= 24,
356		.width		= 4,
357		.fixed_predivs	= &out_prediv,
358		.n_predivs	= 1,
359	},
360	.common		= {
361		.reg		= 0x180,
362		.features	= CCU_FEATURE_FIXED_PREDIV,
363		.hw.init	= CLK_HW_INIT_PARENTS("out-a",
364						      out_parents,
365						      &ccu_mp_ops,
366						      0),
367	},
368};
369
370static struct ccu_mp out_b_clk = {
371	.enable		= BIT(31),
372	.m		= _SUNXI_CCU_DIV(8, 5),
373	.p		= _SUNXI_CCU_DIV(20, 2),
374	.mux		= {
375		.shift		= 24,
376		.width		= 4,
377		.fixed_predivs	= &out_prediv,
378		.n_predivs	= 1,
379	},
380	.common		= {
381		.reg		= 0x184,
382		.features	= CCU_FEATURE_FIXED_PREDIV,
383		.hw.init	= CLK_HW_INIT_PARENTS("out-b",
384						      out_parents,
385						      &ccu_mp_ops,
386						      0),
387	},
388};
389
390static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0" };
391
392static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_0_clk, "nand0-0", mod0_default_parents,
393				  0x400,
394				  0, 4,		/* M */
395				  16, 2,	/* P */
396				  24, 4,	/* mux */
397				  BIT(31),	/* gate */
398				  0);
399
400static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_1_clk, "nand0-1", mod0_default_parents,
401				  0x404,
402				  0, 4,		/* M */
403				  16, 2,	/* P */
404				  24, 4,	/* mux */
405				  BIT(31),	/* gate */
406				  0);
407
408static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_0_clk, "nand1-0", mod0_default_parents,
409				  0x408,
410				  0, 4,		/* M */
411				  16, 2,	/* P */
412				  24, 4,	/* mux */
413				  BIT(31),	/* gate */
414				  0);
415
416static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_1_clk, "nand1-1", mod0_default_parents,
417				  0x40c,
418				  0, 4,		/* M */
419				  16, 2,	/* P */
420				  24, 4,	/* mux */
421				  BIT(31),	/* gate */
422				  0);
423
424static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,
425				  0x410,
426				  0, 4,		/* M */
427				  16, 2,	/* P */
428				  24, 4,	/* mux */
429				  BIT(31),	/* gate */
430				  0);
431
432static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",
433		       0x410, 20, 3, 0);
434static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",
435		       0x410, 8, 3, 0);
436
437static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,
438				  0x414,
439				  0, 4,		/* M */
440				  16, 2,	/* P */
441				  24, 4,	/* mux */
442				  BIT(31),	/* gate */
443				  0);
444
445static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",
446		       0x414, 20, 3, 0);
447static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",
448		       0x414, 8, 3, 0);
449
450static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,
451				  0x418,
452				  0, 4,		/* M */
453				  16, 2,	/* P */
454				  24, 4,	/* mux */
455				  BIT(31),	/* gate */
456				  0);
457
458static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",
459		       0x418, 20, 3, 0);
460static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",
461		       0x418, 8, 3, 0);
462
463static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents,
464				  0x41c,
465				  0, 4,		/* M */
466				  16, 2,	/* P */
467				  24, 4,	/* mux */
468				  BIT(31),	/* gate */
469				  0);
470
471static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3-sample", "mmc3",
472		       0x41c, 20, 3, 0);
473static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3-output", "mmc3",
474		       0x41c, 8, 3, 0);
475
476static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents,
477				  0x428,
478				  0, 4,		/* M */
479				  16, 2,	/* P */
480				  24, 4,	/* mux */
481				  BIT(31),	/* gate */
482				  0);
483
484static const char * const ss_parents[] = { "osc24M", "pll-periph",
485					   "pll-periph1" };
486static const u8 ss_table[] = { 0, 1, 13 };
487static struct ccu_mp ss_clk = {
488	.enable		= BIT(31),
489	.m		= _SUNXI_CCU_DIV(0, 4),
490	.p		= _SUNXI_CCU_DIV(16, 2),
491	.mux		= _SUNXI_CCU_MUX_TABLE(24, 4, ss_table),
492	.common		= {
493		.reg		= 0x42c,
494		.hw.init	= CLK_HW_INIT_PARENTS("ss",
495						      ss_parents,
496						      &ccu_mp_ops,
497						      0),
498	},
499};
500
501static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,
502				  0x430,
503				  0, 4,		/* M */
504				  16, 2,	/* P */
505				  24, 4,	/* mux */
506				  BIT(31),	/* gate */
507				  0);
508
509static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,
510				  0x434,
511				  0, 4,		/* M */
512				  16, 2,	/* P */
513				  24, 4,	/* mux */
514				  BIT(31),	/* gate */
515				  0);
516
517static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents,
518				  0x438,
519				  0, 4,		/* M */
520				  16, 2,	/* P */
521				  24, 4,	/* mux */
522				  BIT(31),	/* gate */
523				  0);
524
525static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents,
526				  0x43c,
527				  0, 4,		/* M */
528				  16, 2,	/* P */
529				  24, 4,	/* mux */
530				  BIT(31),	/* gate */
531				  0);
532
533static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",
534			     0x440, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
535static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",
536			     0x444, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
537static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
538			     0x44c, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
539
540static const char * const sdram_parents[] = { "pll-periph0", "pll-ddr" };
541static const u8 sdram_table[] = { 0, 3 };
542
543static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(sdram_clk, "sdram",
544				       sdram_parents, sdram_table,
545				       0x484,
546				       8, 4,	/* M */
547				       12, 4,	/* mux */
548				       0,	/* no gate */
549				       CLK_IS_CRITICAL);
550
551static SUNXI_CCU_M_WITH_GATE(de_clk, "de", "pll-de", 0x490,
552			     0, 4, BIT(31), CLK_SET_RATE_PARENT);
553
554static SUNXI_CCU_GATE(edp_clk, "edp", "osc24M", 0x494, BIT(31), 0);
555
556static const char * const mp_parents[] = { "pll-video1", "pll-gpu", "pll-de" };
557static const u8 mp_table[] = { 9, 10, 11 };
558static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mp_clk, "mp", mp_parents, mp_table,
559				       0x498,
560				       0, 4,	/* M */
561				       24, 4,	/* mux */
562				       BIT(31),	/* gate */
563				       0);
564
565static const char * const display_parents[] = { "pll-video0", "pll-video1" };
566static const u8 display_table[] = { 8, 9 };
567
568static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd0_clk, "lcd0",
569				       display_parents, display_table,
570				       0x49c,
571				       0, 4,	/* M */
572				       24, 4,	/* mux */
573				       BIT(31),	/* gate */
574				       CLK_SET_RATE_NO_REPARENT |
575				       CLK_SET_RATE_PARENT);
576
577static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd1_clk, "lcd1",
578				       display_parents, display_table,
579				       0x4a0,
580				       0, 4,	/* M */
581				       24, 4,	/* mux */
582				       BIT(31),	/* gate */
583				       CLK_SET_RATE_NO_REPARENT |
584				       CLK_SET_RATE_PARENT);
585
586static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",
587				       display_parents, display_table,
588				       0x4a8,
589				       0, 4,	/* M */
590				       24, 4,	/* mux */
591				       BIT(31),	/* gate */
592				       CLK_SET_RATE_PARENT);
593
594static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video1" };
595static const u8 mipi_dsi1_table[] = { 0, 9 };
596static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",
597				       mipi_dsi1_parents, mipi_dsi1_table,
598				       0x4ac,
599				       0, 4,	/* M */
600				       24, 4,	/* mux */
601				       BIT(31),	/* gate */
602				       CLK_SET_RATE_PARENT);
603
604static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi_clk, "hdmi",
605				       display_parents, display_table,
606				       0x4b0,
607				       0, 4,	/* M */
608				       24, 4,	/* mux */
609				       BIT(31),	/* gate */
610				       CLK_SET_RATE_NO_REPARENT |
611				       CLK_SET_RATE_PARENT);
612
613static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x4b4, BIT(31), 0);
614
615static SUNXI_CCU_M_WITH_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x4bc,
616			     0, 4, BIT(31), 0);
617
618static SUNXI_CCU_M_WITH_GATE(csi_isp_clk, "csi-isp", "pll-isp", 0x4c0,
619			     0, 4, BIT(31), CLK_SET_RATE_PARENT);
620
621static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x4c0, BIT(16), 0);
622
623static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_mclk_clk, "csi0-mclk",
624				       mipi_dsi1_parents, mipi_dsi1_table,
625				       0x4c4,
626				       0, 4,	/* M */
627				       24, 4,	/* mux */
628				       BIT(31),	/* gate */
629				       CLK_SET_RATE_PARENT);
630
631static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_mclk_clk, "csi1-mclk",
632				       mipi_dsi1_parents, mipi_dsi1_table,
633				       0x4c8,
634				       0, 4,	/* M */
635				       24, 4,	/* mux */
636				       BIT(31),	/* gate */
637				       CLK_SET_RATE_PARENT);
638
639static const char * const fd_parents[] = { "pll-periph0", "pll-isp" };
640static const u8 fd_table[] = { 1, 12 };
641static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(fd_clk, "fd", fd_parents, fd_table,
642				       0x4cc,
643				       0, 4,	/* M */
644				       24, 4,	/* mux */
645				       BIT(31),	/* gate */
646				       0);
647static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x4d0,
648			     16, 3, BIT(31), CLK_SET_RATE_PARENT);
649
650static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x4d4, BIT(31), 0);
651
652static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x4f0,
653			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
654static SUNXI_CCU_M_WITH_GATE(gpu_memory_clk, "gpu-memory", "pll-gpu", 0x4f4,
655			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
656
657static const char * const gpu_axi_parents[] = { "pll-periph0", "pll-gpu" };
658static const u8 gpu_axi_table[] = { 1, 10 };
659static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_axi_clk, "gpu-axi",
660				       gpu_axi_parents, gpu_axi_table,
661				       0x4f8,
662				       0, 4,	/* M */
663				       24, 4,	/* mux */
664				       BIT(31),	/* gate */
665				       CLK_SET_RATE_PARENT);
666
667static SUNXI_CCU_M_WITH_GATE(sata_clk, "sata", "pll-periph0", 0x500,
668			     0, 4, BIT(31), 0);
669
670static SUNXI_CCU_M_WITH_GATE(ac97_clk, "ac97", "pll-audio",
671			     0x504, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
672
673static SUNXI_CCU_M_WITH_MUX_GATE(mipi_hsi_clk, "mipi-hsi",
674				 mod0_default_parents, 0x508,
675				 0, 4,		/* M */
676				 24, 4,		/* mux */
677				 BIT(31),	/* gate */
678				 0);
679
680static const char * const gpadc_parents[] = { "osc24M", "pll-audio", "osc32k" };
681static const u8 gpadc_table[] = { 0, 4, 7 };
682static struct ccu_mp gpadc_clk = {
683	.enable		= BIT(31),
684	.m		= _SUNXI_CCU_DIV(0, 4),
685	.p		= _SUNXI_CCU_DIV(16, 2),
686	.mux		= _SUNXI_CCU_MUX_TABLE(24, 4, gpadc_table),
687	.common		= {
688		.reg		= 0x50c,
689		.hw.init	= CLK_HW_INIT_PARENTS("gpadc",
690						      gpadc_parents,
691						      &ccu_mp_ops,
692						      0),
693	},
694};
695
696static const char * const cir_tx_parents[] = { "osc24M", "osc32k" };
697static const u8 cir_tx_table[] = { 0, 7 };
698static struct ccu_mp cir_tx_clk = {
699	.enable		= BIT(31),
700	.m		= _SUNXI_CCU_DIV(0, 4),
701	.p		= _SUNXI_CCU_DIV(16, 2),
702	.mux		= _SUNXI_CCU_MUX_TABLE(24, 4, cir_tx_table),
703	.common		= {
704		.reg		= 0x510,
705		.hw.init	= CLK_HW_INIT_PARENTS("cir-tx",
706						      cir_tx_parents,
707						      &ccu_mp_ops,
708						      0),
709	},
710};
711
712/* AHB0 bus gates */
713static SUNXI_CCU_GATE(bus_fd_clk,	"bus-fd",	"ahb0",
714		      0x580, BIT(0), 0);
715static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb0",
716		      0x580, BIT(1), 0);
717static SUNXI_CCU_GATE(bus_gpu_ctrl_clk,	"bus-gpu-ctrl",	"ahb0",
718		      0x580, BIT(3), 0);
719static SUNXI_CCU_GATE(bus_ss_clk,	"bus-ss",	"ahb0",
720		      0x580, BIT(5), 0);
721static SUNXI_CCU_GATE(bus_mmc_clk,	"bus-mmc",	"ahb0",
722		      0x580, BIT(8), 0);
723static SUNXI_CCU_GATE(bus_nand0_clk,	"bus-nand0",	"ahb0",
724		      0x580, BIT(12), 0);
725static SUNXI_CCU_GATE(bus_nand1_clk,	"bus-nand1",	"ahb0",
726		      0x580, BIT(13), 0);
727static SUNXI_CCU_GATE(bus_sdram_clk,	"bus-sdram",	"ahb0",
728		      0x580, BIT(14), 0);
729static SUNXI_CCU_GATE(bus_mipi_hsi_clk,	"bus-mipi-hsi",	"ahb0",
730		      0x580, BIT(15), 0);
731static SUNXI_CCU_GATE(bus_sata_clk,	"bus-sata",	"ahb0",
732		      0x580, BIT(16), 0);
733static SUNXI_CCU_GATE(bus_ts_clk,	"bus-ts",	"ahb0",
734		      0x580, BIT(18), 0);
735static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb0",
736		      0x580, BIT(20), 0);
737static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb0",
738		      0x580, BIT(21), 0);
739static SUNXI_CCU_GATE(bus_spi2_clk,	"bus-spi2",	"ahb0",
740		      0x580, BIT(22), 0);
741static SUNXI_CCU_GATE(bus_spi3_clk,	"bus-spi3",	"ahb0",
742		      0x580, BIT(23), 0);
743
744/* AHB1 bus gates */
745static SUNXI_CCU_GATE(bus_otg_clk,	"bus-otg",	"ahb1",
746		      0x584, BIT(0), 0);
747static SUNXI_CCU_GATE(bus_usb_clk,	"bus-usb",	"ahb1",
748		      0x584, BIT(1), 0);
749static SUNXI_CCU_GATE(bus_gmac_clk,	"bus-gmac",	"ahb1",
750		      0x584, BIT(17), 0);
751static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
752		      0x584, BIT(21), 0);
753static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
754		      0x584, BIT(22), 0);
755static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
756		      0x584, BIT(23), 0);
757static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
758		      0x584, BIT(24), 0);
759
760/* AHB2 bus gates */
761static SUNXI_CCU_GATE(bus_lcd0_clk,	"bus-lcd0",	"ahb2",
762		      0x588, BIT(0), 0);
763static SUNXI_CCU_GATE(bus_lcd1_clk,	"bus-lcd1",	"ahb2",
764		      0x588, BIT(1), 0);
765static SUNXI_CCU_GATE(bus_edp_clk,	"bus-edp",	"ahb2",
766		      0x588, BIT(2), 0);
767static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb2",
768		      0x588, BIT(4), 0);
769static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb2",
770		      0x588, BIT(5), 0);
771static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb2",
772		      0x588, BIT(7), 0);
773static SUNXI_CCU_GATE(bus_mp_clk,	"bus-mp",	"ahb2",
774		      0x588, BIT(8), 0);
775static SUNXI_CCU_GATE(bus_mipi_dsi_clk,	"bus-mipi-dsi",	"ahb2",
776		      0x588, BIT(11), 0);
777
778/* APB0 bus gates */
779static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb0",
780		      0x590, BIT(1), 0);
781static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb0",
782		      0x590, BIT(5), 0);
783static SUNXI_CCU_GATE(bus_ac97_clk,	"bus-ac97",	"apb0",
784		      0x590, BIT(11), 0);
785static SUNXI_CCU_GATE(bus_i2s0_clk,	"bus-i2s0",	"apb0",
786		      0x590, BIT(12), 0);
787static SUNXI_CCU_GATE(bus_i2s1_clk,	"bus-i2s1",	"apb0",
788		      0x590, BIT(13), 0);
789static SUNXI_CCU_GATE(bus_lradc_clk,	"bus-lradc",	"apb0",
790		      0x590, BIT(15), 0);
791static SUNXI_CCU_GATE(bus_gpadc_clk,	"bus-gpadc",	"apb0",
792		      0x590, BIT(17), 0);
793static SUNXI_CCU_GATE(bus_twd_clk,	"bus-twd",	"apb0",
794		      0x590, BIT(18), 0);
795static SUNXI_CCU_GATE(bus_cir_tx_clk,	"bus-cir-tx",	"apb0",
796		      0x590, BIT(19), 0);
797
798/* APB1 bus gates */
799static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb1",
800		      0x594, BIT(0), 0);
801static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb1",
802		      0x594, BIT(1), 0);
803static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb1",
804		      0x594, BIT(2), 0);
805static SUNXI_CCU_GATE(bus_i2c3_clk,	"bus-i2c3",	"apb1",
806		      0x594, BIT(3), 0);
807static SUNXI_CCU_GATE(bus_i2c4_clk,	"bus-i2c4",	"apb1",
808		      0x594, BIT(4), 0);
809static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb1",
810		      0x594, BIT(16), 0);
811static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb1",
812		      0x594, BIT(17), 0);
813static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb1",
814		      0x594, BIT(18), 0);
815static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb1",
816		      0x594, BIT(19), 0);
817static SUNXI_CCU_GATE(bus_uart4_clk,	"bus-uart4",	"apb1",
818		      0x594, BIT(20), 0);
819static SUNXI_CCU_GATE(bus_uart5_clk,	"bus-uart5",	"apb1",
820		      0x594, BIT(21), 0);
821
822static struct ccu_common *sun9i_a80_ccu_clks[] = {
823	&pll_c0cpux_clk.common,
824	&pll_c1cpux_clk.common,
825	&pll_audio_clk.common,
826	&pll_periph0_clk.common,
827	&pll_ve_clk.common,
828	&pll_ddr_clk.common,
829	&pll_video0_clk.common,
830	&pll_video1_clk.common,
831	&pll_gpu_clk.common,
832	&pll_de_clk.common,
833	&pll_isp_clk.common,
834	&pll_periph1_clk.common,
835	&c0cpux_clk.common,
836	&c1cpux_clk.common,
837	&atb0_clk.common,
838	&axi0_clk.common,
839	&atb1_clk.common,
840	&axi1_clk.common,
841	&gtbus_clk.common,
842	&ahb0_clk.common,
843	&ahb1_clk.common,
844	&ahb2_clk.common,
845	&apb0_clk.common,
846	&apb1_clk.common,
847	&cci400_clk.common,
848	&ats_clk.common,
849	&trace_clk.common,
850
851	&out_a_clk.common,
852	&out_b_clk.common,
853
854	/* module clocks */
855	&nand0_0_clk.common,
856	&nand0_1_clk.common,
857	&nand1_0_clk.common,
858	&nand1_1_clk.common,
859	&mmc0_clk.common,
860	&mmc0_sample_clk.common,
861	&mmc0_output_clk.common,
862	&mmc1_clk.common,
863	&mmc1_sample_clk.common,
864	&mmc1_output_clk.common,
865	&mmc2_clk.common,
866	&mmc2_sample_clk.common,
867	&mmc2_output_clk.common,
868	&mmc3_clk.common,
869	&mmc3_sample_clk.common,
870	&mmc3_output_clk.common,
871	&ts_clk.common,
872	&ss_clk.common,
873	&spi0_clk.common,
874	&spi1_clk.common,
875	&spi2_clk.common,
876	&spi3_clk.common,
877	&i2s0_clk.common,
878	&i2s1_clk.common,
879	&spdif_clk.common,
880	&sdram_clk.common,
881	&de_clk.common,
882	&edp_clk.common,
883	&mp_clk.common,
884	&lcd0_clk.common,
885	&lcd1_clk.common,
886	&mipi_dsi0_clk.common,
887	&mipi_dsi1_clk.common,
888	&hdmi_clk.common,
889	&hdmi_slow_clk.common,
890	&mipi_csi_clk.common,
891	&csi_isp_clk.common,
892	&csi_misc_clk.common,
893	&csi0_mclk_clk.common,
894	&csi1_mclk_clk.common,
895	&fd_clk.common,
896	&ve_clk.common,
897	&avs_clk.common,
898	&gpu_core_clk.common,
899	&gpu_memory_clk.common,
900	&gpu_axi_clk.common,
901	&sata_clk.common,
902	&ac97_clk.common,
903	&mipi_hsi_clk.common,
904	&gpadc_clk.common,
905	&cir_tx_clk.common,
906
907	/* AHB0 bus gates */
908	&bus_fd_clk.common,
909	&bus_ve_clk.common,
910	&bus_gpu_ctrl_clk.common,
911	&bus_ss_clk.common,
912	&bus_mmc_clk.common,
913	&bus_nand0_clk.common,
914	&bus_nand1_clk.common,
915	&bus_sdram_clk.common,
916	&bus_mipi_hsi_clk.common,
917	&bus_sata_clk.common,
918	&bus_ts_clk.common,
919	&bus_spi0_clk.common,
920	&bus_spi1_clk.common,
921	&bus_spi2_clk.common,
922	&bus_spi3_clk.common,
923
924	/* AHB1 bus gates */
925	&bus_otg_clk.common,
926	&bus_usb_clk.common,
927	&bus_gmac_clk.common,
928	&bus_msgbox_clk.common,
929	&bus_spinlock_clk.common,
930	&bus_hstimer_clk.common,
931	&bus_dma_clk.common,
932
933	/* AHB2 bus gates */
934	&bus_lcd0_clk.common,
935	&bus_lcd1_clk.common,
936	&bus_edp_clk.common,
937	&bus_csi_clk.common,
938	&bus_hdmi_clk.common,
939	&bus_de_clk.common,
940	&bus_mp_clk.common,
941	&bus_mipi_dsi_clk.common,
942
943	/* APB0 bus gates */
944	&bus_spdif_clk.common,
945	&bus_pio_clk.common,
946	&bus_ac97_clk.common,
947	&bus_i2s0_clk.common,
948	&bus_i2s1_clk.common,
949	&bus_lradc_clk.common,
950	&bus_gpadc_clk.common,
951	&bus_twd_clk.common,
952	&bus_cir_tx_clk.common,
953
954	/* APB1 bus gates */
955	&bus_i2c0_clk.common,
956	&bus_i2c1_clk.common,
957	&bus_i2c2_clk.common,
958	&bus_i2c3_clk.common,
959	&bus_i2c4_clk.common,
960	&bus_uart0_clk.common,
961	&bus_uart1_clk.common,
962	&bus_uart2_clk.common,
963	&bus_uart3_clk.common,
964	&bus_uart4_clk.common,
965	&bus_uart5_clk.common,
966};
967
968static struct clk_hw_onecell_data sun9i_a80_hw_clks = {
969	.hws	= {
970		[CLK_PLL_C0CPUX]	= &pll_c0cpux_clk.common.hw,
971		[CLK_PLL_C1CPUX]	= &pll_c1cpux_clk.common.hw,
972		[CLK_PLL_AUDIO]		= &pll_audio_clk.common.hw,
973		[CLK_PLL_PERIPH0]	= &pll_periph0_clk.common.hw,
974		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
975		[CLK_PLL_DDR]		= &pll_ddr_clk.common.hw,
976		[CLK_PLL_VIDEO0]	= &pll_video0_clk.common.hw,
977		[CLK_PLL_VIDEO1]	= &pll_video1_clk.common.hw,
978		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
979		[CLK_PLL_DE]		= &pll_de_clk.common.hw,
980		[CLK_PLL_ISP]		= &pll_isp_clk.common.hw,
981		[CLK_PLL_PERIPH1]	= &pll_periph1_clk.common.hw,
982		[CLK_C0CPUX]		= &c0cpux_clk.common.hw,
983		[CLK_C1CPUX]		= &c1cpux_clk.common.hw,
984		[CLK_ATB0]		= &atb0_clk.common.hw,
985		[CLK_AXI0]		= &axi0_clk.common.hw,
986		[CLK_ATB1]		= &atb1_clk.common.hw,
987		[CLK_AXI1]		= &axi1_clk.common.hw,
988		[CLK_GTBUS]		= &gtbus_clk.common.hw,
989		[CLK_AHB0]		= &ahb0_clk.common.hw,
990		[CLK_AHB1]		= &ahb1_clk.common.hw,
991		[CLK_AHB2]		= &ahb2_clk.common.hw,
992		[CLK_APB0]		= &apb0_clk.common.hw,
993		[CLK_APB1]		= &apb1_clk.common.hw,
994		[CLK_CCI400]		= &cci400_clk.common.hw,
995		[CLK_ATS]		= &ats_clk.common.hw,
996		[CLK_TRACE]		= &trace_clk.common.hw,
997
998		[CLK_OUT_A]		= &out_a_clk.common.hw,
999		[CLK_OUT_B]		= &out_b_clk.common.hw,
1000
1001		[CLK_NAND0_0]		= &nand0_0_clk.common.hw,
1002		[CLK_NAND0_1]		= &nand0_1_clk.common.hw,
1003		[CLK_NAND1_0]		= &nand1_0_clk.common.hw,
1004		[CLK_NAND1_1]		= &nand1_1_clk.common.hw,
1005		[CLK_MMC0]		= &mmc0_clk.common.hw,
1006		[CLK_MMC0_SAMPLE]	= &mmc0_sample_clk.common.hw,
1007		[CLK_MMC0_OUTPUT]	= &mmc0_output_clk.common.hw,
1008		[CLK_MMC1]		= &mmc1_clk.common.hw,
1009		[CLK_MMC1_SAMPLE]	= &mmc1_sample_clk.common.hw,
1010		[CLK_MMC1_OUTPUT]	= &mmc1_output_clk.common.hw,
1011		[CLK_MMC2]		= &mmc2_clk.common.hw,
1012		[CLK_MMC2_SAMPLE]	= &mmc2_sample_clk.common.hw,
1013		[CLK_MMC2_OUTPUT]	= &mmc2_output_clk.common.hw,
1014		[CLK_MMC3]		= &mmc3_clk.common.hw,
1015		[CLK_MMC3_SAMPLE]	= &mmc3_sample_clk.common.hw,
1016		[CLK_MMC3_OUTPUT]	= &mmc3_output_clk.common.hw,
1017		[CLK_TS]		= &ts_clk.common.hw,
1018		[CLK_SS]		= &ss_clk.common.hw,
1019		[CLK_SPI0]		= &spi0_clk.common.hw,
1020		[CLK_SPI1]		= &spi1_clk.common.hw,
1021		[CLK_SPI2]		= &spi2_clk.common.hw,
1022		[CLK_SPI3]		= &spi3_clk.common.hw,
1023		[CLK_I2S0]		= &i2s0_clk.common.hw,
1024		[CLK_I2S1]		= &i2s1_clk.common.hw,
1025		[CLK_SPDIF]		= &spdif_clk.common.hw,
1026		[CLK_SDRAM]		= &sdram_clk.common.hw,
1027		[CLK_DE]		= &de_clk.common.hw,
1028		[CLK_EDP]		= &edp_clk.common.hw,
1029		[CLK_MP]		= &mp_clk.common.hw,
1030		[CLK_LCD0]		= &lcd0_clk.common.hw,
1031		[CLK_LCD1]		= &lcd1_clk.common.hw,
1032		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
1033		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
1034		[CLK_HDMI]		= &hdmi_clk.common.hw,
1035		[CLK_HDMI_SLOW]		= &hdmi_slow_clk.common.hw,
1036		[CLK_MIPI_CSI]		= &mipi_csi_clk.common.hw,
1037		[CLK_CSI_ISP]		= &csi_isp_clk.common.hw,
1038		[CLK_CSI_MISC]		= &csi_misc_clk.common.hw,
1039		[CLK_CSI0_MCLK]		= &csi0_mclk_clk.common.hw,
1040		[CLK_CSI1_MCLK]		= &csi1_mclk_clk.common.hw,
1041		[CLK_FD]		= &fd_clk.common.hw,
1042		[CLK_VE]		= &ve_clk.common.hw,
1043		[CLK_AVS]		= &avs_clk.common.hw,
1044		[CLK_GPU_CORE]		= &gpu_core_clk.common.hw,
1045		[CLK_GPU_MEMORY]	= &gpu_memory_clk.common.hw,
1046		[CLK_GPU_AXI]		= &gpu_axi_clk.common.hw,
1047		[CLK_SATA]		= &sata_clk.common.hw,
1048		[CLK_AC97]		= &ac97_clk.common.hw,
1049		[CLK_MIPI_HSI]		= &mipi_hsi_clk.common.hw,
1050		[CLK_GPADC]		= &gpadc_clk.common.hw,
1051		[CLK_CIR_TX]		= &cir_tx_clk.common.hw,
1052
1053		[CLK_BUS_FD]		= &bus_fd_clk.common.hw,
1054		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
1055		[CLK_BUS_GPU_CTRL]	= &bus_gpu_ctrl_clk.common.hw,
1056		[CLK_BUS_SS]		= &bus_ss_clk.common.hw,
1057		[CLK_BUS_MMC]		= &bus_mmc_clk.common.hw,
1058		[CLK_BUS_NAND0]		= &bus_nand0_clk.common.hw,
1059		[CLK_BUS_NAND1]		= &bus_nand1_clk.common.hw,
1060		[CLK_BUS_SDRAM]		= &bus_sdram_clk.common.hw,
1061		[CLK_BUS_MIPI_HSI]	= &bus_mipi_hsi_clk.common.hw,
1062		[CLK_BUS_SATA]		= &bus_sata_clk.common.hw,
1063		[CLK_BUS_TS]		= &bus_ts_clk.common.hw,
1064		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
1065		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
1066		[CLK_BUS_SPI2]		= &bus_spi2_clk.common.hw,
1067		[CLK_BUS_SPI3]		= &bus_spi3_clk.common.hw,
1068
1069		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
1070		[CLK_BUS_USB]		= &bus_usb_clk.common.hw,
1071		[CLK_BUS_GMAC]		= &bus_gmac_clk.common.hw,
1072		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
1073		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
1074		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
1075		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
1076
1077		[CLK_BUS_LCD0]		= &bus_lcd0_clk.common.hw,
1078		[CLK_BUS_LCD1]		= &bus_lcd1_clk.common.hw,
1079		[CLK_BUS_EDP]		= &bus_edp_clk.common.hw,
1080		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
1081		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
1082		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
1083		[CLK_BUS_MP]		= &bus_mp_clk.common.hw,
1084		[CLK_BUS_MIPI_DSI]	= &bus_mipi_dsi_clk.common.hw,
1085
1086		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
1087		[CLK_BUS_PIO]		= &bus_pio_clk.common.hw,
1088		[CLK_BUS_AC97]		= &bus_ac97_clk.common.hw,
1089		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
1090		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
1091		[CLK_BUS_LRADC]		= &bus_lradc_clk.common.hw,
1092		[CLK_BUS_GPADC]		= &bus_gpadc_clk.common.hw,
1093		[CLK_BUS_TWD]		= &bus_twd_clk.common.hw,
1094		[CLK_BUS_CIR_TX]	= &bus_cir_tx_clk.common.hw,
1095
1096		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
1097		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
1098		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
1099		[CLK_BUS_I2C3]		= &bus_i2c3_clk.common.hw,
1100		[CLK_BUS_I2C4]		= &bus_i2c4_clk.common.hw,
1101		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
1102		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
1103		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
1104		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
1105		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
1106		[CLK_BUS_UART5]		= &bus_uart5_clk.common.hw,
1107	},
1108	.num	= CLK_NUMBER,
1109};
1110
1111static struct ccu_reset_map sun9i_a80_ccu_resets[] = {
1112	/* AHB0 reset controls */
1113	[RST_BUS_FD]		= { 0x5a0, BIT(0) },
1114	[RST_BUS_VE]		= { 0x5a0, BIT(1) },
1115	[RST_BUS_GPU_CTRL]	= { 0x5a0, BIT(3) },
1116	[RST_BUS_SS]		= { 0x5a0, BIT(5) },
1117	[RST_BUS_MMC]		= { 0x5a0, BIT(8) },
1118	[RST_BUS_NAND0]		= { 0x5a0, BIT(12) },
1119	[RST_BUS_NAND1]		= { 0x5a0, BIT(13) },
1120	[RST_BUS_SDRAM]		= { 0x5a0, BIT(14) },
1121	[RST_BUS_SATA]		= { 0x5a0, BIT(16) },
1122	[RST_BUS_TS]		= { 0x5a0, BIT(18) },
1123	[RST_BUS_SPI0]		= { 0x5a0, BIT(20) },
1124	[RST_BUS_SPI1]		= { 0x5a0, BIT(21) },
1125	[RST_BUS_SPI2]		= { 0x5a0, BIT(22) },
1126	[RST_BUS_SPI3]		= { 0x5a0, BIT(23) },
1127
1128	/* AHB1 reset controls */
1129	[RST_BUS_OTG]		= { 0x5a4, BIT(0) },
1130	[RST_BUS_OTG_PHY]	= { 0x5a4, BIT(1) },
1131	[RST_BUS_MIPI_HSI]	= { 0x5a4, BIT(9) },
1132	[RST_BUS_GMAC]		= { 0x5a4, BIT(17) },
1133	[RST_BUS_MSGBOX]	= { 0x5a4, BIT(21) },
1134	[RST_BUS_SPINLOCK]	= { 0x5a4, BIT(22) },
1135	[RST_BUS_HSTIMER]	= { 0x5a4, BIT(23) },
1136	[RST_BUS_DMA]		= { 0x5a4, BIT(24) },
1137
1138	/* AHB2 reset controls */
1139	[RST_BUS_LCD0]		= { 0x5a8, BIT(0) },
1140	[RST_BUS_LCD1]		= { 0x5a8, BIT(1) },
1141	[RST_BUS_EDP]		= { 0x5a8, BIT(2) },
1142	[RST_BUS_LVDS]		= { 0x5a8, BIT(3) },
1143	[RST_BUS_CSI]		= { 0x5a8, BIT(4) },
1144	[RST_BUS_HDMI0]		= { 0x5a8, BIT(5) },
1145	[RST_BUS_HDMI1]		= { 0x5a8, BIT(6) },
1146	[RST_BUS_DE]		= { 0x5a8, BIT(7) },
1147	[RST_BUS_MP]		= { 0x5a8, BIT(8) },
1148	[RST_BUS_GPU]		= { 0x5a8, BIT(9) },
1149	[RST_BUS_MIPI_DSI]	= { 0x5a8, BIT(11) },
1150
1151	/* APB0 reset controls */
1152	[RST_BUS_SPDIF]		= { 0x5b0, BIT(1) },
1153	[RST_BUS_AC97]		= { 0x5b0, BIT(11) },
1154	[RST_BUS_I2S0]		= { 0x5b0, BIT(12) },
1155	[RST_BUS_I2S1]		= { 0x5b0, BIT(13) },
1156	[RST_BUS_LRADC]		= { 0x5b0, BIT(15) },
1157	[RST_BUS_GPADC]		= { 0x5b0, BIT(17) },
1158	[RST_BUS_CIR_TX]	= { 0x5b0, BIT(19) },
1159
1160	/* APB1 reset controls */
1161	[RST_BUS_I2C0]		= { 0x5b4, BIT(0) },
1162	[RST_BUS_I2C1]		= { 0x5b4, BIT(1) },
1163	[RST_BUS_I2C2]		= { 0x5b4, BIT(2) },
1164	[RST_BUS_I2C3]		= { 0x5b4, BIT(3) },
1165	[RST_BUS_I2C4]		= { 0x5b4, BIT(4) },
1166	[RST_BUS_UART0]		= { 0x5b4, BIT(16) },
1167	[RST_BUS_UART1]		= { 0x5b4, BIT(17) },
1168	[RST_BUS_UART2]		= { 0x5b4, BIT(18) },
1169	[RST_BUS_UART3]		= { 0x5b4, BIT(19) },
1170	[RST_BUS_UART4]		= { 0x5b4, BIT(20) },
1171	[RST_BUS_UART5]		= { 0x5b4, BIT(21) },
1172};
1173
1174static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
1175	.ccu_clks	= sun9i_a80_ccu_clks,
1176	.num_ccu_clks	= ARRAY_SIZE(sun9i_a80_ccu_clks),
1177
1178	.hw_clks	= &sun9i_a80_hw_clks,
1179
1180	.resets		= sun9i_a80_ccu_resets,
1181	.num_resets	= ARRAY_SIZE(sun9i_a80_ccu_resets),
1182};
1183
1184#define SUN9I_A80_PLL_P_SHIFT	16
1185#define SUN9I_A80_PLL_N_SHIFT	8
1186#define SUN9I_A80_PLL_N_WIDTH	8
1187
1188static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
1189{
1190	u32 val = readl(reg);
1191
1192	/* bail out if P divider is not used */
1193	if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
1194		return;
1195
1196	/*
1197	 * If P is used, output should be less than 288 MHz. When we
1198	 * set P to 1, we should also decrease the multiplier so the
1199	 * output doesn't go out of range, but not too much such that
1200	 * the multiplier stays above 12, the minimal operation value.
1201	 *
1202	 * To keep it simple, set the multiplier to 17, the reset value.
1203	 */
1204	val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
1205			SUN9I_A80_PLL_N_SHIFT);
1206	val |= 17 << SUN9I_A80_PLL_N_SHIFT;
1207
1208	/* And clear P */
1209	val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
1210
1211	writel(val, reg);
1212}
1213
1214static int sun9i_a80_ccu_probe(struct platform_device *pdev)
1215{
1216	struct resource *res;
1217	void __iomem *reg;
1218	u32 val;
1219
1220	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1221	reg = devm_ioremap_resource(&pdev->dev, res);
1222	if (IS_ERR(reg))
1223		return PTR_ERR(reg);
1224
1225	/* Enforce d1 = 0, d2 = 0 for Audio PLL */
1226	val = readl(reg + SUN9I_A80_PLL_AUDIO_REG);
1227	val &= ~(BIT(16) | BIT(18));
1228	writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
1229
1230	/* Enforce P = 1 for both CPU cluster PLLs */
1231	sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
1232	sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
1233
1234	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc);
1235}
1236
1237static const struct of_device_id sun9i_a80_ccu_ids[] = {
1238	{ .compatible = "allwinner,sun9i-a80-ccu" },
1239	{ }
1240};
1241
1242static struct platform_driver sun9i_a80_ccu_driver = {
1243	.probe	= sun9i_a80_ccu_probe,
1244	.driver	= {
1245		.name	= "sun9i-a80-ccu",
1246		.of_match_table	= sun9i_a80_ccu_ids,
1247	},
1248};
1249builtin_platform_driver(sun9i_a80_ccu_driver);
1250