1// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2015 Google, Inc
4 * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
5 */
6
7#include <bitfield.h>
8#include <common.h>
9#include <clk-uclass.h>
10#include <dm.h>
11#include <dt-structs.h>
12#include <errno.h>
13#include <log.h>
14#include <malloc.h>
15#include <mapmem.h>
16#include <syscon.h>
17#include <asm/arch-rockchip/clock.h>
18#include <asm/arch-rockchip/cru_rk3066.h>
19#include <asm/arch-rockchip/grf_rk3066.h>
20#include <asm/arch-rockchip/hardware.h>
21#include <dt-bindings/clock/rk3066a-cru.h>
22#include <dm/device_compat.h>
23#include <dm/device-internal.h>
24#include <dm/lists.h>
25#include <dm/uclass-internal.h>
26#include <linux/delay.h>
27#include <linux/err.h>
28#include <linux/log2.h>
29#include <linux/stringify.h>
30
31struct rk3066_clk_plat {
32#if CONFIG_IS_ENABLED(OF_PLATDATA)
33	struct dtd_rockchip_rk3066a_cru dtd;
34#endif
35};
36
37struct pll_div {
38	u32 nr;
39	u32 nf;
40	u32 no;
41};
42
43enum {
44	VCO_MAX_HZ	= 1416U * 1000000,
45	VCO_MIN_HZ	= 300 * 1000000,
46	OUTPUT_MAX_HZ	= 1416U * 1000000,
47	OUTPUT_MIN_HZ	= 30 * 1000000,
48	FREF_MAX_HZ	= 1416U * 1000000,
49	FREF_MIN_HZ	= 30 * 1000,
50};
51
52enum {
53	/* PLL CON0 */
54	PLL_OD_MASK		= GENMASK(3, 0),
55
56	/* PLL CON1 */
57	PLL_NF_MASK		= GENMASK(12, 0),
58
59	/* PLL CON2 */
60	PLL_BWADJ_MASK		= GENMASK(11, 0),
61
62	/* PLL CON3 */
63	PLL_RESET_SHIFT		= 5,
64
65	/* GRF_SOC_STATUS0 */
66	SOCSTS_DPLL_LOCK	= BIT(4),
67	SOCSTS_APLL_LOCK	= BIT(5),
68	SOCSTS_CPLL_LOCK	= BIT(6),
69	SOCSTS_GPLL_LOCK	= BIT(7),
70};
71
72#define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
73
74#define PLL_DIVISORS(hz, _nr, _no) {\
75	.nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
76	_Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
77		       (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
78		       "divisors on line " __stringify(__LINE__))
79
80/* Keep divisors as low as possible to reduce jitter and power usage. */
81static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
82static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
83
84static int rk3066_clk_set_pll(struct rk3066_cru *cru, enum rk_clk_id clk_id,
85			      const struct pll_div *div)
86{
87	int pll_id = rk_pll_id(clk_id);
88	struct rk3066_pll *pll = &cru->pll[pll_id];
89	/* All PLLs have the same VCO and output frequency range restrictions. */
90	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
91	uint output_hz = vco_hz / div->no;
92
93	debug("%s: PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", __func__,
94	      (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
95	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
96	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
97	       (div->no == 1 || !(div->no % 2)));
98
99	/* Enter reset. */
100	rk_setreg(&pll->con3, BIT(PLL_RESET_SHIFT));
101
102	rk_clrsetreg(&pll->con0,
103		     CLKR_MASK | PLL_OD_MASK,
104		     ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
105	rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
106
107	rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
108
109	/* Exit reset. */
110	rk_clrreg(&pll->con3, BIT(PLL_RESET_SHIFT));
111
112	return 0;
113}
114
115static int rk3066_clk_configure_ddr(struct rk3066_cru *cru, struct rk3066_grf *grf,
116				    unsigned int hz)
117{
118	static const struct pll_div dpll_cfg[] = {
119		{.nf = 25, .nr = 2, .no = 1},
120		{.nf = 400, .nr = 9, .no = 2},
121		{.nf = 500, .nr = 9, .no = 2},
122		{.nf = 100, .nr = 3, .no = 1},
123	};
124	int cfg;
125
126	switch (hz) {
127	case 300000000:
128		cfg = 0;
129		break;
130	case 533000000:	/* actually 533.3P MHz */
131		cfg = 1;
132		break;
133	case 666000000:	/* actually 666.6P MHz */
134		cfg = 2;
135		break;
136	case 800000000:
137		cfg = 3;
138		break;
139	default:
140		debug("%s: unsupported SDRAM frequency", __func__);
141		return -EINVAL;
142	}
143
144	/* Enter PLL slow mode. */
145	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK,
146		     PLL_MODE_SLOW << DPLL_MODE_SHIFT);
147
148	rk3066_clk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg]);
149
150	/* Wait for PLL lock. */
151	while (!(readl(&grf->soc_status0) & SOCSTS_DPLL_LOCK))
152		udelay(1);
153
154	/* Enter PLL normal mode. */
155	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK,
156		     PLL_MODE_NORMAL << DPLL_MODE_SHIFT);
157
158	return 0;
159}
160
161static int rk3066_clk_configure_cpu(struct rk3066_cru *cru, struct rk3066_grf *grf,
162				    unsigned int hz)
163{
164	static const struct pll_div apll_cfg[] = {
165		{.nf = 50, .nr = 1, .no = 2},
166		{.nf = 59, .nr = 1, .no = 1},
167	};
168	int div_core_peri, div_cpu_aclk, cfg;
169
170	/*
171	 * We support two possible frequencies, the safe 600MHz
172	 * which will work with default pmic settings and will
173	 * be set to get away from the 24MHz default and
174	 * the maximum of 1.416Ghz, which boards can set if they
175	 * were able to get pmic support for it.
176	 */
177	switch (hz) {
178	case APLL_SAFE_HZ:
179		cfg = 0;
180		div_core_peri = 1;
181		div_cpu_aclk = 3;
182		break;
183	case APLL_HZ:
184		cfg = 1;
185		div_core_peri = 2;
186		div_cpu_aclk = 3;
187		break;
188	default:
189		debug("unsupported ARMCLK frequency");
190		return -EINVAL;
191	}
192
193	/* Enter PLL slow mode. */
194	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
195		     PLL_MODE_SLOW << APLL_MODE_SHIFT);
196
197	rk3066_clk_set_pll(cru, CLK_ARM, &apll_cfg[cfg]);
198
199	/* Wait for PLL lock. */
200	while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK))
201		udelay(1);
202
203	/* Set divider for peripherals attached to the CPU core. */
204	rk_clrsetreg(&cru->cru_clksel_con[0],
205		     CORE_PERI_DIV_MASK,
206		     div_core_peri << CORE_PERI_DIV_SHIFT);
207
208	/* Set up dependent divisor for cpu_aclk. */
209	rk_clrsetreg(&cru->cru_clksel_con[1],
210		     CPU_ACLK_DIV_MASK,
211		     div_cpu_aclk << CPU_ACLK_DIV_SHIFT);
212
213	/* Enter PLL normal mode. */
214	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
215		     PLL_MODE_NORMAL << APLL_MODE_SHIFT);
216
217	return hz;
218}
219
220static uint32_t rk3066_clk_pll_get_rate(struct rk3066_cru *cru,
221					enum rk_clk_id clk_id)
222{
223	u32 nr, no, nf;
224	u32 con;
225	int pll_id = rk_pll_id(clk_id);
226	struct rk3066_pll *pll = &cru->pll[pll_id];
227	static u8 clk_shift[CLK_COUNT] = {
228		0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
229		GPLL_MODE_SHIFT
230	};
231	uint shift;
232
233	con = readl(&cru->cru_mode_con);
234	shift = clk_shift[clk_id];
235	switch (FIELD_GET(APLL_MODE_MASK, con >> shift)) {
236	case PLL_MODE_SLOW:
237		return OSC_HZ;
238	case PLL_MODE_NORMAL:
239		/* normal mode */
240		con = readl(&pll->con0);
241		no = bitfield_extract_by_mask(con, CLKOD_MASK) + 1;
242		nr = bitfield_extract_by_mask(con, CLKR_MASK) + 1;
243		con = readl(&pll->con1);
244		nf = bitfield_extract_by_mask(con, CLKF_MASK) + 1;
245
246		return (OSC_HZ * nf) / (nr * no);
247	case PLL_MODE_DEEP:
248	default:
249		return 32768;
250	}
251}
252
253static ulong rk3066_clk_mmc_get_clk(struct rk3066_cru *cru, uint gclk_rate,
254				    int periph)
255{
256	uint div;
257	u32 con;
258
259	switch (periph) {
260	case HCLK_EMMC:
261	case SCLK_EMMC:
262		con = readl(&cru->cru_clksel_con[12]);
263		div = bitfield_extract_by_mask(con, EMMC_DIV_MASK);
264		break;
265	case HCLK_SDMMC:
266	case SCLK_SDMMC:
267		con = readl(&cru->cru_clksel_con[11]);
268		div = bitfield_extract_by_mask(con, MMC0_DIV_MASK);
269		break;
270	case HCLK_SDIO:
271	case SCLK_SDIO:
272		con = readl(&cru->cru_clksel_con[12]);
273		div = bitfield_extract_by_mask(con, SDIO_DIV_MASK);
274		break;
275	default:
276		return -EINVAL;
277	}
278
279	return DIV_TO_RATE(gclk_rate, div) / 2;
280}
281
282static ulong rk3066_clk_mmc_set_clk(struct rk3066_cru *cru, uint gclk_rate,
283				    int  periph, uint freq)
284{
285	int src_clk_div;
286
287	debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
288	/* MMC clock by default divides by 2 internally, so need to provide double in CRU. */
289	src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq) - 1;
290	assert(src_clk_div <= 0x3f);
291
292	switch (periph) {
293	case HCLK_EMMC:
294	case SCLK_EMMC:
295		rk_clrsetreg(&cru->cru_clksel_con[12],
296			     EMMC_DIV_MASK,
297			     src_clk_div << EMMC_DIV_SHIFT);
298		break;
299	case HCLK_SDMMC:
300	case SCLK_SDMMC:
301		rk_clrsetreg(&cru->cru_clksel_con[11],
302			     MMC0_DIV_MASK,
303			     src_clk_div << MMC0_DIV_SHIFT);
304		break;
305	case HCLK_SDIO:
306	case SCLK_SDIO:
307		rk_clrsetreg(&cru->cru_clksel_con[12],
308			     SDIO_DIV_MASK,
309			     src_clk_div << SDIO_DIV_SHIFT);
310		break;
311	default:
312		return -EINVAL;
313	}
314
315	return rk3066_clk_mmc_get_clk(cru, gclk_rate, periph);
316}
317
318static ulong rk3066_clk_spi_get_clk(struct rk3066_cru *cru, uint gclk_rate,
319				    int periph)
320{
321	uint div;
322	u32 con;
323
324	switch (periph) {
325	case SCLK_SPI0:
326		con = readl(&cru->cru_clksel_con[25]);
327		div = bitfield_extract_by_mask(con, SPI0_DIV_MASK);
328		break;
329	case SCLK_SPI1:
330		con = readl(&cru->cru_clksel_con[25]);
331		div = bitfield_extract_by_mask(con, SPI1_DIV_MASK);
332		break;
333	default:
334		return -EINVAL;
335	}
336
337	return DIV_TO_RATE(gclk_rate, div);
338}
339
340static ulong rk3066_clk_spi_set_clk(struct rk3066_cru *cru, uint gclk_rate,
341				    int periph, uint freq)
342{
343	int src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1;
344
345	assert(src_clk_div < 128);
346	switch (periph) {
347	case SCLK_SPI0:
348		assert(src_clk_div <= SPI0_DIV_MASK >> SPI0_DIV_SHIFT);
349		rk_clrsetreg(&cru->cru_clksel_con[25],
350			     SPI0_DIV_MASK,
351			     src_clk_div << SPI0_DIV_SHIFT);
352		break;
353	case SCLK_SPI1:
354		assert(src_clk_div <= SPI1_DIV_MASK >> SPI1_DIV_SHIFT);
355		rk_clrsetreg(&cru->cru_clksel_con[25],
356			     SPI1_DIV_MASK,
357			     src_clk_div << SPI1_DIV_SHIFT);
358		break;
359	default:
360		return -EINVAL;
361	}
362
363	return rk3066_clk_spi_get_clk(cru, gclk_rate, periph);
364}
365
366static ulong rk3066_clk_saradc_get_clk(struct rk3066_cru *cru, int periph)
367{
368	u32 div, con;
369
370	switch (periph) {
371	case SCLK_SARADC:
372		con = readl(&cru->cru_clksel_con[24]);
373		div = bitfield_extract_by_mask(con, SARADC_DIV_MASK);
374		break;
375	case SCLK_TSADC:
376		con = readl(&cru->cru_clksel_con[34]);
377		div = bitfield_extract_by_mask(con, TSADC_DIV_MASK);
378		break;
379	default:
380		return -EINVAL;
381	}
382	return DIV_TO_RATE(PERI_PCLK_HZ, div);
383}
384
385static ulong rk3066_clk_saradc_set_clk(struct rk3066_cru *cru, uint hz,
386				       int periph)
387{
388	int src_clk_div;
389
390	src_clk_div = DIV_ROUND_UP(PERI_PCLK_HZ, hz) - 1;
391	assert(src_clk_div < 128);
392
393	switch (periph) {
394	case SCLK_SARADC:
395		rk_clrsetreg(&cru->cru_clksel_con[24],
396			     SARADC_DIV_MASK,
397			     src_clk_div << SARADC_DIV_SHIFT);
398		break;
399	case SCLK_TSADC:
400		rk_clrsetreg(&cru->cru_clksel_con[34],
401			     SARADC_DIV_MASK,
402			     src_clk_div << SARADC_DIV_SHIFT);
403		break;
404	default:
405		return -EINVAL;
406	}
407
408	return rk3066_clk_saradc_get_clk(cru, periph);
409}
410
411static void rk3066_clk_init(struct rk3066_cru *cru, struct rk3066_grf *grf)
412{
413	u32 aclk_div, hclk_div, pclk_div, h2p_div;
414
415	/* Enter PLL slow mode. */
416	rk_clrsetreg(&cru->cru_mode_con,
417		     GPLL_MODE_MASK |
418		     CPLL_MODE_MASK,
419		     PLL_MODE_SLOW << GPLL_MODE_SHIFT |
420		     PLL_MODE_SLOW << CPLL_MODE_SHIFT);
421
422	/* Init PLL. */
423	rk3066_clk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
424	rk3066_clk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
425
426	/* Wait for PLL lock. */
427	while ((readl(&grf->soc_status0) &
428		(SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) !=
429	       (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK))
430		udelay(1);
431
432	/*
433	 * Select CPU clock PLL source and
434	 * reparent aclk_cpu_pre from APPL to GPLL.
435	 * Set up dependent divisors for PCLK/HCLK and ACLK clocks.
436	 */
437	aclk_div = DIV_ROUND_UP(GPLL_HZ, CPU_ACLK_HZ) - 1;
438	assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
439
440	rk_clrsetreg(&cru->cru_clksel_con[0],
441		     CPU_ACLK_PLL_MASK |
442		     A9_CORE_DIV_MASK,
443		     CPU_ACLK_PLL_SELECT_GPLL << CPU_ACLK_PLL_SHIFT |
444		     aclk_div << A9_CORE_DIV_SHIFT);
445
446	hclk_div = ilog2(CPU_ACLK_HZ / CPU_HCLK_HZ);
447	assert((1 << hclk_div) * CPU_HCLK_HZ == CPU_ACLK_HZ && hclk_div < 0x3);
448	pclk_div = ilog2(CPU_ACLK_HZ / CPU_PCLK_HZ);
449	assert((1 << pclk_div) * CPU_PCLK_HZ == CPU_ACLK_HZ && pclk_div < 0x4);
450	h2p_div = ilog2(CPU_HCLK_HZ / CPU_H2P_HZ);
451	assert((1 << h2p_div) * CPU_H2P_HZ == CPU_HCLK_HZ && pclk_div < 0x3);
452
453	rk_clrsetreg(&cru->cru_clksel_con[1],
454		     AHB2APB_DIV_MASK |
455		     CPU_PCLK_DIV_MASK |
456		     CPU_HCLK_DIV_MASK,
457		     h2p_div << AHB2APB_DIV_SHIFT |
458		     pclk_div << CPU_PCLK_DIV_SHIFT |
459		     hclk_div << CPU_HCLK_DIV_SHIFT);
460
461	/*
462	 * Select PERI clock PLL source and
463	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
464	 */
465	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
466	assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
467
468	hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
469	assert((1 << hclk_div) * PERI_HCLK_HZ ==
470	       PERI_ACLK_HZ && (hclk_div < 0x4));
471
472	pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
473	assert((1 << pclk_div) * PERI_PCLK_HZ ==
474	       PERI_ACLK_HZ && (pclk_div < 0x4));
475
476	rk_clrsetreg(&cru->cru_clksel_con[10],
477		     PERI_PCLK_DIV_MASK |
478		     PERI_HCLK_DIV_MASK |
479		     PERI_ACLK_DIV_MASK,
480		     PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT |
481		     pclk_div << PERI_PCLK_DIV_SHIFT |
482		     hclk_div << PERI_HCLK_DIV_SHIFT |
483		     aclk_div << PERI_ACLK_DIV_SHIFT);
484
485	/* Enter PLL normal mode. */
486	rk_clrsetreg(&cru->cru_mode_con,
487		     GPLL_MODE_MASK |
488		     CPLL_MODE_MASK,
489		     PLL_MODE_NORMAL << GPLL_MODE_SHIFT |
490		     PLL_MODE_NORMAL << CPLL_MODE_SHIFT);
491
492	rk3066_clk_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000);
493}
494
495static ulong rk3066_clk_get_rate(struct clk *clk)
496{
497	struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
498	ulong new_rate, gclk_rate;
499
500	gclk_rate = rk3066_clk_pll_get_rate(priv->cru, CLK_GENERAL);
501	switch (clk->id) {
502	case 1 ... 4:
503		new_rate = rk3066_clk_pll_get_rate(priv->cru, clk->id);
504		break;
505	case HCLK_EMMC:
506	case HCLK_SDMMC:
507	case HCLK_SDIO:
508	case SCLK_EMMC:
509	case SCLK_SDMMC:
510	case SCLK_SDIO:
511		new_rate = rk3066_clk_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
512						  clk->id);
513		break;
514	case SCLK_SPI0:
515	case SCLK_SPI1:
516		new_rate = rk3066_clk_spi_get_clk(priv->cru, PERI_PCLK_HZ,
517						  clk->id);
518		break;
519	case PCLK_I2C0:
520	case PCLK_I2C1:
521	case PCLK_I2C2:
522	case PCLK_I2C3:
523	case PCLK_I2C4:
524		return gclk_rate;
525	case SCLK_SARADC:
526	case SCLK_TSADC:
527		new_rate = rk3066_clk_saradc_get_clk(priv->cru, clk->id);
528		break;
529	case SCLK_TIMER0:
530	case SCLK_TIMER1:
531	case SCLK_TIMER2:
532	case SCLK_UART0:
533	case SCLK_UART1:
534	case SCLK_UART2:
535	case SCLK_UART3:
536		return OSC_HZ;
537	default:
538		return -ENOENT;
539	}
540
541	return new_rate;
542}
543
544static ulong rk3066_clk_set_rate(struct clk *clk, ulong rate)
545{
546	struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
547	struct rk3066_cru *cru = priv->cru;
548	ulong new_rate;
549
550	switch (clk->id) {
551	case PLL_APLL:
552		new_rate = rk3066_clk_configure_cpu(priv->cru, priv->grf, rate);
553		break;
554	case CLK_DDR:
555		new_rate = rk3066_clk_configure_ddr(priv->cru, priv->grf, rate);
556		break;
557	case HCLK_EMMC:
558	case HCLK_SDMMC:
559	case HCLK_SDIO:
560	case SCLK_EMMC:
561	case SCLK_SDMMC:
562	case SCLK_SDIO:
563		new_rate = rk3066_clk_mmc_set_clk(cru, PERI_HCLK_HZ,
564						  clk->id, rate);
565		break;
566	case SCLK_SPI0:
567	case SCLK_SPI1:
568		new_rate = rk3066_clk_spi_set_clk(cru, PERI_PCLK_HZ,
569						  clk->id, rate);
570		break;
571	case SCLK_SARADC:
572	case SCLK_TSADC:
573		new_rate = rk3066_clk_saradc_set_clk(cru, rate, clk->id);
574		break;
575	case PLL_CPLL:
576	case PLL_GPLL:
577	case ACLK_CPU:
578	case HCLK_CPU:
579	case PCLK_CPU:
580	case ACLK_PERI:
581	case HCLK_PERI:
582	case PCLK_PERI:
583		return 0;
584	default:
585		return -ENOENT;
586	}
587
588	return new_rate;
589}
590
591static int rk3066_clk_enable(struct clk *clk)
592{
593	struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
594
595	switch (clk->id) {
596	case HCLK_NANDC0:
597		rk_clrreg(&priv->cru->cru_clkgate_con[5], BIT(9));
598		break;
599	case HCLK_SDMMC:
600		rk_clrreg(&priv->cru->cru_clkgate_con[5], BIT(10));
601		break;
602	case HCLK_SDIO:
603		rk_clrreg(&priv->cru->cru_clkgate_con[5], BIT(11));
604		break;
605	}
606
607	return 0;
608}
609
610static int rk3066_clk_disable(struct clk *clk)
611{
612	struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
613
614	switch (clk->id) {
615	case HCLK_NANDC0:
616		rk_setreg(&priv->cru->cru_clkgate_con[5], BIT(9));
617		break;
618	case HCLK_SDMMC:
619		rk_setreg(&priv->cru->cru_clkgate_con[5], BIT(10));
620		break;
621	case HCLK_SDIO:
622		rk_setreg(&priv->cru->cru_clkgate_con[5], BIT(11));
623		break;
624	}
625
626	return 0;
627}
628
629static struct clk_ops rk3066_clk_ops = {
630	.disable	= rk3066_clk_disable,
631	.enable	= rk3066_clk_enable,
632	.get_rate	= rk3066_clk_get_rate,
633	.set_rate	= rk3066_clk_set_rate,
634};
635
636static int rk3066_clk_of_to_plat(struct udevice *dev)
637{
638	if (CONFIG_IS_ENABLED(OF_REAL)) {
639		struct rk3066_clk_priv *priv = dev_get_priv(dev);
640
641		priv->cru = dev_read_addr_ptr(dev);
642	}
643
644	return 0;
645}
646
647static int rk3066_clk_probe(struct udevice *dev)
648{
649	struct rk3066_clk_priv *priv = dev_get_priv(dev);
650
651	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
652	if (IS_ERR(priv->grf))
653		return PTR_ERR(priv->grf);
654
655#if CONFIG_IS_ENABLED(OF_PLATDATA)
656	struct rk3066_clk_plat *plat = dev_get_plat(dev);
657
658	priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
659#endif
660
661	if (IS_ENABLED(CONFIG_TPL_BUILD)) {
662		rk3066_clk_init(priv->cru, priv->grf);
663
664		/* Init CPU frequency. */
665		rk3066_clk_configure_cpu(priv->cru, priv->grf, APLL_SAFE_HZ);
666	}
667
668	return 0;
669}
670
671static int rk3066_clk_bind(struct udevice *dev)
672{
673	struct udevice *sys_child;
674	struct sysreset_reg *priv;
675	int reg_offset, ret;
676
677	/* The reset driver does not have a device node, so bind it here. */
678	ret = device_bind(dev, DM_DRIVER_GET(sysreset_rockchip), "sysreset",
679			  NULL, ofnode_null(), &sys_child);
680	if (ret) {
681		dev_dbg(dev, "Warning: No sysreset driver: ret=%d\n", ret);
682	} else {
683		priv = malloc(sizeof(struct sysreset_reg));
684		priv->glb_srst_fst_value = offsetof(struct rk3066_cru,
685						    cru_glb_srst_fst_value);
686		priv->glb_srst_snd_value = offsetof(struct rk3066_cru,
687						    cru_glb_srst_snd_value);
688		dev_set_priv(sys_child, priv);
689	}
690
691	if (CONFIG_IS_ENABLED(RESET_ROCKCHIP)) {
692		reg_offset = offsetof(struct rk3066_cru, cru_softrst_con[0]);
693		ret = rockchip_reset_bind(dev, reg_offset, 9);
694		if (ret)
695			dev_dbg(dev, "Warning: software reset driver bind failed\n");
696	}
697
698	return 0;
699}
700
701static const struct udevice_id rk3066_clk_ids[] = {
702	{ .compatible = "rockchip,rk3066a-cru" },
703	{ }
704};
705
706U_BOOT_DRIVER(rockchip_rk3066a_cru) = {
707	.name		= "rockchip_rk3066a_cru",
708	.id		= UCLASS_CLK,
709	.ops		= &rk3066_clk_ops,
710	.probe		= rk3066_clk_probe,
711	.bind		= rk3066_clk_bind,
712	.of_match	= rk3066_clk_ids,
713	.of_to_plat	= rk3066_clk_of_to_plat,
714	.priv_auto	= sizeof(struct rk3066_clk_priv),
715	.plat_auto	= sizeof(struct rk3066_clk_plat),
716};
717