xref: /openbsd-src/sys/dev/fdt/rkpinctrl.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: rkpinctrl.c,v 1.5 2018/02/25 13:26:44 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2017, 2018 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/device.h>
21 #include <sys/malloc.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_misc.h>
29 #include <dev/ofw/ofw_pinctrl.h>
30 #include <dev/ofw/fdt.h>
31 
32 #ifdef __armv7__
33 #include <arm/simplebus/simplebusvar.h>
34 #else
35 #include <arm64/dev/simplebusvar.h>
36 #endif
37 
38 /* RK3288 registers */
39 #define RK3288_GRF_GPIO1A_IOMUX		0x0000
40 #define RK3288_PMUGRF_GPIO0A_IOMUX	0x0084
41 
42 /* RK3328 registers */
43 #define RK3328_GRF_GPIO0A_IOMUX		0x0000
44 
45 /* RK3399 registers */
46 #define RK3399_GRF_GPIO2A_IOMUX		0xe000
47 #define RK3399_PMUGRF_GPIO0A_IOMUX	0x0000
48 
49 struct rkpinctrl_softc {
50 	struct simplebus_softc	sc_sbus;
51 
52 	struct regmap		*sc_grf;
53 	struct regmap		*sc_pmu;
54 };
55 
56 int	rkpinctrl_match(struct device *, void *, void *);
57 void	rkpinctrl_attach(struct device *, struct device *, void *);
58 
59 struct cfattach	rkpinctrl_ca = {
60 	sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach
61 };
62 
63 struct cfdriver rkpinctrl_cd = {
64 	NULL, "rkpinctrl", DV_DULL
65 };
66 
67 int	rk3288_pinctrl(uint32_t, void *);
68 int	rk3328_pinctrl(uint32_t, void *);
69 int	rk3399_pinctrl(uint32_t, void *);
70 
71 int
72 rkpinctrl_match(struct device *parent, void *match, void *aux)
73 {
74 	struct fdt_attach_args *faa = aux;
75 
76 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") ||
77 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") ||
78 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl"));
79 }
80 
81 void
82 rkpinctrl_attach(struct device *parent, struct device *self, void *aux)
83 {
84 	struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self;
85 	struct fdt_attach_args *faa = aux;
86 	uint32_t grf, pmu;
87 
88 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
89 	pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0);
90 	sc->sc_grf = regmap_byphandle(grf);
91 	sc->sc_pmu = regmap_byphandle(pmu);
92 
93 	if (sc->sc_grf == NULL && sc->sc_pmu == NULL) {
94 		printf(": no registers\n");
95 		return;
96 	}
97 
98 	if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl"))
99 		pinctrl_register(faa->fa_node, rk3288_pinctrl, sc);
100 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl"))
101 		pinctrl_register(faa->fa_node, rk3328_pinctrl, sc);
102 	else
103 		pinctrl_register(faa->fa_node, rk3399_pinctrl, sc);
104 
105 	/* Attach GPIO banks. */
106 	simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa);
107 }
108 
109 /*
110  * Rockchip RK3288
111  */
112 
113 int
114 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
115 {
116 	int node;
117 
118 	node = OF_getnodebyphandle(phandle);
119 	if (node == 0)
120 		return -1;
121 
122 	/* XXX */
123 	if (bank == 0)
124 		return -1;
125 
126 	if (OF_getproplen(node, "bias-disable") == 0)
127 		return 0;
128 	if (OF_getproplen(node, "bias-pull-up") == 0)
129 		return 1;
130 	if (OF_getproplen(node, "bias-pull-down") == 0)
131 		return 2;
132 
133 	return -1;
134 }
135 
136 int
137 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
138 {
139 	int strength, level;
140 	int levels[4] = { 2, 4, 8, 12 };
141 	int node;
142 
143 	node = OF_getnodebyphandle(phandle);
144 	if (node == 0)
145 		return -1;
146 
147 	/* XXX */
148 	if (bank == 0)
149 		return -1;
150 
151 	strength = OF_getpropint(node, "drive-strength", -1);
152 	if (strength == -1)
153 		return -1;
154 
155 	/* Convert drive strength to level. */
156 	for (level = 3; level >= 0; level--) {
157 		if (strength >= levels[level])
158 			break;
159 	}
160 	return level;
161 }
162 
163 int
164 rk3288_pinctrl(uint32_t phandle, void *cookie)
165 {
166 	struct rkpinctrl_softc *sc = cookie;
167 	uint32_t *pins;
168 	int node, len, i;
169 
170 	KASSERT(sc->sc_grf);
171 	KASSERT(sc->sc_pmu);
172 
173 	node = OF_getnodebyphandle(phandle);
174 	if (node == 0)
175 		return -1;
176 
177 	len = OF_getproplen(node, "rockchip,pins");
178 	if (len <= 0)
179 		return -1;
180 
181 	pins = malloc(len, M_TEMP, M_WAITOK);
182 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
183 		goto fail;
184 
185 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
186 		struct regmap *rm;
187 		bus_size_t base, off;
188 		uint32_t bank, idx, mux;
189 		int pull, strength;
190 		uint32_t mask, bits;
191 		int s;
192 
193 		bank = pins[i];
194 		idx = pins[i + 1];
195 		mux = pins[i + 2];
196 		pull = rk3288_pull(bank, idx, pins[i + 3]);
197 		strength = rk3288_strength(bank, idx, pins[i + 3]);
198 
199 		if (bank > 8 || idx > 32 || mux > 7)
200 			continue;
201 
202 		/* Bank 0 lives in the PMU. */
203 		if (bank < 1) {
204 			rm = sc->sc_pmu;
205 			base = RK3288_PMUGRF_GPIO0A_IOMUX;
206 		} else {
207 			rm = sc->sc_grf;
208 			base = RK3288_GRF_GPIO1A_IOMUX - 0x10;
209 		}
210 
211 		s = splhigh();
212 
213 		/* IOMUX control */
214 		off = bank * 0x10 + (idx / 8) * 0x04;
215 
216 		/* GPIO3D, GPIO4A and GPIO4B are special. */
217 		if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) {
218 			mask = (0x7 << ((idx % 4) * 4));
219 			bits = (mux << ((idx % 4) * 4));
220 		} else {
221 			mask = (0x3 << ((idx % 8) * 2));
222 			bits = (mux << ((idx % 8) * 2));
223 		}
224 		if (bank > 3 || (bank == 3 && idx >= 28))
225 			off += 0x04;
226 		if (bank > 4 || (bank == 4 && idx >= 4))
227 			off += 0x04;
228 		if (bank > 4 || (bank == 4 && idx >= 12))
229 			off += 0x04;
230 		regmap_write_4(rm, base + off, mask << 16 | bits);
231 
232 		/* GPIO pad pull down and pull up control */
233 		if (pull >= 0) {
234 			off = 0x140 + bank * 0x10 + (idx / 8) * 0x04;
235 			mask = (0x3 << ((idx % 8) * 2));
236 			bits = (pull << ((idx % 8) * 2));
237 			regmap_write_4(rm, base + off, mask << 16 | bits);
238 		}
239 
240 		/* GPIO drive strength control */
241 		if (strength >= 0) {
242 			off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04;
243 			mask = (0x3 << ((idx % 8) * 2));
244 			bits = (strength << ((idx % 8) * 2));
245 			regmap_write_4(rm, base + off, mask << 16 | bits);
246 		}
247 
248 		splx(s);
249 	}
250 
251 	free(pins, M_TEMP, len);
252 	return 0;
253 
254 fail:
255 	free(pins, M_TEMP, len);
256 	return -1;
257 }
258 
259 /*
260  * Rockchip RK3328
261  */
262 
263 int
264 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
265 {
266 	int node;
267 
268 	node = OF_getnodebyphandle(phandle);
269 	if (node == 0)
270 		return -1;
271 
272 	if (OF_getproplen(node, "bias-disable") == 0)
273 		return 0;
274 	if (OF_getproplen(node, "bias-pull-up") == 0)
275 		return 1;
276 	if (OF_getproplen(node, "bias-pull-down") == 0)
277 		return 2;
278 
279 	return -1;
280 }
281 
282 int
283 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
284 {
285 	int strength, level;
286 	int levels[4] = { 2, 4, 8, 12 };
287 	int node;
288 
289 	node = OF_getnodebyphandle(phandle);
290 	if (node == 0)
291 		return -1;
292 
293 	strength = OF_getpropint(node, "drive-strength", -1);
294 	if (strength == -1)
295 		return -1;
296 
297 	/* Convert drive strength to level. */
298 	for (level = 3; level >= 0; level--) {
299 		if (strength >= levels[level])
300 			break;
301 	}
302 	return level;
303 }
304 
305 int
306 rk3328_pinctrl(uint32_t phandle, void *cookie)
307 {
308 	struct rkpinctrl_softc *sc = cookie;
309 	uint32_t *pins;
310 	int node, len, i;
311 
312 	KASSERT(sc->sc_grf);
313 
314 	node = OF_getnodebyphandle(phandle);
315 	if (node == 0)
316 		return -1;
317 
318 	len = OF_getproplen(node, "rockchip,pins");
319 	if (len <= 0)
320 		return -1;
321 
322 	pins = malloc(len, M_TEMP, M_WAITOK);
323 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
324 		goto fail;
325 
326 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
327 		struct regmap *rm = sc->sc_grf;
328 		bus_size_t base, off;
329 		uint32_t bank, idx, mux;
330 		int pull, strength;
331 		uint32_t mask, bits;
332 		int s;
333 
334 		bank = pins[i];
335 		idx = pins[i + 1];
336 		mux = pins[i + 2];
337 		pull = rk3288_pull(bank, idx, pins[i + 3]);
338 		strength = rk3288_strength(bank, idx, pins[i + 3]);
339 
340 		if (bank > 3 || idx > 32 || mux > 3)
341 			continue;
342 
343 		base = RK3328_GRF_GPIO0A_IOMUX;
344 
345 		s = splhigh();
346 
347 		/* IOMUX control */
348 		off = bank * 0x10 + (idx / 8) * 0x04;
349 
350 		/* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */
351 		if (bank == 2 && idx == 15) {
352 			mask = 0x7;
353 			bits = mux;
354 		} else if (bank == 2 && idx >= 16 && idx <= 20) {
355 			mask = (0x7 << ((idx - 16) * 3));
356 			bits = (mux << ((idx - 16) * 3));
357 		} else if (bank == 2 && idx >= 21 && idx <= 23) {
358 			mask = (0x7 << ((idx - 21) * 3));
359 			bits = (mux << ((idx - 21) * 3));
360 		} else if (bank == 3 && idx <= 4) {
361 			mask = (0x7 << (idx * 3));
362 			bits = (mux << (idx * 3));
363 		} else if (bank == 3 && idx >= 5 && idx <= 7) {
364 			mask = (0x7 << ((idx - 5) * 3));
365 			bits = (mux << ((idx - 5) * 3));
366 		} else if (bank == 3 && idx >= 8 && idx <= 12) {
367 			mask = (0x7 << ((idx - 8) * 3));
368 			bits = (mux << ((idx - 8) * 3));
369 		} else if (bank == 3 && idx >= 13 && idx <= 15) {
370 			mask = (0x7 << ((idx - 13) * 3));
371 			bits = (mux << ((idx - 13) * 3));
372 		} else {
373 			mask = (0x3 << ((idx % 8) * 2));
374 			bits = (mux << ((idx % 8) * 2));
375 		}
376 		if (bank > 2 || (bank == 2 && idx >= 15))
377 			off += 0x04;
378 		if (bank > 2 || (bank == 2 && idx >= 21))
379 			off += 0x04;
380 		if (bank > 3 || (bank == 3 && idx >= 5))
381 			off += 0x04;
382 		if (bank > 3 || (bank == 3 && idx >= 13))
383 			off += 0x04;
384 		regmap_write_4(rm, base + off, mask << 16 | bits);
385 
386 		/* GPIO pad pull down and pull up control */
387 		if (pull >= 0) {
388 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
389 			mask = (0x3 << ((idx % 8) * 2));
390 			bits = (pull << ((idx % 8) * 2));
391 			regmap_write_4(rm, base + off, mask << 16 | bits);
392 		}
393 
394 		/* GPIO drive strength control */
395 		if (strength >= 0) {
396 			off = 0x200 + bank * 0x10 + (idx / 8) * 0x04;
397 			mask = (0x3 << ((idx % 8) * 2));
398 			bits = (strength << ((idx % 8) * 2));
399 			regmap_write_4(rm, base + off, mask << 16 | bits);
400 		}
401 
402 		splx(s);
403 	}
404 
405 	free(pins, M_TEMP, len);
406 	return 0;
407 
408 fail:
409 	free(pins, M_TEMP, len);
410 	return -1;
411 }
412 
413 /*
414  * Rockchip RK3399
415  */
416 
417 int
418 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
419 {
420 	int pull_up, pull_down;
421 	int node;
422 
423 	node = OF_getnodebyphandle(phandle);
424 	if (node == 0)
425 		return -1;
426 
427 	if (bank == 2 && idx >= 16) {
428 		pull_up = 3;
429 		pull_down = 1;
430 	} else {
431 		pull_up = 1;
432 		pull_down = 2;
433 	}
434 
435 	if (OF_getproplen(node, "bias-disable") == 0)
436 		return 0;
437 	if (OF_getproplen(node, "bias-pull-up") == 0)
438 		return pull_up;
439 	if (OF_getproplen(node, "bias-pull-down") == 0)
440 		return pull_down;
441 
442 	return -1;
443 }
444 
445 /* Magic because the drive strength configurations vary wildly. */
446 
447 int rk3399_strength_levels[][8] = {
448 	{ 2, 4, 8, 12 },			/* default */
449 	{ 3, 6, 9, 12 },			/* 1.8V or 3.0V */
450 	{ 5, 10, 15, 20 },			/* 1.8V only */
451 	{ 4, 6, 8, 10, 12, 14, 16, 18 },	/* 1.8V or 3.0V auto */
452 	{ 4, 7, 10, 13, 16, 19, 22, 26 },	/* 3.3V */
453 };
454 
455 int rk3399_strength_types[][4] = {
456 	{ 2, 2, 0, 0 },
457 	{ 1, 1, 1, 1 },
458 	{ 1, 1, 2, 2 },
459 	{ 4, 4, 4, 1 },
460 	{ 1, 3, 1, 1 },
461 };
462 
463 int rk3399_strength_regs[][4] = {
464 	{ 0x0080, 0x0088, 0x0090, 0x0098 },
465 	{ 0x00a0, 0x00a8, 0x00b0, 0x00b8 },
466 	{ 0x0100, 0x0104, 0x0108, 0x010c },
467 	{ 0x0110, 0x0118, 0x0120, 0x0128 },
468 	{ 0x012c, 0x0130, 0x0138, 0x013c },
469 };
470 
471 int
472 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
473 {
474 	int strength, type, level;
475 	int *levels;
476 	int node;
477 
478 	node = OF_getnodebyphandle(phandle);
479 	if (node == 0)
480 		return -1;
481 
482 	strength = OF_getpropint(node, "drive-strength", -1);
483 	if (strength == -1)
484 		return -1;
485 
486 	/* Convert drive strength to level. */
487 	type = rk3399_strength_types[bank][idx / 8];
488 	levels = rk3399_strength_levels[type];
489 	for (level = 7; level >= 0; level--) {
490 		if (strength >= levels[level] && levels[level] > 0)
491 			break;
492 	}
493 	return level;
494 }
495 
496 int
497 rk3399_pinctrl(uint32_t phandle, void *cookie)
498 {
499 	struct rkpinctrl_softc *sc = cookie;
500 	uint32_t *pins;
501 	int node, len, i;
502 
503 	KASSERT(sc->sc_grf);
504 	KASSERT(sc->sc_pmu);
505 
506 	node = OF_getnodebyphandle(phandle);
507 	if (node == 0)
508 		return -1;
509 
510 	len = OF_getproplen(node, "rockchip,pins");
511 	if (len <= 0)
512 		return -1;
513 
514 	pins = malloc(len, M_TEMP, M_WAITOK);
515 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
516 		goto fail;
517 
518 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
519 		struct regmap *rm;
520 		bus_size_t base, off;
521 		uint32_t bank, idx, mux;
522 		int pull, strength, type, shift;
523 		uint32_t mask, bits;
524 		int s;
525 
526 		bank = pins[i];
527 		idx = pins[i + 1];
528 		mux = pins[i + 2];
529 		pull = rk3399_pull(bank, idx, pins[i + 3]);
530 		strength = rk3399_strength(bank, idx, pins[i + 3]);
531 
532 		if (bank > 5 || idx > 32 || mux > 3)
533 			continue;
534 
535 		/* Bank 0 and 1 live in the PMU. */
536 		if (bank < 2) {
537 			rm = sc->sc_pmu;
538 			base = RK3399_PMUGRF_GPIO0A_IOMUX;
539 		} else {
540 			rm = sc->sc_grf;
541 			base = RK3399_GRF_GPIO2A_IOMUX - 0x20;
542 		}
543 
544 		s = splhigh();
545 
546 		/* IOMUX control */
547 		off = bank * 0x10 + (idx / 8) * 0x04;
548 		mask = (0x3 << ((idx % 8) * 2));
549 		bits = (mux << ((idx % 8) * 2));
550 		regmap_write_4(rm, base + off, mask << 16 | bits);
551 
552 		/* GPIO pad pull down and pull up control */
553 		if (pull >= 0) {
554 			off = 0x40 + bank * 0x10 + (idx / 8) * 0x04;
555 			mask = (0x3 << ((idx % 8) * 2));
556 			bits = (pull << ((idx % 8) * 2));
557 			regmap_write_4(rm, base + off, mask << 16 | bits);
558 		}
559 
560 		/* GPIO drive strength control */
561 		if (strength >= 0) {
562 			off = rk3399_strength_regs[bank][idx / 8];
563 			type = rk3399_strength_types[bank][idx / 8];
564 			shift = (type > 2) ? 3 : 2;
565 			mask = (((1 << shift) - 1) << ((idx % 8) * shift));
566 			bits = (strength << ((idx % 8) * shift));
567 			if (mask & 0x0000ffff) {
568 				regmap_write_4(rm, base + off,
569 				    mask << 16 | (bits & 0x0000ffff));
570 			}
571 			if (mask & 0xffff0000) {
572 				regmap_write_4(rm, base + off + 0x04,
573 				    (mask & 0xffff0000) | bits >> 16);
574 			}
575 		}
576 
577 		splx(s);
578 	}
579 
580 	free(pins, M_TEMP, len);
581 	return 0;
582 
583 fail:
584 	free(pins, M_TEMP, len);
585 	return -1;
586 }
587