xref: /openbsd-src/sys/dev/fdt/rkclock.c (revision c7e8ea31cd41a963f06f0a8ba93948b06aa6b4a4)
1 /*	$OpenBSD: rkclock.c,v 1.10 2017/08/21 21:02:12 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/sysctl.h>
21 #include <sys/device.h>
22 
23 #include <machine/intr.h>
24 #include <machine/bus.h>
25 #include <machine/fdt.h>
26 
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/ofw_clock.h>
29 #include <dev/ofw/fdt.h>
30 
31 /* RK3288 registers */
32 #define RK3288_CRU_CPLL_CON(i)		(0x0020 + (i) * 4)
33 #define RK3288_CRU_GPLL_CON(i)		(0x0030 + (i) * 4)
34 #define RK3288_CRU_CLKSEL_CON(i)	(0x0060 + (i) * 4)
35 
36 /* RK3399 registers */
37 #define RK3399_CRU_LPLL_CON(i)		(0x0000 + (i) * 4)
38 #define RK3399_CRU_BPLL_CON(i)		(0x0020 + (i) * 4)
39 #define RK3399_CRU_DPLL_CON(i)		(0x0020 + (i) * 4)
40 #define RK3399_CRU_CPLL_CON(i)		(0x0060 + (i) * 4)
41 #define RK3399_CRU_GPLL_CON(i)		(0x0080 + (i) * 4)
42 #define RK3399_CRU_NPLL_CON(i)		(0x00a0 + (i) * 4)
43 #define RK3399_CRU_CLKSEL_CON(i)	(0x0100 + (i) * 4)
44 #define RK3399_CRU_CLKGATE_CON(i)	(0x0300 + (i) * 4)
45 #define RK3399_CRU_SOFTRST_CON(i)	(0x0400 + (i) * 4)
46 #define RK3399_CRU_SDMMC_CON(i)		(0x0580 + (i) * 4)
47 
48 #include "rkclock_clocks.h"
49 
50 #define HREAD4(sc, reg)							\
51 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
52 #define HWRITE4(sc, reg, val)						\
53 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
54 #define HSET4(sc, reg, bits)						\
55 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
56 #define HCLR4(sc, reg, bits)						\
57 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
58 
59 struct rkclock_softc {
60 	struct device		sc_dev;
61 	bus_space_tag_t		sc_iot;
62 	bus_space_handle_t	sc_ioh;
63 
64 	struct clock_device	sc_cd;
65 	struct reset_device	sc_rd;
66 };
67 
68 int rkclock_match(struct device *, void *, void *);
69 void rkclock_attach(struct device *, struct device *, void *);
70 
71 struct cfattach	rkclock_ca = {
72 	sizeof (struct rkclock_softc), rkclock_match, rkclock_attach
73 };
74 
75 struct cfdriver rkclock_cd = {
76 	NULL, "rkclock", DV_DULL
77 };
78 
79 struct rkclock_softc *rkclock_cpuspeed_sc;
80 
81 uint32_t rk3288_get_frequency(void *, uint32_t *);
82 int	rk3288_set_frequency(void *, uint32_t *, uint32_t);
83 void	rk3288_enable(void *, uint32_t *, int);
84 void	rk3288_reset(void *, uint32_t *, int);
85 
86 uint32_t rk3399_get_frequency(void *, uint32_t *);
87 int	rk3399_set_frequency(void *, uint32_t *, uint32_t);
88 void	rk3399_enable(void *, uint32_t *, int);
89 void	rk3399_reset(void *, uint32_t *, int);
90 int	rk3399_cpuspeed(int *);
91 
92 uint32_t rk3399_pmu_get_frequency(void *, uint32_t *);
93 int	rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t);
94 void	rk3399_pmu_enable(void *, uint32_t *, int);
95 void	rk3399_pmu_reset(void *, uint32_t *, int);
96 
97 struct rkclock_compat {
98 	const char *compat;
99 	void	(*enable)(void *, uint32_t *, int);
100 	uint32_t (*get_frequency)(void *, uint32_t *);
101 	int	(*set_frequency)(void *, uint32_t *, uint32_t);
102 	void	(*reset)(void *, uint32_t *, int);
103 	int	(*cpuspeed)(int *);
104 };
105 
106 struct rkclock_compat rkclock_compat[] = {
107 	{
108 		"rockchip,rk3288-cru",
109 		rk3288_enable, rk3288_get_frequency,
110 		rk3288_set_frequency, rk3288_reset
111 	},
112 	{
113 		"rockchip,rk3399-cru",
114 		rk3399_enable, rk3399_get_frequency,
115 		rk3399_set_frequency, rk3399_reset,
116 		rk3399_cpuspeed
117 	},
118 	{
119 		"rockchip,rk3399-pmucru",
120 		rk3399_pmu_enable, rk3399_pmu_get_frequency,
121 		rk3399_pmu_set_frequency, rk3399_pmu_reset
122 	}
123 };
124 
125 int
126 rkclock_match(struct device *parent, void *match, void *aux)
127 {
128 	struct fdt_attach_args *faa = aux;
129 	int i;
130 
131 	for (i = 0; i < nitems(rkclock_compat); i++) {
132 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat))
133 			return 1;
134 	}
135 
136 	return 0;
137 }
138 
139 void
140 rkclock_attach(struct device *parent, struct device *self, void *aux)
141 {
142 	struct rkclock_softc *sc = (struct rkclock_softc *)self;
143 	struct fdt_attach_args *faa = aux;
144 	int i;
145 
146 	if (faa->fa_nreg < 1) {
147 		printf(": no registers\n");
148 		return;
149 	}
150 
151 	sc->sc_iot = faa->fa_iot;
152 
153 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
154 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
155 		printf(": can't map registers\n");
156 		return;
157 	}
158 
159 	printf("\n");
160 
161 	for (i = 0; i < nitems(rkclock_compat); i++) {
162 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) {
163 			sc->sc_cd.cd_enable = rkclock_compat[i].enable;
164 			sc->sc_cd.cd_get_frequency =
165 			    rkclock_compat[i].get_frequency;
166 			sc->sc_cd.cd_set_frequency =
167 			    rkclock_compat[i].set_frequency;
168 			sc->sc_rd.rd_reset = rkclock_compat[i].reset;
169 			if (rkclock_compat[i].cpuspeed) {
170 				rkclock_cpuspeed_sc = sc;
171 				cpu_cpuspeed = rkclock_compat[i].cpuspeed;
172 			}
173 			break;
174 		}
175 	}
176 
177 	sc->sc_cd.cd_node = faa->fa_node;
178 	sc->sc_cd.cd_cookie = sc;
179 	clock_register(&sc->sc_cd);
180 
181 	sc->sc_rd.rd_node = faa->fa_node;
182 	sc->sc_rd.rd_cookie = sc;
183 	reset_register(&sc->sc_rd);
184 }
185 
186 /*
187  * Rockchip RK3288
188  */
189 
190 uint32_t
191 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
192 {
193 	uint32_t clkod, clkr, clkf;
194 	uint32_t reg;
195 
196 	reg = HREAD4(sc, base);
197 	clkod = (reg >> 0) & 0xf;
198 	clkr = (reg >> 8) & 0x3f;
199 	reg = HREAD4(sc, base + 4);
200 	clkf = (reg >> 0) & 0x1fff;
201 	return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
202 }
203 
204 uint32_t
205 rk3288_get_frequency(void *cookie, uint32_t *cells)
206 {
207 	struct rkclock_softc *sc = cookie;
208 	uint32_t idx = cells[0];
209 	uint32_t reg, mux, div_con;
210 
211 	switch (idx) {
212 	case RK3288_PLL_CPLL:
213 		return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
214 	case RK3288_PLL_GPLL:
215 		return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
216 	case RK3288_CLK_SDMMC:
217 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(11));
218 		mux = (reg >> 6) & 0x3;
219 		div_con = reg & 0x3f;
220 		switch (mux) {
221 		case 0:
222 			idx = RK3288_PLL_CPLL;
223 			break;
224 		case 1:
225 			idx = RK3288_PLL_GPLL;
226 			break;
227 		case 2:
228 			return 24000000 / (div_con + 1);
229 		default:
230 			return 0;
231 		}
232 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
233 		break;
234 	case RK3288_CLK_UART0:
235 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
236 		mux = (reg >> 8) & 0x3;
237 		div_con = reg & 0x7f;
238 		if (mux == 2)
239 			return 24000000 / (div_con + 1);
240 		break;
241 	case RK3288_CLK_UART1:
242 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
243 		mux = (reg >> 8) & 0x3;
244 		div_con = reg & 0x7f;
245 		if (mux == 2)
246 			return 24000000 / (div_con + 1);
247 		break;
248 	case RK3288_CLK_UART2:
249 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
250 		mux = (reg >> 8) & 0x3;
251 		div_con = reg & 0x7f;
252 		if (mux == 2)
253 			return 24000000 / (div_con + 1);
254 		break;
255 	case RK3288_CLK_UART3:
256 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
257 		mux = (reg >> 8) & 0x3;
258 		div_con = reg & 0x7f;
259 		if (mux == 2)
260 			return 24000000 / (div_con + 1);
261 		break;
262 	case RK3288_CLK_UART4:
263 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
264 		mux = (reg >> 8) & 0x3;
265 		div_con = reg & 0x7f;
266 		if (mux == 2)
267 			return 24000000 / (div_con + 1);
268 		break;
269 	default:
270 		break;
271 	}
272 
273 	printf("%s: 0x%08x\n", __func__, idx);
274 	return 0;
275 }
276 
277 int
278 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
279 {
280 	uint32_t idx = cells[0];
281 
282 	printf("%s: 0x%08x\n", __func__, idx);
283 	return -1;
284 }
285 
286 void
287 rk3288_enable(void *cookie, uint32_t *cells, int on)
288 {
289 	uint32_t idx = cells[0];
290 
291 	switch (idx) {
292 	case RK3288_CLK_SDMMC:
293 	case RK3288_CLK_UART0:
294 	case RK3288_CLK_UART1:
295 	case RK3288_CLK_UART2:
296 	case RK3288_CLK_UART3:
297 	case RK3288_CLK_UART4:
298 	case RK3288_CLK_MAC_RX:
299 	case RK3288_CLK_MAC_TX:
300 	case RK3288_CLK_SDMMC_DRV:
301 	case RK3288_CLK_SDMMC_SAMPLE:
302 	case RK3288_CLK_MAC:
303 	case RK3288_ACLK_GMAC:
304 	case RK3288_PCLK_GMAC:
305 	case RK3288_HCLK_HOST0:
306 	case RK3288_HCLK_SDMMC:
307 		/* Enabled by default. */
308 		break;
309 	default:
310 		printf("%s: 0x%08x\n", __func__, idx);
311 		break;
312 	}
313 }
314 
315 void
316 rk3288_reset(void *cookie, uint32_t *cells, int on)
317 {
318 	uint32_t idx = cells[0];
319 
320 	printf("%s: 0x%08x\n", __func__, idx);
321 }
322 
323 /*
324  * Rockchip RK3399
325  */
326 
327 uint32_t
328 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
329 {
330 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
331 	uint32_t pll_work_mode;
332 	uint32_t reg;
333 
334 	reg = HREAD4(sc, base + 0x000c);
335 	pll_work_mode = (reg >> 8) & 0x3;
336 	if (pll_work_mode == 0)
337 		return 24000000;
338 	if (pll_work_mode == 2)
339 		return 32768;
340 
341 	reg = HREAD4(sc, base + 0x0000);
342 	fbdiv = reg & 0xfff;
343 	reg = HREAD4(sc, base + 0x0004);
344 	postdiv2 = (reg >> 12) & 0x7;
345 	postdiv1 = (reg >> 8) & 0x7;
346 	refdiv = reg & 0x3f;
347 	return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
348 }
349 
350 uint32_t
351 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
352 {
353 	uint32_t reg, mux, div_con;
354 	uint32_t idx;
355 
356 	reg = HREAD4(sc, clksel);
357 	mux = (reg >> 6) & 0x3;
358 	div_con = reg & 0x1f;
359 	switch (mux) {
360 	case 0:
361 		idx = RK3399_PLL_ALPLL;
362 		break;
363 	case 1:
364 		idx = RK3399_PLL_ABPLL;
365 		break;
366 	case 2:
367 		idx = RK3399_PLL_DPLL;
368 		break;
369 	case 3:
370 		idx = RK3399_PLL_GPLL;
371 		break;
372 	}
373 
374 	return rk3399_get_frequency(sc, &idx) / (div_con + 1);
375 }
376 
377 uint32_t
378 rk3399_get_frequency(void *cookie, uint32_t *cells)
379 {
380 	struct rkclock_softc *sc = cookie;
381 	uint32_t idx = cells[0];
382 	uint32_t reg, mux, div_con;
383 
384 	switch (idx) {
385 	case RK3399_PLL_ALPLL:
386 		return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
387 	case RK3399_PLL_ABPLL:
388 		return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
389 	case RK3399_PLL_DPLL:
390 		return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
391 	case RK3399_PLL_CPLL:
392 		return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
393 	case RK3399_PLL_GPLL:
394 		return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
395 	case RK3399_PLL_NPLL:
396 		return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
397 	case RK3399_ARMCLKL:
398 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
399 		break;
400 	case RK3399_ARMCLKB:
401 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
402 		break;
403 	case RK3399_CLK_SDMMC:
404 		reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(16));
405 		mux = (reg >> 8) & 0x7;
406 		div_con = reg & 0x7f;
407 		switch (mux) {
408 		case 0:
409 			idx = RK3399_PLL_CPLL;
410 			break;
411 		case 1:
412 			idx = RK3399_PLL_GPLL;
413 			break;
414 		case 2:
415 			idx = RK3399_PLL_NPLL;
416 			break;
417 #ifdef notyet
418 		case 3:
419 			idx = RK3399_PLL_PPLL;
420 			break;
421 		case 4:
422 			idx = RK3399_USB_480M;
423 			break;
424 #endif
425 		case 5:
426 			return 24000000 / (div_con + 1);
427 		default:
428 			return 0;
429 		}
430 		return rk3399_get_frequency(sc, &idx) / (div_con + 1);
431 		break;
432 	case RK3399_CLK_UART0:
433 		reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(33));
434 		mux = (reg >> 8) & 0x3;
435 		div_con = reg & 0x7f;
436 		if (mux == 2)
437 			return 24000000 / (div_con + 1);
438 		break;
439 	case RK3399_CLK_UART1:
440 		reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(34));
441 		mux = (reg >> 8) & 0x3;
442 		div_con = reg & 0x7f;
443 		if (mux == 2)
444 			return 24000000 / (div_con + 1);
445 		break;
446 	case RK3399_CLK_UART2:
447 		reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(35));
448 		mux = (reg >> 8) & 0x3;
449 		div_con = reg & 0x7f;
450 		if (mux == 2)
451 			return 24000000 / (div_con + 1);
452 		break;
453 	case RK3399_CLK_UART3:
454 		reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(36));
455 		mux = (reg >> 8) & 0x3;
456 		div_con = reg & 0x7f;
457 		if (mux == 2)
458 			return 24000000 / (div_con + 1);
459 		break;
460 	case RK3399_HCLK_SDMMC:
461 		reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(13));
462 		mux = (reg >> 15) & 0x1;
463 		div_con = (reg >> 8) & 0x1f;
464 		idx = mux ? RK3399_PLL_GPLL : RK3399_PLL_GPLL;
465 		return rk3399_get_frequency(sc, &idx) / (div_con + 1);
466 	default:
467 		break;
468 	}
469 
470 	printf("%s: 0x%08x\n", __func__, idx);
471 	return 0;
472 }
473 
474 int
475 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
476 {
477 	uint32_t idx = cells[0];
478 
479 	printf("%s: 0x%08x\n", __func__, idx);
480 	return -1;
481 }
482 
483 void
484 rk3399_enable(void *cookie, uint32_t *cells, int on)
485 {
486 	uint32_t idx = cells[0];
487 
488 	switch (idx) {
489 	case RK3399_CLK_SDMMC:
490 	case RK3399_CLK_EMMC:
491 	case RK3399_CLK_UART0:
492 	case RK3399_CLK_UART1:
493 	case RK3399_CLK_UART2:
494 	case RK3399_CLK_UART3:
495 	case RK3399_CLK_MAC_RX:
496 	case RK3399_CLK_MAC_TX:
497 	case RK3399_CLK_MAC:
498 	case RK3399_CLK_USB3OTG0_REF:
499 	case RK3399_CLK_USB3OTG1_REF:
500 	case RK3399_CLK_USB3OTG0_SUSPEND:
501 	case RK3399_CLK_USB3OTG1_SUSPEND:
502 	case RK3399_CLK_SDMMC_DRV:
503 	case RK3399_CLK_SDMMC_SAMPLE:
504 	case RK3399_ACLK_EMMC:
505 	case RK3399_ACLK_GMAC:
506 	case RK3399_ACLK_USB3OTG0:
507 	case RK3399_ACLK_USB3OTG1:
508 	case RK3399_ACLK_USB3_GRF:
509 	case RK3399_PCLK_GMAC:
510 	case RK3399_HCLK_HOST0:
511 	case RK3399_HCLK_HOST0_ARB:
512 	case RK3399_HCLK_HOST1:
513 	case RK3399_HCLK_HOST1_ARB:
514 	case RK3399_HCLK_SDMMC:
515 		/* Enabled by default. */
516 		break;
517 	default:
518 		printf("%s: 0x%08x\n", __func__, idx);
519 		break;
520 	}
521 }
522 
523 void
524 rk3399_reset(void *cookie, uint32_t *cells, int on)
525 {
526 	struct rkclock_softc *sc = cookie;
527 	uint32_t idx = cells[0];
528 	uint32_t mask = (1 << (idx % 16));
529 
530 	HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
531 	    mask << 16 | (on ? mask : 0));
532 }
533 
534 int
535 rk3399_cpuspeed(int *freq)
536 {
537 	uint32_t idx = RK3399_ARMCLKL;
538 
539 	*freq = rk3399_get_frequency(rkclock_cpuspeed_sc, &idx) / 1000000;
540 	return 0;
541 }
542 
543 uint32_t
544 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
545 {
546 	uint32_t idx = cells[0];
547 
548 	printf("%s: 0x%08x\n", __func__, idx);
549 	return 0;
550 }
551 
552 int
553 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
554 {
555 	uint32_t idx = cells[0];
556 
557 	printf("%s: 0x%08x\n", __func__, idx);
558 	return -1;
559 }
560 
561 void
562 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
563 {
564 	uint32_t idx = cells[0];
565 
566 	printf("%s: 0x%08x\n", __func__, idx);
567 }
568 
569 void
570 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
571 {
572 	uint32_t idx = cells[0];
573 
574 	printf("%s: 0x%08x\n", __func__, idx);
575 }
576