xref: /openbsd/sys/dev/fdt/sxipio.c (revision 3cab2bb3)
1 /*	$OpenBSD: sxipio.c,v 1.12 2020/03/29 09:35:10 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2010 Miodrag Vallat.
4  * Copyright (c) 2013 Artturi Alm
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/gpio.h>
23 #include <sys/evcount.h>
24 #include <sys/malloc.h>
25 
26 #include <machine/bus.h>
27 #include <machine/fdt.h>
28 #include <machine/intr.h>
29 
30 #include <dev/gpio/gpiovar.h>
31 #include <dev/ofw/openfirm.h>
32 #include <dev/ofw/ofw_clock.h>
33 #include <dev/ofw/ofw_gpio.h>
34 #include <dev/ofw/ofw_pinctrl.h>
35 #include <dev/ofw/ofw_regulator.h>
36 #include <dev/ofw/fdt.h>
37 
38 #include <dev/fdt/sunxireg.h>
39 #include <dev/fdt/sxipiovar.h>
40 
41 #include "gpio.h"
42 
43 #define	SXIPIO_NPORT		9
44 
45 struct sxipio_softc;
46 
47 struct sxipio_gpio {
48 	struct sxipio_softc *sc;
49 	int port;
50 };
51 
52 struct intrhand {
53 	int (*ih_func)(void *);		/* handler */
54 	void *ih_arg;			/* arg for handler */
55 	int ih_ipl;			/* IPL_* */
56 	int ih_irq;			/* IRQ number */
57 	int ih_gpio;			/* gpio pin */
58 	struct evcount ih_count;
59 	char *ih_name;
60 };
61 
62 struct sxipio_softc {
63 	struct device		sc_dev;
64 	bus_space_tag_t		sc_iot;
65 	bus_space_handle_t	sc_ioh;
66 	int			sc_node;
67 	void			*sc_ih_h;
68 	void			*sc_ih_l;
69 	int 			sc_max_il;
70 	int 			sc_min_il;
71 
72 	struct sxipio_pin	*sc_pins;
73 	int			sc_npins;
74 	struct gpio_controller	sc_gc;
75 
76 	struct sxipio_gpio	sc_gpio[SXIPIO_NPORT];
77 	struct gpio_chipset_tag	sc_gpio_tag[SXIPIO_NPORT];
78 	gpio_pin_t		sc_gpio_pins[SXIPIO_NPORT][32];
79 
80 	struct intrhand		*sc_handlers[32];
81 
82 	void			(*sc_bias_cfg)(struct sxipio_softc *,
83 				    int, uint32_t);
84 };
85 
86 #define	SXIPIO_CFG(port, pin)	0x00 + ((port) * 0x24) + (((pin) >> 3) * 0x04)
87 #define	SXIPIO_DAT(port)	0x10 + ((port) * 0x24)
88 #define	SXIPIO_DRV(port, pin)	0x14 + ((port) * 0x24) + (((pin) >> 4) * 0x04)
89 #define	SXIPIO_PUL(port, pin)	0x1c + ((port) * 0x24) + (((pin) >> 4) * 0x04)
90 #define	SXIPIO_INT_CFG0(port)	0x0200 + ((port) * 0x04)
91 #define	SXIPIO_INT_CTL		0x0210
92 #define	SXIPIO_INT_STA		0x0214
93 #define	SXIPIO_INT_DEB		0x0218 /* debounce register */
94 #define	SXIPIO_GRP_CFG(port)	0x0300 + ((port) * 0x04)
95 #define	 SXIPIO_IO_BIAS_MASK		(0xf << 0)
96 #define	 SXIPIO_IO_BIAS_1_8V		0x0
97 #define	 SXIPIO_IO_BIAS_2_5V		0x6
98 #define	 SXIPIO_IO_BIAS_2_8V		0x9
99 #define	 SXIPIO_IO_BIAS_3_0V		0xa
100 #define	 SXIPIO_IO_BIAS_3_3V		0xd
101 
102 #define SXIPIO_GPIO_IN		0
103 #define SXIPIO_GPIO_OUT		1
104 #define SXIPIO_DISABLED		7
105 
106 int	sxipio_match(struct device *, void *, void *);
107 void	sxipio_attach(struct device *, struct device *, void *);
108 
109 struct cfattach sxipio_ca = {
110 	sizeof (struct sxipio_softc), sxipio_match, sxipio_attach
111 };
112 
113 struct cfdriver sxipio_cd = {
114 	NULL, "sxipio", DV_DULL
115 };
116 
117 void	sxipio_attach_gpio(struct device *);
118 int	sxipio_pinctrl(uint32_t, void *);
119 void	sxipio_config_pin(void *, uint32_t *, int);
120 int	sxipio_get_pin(void *, uint32_t *);
121 void	sxipio_set_pin(void *, uint32_t *, int);
122 void	sxipio_a80_bias_cfg(struct sxipio_softc *, int, uint32_t);
123 
124 #include "sxipio_pins.h"
125 
126 struct sxipio_pins {
127 	const char *compat;
128 	struct sxipio_pin *pins;
129 	int npins;
130 };
131 
132 struct sxipio_pins sxipio_pins[] = {
133 	{
134 		"allwinner,sun4i-a10-pinctrl",
135 		sun4i_a10_pins, nitems(sun4i_a10_pins)
136 	},
137 	{
138 		"allwinner,sun5i-a10s-pinctrl",
139 		sun5i_a10s_pins, nitems(sun5i_a10s_pins)
140 	},
141 	{
142 		"allwinner,sun5i-a13-pinctrl",
143 		sun5i_a13_pins, nitems(sun5i_a13_pins)
144 	},
145 	{
146 		"allwinner,sun5i-gr8-pinctrl",
147 		sun5i_gr8_pins, nitems(sun5i_gr8_pins)
148 	},
149 	{
150 		"allwinner,sun7i-a20-pinctrl",
151 		sun7i_a20_pins, nitems(sun7i_a20_pins)
152 	},
153 	{
154 		"allwinner,sun8i-r40-pinctrl",
155 		sun8i_r40_pins, nitems(sun8i_r40_pins)
156 	},
157 	{
158 		"allwinner,sun8i-a33-pinctrl",
159 		sun8i_a33_pins, nitems(sun8i_a33_pins)
160 	},
161 	{
162 		"allwinner,sun8i-h3-pinctrl",
163 		sun8i_h3_pins, nitems(sun8i_h3_pins)
164 	},
165 	{
166 		"allwinner,sun8i-h3-r-pinctrl",
167 		sun8i_h3_r_pins, nitems(sun8i_h3_r_pins)
168 	},
169 	{
170 		"allwinner,sun8i-v3s-pinctrl",
171 		sun8i_v3s_pins, nitems(sun8i_v3s_pins)
172 	},
173 	{
174 		"allwinner,sun9i-a80-pinctrl",
175 		sun9i_a80_pins, nitems(sun9i_a80_pins)
176 	},
177 	{
178 		"allwinner,sun9i-a80-r-pinctrl",
179 		sun9i_a80_r_pins, nitems(sun9i_a80_r_pins)
180 	},
181 	{
182 		"allwinner,sun50i-a64-pinctrl",
183 		sun50i_a64_pins, nitems(sun50i_a64_pins)
184 	},
185 	{
186 		"allwinner,sun50i-a64-r-pinctrl",
187 		sun50i_a64_r_pins, nitems(sun50i_a64_r_pins)
188 	},
189 	{
190 		"allwinner,sun50i-h5-pinctrl",
191 		sun50i_h5_pins, nitems(sun50i_h5_pins)
192 	},
193 	{
194 		"allwinner,sun50i-h6-pinctrl",
195 		sun50i_h6_pins, nitems(sun50i_h6_pins)
196 	},
197 	{
198 		"allwinner,sun50i-h6-r-pinctrl",
199 		sun50i_h6_r_pins, nitems(sun50i_h6_r_pins)
200 	},
201 };
202 
203 int
204 sxipio_match(struct device *parent, void *match, void *aux)
205 {
206 	struct fdt_attach_args *faa = aux;
207 	int i;
208 
209 	for (i = 0; i < nitems(sxipio_pins); i++) {
210 		if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat))
211 			return 1;
212 	}
213 
214 	return 0;
215 }
216 
217 void
218 sxipio_attach(struct device *parent, struct device *self, void *aux)
219 {
220 	struct sxipio_softc *sc = (struct sxipio_softc *)self;
221 	struct fdt_attach_args	*faa = aux;
222 	int i;
223 
224 	sc->sc_iot = faa->fa_iot;
225 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
226 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
227 		panic("%s: bus_space_map failed!", __func__);
228 	sc->sc_node = faa->fa_node;
229 
230 	clock_enable_all(faa->fa_node);
231 	reset_deassert_all(faa->fa_node);
232 
233 	for (i = 0; i < nitems(sxipio_pins); i++) {
234 		if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) {
235 			sc->sc_pins = sxipio_pins[i].pins;
236 			sc->sc_npins = sxipio_pins[i].npins;
237 			break;
238 		}
239 	}
240 
241 	/* Allwinner A80 needs IO pad bias configuration. */
242 	if (OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-pinctrl") ||
243 	    OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-r-pinctrl"))
244 		sc->sc_bias_cfg = sxipio_a80_bias_cfg;
245 
246 	KASSERT(sc->sc_pins);
247 	pinctrl_register(faa->fa_node, sxipio_pinctrl, sc);
248 
249 	sc->sc_gc.gc_node = faa->fa_node;
250 	sc->sc_gc.gc_cookie = sc;
251 	sc->sc_gc.gc_config_pin = sxipio_config_pin;
252 	sc->sc_gc.gc_get_pin = sxipio_get_pin;
253 	sc->sc_gc.gc_set_pin = sxipio_set_pin;
254 	gpio_controller_register(&sc->sc_gc);
255 
256 	config_defer(self, sxipio_attach_gpio);
257 
258 	printf(": %d pins\n", sc->sc_npins);
259 }
260 
261 int
262 sxipio_drive(int node)
263 {
264 	int drive;
265 
266 	drive = OF_getpropint(node, "allwinner,drive", -1);
267 	if (drive >= 0)
268 		return drive;
269 	drive = OF_getpropint(node, "drive-strength", 0) - 10;
270 	if (drive >= 0)
271 		return (drive / 10);
272 	return -1;
273 }
274 
275 int
276 sxipio_pull(int node)
277 {
278 	int pull;
279 
280 	pull = OF_getpropint(node, "allwinner,pull", -1);
281 	if (pull >= 0)
282 		return pull;
283 	if (OF_getproplen(node, "bias-disable") == 0)
284 		return 0;
285 	if (OF_getproplen(node, "bias-pull-up") == 0)
286 		return 1;
287 	if (OF_getproplen(node, "bias-pull-down") == 0)
288 		return 2;
289 	return -1;
290 }
291 
292 int
293 sxipio_pinctrl(uint32_t phandle, void *cookie)
294 {
295 	struct sxipio_softc *sc = cookie;
296 	char func[32];
297 	char vcc[16];
298 	char *names, *name;
299 	uint32_t supply;
300 	int group, port, pin, off, mask;
301 	int mux, drive, pull;
302 	int node;
303 	int len;
304 	int i, j;
305 	int s;
306 
307 	node = OF_getnodebyphandle(phandle);
308 	if (node == 0)
309 		return -1;
310 
311 	len = OF_getprop(node, "allwinner,function", func, sizeof(func));
312 	if (len <= 0 || len >= sizeof(func)) {
313 		len = OF_getprop(node, "function", func, sizeof(func));
314 		if (len <= 0 || len >= sizeof(func))
315 			return -1;
316 	}
317 
318 	len = OF_getproplen(node, "allwinner,pins");
319 	if (len <= 0) {
320 		len = OF_getproplen(node, "pins");
321 		if (len <= 0)
322 			return -1;
323 	}
324 
325 	names = malloc(len, M_TEMP, M_WAITOK);
326 	if (OF_getprop(node, "allwinner,pins", names, len) <= 0)
327 		OF_getprop(node, "pins", names, len);
328 
329 	drive = sxipio_drive(node);
330 	pull = sxipio_pull(node);
331 
332 	name = names;
333 	while (len > 0) {
334 		/* Lookup the pin. */
335 		for (i = 0; i < sc->sc_npins; i++) {
336 			if (strcmp(name, sc->sc_pins[i].name) == 0)
337 				break;
338 		}
339 		if (i >= sc->sc_npins)
340 			goto err;
341 
342 		/* Lookup the function of the pin. */
343 		for (j = 0; j < nitems(sc->sc_pins[i].funcs); j++) {
344 			if (sc->sc_pins[i].funcs[j].name == NULL)
345 				continue;
346 			if (strcmp(func, sc->sc_pins[i].funcs[j].name) == 0)
347 				break;
348 		}
349 		if (j > nitems(sc->sc_pins[i].funcs))
350 			goto err;
351 
352 		group = sc->sc_pins[i].name[1] - 'A';
353 		port = sc->sc_pins[i].port;
354 		pin = sc->sc_pins[i].pin;
355 		mux = sc->sc_pins[i].funcs[j].mux;
356 
357 		snprintf(vcc, sizeof(vcc), "vcc-p%c-supply", 'a' + group);
358 		supply = OF_getpropint(sc->sc_node, vcc, 0);
359 		if (supply) {
360 			regulator_enable(supply);
361 			if (sc->sc_bias_cfg)
362 				sc->sc_bias_cfg(sc, port, supply);
363 		}
364 
365 		s = splhigh();
366 		off = (pin & 0x7) << 2, mask = (0x7 << off);
367 		SXICMS4(sc, SXIPIO_CFG(port, pin), mask, mux << off);
368 		off = (pin & 0xf) << 1, mask = (0x3 << off);
369 		if (drive >= 0 && drive < 4)
370 			SXICMS4(sc, SXIPIO_DRV(port, pin), mask, drive << off);
371 		if (pull >= 0 && pull < 3)
372 			SXICMS4(sc, SXIPIO_PUL(port, pin), mask, pull << off);
373 		splx(s);
374 
375 		len -= strlen(name) + 1;
376 		name += strlen(name) + 1;
377 	}
378 
379 	free(names, M_TEMP, len);
380 	return 0;
381 
382 err:
383 	free(names, M_TEMP, len);
384 	return -1;
385 }
386 
387 void
388 sxipio_config_pin(void *cookie, uint32_t *cells, int config)
389 {
390 	struct sxipio_softc *sc = cookie;
391 	uint32_t port = cells[0];
392 	uint32_t pin = cells[1];
393 	int mux, off;
394 
395 	if (port > SXIPIO_NPORT || pin > 32)
396 		return;
397 
398 	mux = (config & GPIO_CONFIG_OUTPUT) ? 1 : 0;
399 	off = (pin & 0x7) << 2;
400 	SXICMS4(sc, SXIPIO_CFG(port, pin), 0x7 << off, mux << off);
401 }
402 
403 int
404 sxipio_get_pin(void *cookie, uint32_t *cells)
405 {
406 	struct sxipio_softc *sc = cookie;
407 	uint32_t port = cells[0];
408 	uint32_t pin = cells[1];
409 	uint32_t flags = cells[2];
410 	uint32_t reg;
411 	int val;
412 
413 	if (port > SXIPIO_NPORT || pin > 32)
414 		return 0;
415 
416 	reg = SXIREAD4(sc, SXIPIO_DAT(port));
417 	reg &= (1 << pin);
418 	val = (reg >> pin) & 1;
419 	if (flags & GPIO_ACTIVE_LOW)
420 		val = !val;
421 	return val;
422 }
423 
424 void
425 sxipio_set_pin(void *cookie, uint32_t *cells, int val)
426 {
427 	struct sxipio_softc *sc = cookie;
428 	uint32_t port = cells[0];
429 	uint32_t pin = cells[1];
430 	uint32_t flags = cells[2];
431 	uint32_t reg;
432 
433 	if (port > SXIPIO_NPORT || pin > 32)
434 		return;
435 
436 	reg = SXIREAD4(sc, SXIPIO_DAT(port));
437 	if (flags & GPIO_ACTIVE_LOW)
438 		val = !val;
439 	if (val)
440 		reg |= (1 << pin);
441 	else
442 		reg &= ~(1 << pin);
443 	SXIWRITE4(sc, SXIPIO_DAT(port), reg);
444 }
445 
446 void
447 sxipio_a80_bias_cfg(struct sxipio_softc *sc, int port, uint32_t supply)
448 {
449 	uint32_t voltage;
450 	uint32_t bias;
451 
452 	voltage = regulator_get_voltage(supply);
453 	if (voltage <= 1800000)
454 		bias = SXIPIO_IO_BIAS_1_8V;
455 	else if (voltage <= 2500000)
456 		bias = SXIPIO_IO_BIAS_2_5V;
457 	else if (voltage <= 2800000)
458 		bias = SXIPIO_IO_BIAS_2_8V;
459 	else if (voltage <= 3000000)
460 		bias = SXIPIO_IO_BIAS_3_0V;
461 	else
462 		bias = SXIPIO_IO_BIAS_3_3V;
463 
464 	SXICMS4(sc, SXIPIO_GRP_CFG(port), SXIPIO_IO_BIAS_MASK, bias);
465 }
466 
467 /*
468  * GPIO support code
469  */
470 
471 int	sxipio_pin_read(void *, int);
472 void	sxipio_pin_write(void *, int, int);
473 void	sxipio_pin_ctl(void *, int, int);
474 
475 static const struct gpio_chipset_tag sxipio_gpio_tag = {
476 	.gp_pin_read = sxipio_pin_read,
477 	.gp_pin_write = sxipio_pin_write,
478 	.gp_pin_ctl = sxipio_pin_ctl
479 };
480 
481 int
482 sxipio_pin_read(void *cookie, int pin)
483 {
484 	struct sxipio_gpio *gpio = cookie;
485 	uint32_t cells[3];
486 
487 	cells[0] = gpio->port;
488 	cells[1] = pin;
489 	cells[2] = 0;
490 
491 	return sxipio_get_pin(gpio->sc, cells) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
492 }
493 
494 void
495 sxipio_pin_write(void *cookie, int pin, int val)
496 {
497 	struct sxipio_gpio *gpio = cookie;
498 	uint32_t cells[3];
499 
500 	cells[0] = gpio->port;
501 	cells[1] = pin;
502 	cells[2] = 0;
503 
504 	sxipio_set_pin(gpio->sc, cells, val);
505 }
506 
507 void
508 sxipio_pin_ctl(void *cookie, int pin, int flags)
509 {
510 	struct sxipio_gpio *gpio = cookie;
511 	uint32_t cells[3];
512 
513 	cells[0] = gpio->port;
514 	cells[1] = pin;
515 	cells[2] = 0;
516 
517 	if (ISSET(flags, GPIO_PIN_OUTPUT))
518 		sxipio_config_pin(gpio->sc, cells, GPIO_CONFIG_OUTPUT);
519 	else
520 		sxipio_config_pin(gpio->sc, cells, 0);
521 }
522 
523 void
524 sxipio_attach_gpio(struct device *parent)
525 {
526 	struct sxipio_softc *sc = (struct sxipio_softc *)parent;
527 	struct gpiobus_attach_args gba;
528 	uint32_t reg;
529 	int port, pin;
530 	int off, mux;
531 	int state, flags;
532 	int i;
533 
534 	for (i = 0; i < sc->sc_npins; i++) {
535 		/* Skip pins that have no gpio function. */
536 		if (strcmp(sc->sc_pins[i].funcs[0].name, "gpio_in") != 0 ||
537 		    strcmp(sc->sc_pins[i].funcs[1].name, "gpio_out") != 0)
538 			continue;
539 
540 		port = sc->sc_pins[i].port;
541 		pin = sc->sc_pins[i].pin;
542 
543 		/* Get pin configuration. */
544 		reg = SXIREAD4(sc, SXIPIO_CFG(port, pin));
545 		off = (pin & 0x7) << 2;
546 		mux = (reg >> off) & 0x7;
547 
548 		/* Skip pins that have been assigned other functions. */
549 		if (mux != SXIPIO_GPIO_IN && mux != SXIPIO_GPIO_OUT &&
550 		    mux != SXIPIO_DISABLED)
551 			continue;
552 
553 		switch (mux) {
554 		case SXIPIO_GPIO_IN:
555 			flags = GPIO_PIN_SET | GPIO_PIN_INPUT;
556 			break;
557 		case SXIPIO_GPIO_OUT:
558 			flags = GPIO_PIN_SET | GPIO_PIN_OUTPUT;
559 			break;
560 		default:
561 			flags = GPIO_PIN_SET;
562 		}
563 
564 		/* Get pin state. */
565 		reg = SXIREAD4(sc, SXIPIO_DAT(port));
566 		state = (reg >> pin) & 1;
567 
568 		sc->sc_gpio_pins[port][pin].pin_caps =
569 		    GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
570 		sc->sc_gpio_pins[port][pin].pin_flags = flags;
571 		sc->sc_gpio_pins[port][pin].pin_state = state;
572 		sc->sc_gpio_pins[port][pin].pin_num = pin;
573 	}
574 
575 	for (i = 0; i <= port; i++) {
576 		memcpy(&sc->sc_gpio_tag[i], &sxipio_gpio_tag, sizeof(sxipio_gpio_tag));
577 		sc->sc_gpio_tag[i].gp_cookie = &sc->sc_gpio[i];
578 		sc->sc_gpio[i].sc = sc;
579 		sc->sc_gpio[i].port = i;
580 
581 		gba.gba_name = "gpio";
582 		gba.gba_gc = &sc->sc_gpio_tag[i];
583 		gba.gba_pins = &sc->sc_gpio_pins[i][0];
584 		gba.gba_npins = 32;
585 
586 #if NGPIO > 0
587 		config_found(&sc->sc_dev, &gba, gpiobus_print);
588 #endif
589 	}
590 }
591