Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved.
  4 */
  5
  6#include <linux/clk-provider.h>
  7#include <linux/io.h>
  8#include <linux/module.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_mux.h"
 18#include "ccu_nkmp.h"
 19#include "ccu_nm.h"
 20#include "ccu_phase.h"
 21
 22#include "ccu-sun8i-a83t.h"
 23
 24#define CCU_SUN8I_A83T_LOCK_REG	0x20c
 25
 26/*
 27 * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
 28 * P should only be used for output frequencies lower than 228 MHz.
 29 * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
 30 *
 31 * For now we can just model it as a multiplier clock, and force P to /1.
 32 */
 33#define SUN8I_A83T_PLL_C0CPUX_REG	0x000
 34#define SUN8I_A83T_PLL_C1CPUX_REG	0x004
 35
 36static struct ccu_mult pll_c0cpux_clk = {
 37	.enable		= BIT(31),
 38	.lock		= BIT(0),
 39	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 40	.common		= {
 41		.reg		= SUN8I_A83T_PLL_C0CPUX_REG,
 42		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
 43		.features	= CCU_FEATURE_LOCK_REG,
 44		.hw.init	= CLK_HW_INIT("pll-c0cpux", "osc24M",
 45					      &ccu_mult_ops,
 46					      CLK_SET_RATE_UNGATE),
 47	},
 48};
 49
 50static struct ccu_mult pll_c1cpux_clk = {
 51	.enable		= BIT(31),
 52	.lock		= BIT(1),
 53	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 54	.common		= {
 55		.reg		= SUN8I_A83T_PLL_C1CPUX_REG,
 56		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
 57		.features	= CCU_FEATURE_LOCK_REG,
 58		.hw.init	= CLK_HW_INIT("pll-c1cpux", "osc24M",
 59					      &ccu_mult_ops,
 60					      CLK_SET_RATE_UNGATE),
 61	},
 62};
 63
 64/*
 65 * The Audio PLL has d1, d2 dividers in addition to the usual N, M
 66 * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
 67 * and 24.576 MHz, ignore them for now. Enforce the default for them,
 68 * which is d1 = 0, d2 = 1.
 69 */
 70#define SUN8I_A83T_PLL_AUDIO_REG	0x008
 71
 72/* clock rates doubled for post divider */
 73static struct ccu_sdm_setting pll_audio_sdm_table[] = {
 74	{ .rate = 45158400, .pattern = 0xc00121ff, .m = 29, .n = 54 },
 75	{ .rate = 49152000, .pattern = 0xc000e147, .m = 30, .n = 61 },
 76};
 77
 78static struct ccu_nm pll_audio_clk = {
 79	.enable		= BIT(31),
 80	.lock		= BIT(2),
 81	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 82	.m		= _SUNXI_CCU_DIV(0, 6),
 83	.fixed_post_div	= 2,
 84	.sdm		= _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24),
 85					 0x284, BIT(31)),
 86	.common		= {
 87		.reg		= SUN8I_A83T_PLL_AUDIO_REG,
 88		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
 89		.features	= CCU_FEATURE_LOCK_REG |
 90				  CCU_FEATURE_FIXED_POSTDIV |
 91				  CCU_FEATURE_SIGMA_DELTA_MOD,
 92		.hw.init	= CLK_HW_INIT("pll-audio", "osc24M",
 93					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
 94	},
 95};
 96
 97/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
 98static struct ccu_nkmp pll_video0_clk = {
 99	.enable		= BIT(31),
100	.lock		= BIT(3),
101	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
102	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
103	.p		= _SUNXI_CCU_DIV(0, 2), /* output divider */
104	.max_rate	= 3000000000UL,
105	.common		= {
106		.reg		= 0x010,
107		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
108		.features	= CCU_FEATURE_LOCK_REG,
109		.hw.init	= CLK_HW_INIT("pll-video0", "osc24M",
110					      &ccu_nkmp_ops,
111					      CLK_SET_RATE_UNGATE),
112	},
113};
114
115static struct ccu_nkmp pll_ve_clk = {
116	.enable		= BIT(31),
117	.lock		= BIT(4),
118	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
119	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
120	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
121	.common		= {
122		.reg		= 0x018,
123		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
124		.features	= CCU_FEATURE_LOCK_REG,
125		.hw.init	= CLK_HW_INIT("pll-ve", "osc24M",
126					      &ccu_nkmp_ops,
127					      CLK_SET_RATE_UNGATE),
128	},
129};
130
131static struct ccu_nkmp pll_ddr_clk = {
132	.enable		= BIT(31),
133	.lock		= BIT(5),
134	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
135	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
136	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
137	.common		= {
138		.reg		= 0x020,
139		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
140		.features	= CCU_FEATURE_LOCK_REG,
141		.hw.init	= CLK_HW_INIT("pll-ddr", "osc24M",
142					      &ccu_nkmp_ops,
143					      CLK_SET_RATE_UNGATE),
144	},
145};
146
147static struct ccu_nkmp pll_periph_clk = {
148	.enable		= BIT(31),
149	.lock		= BIT(6),
150	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
151	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
152	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
153	.common		= {
154		.reg		= 0x028,
155		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
156		.features	= CCU_FEATURE_LOCK_REG,
157		.hw.init	= CLK_HW_INIT("pll-periph", "osc24M",
158					      &ccu_nkmp_ops,
159					      CLK_SET_RATE_UNGATE),
160	},
161};
162
163static struct ccu_nkmp pll_gpu_clk = {
164	.enable		= BIT(31),
165	.lock		= BIT(7),
166	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
167	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
168	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
169	.common		= {
170		.reg		= 0x038,
171		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
172		.features	= CCU_FEATURE_LOCK_REG,
173		.hw.init	= CLK_HW_INIT("pll-gpu", "osc24M",
174					      &ccu_nkmp_ops,
175					      CLK_SET_RATE_UNGATE),
176	},
177};
178
179static struct ccu_nkmp pll_hsic_clk = {
180	.enable		= BIT(31),
181	.lock		= BIT(8),
182	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
183	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
184	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
185	.common		= {
186		.reg		= 0x044,
187		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
188		.features	= CCU_FEATURE_LOCK_REG,
189		.hw.init	= CLK_HW_INIT("pll-hsic", "osc24M",
190					      &ccu_nkmp_ops,
191					      CLK_SET_RATE_UNGATE),
192	},
193};
194
195static struct ccu_nkmp pll_de_clk = {
196	.enable		= BIT(31),
197	.lock		= BIT(9),
198	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
199	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
200	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
201	.common		= {
202		.reg		= 0x048,
203		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
204		.features	= CCU_FEATURE_LOCK_REG,
205		.hw.init	= CLK_HW_INIT("pll-de", "osc24M",
206					      &ccu_nkmp_ops,
207					      CLK_SET_RATE_UNGATE),
208	},
209};
210
211static struct ccu_nkmp pll_video1_clk = {
212	.enable		= BIT(31),
213	.lock		= BIT(10),
214	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
215	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
216	.p		= _SUNXI_CCU_DIV(0, 2), /* external divider p */
217	.max_rate	= 3000000000UL,
218	.common		= {
219		.reg		= 0x04c,
220		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
221		.features	= CCU_FEATURE_LOCK_REG,
222		.hw.init	= CLK_HW_INIT("pll-video1", "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, 12, 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, 28, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
235
236static SUNXI_CCU_M(axi0_clk, "axi0", "c0cpux", 0x050, 0, 2, 0);
237static SUNXI_CCU_M(axi1_clk, "axi1", "c1cpux", 0x050, 16, 2, 0);
238
239static const char * const ahb1_parents[] = { "osc16M-d512", "osc24M",
240					     "pll-periph",
241					     "pll-periph" };
242static const struct ccu_mux_var_prediv ahb1_predivs[] = {
243	{ .index = 2, .shift = 6, .width = 2 },
244	{ .index = 3, .shift = 6, .width = 2 },
245};
246static struct ccu_div ahb1_clk = {
247	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
248	.mux		= {
249		.shift	= 12,
250		.width	= 2,
251
252		.var_predivs	= ahb1_predivs,
253		.n_var_predivs	= ARRAY_SIZE(ahb1_predivs),
254	},
255	.common		= {
256		.reg		= 0x054,
257		.hw.init	= CLK_HW_INIT_PARENTS("ahb1",
258						      ahb1_parents,
259						      &ccu_div_ops,
260						      0),
261	},
262};
263
264static SUNXI_CCU_M(apb1_clk, "apb1", "ahb1", 0x054, 8, 2, 0);
265
266static const char * const apb2_parents[] = { "osc16M-d512", "osc24M",
267					     "pll-periph", "pll-periph" };
268
269static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
270			     0, 5,	/* M */
271			     16, 2,	/* P */
272			     24, 2,	/* mux */
273			     0);
274
275static const char * const ahb2_parents[] = { "ahb1", "pll-periph" };
276static const struct ccu_mux_fixed_prediv ahb2_prediv = {
277	.index = 1, .div = 2
278};
279static struct ccu_mux ahb2_clk = {
280	.mux		= {
281		.shift		= 0,
282		.width		= 2,
283		.fixed_predivs	= &ahb2_prediv,
284		.n_predivs	= 1,
285	},
286	.common		= {
287		.reg		= 0x05c,
288		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
289						      ahb2_parents,
290						      &ccu_mux_ops,
291						      0),
292	},
293};
294
295static SUNXI_CCU_GATE(bus_mipi_dsi_clk,	"bus-mipi-dsi",	"ahb1",
296		      0x060, BIT(1), 0);
297static SUNXI_CCU_GATE(bus_ss_clk,	"bus-ss",	"ahb1",
298		      0x060, BIT(5), 0);
299static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
300		      0x060, BIT(6), 0);
301static SUNXI_CCU_GATE(bus_mmc0_clk,	"bus-mmc0",	"ahb1",
302		      0x060, BIT(8), 0);
303static SUNXI_CCU_GATE(bus_mmc1_clk,	"bus-mmc1",	"ahb1",
304		      0x060, BIT(9), 0);
305static SUNXI_CCU_GATE(bus_mmc2_clk,	"bus-mmc2",	"ahb1",
306		      0x060, BIT(10), 0);
307static SUNXI_CCU_GATE(bus_nand_clk,	"bus-nand",	"ahb1",
308		      0x060, BIT(13), 0);
309static SUNXI_CCU_GATE(bus_dram_clk,	"bus-dram",	"ahb1",
310		      0x060, BIT(14), 0);
311static SUNXI_CCU_GATE(bus_emac_clk,	"bus-emac",	"ahb2",
312		      0x060, BIT(17), 0);
313static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
314		      0x060, BIT(19), 0);
315static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb1",
316		      0x060, BIT(20), 0);
317static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb1",
318		      0x060, BIT(21), 0);
319static SUNXI_CCU_GATE(bus_otg_clk,	"bus-otg",	"ahb1",
320		      0x060, BIT(24), 0);
321static SUNXI_CCU_GATE(bus_ehci0_clk,	"bus-ehci0",	"ahb2",
322		      0x060, BIT(26), 0);
323static SUNXI_CCU_GATE(bus_ehci1_clk,	"bus-ehci1",	"ahb2",
324		      0x060, BIT(27), 0);
325static SUNXI_CCU_GATE(bus_ohci0_clk,	"bus-ohci0",	"ahb2",
326		      0x060, BIT(29), 0);
327
328static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb1",
329		      0x064, BIT(0), 0);
330static SUNXI_CCU_GATE(bus_tcon0_clk,	"bus-tcon0",	"ahb1",
331		      0x064, BIT(4), 0);
332static SUNXI_CCU_GATE(bus_tcon1_clk,	"bus-tcon1",	"ahb1",
333		      0x064, BIT(5), 0);
334static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb1",
335		      0x064, BIT(8), 0);
336static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb1",
337		      0x064, BIT(11), 0);
338static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb1",
339		      0x064, BIT(12), 0);
340static SUNXI_CCU_GATE(bus_gpu_clk,	"bus-gpu",	"ahb1",
341		      0x064, BIT(20), 0);
342static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
343		      0x064, BIT(21), 0);
344static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
345		      0x064, BIT(22), 0);
346
347static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb1",
348		      0x068, BIT(1), 0);
349static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb1",
350		      0x068, BIT(5), 0);
351static SUNXI_CCU_GATE(bus_i2s0_clk,	"bus-i2s0",	"apb1",
352		      0x068, BIT(12), 0);
353static SUNXI_CCU_GATE(bus_i2s1_clk,	"bus-i2s1",	"apb1",
354		      0x068, BIT(13), 0);
355static SUNXI_CCU_GATE(bus_i2s2_clk,	"bus-i2s2",	"apb1",
356		      0x068, BIT(14), 0);
357static SUNXI_CCU_GATE(bus_tdm_clk,	"bus-tdm",	"apb1",
358		      0x068, BIT(15), 0);
359
360static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb2",
361		      0x06c, BIT(0), 0);
362static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb2",
363		      0x06c, BIT(1), 0);
364static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb2",
365		      0x06c, BIT(2), 0);
366static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb2",
367		      0x06c, BIT(16), 0);
368static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb2",
369		      0x06c, BIT(17), 0);
370static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb2",
371		      0x06c, BIT(18), 0);
372static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb2",
373		      0x06c, BIT(19), 0);
374static SUNXI_CCU_GATE(bus_uart4_clk,	"bus-uart4",	"apb2",
375		      0x06c, BIT(20), 0);
376
377static const char * const cci400_parents[] = { "osc24M", "pll-periph",
378					       "pll-hsic" };
379static struct ccu_div cci400_clk = {
380	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, 0),
381	.mux		= _SUNXI_CCU_MUX(24, 2),
382	.common		= {
383		.reg		= 0x078,
384		.hw.init	= CLK_HW_INIT_PARENTS("cci400",
385						      cci400_parents,
386						      &ccu_div_ops,
387						      CLK_IS_CRITICAL),
388	},
389};
390
391static const char * const mod0_default_parents[] = { "osc24M", "pll-periph" };
392
393static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents,
394				  0x080,
395				  0, 4,		/* M */
396				  16, 2,	/* P */
397				  24, 2,	/* mux */
398				  BIT(31),	/* gate */
399				  0);
400
401static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,
402				  0x088,
403				  0, 4,		/* M */
404				  16, 2,	/* P */
405				  24, 2,	/* mux */
406				  BIT(31),	/* gate */
407				  0);
408
409static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",
410		       0x088, 20, 3, 0);
411static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",
412		       0x088, 8, 3, 0);
413
414static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,
415				  0x08c,
416				  0, 4,		/* M */
417				  16, 2,	/* P */
418				  24, 2,	/* mux */
419				  BIT(31),	/* gate */
420				  0);
421
422static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",
423		       0x08c, 20, 3, 0);
424static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",
425		       0x08c, 8, 3, 0);
426
427static SUNXI_CCU_MP_MMC_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,
428				      0x090, 0);
429
430static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",
431		       0x090, 20, 3, 0);
432static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",
433		       0x090, 8, 3, 0);
434
435static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents,
436				  0x09c,
437				  0, 4,		/* M */
438				  16, 2,	/* P */
439				  24, 2,	/* mux */
440				  BIT(31),	/* gate */
441				  0);
442
443static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,
444				  0x0a0,
445				  0, 4,		/* M */
446				  16, 2,	/* P */
447				  24, 4,	/* mux */
448				  BIT(31),	/* gate */
449				  0);
450
451static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,
452				  0x0a4,
453				  0, 4,		/* M */
454				  16, 2,	/* P */
455				  24, 4,	/* mux */
456				  BIT(31),	/* gate */
457				  0);
458
459static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",
460			     0x0b0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
461static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",
462			     0x0b4, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
463static SUNXI_CCU_M_WITH_GATE(i2s2_clk, "i2s2", "pll-audio",
464			     0x0b8, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
465static SUNXI_CCU_M_WITH_GATE(tdm_clk, "tdm", "pll-audio",
466			     0x0bc, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
467static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
468			     0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
469
470static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
471		      0x0cc, BIT(8), 0);
472static SUNXI_CCU_GATE(usb_phy1_clk,	"usb-phy1",	"osc24M",
473		      0x0cc, BIT(9), 0);
474static SUNXI_CCU_GATE(usb_hsic_clk,	"usb-hsic",	"pll-hsic",
475		      0x0cc, BIT(10), 0);
476static struct ccu_gate usb_hsic_12m_clk = {
477	.enable	= BIT(11),
478	.common	= {
479		.reg		= 0x0cc,
480		.prediv		= 2,
481		.features	= CCU_FEATURE_ALL_PREDIV,
482		.hw.init	= CLK_HW_INIT("usb-hsic-12m", "osc24M",
483					      &ccu_gate_ops, 0),
484	}
485};
486static SUNXI_CCU_GATE(usb_ohci0_clk,	"usb-ohci0",	"osc24M",
487		      0x0cc, BIT(16), 0);
488
489/* TODO divider has minimum of 2 */
490static SUNXI_CCU_M(dram_clk, "dram", "pll-ddr", 0x0f4, 0, 4, CLK_IS_CRITICAL);
491
492static SUNXI_CCU_GATE(dram_ve_clk,	"dram-ve",	"dram",
493		      0x100, BIT(0), 0);
494static SUNXI_CCU_GATE(dram_csi_clk,	"dram-csi",	"dram",
495		      0x100, BIT(1), 0);
496
497static const char * const tcon0_parents[] = { "pll-video0" };
498static SUNXI_CCU_MUX_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
499				 0x118, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
500
501static const char * const tcon1_parents[] = { "pll-video1" };
502static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_clk, "tcon1", tcon1_parents,
503				 0x11c, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
504
505static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x130, BIT(16), 0);
506
507static SUNXI_CCU_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x130, BIT(31), 0);
508
509static const char * const csi_mclk_parents[] = { "pll-video0", "pll-de",
510						 "osc24M" };
511static const u8 csi_mclk_table[] = { 0, 3, 5 };
512static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk",
513				       csi_mclk_parents, csi_mclk_table,
514				       0x134,
515				       0, 5,	/* M */
516				       8, 3,	/* mux */
517				       BIT(15),	/* gate */
518				       0);
519
520static const char * const csi_sclk_parents[] = { "pll-periph", "pll-ve" };
521static const u8 csi_sclk_table[] = { 0, 5 };
522static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_sclk_clk, "csi-sclk",
523				       csi_sclk_parents, csi_sclk_table,
524				       0x134,
525				       16, 4,	/* M */
526				       24, 3,	/* mux */
527				       BIT(31),	/* gate */
528				       0);
529
530static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c,
531			     16, 3, BIT(31), CLK_SET_RATE_PARENT);
532
533static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x144, BIT(31), 0);
534
535static const char * const hdmi_parents[] = { "pll-video1" };
536static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
537				 0x150,
538				 0, 4,	/* M */
539				 24, 2,	/* mux */
540				 BIT(31),	/* gate */
541				 CLK_SET_RATE_PARENT);
542
543static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x154, BIT(31), 0);
544
545static const char * const mbus_parents[] = { "osc24M", "pll-periph",
546					     "pll-ddr" };
547static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
548				 0x15c,
549				 0, 3,	/* M */
550				 24, 2,	/* mux */
551				 BIT(31),	/* gate */
552				 CLK_IS_CRITICAL);
553
554static const char * const mipi_dsi0_parents[] = { "pll-video0" };
555static const u8 mipi_dsi0_table[] = { 8 };
556static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",
557				       mipi_dsi0_parents, mipi_dsi0_table,
558				       0x168,
559				       0, 4,	/* M */
560				       24, 4,	/* mux */
561				       BIT(31),	/* gate */
562				       CLK_SET_RATE_PARENT);
563
564static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video0" };
565static const u8 mipi_dsi1_table[] = { 0, 9 };
566static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",
567				       mipi_dsi1_parents, mipi_dsi1_table,
568				       0x16c,
569				       0, 4,	/* M */
570				       24, 4,	/* mux */
571				       BIT(31),	/* gate */
572				       CLK_SET_RATE_PARENT);
573
574static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x1a0,
575			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
576
577static const char * const gpu_memory_parents[] = { "pll-gpu", "pll-ddr" };
578static SUNXI_CCU_M_WITH_MUX_GATE(gpu_memory_clk, "gpu-memory",
579				 gpu_memory_parents,
580				 0x1a4,
581				 0, 3,		/* M */
582				 24, 1,		/* mux */
583				 BIT(31),	/* gate */
584				 CLK_SET_RATE_PARENT);
585
586static SUNXI_CCU_M_WITH_GATE(gpu_hyd_clk, "gpu-hyd", "pll-gpu", 0x1a8,
587			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
588
589static struct ccu_common *sun8i_a83t_ccu_clks[] = {
590	&pll_c0cpux_clk.common,
591	&pll_c1cpux_clk.common,
592	&pll_audio_clk.common,
593	&pll_video0_clk.common,
594	&pll_ve_clk.common,
595	&pll_ddr_clk.common,
596	&pll_periph_clk.common,
597	&pll_gpu_clk.common,
598	&pll_hsic_clk.common,
599	&pll_de_clk.common,
600	&pll_video1_clk.common,
601	&c0cpux_clk.common,
602	&c1cpux_clk.common,
603	&axi0_clk.common,
604	&axi1_clk.common,
605	&ahb1_clk.common,
606	&ahb2_clk.common,
607	&apb1_clk.common,
608	&apb2_clk.common,
609	&bus_mipi_dsi_clk.common,
610	&bus_ss_clk.common,
611	&bus_dma_clk.common,
612	&bus_mmc0_clk.common,
613	&bus_mmc1_clk.common,
614	&bus_mmc2_clk.common,
615	&bus_nand_clk.common,
616	&bus_dram_clk.common,
617	&bus_emac_clk.common,
618	&bus_hstimer_clk.common,
619	&bus_spi0_clk.common,
620	&bus_spi1_clk.common,
621	&bus_otg_clk.common,
622	&bus_ehci0_clk.common,
623	&bus_ehci1_clk.common,
624	&bus_ohci0_clk.common,
625	&bus_ve_clk.common,
626	&bus_tcon0_clk.common,
627	&bus_tcon1_clk.common,
628	&bus_csi_clk.common,
629	&bus_hdmi_clk.common,
630	&bus_de_clk.common,
631	&bus_gpu_clk.common,
632	&bus_msgbox_clk.common,
633	&bus_spinlock_clk.common,
634	&bus_spdif_clk.common,
635	&bus_pio_clk.common,
636	&bus_i2s0_clk.common,
637	&bus_i2s1_clk.common,
638	&bus_i2s2_clk.common,
639	&bus_tdm_clk.common,
640	&bus_i2c0_clk.common,
641	&bus_i2c1_clk.common,
642	&bus_i2c2_clk.common,
643	&bus_uart0_clk.common,
644	&bus_uart1_clk.common,
645	&bus_uart2_clk.common,
646	&bus_uart3_clk.common,
647	&bus_uart4_clk.common,
648	&cci400_clk.common,
649	&nand_clk.common,
650	&mmc0_clk.common,
651	&mmc0_sample_clk.common,
652	&mmc0_output_clk.common,
653	&mmc1_clk.common,
654	&mmc1_sample_clk.common,
655	&mmc1_output_clk.common,
656	&mmc2_clk.common,
657	&mmc2_sample_clk.common,
658	&mmc2_output_clk.common,
659	&ss_clk.common,
660	&spi0_clk.common,
661	&spi1_clk.common,
662	&i2s0_clk.common,
663	&i2s1_clk.common,
664	&i2s2_clk.common,
665	&tdm_clk.common,
666	&spdif_clk.common,
667	&usb_phy0_clk.common,
668	&usb_phy1_clk.common,
669	&usb_hsic_clk.common,
670	&usb_hsic_12m_clk.common,
671	&usb_ohci0_clk.common,
672	&dram_clk.common,
673	&dram_ve_clk.common,
674	&dram_csi_clk.common,
675	&tcon0_clk.common,
676	&tcon1_clk.common,
677	&csi_misc_clk.common,
678	&mipi_csi_clk.common,
679	&csi_mclk_clk.common,
680	&csi_sclk_clk.common,
681	&ve_clk.common,
682	&avs_clk.common,
683	&hdmi_clk.common,
684	&hdmi_slow_clk.common,
685	&mbus_clk.common,
686	&mipi_dsi0_clk.common,
687	&mipi_dsi1_clk.common,
688	&gpu_core_clk.common,
689	&gpu_memory_clk.common,
690	&gpu_hyd_clk.common,
691};
692
693static struct clk_hw_onecell_data sun8i_a83t_hw_clks = {
694	.hws	= {
695		[CLK_PLL_C0CPUX]	= &pll_c0cpux_clk.common.hw,
696		[CLK_PLL_C1CPUX]	= &pll_c1cpux_clk.common.hw,
697		[CLK_PLL_AUDIO]		= &pll_audio_clk.common.hw,
698		[CLK_PLL_VIDEO0]	= &pll_video0_clk.common.hw,
699		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
700		[CLK_PLL_DDR]		= &pll_ddr_clk.common.hw,
701		[CLK_PLL_PERIPH]	= &pll_periph_clk.common.hw,
702		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
703		[CLK_PLL_HSIC]		= &pll_hsic_clk.common.hw,
704		[CLK_PLL_DE]		= &pll_de_clk.common.hw,
705		[CLK_PLL_VIDEO1]	= &pll_video1_clk.common.hw,
706		[CLK_C0CPUX]		= &c0cpux_clk.common.hw,
707		[CLK_C1CPUX]		= &c1cpux_clk.common.hw,
708		[CLK_AXI0]		= &axi0_clk.common.hw,
709		[CLK_AXI1]		= &axi1_clk.common.hw,
710		[CLK_AHB1]		= &ahb1_clk.common.hw,
711		[CLK_AHB2]		= &ahb2_clk.common.hw,
712		[CLK_APB1]		= &apb1_clk.common.hw,
713		[CLK_APB2]		= &apb2_clk.common.hw,
714		[CLK_BUS_MIPI_DSI]	= &bus_mipi_dsi_clk.common.hw,
715		[CLK_BUS_SS]		= &bus_ss_clk.common.hw,
716		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
717		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
718		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
719		[CLK_BUS_MMC2]		= &bus_mmc2_clk.common.hw,
720		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
721		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
722		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
723		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
724		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
725		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
726		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
727		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
728		[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common.hw,
729		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
730		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
731		[CLK_BUS_TCON0]		= &bus_tcon0_clk.common.hw,
732		[CLK_BUS_TCON1]		= &bus_tcon1_clk.common.hw,
733		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
734		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
735		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
736		[CLK_BUS_GPU]		= &bus_gpu_clk.common.hw,
737		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
738		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
739		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
740		[CLK_BUS_PIO]		= &bus_pio_clk.common.hw,
741		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
742		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
743		[CLK_BUS_I2S2]		= &bus_i2s2_clk.common.hw,
744		[CLK_BUS_TDM]		= &bus_tdm_clk.common.hw,
745		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
746		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
747		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
748		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
749		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
750		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
751		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
752		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
753		[CLK_CCI400]		= &cci400_clk.common.hw,
754		[CLK_NAND]		= &nand_clk.common.hw,
755		[CLK_MMC0]		= &mmc0_clk.common.hw,
756		[CLK_MMC0_SAMPLE]	= &mmc0_sample_clk.common.hw,
757		[CLK_MMC0_OUTPUT]	= &mmc0_output_clk.common.hw,
758		[CLK_MMC1]		= &mmc1_clk.common.hw,
759		[CLK_MMC1_SAMPLE]	= &mmc1_sample_clk.common.hw,
760		[CLK_MMC1_OUTPUT]	= &mmc1_output_clk.common.hw,
761		[CLK_MMC2]		= &mmc2_clk.common.hw,
762		[CLK_MMC2_SAMPLE]	= &mmc2_sample_clk.common.hw,
763		[CLK_MMC2_OUTPUT]	= &mmc2_output_clk.common.hw,
764		[CLK_SS]		= &ss_clk.common.hw,
765		[CLK_SPI0]		= &spi0_clk.common.hw,
766		[CLK_SPI1]		= &spi1_clk.common.hw,
767		[CLK_I2S0]		= &i2s0_clk.common.hw,
768		[CLK_I2S1]		= &i2s1_clk.common.hw,
769		[CLK_I2S2]		= &i2s2_clk.common.hw,
770		[CLK_TDM]		= &tdm_clk.common.hw,
771		[CLK_SPDIF]		= &spdif_clk.common.hw,
772		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
773		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
774		[CLK_USB_HSIC]		= &usb_hsic_clk.common.hw,
775		[CLK_USB_HSIC_12M]	= &usb_hsic_12m_clk.common.hw,
776		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
777		[CLK_DRAM]		= &dram_clk.common.hw,
778		[CLK_DRAM_VE]		= &dram_ve_clk.common.hw,
779		[CLK_DRAM_CSI]		= &dram_csi_clk.common.hw,
780		[CLK_TCON0]		= &tcon0_clk.common.hw,
781		[CLK_TCON1]		= &tcon1_clk.common.hw,
782		[CLK_CSI_MISC]		= &csi_misc_clk.common.hw,
783		[CLK_MIPI_CSI]		= &mipi_csi_clk.common.hw,
784		[CLK_CSI_MCLK]		= &csi_mclk_clk.common.hw,
785		[CLK_CSI_SCLK]		= &csi_sclk_clk.common.hw,
786		[CLK_VE]		= &ve_clk.common.hw,
787		[CLK_AVS]		= &avs_clk.common.hw,
788		[CLK_HDMI]		= &hdmi_clk.common.hw,
789		[CLK_HDMI_SLOW]		= &hdmi_slow_clk.common.hw,
790		[CLK_MBUS]		= &mbus_clk.common.hw,
791		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
792		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
793		[CLK_GPU_CORE]		= &gpu_core_clk.common.hw,
794		[CLK_GPU_MEMORY]	= &gpu_memory_clk.common.hw,
795		[CLK_GPU_HYD]		= &gpu_hyd_clk.common.hw,
796	},
797	.num	= CLK_NUMBER,
798};
799
800static const struct ccu_reset_map sun8i_a83t_ccu_resets[] = {
801	[RST_USB_PHY0]		= { 0x0cc, BIT(0) },
802	[RST_USB_PHY1]		= { 0x0cc, BIT(1) },
803	[RST_USB_HSIC]		= { 0x0cc, BIT(2) },
804	[RST_DRAM]		= { 0x0f4, BIT(31) },
805	[RST_MBUS]		= { 0x0fc, BIT(31) },
806	[RST_BUS_MIPI_DSI]	= { 0x2c0, BIT(1) },
807	[RST_BUS_SS]		= { 0x2c0, BIT(5) },
808	[RST_BUS_DMA]		= { 0x2c0, BIT(6) },
809	[RST_BUS_MMC0]		= { 0x2c0, BIT(8) },
810	[RST_BUS_MMC1]		= { 0x2c0, BIT(9) },
811	[RST_BUS_MMC2]		= { 0x2c0, BIT(10) },
812	[RST_BUS_NAND]		= { 0x2c0, BIT(13) },
813	[RST_BUS_DRAM]		= { 0x2c0, BIT(14) },
814	[RST_BUS_EMAC]		= { 0x2c0, BIT(17) },
815	[RST_BUS_HSTIMER]	= { 0x2c0, BIT(19) },
816	[RST_BUS_SPI0]		= { 0x2c0, BIT(20) },
817	[RST_BUS_SPI1]		= { 0x2c0, BIT(21) },
818	[RST_BUS_OTG]		= { 0x2c0, BIT(24) },
819	[RST_BUS_EHCI0]		= { 0x2c0, BIT(26) },
820	[RST_BUS_EHCI1]		= { 0x2c0, BIT(27) },
821	[RST_BUS_OHCI0]		= { 0x2c0, BIT(29) },
822	[RST_BUS_VE]		= { 0x2c4, BIT(0) },
823	[RST_BUS_TCON0]		= { 0x2c4, BIT(4) },
824	[RST_BUS_TCON1]		= { 0x2c4, BIT(5) },
825	[RST_BUS_CSI]		= { 0x2c4, BIT(8) },
826	[RST_BUS_HDMI0]		= { 0x2c4, BIT(10) },
827	[RST_BUS_HDMI1]		= { 0x2c4, BIT(11) },
828	[RST_BUS_DE]		= { 0x2c4, BIT(12) },
829	[RST_BUS_GPU]		= { 0x2c4, BIT(20) },
830	[RST_BUS_MSGBOX]	= { 0x2c4, BIT(21) },
831	[RST_BUS_SPINLOCK]	= { 0x2c4, BIT(22) },
832	[RST_BUS_LVDS]		= { 0x2c8, BIT(0) },
833	[RST_BUS_SPDIF]		= { 0x2d0, BIT(1) },
834	[RST_BUS_I2S0]		= { 0x2d0, BIT(12) },
835	[RST_BUS_I2S1]		= { 0x2d0, BIT(13) },
836	[RST_BUS_I2S2]		= { 0x2d0, BIT(14) },
837	[RST_BUS_TDM]		= { 0x2d0, BIT(15) },
838	[RST_BUS_I2C0]		= { 0x2d8, BIT(0) },
839	[RST_BUS_I2C1]		= { 0x2d8, BIT(1) },
840	[RST_BUS_I2C2]		= { 0x2d8, BIT(2) },
841	[RST_BUS_UART0]		= { 0x2d8, BIT(16) },
842	[RST_BUS_UART1]		= { 0x2d8, BIT(17) },
843	[RST_BUS_UART2]		= { 0x2d8, BIT(18) },
844	[RST_BUS_UART3]		= { 0x2d8, BIT(19) },
845	[RST_BUS_UART4]		= { 0x2d8, BIT(20) },
846};
847
848static const struct sunxi_ccu_desc sun8i_a83t_ccu_desc = {
849	.ccu_clks	= sun8i_a83t_ccu_clks,
850	.num_ccu_clks	= ARRAY_SIZE(sun8i_a83t_ccu_clks),
851
852	.hw_clks	= &sun8i_a83t_hw_clks,
853
854	.resets		= sun8i_a83t_ccu_resets,
855	.num_resets	= ARRAY_SIZE(sun8i_a83t_ccu_resets),
856};
857
858#define SUN8I_A83T_PLL_P_SHIFT	16
859#define SUN8I_A83T_PLL_N_SHIFT	8
860#define SUN8I_A83T_PLL_N_WIDTH	8
861
862static void sun8i_a83t_cpu_pll_fixup(void __iomem *reg)
863{
864	u32 val = readl(reg);
865
866	/* bail out if P divider is not used */
867	if (!(val & BIT(SUN8I_A83T_PLL_P_SHIFT)))
868		return;
869
870	/*
871	 * If P is used, output should be less than 288 MHz. When we
872	 * set P to 1, we should also decrease the multiplier so the
873	 * output doesn't go out of range, but not too much such that
874	 * the multiplier stays above 12, the minimal operation value.
875	 *
876	 * To keep it simple, set the multiplier to 17, the reset value.
877	 */
878	val &= ~GENMASK(SUN8I_A83T_PLL_N_SHIFT + SUN8I_A83T_PLL_N_WIDTH - 1,
879			SUN8I_A83T_PLL_N_SHIFT);
880	val |= 17 << SUN8I_A83T_PLL_N_SHIFT;
881
882	/* And clear P */
883	val &= ~BIT(SUN8I_A83T_PLL_P_SHIFT);
884
885	writel(val, reg);
886}
887
888static int sun8i_a83t_ccu_probe(struct platform_device *pdev)
889{
890	void __iomem *reg;
891	u32 val;
892
893	reg = devm_platform_ioremap_resource(pdev, 0);
894	if (IS_ERR(reg))
895		return PTR_ERR(reg);
896
897	/* Enforce d1 = 0, d2 = 1 for Audio PLL */
898	val = readl(reg + SUN8I_A83T_PLL_AUDIO_REG);
899	val &= ~BIT(16);
900	val |= BIT(18);
901	writel(val, reg + SUN8I_A83T_PLL_AUDIO_REG);
902
903	/* Enforce P = 1 for both CPU cluster PLLs */
904	sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG);
905	sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG);
906
907	return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc);
908}
909
910static const struct of_device_id sun8i_a83t_ccu_ids[] = {
911	{ .compatible = "allwinner,sun8i-a83t-ccu" },
912	{ }
913};
914MODULE_DEVICE_TABLE(of, sun8i_a83t_ccu_ids);
915
916static struct platform_driver sun8i_a83t_ccu_driver = {
917	.probe	= sun8i_a83t_ccu_probe,
918	.driver	= {
919		.name	= "sun8i-a83t-ccu",
920		.suppress_bind_attrs = true,
921		.of_match_table	= sun8i_a83t_ccu_ids,
922	},
923};
924module_platform_driver(sun8i_a83t_ccu_driver);
925
926MODULE_IMPORT_NS("SUNXI_CCU");
927MODULE_DESCRIPTION("Support for the Allwinner A83T CCU");
928MODULE_LICENSE("GPL");