a10_gpio.c revision 324755
1/*-
2 * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
3 * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
4 * Copyright (c) 2012 Luiz Otavio O Souza.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: stable/11/sys/arm/allwinner/a10_gpio.c 324755 2017-10-19 16:07:57Z ian $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35
36#include <sys/kernel.h>
37#include <sys/module.h>
38#include <sys/rman.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/gpio.h>
42
43#include <machine/bus.h>
44#include <machine/resource.h>
45#include <machine/intr.h>
46
47#include <dev/fdt/fdt_common.h>
48#include <dev/fdt/fdt_pinctrl.h>
49#include <dev/gpio/gpiobusvar.h>
50#include <dev/ofw/ofw_bus.h>
51#include <dev/ofw/ofw_bus_subr.h>
52
53#include <arm/allwinner/aw_machdep.h>
54#include <arm/allwinner/allwinner_pinctrl.h>
55#include <dev/extres/clk/clk.h>
56#include <dev/extres/hwreset/hwreset.h>
57
58#include "gpio_if.h"
59
60#define	A10_GPIO_DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |	\
61    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
62
63#define	A10_GPIO_NONE		0
64#define	A10_GPIO_PULLUP		1
65#define	A10_GPIO_PULLDOWN	2
66
67#define	A10_GPIO_INPUT		0
68#define	A10_GPIO_OUTPUT		1
69
70#define	AW_GPIO_DRV_MASK	0x3
71#define	AW_GPIO_PUD_MASK	0x3
72
73#define	AW_PINCTRL	1
74#define	AW_R_PINCTRL	2
75
76/* Defined in a10_padconf.c */
77#ifdef SOC_ALLWINNER_A10
78extern const struct allwinner_padconf a10_padconf;
79#endif
80
81/* Defined in a13_padconf.c */
82#ifdef SOC_ALLWINNER_A13
83extern const struct allwinner_padconf a13_padconf;
84#endif
85
86/* Defined in a20_padconf.c */
87#ifdef SOC_ALLWINNER_A20
88extern const struct allwinner_padconf a20_padconf;
89#endif
90
91/* Defined in a31_padconf.c */
92#ifdef SOC_ALLWINNER_A31
93extern const struct allwinner_padconf a31_padconf;
94#endif
95
96/* Defined in a31s_padconf.c */
97#ifdef SOC_ALLWINNER_A31S
98extern const struct allwinner_padconf a31s_padconf;
99#endif
100
101#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
102extern const struct allwinner_padconf a31_r_padconf;
103#endif
104
105/* Defined in h3_padconf.c */
106#ifdef SOC_ALLWINNER_H3
107extern const struct allwinner_padconf h3_padconf;
108extern const struct allwinner_padconf h3_r_padconf;
109#endif
110
111/* Defined in a83t_padconf.c */
112#ifdef SOC_ALLWINNER_A83T
113extern const struct allwinner_padconf a83t_padconf;
114extern const struct allwinner_padconf a83t_r_padconf;
115#endif
116
117static struct ofw_compat_data compat_data[] = {
118#ifdef SOC_ALLWINNER_A10
119	{"allwinner,sun4i-a10-pinctrl",		(uintptr_t)&a10_padconf},
120#endif
121#ifdef SOC_ALLWINNER_A13
122	{"allwinner,sun5i-a13-pinctrl",		(uintptr_t)&a13_padconf},
123#endif
124#ifdef SOC_ALLWINNER_A20
125	{"allwinner,sun7i-a20-pinctrl",		(uintptr_t)&a20_padconf},
126#endif
127#ifdef SOC_ALLWINNER_A31
128	{"allwinner,sun6i-a31-pinctrl",		(uintptr_t)&a31_padconf},
129#endif
130#ifdef SOC_ALLWINNER_A31S
131	{"allwinner,sun6i-a31s-pinctrl",	(uintptr_t)&a31s_padconf},
132#endif
133#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
134	{"allwinner,sun6i-a31-r-pinctrl",	(uintptr_t)&a31_r_padconf},
135#endif
136#ifdef SOC_ALLWINNER_A83T
137	{"allwinner,sun8i-a83t-pinctrl",	(uintptr_t)&a83t_padconf},
138	{"allwinner,sun8i-a83t-r-pinctrl",	(uintptr_t)&a83t_r_padconf},
139#endif
140#ifdef SOC_ALLWINNER_H3
141	{"allwinner,sun8i-h3-pinctrl",		(uintptr_t)&h3_padconf},
142	{"allwinner,sun8i-h3-r-pinctrl",	(uintptr_t)&h3_r_padconf},
143#endif
144	{NULL,	0}
145};
146
147struct a10_gpio_softc {
148	device_t		sc_dev;
149	device_t		sc_busdev;
150	struct mtx		sc_mtx;
151	struct resource *	sc_mem_res;
152	struct resource *	sc_irq_res;
153	bus_space_tag_t		sc_bst;
154	bus_space_handle_t	sc_bsh;
155	void *			sc_intrhand;
156	const struct allwinner_padconf *	padconf;
157};
158
159#define	A10_GPIO_LOCK(_sc)		mtx_lock_spin(&(_sc)->sc_mtx)
160#define	A10_GPIO_UNLOCK(_sc)		mtx_unlock_spin(&(_sc)->sc_mtx)
161#define	A10_GPIO_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
162
163#define	A10_GPIO_GP_CFG(_bank, _idx)	0x00 + ((_bank) * 0x24) + ((_idx) << 2)
164#define	A10_GPIO_GP_DAT(_bank)		0x10 + ((_bank) * 0x24)
165#define	A10_GPIO_GP_DRV(_bank, _idx)	0x14 + ((_bank) * 0x24) + ((_idx) << 2)
166#define	A10_GPIO_GP_PUL(_bank, _idx)	0x1c + ((_bank) * 0x24) + ((_idx) << 2)
167
168#define	A10_GPIO_GP_INT_CFG0		0x200
169#define	A10_GPIO_GP_INT_CFG1		0x204
170#define	A10_GPIO_GP_INT_CFG2		0x208
171#define	A10_GPIO_GP_INT_CFG3		0x20c
172
173#define	A10_GPIO_GP_INT_CTL		0x210
174#define	A10_GPIO_GP_INT_STA		0x214
175#define	A10_GPIO_GP_INT_DEB		0x218
176
177static int a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value);
178static int a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
179
180#define	A10_GPIO_WRITE(_sc, _off, _val)		\
181    bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
182#define	A10_GPIO_READ(_sc, _off)		\
183    bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
184
185static uint32_t
186a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin)
187{
188	uint32_t bank, func, offset;
189
190	/* Must be called with lock held. */
191	A10_GPIO_LOCK_ASSERT(sc);
192
193	if (pin > sc->padconf->npins)
194		return (0);
195	bank = sc->padconf->pins[pin].port;
196	pin = sc->padconf->pins[pin].pin;
197	offset = ((pin & 0x07) << 2);
198
199	func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
200
201	return ((func >> offset) & 0x7);
202}
203
204static int
205a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
206{
207	uint32_t bank, data, offset;
208
209	/* Check if the function exists in the padconf data */
210	if (sc->padconf->pins[pin].functions[f] == NULL)
211		return (EINVAL);
212
213	/* Must be called with lock held. */
214	A10_GPIO_LOCK_ASSERT(sc);
215
216	bank = sc->padconf->pins[pin].port;
217	pin = sc->padconf->pins[pin].pin;
218	offset = ((pin & 0x07) << 2);
219
220	data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
221	data &= ~(7 << offset);
222	data |= (f << offset);
223	A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data);
224
225	return (0);
226}
227
228static uint32_t
229a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin)
230{
231	uint32_t bank, offset, val;
232
233	/* Must be called with lock held. */
234	A10_GPIO_LOCK_ASSERT(sc);
235
236	bank = sc->padconf->pins[pin].port;
237	pin = sc->padconf->pins[pin].pin;
238	offset = ((pin & 0x0f) << 1);
239
240	val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
241
242	return ((val >> offset) & AW_GPIO_PUD_MASK);
243}
244
245static void
246a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
247{
248	uint32_t bank, offset, val;
249
250	/* Must be called with lock held. */
251	A10_GPIO_LOCK_ASSERT(sc);
252
253	bank = sc->padconf->pins[pin].port;
254	pin = sc->padconf->pins[pin].pin;
255	offset = ((pin & 0x0f) << 1);
256
257	val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
258	val &= ~(AW_GPIO_PUD_MASK << offset);
259	val |= (state << offset);
260	A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val);
261}
262
263static uint32_t
264a10_gpio_get_drv(struct a10_gpio_softc *sc, uint32_t pin)
265{
266	uint32_t bank, offset, val;
267
268	/* Must be called with lock held. */
269	A10_GPIO_LOCK_ASSERT(sc);
270
271	bank = sc->padconf->pins[pin].port;
272	pin = sc->padconf->pins[pin].pin;
273	offset = ((pin & 0x0f) << 1);
274
275	val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4));
276
277	return ((val >> offset) & AW_GPIO_DRV_MASK);
278}
279
280static void
281a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive)
282{
283	uint32_t bank, offset, val;
284
285	/* Must be called with lock held. */
286	A10_GPIO_LOCK_ASSERT(sc);
287
288	bank = sc->padconf->pins[pin].port;
289	pin = sc->padconf->pins[pin].pin;
290	offset = ((pin & 0x0f) << 1);
291
292	val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4));
293	val &= ~(AW_GPIO_DRV_MASK << offset);
294	val |= (drive << offset);
295	A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val);
296}
297
298static int
299a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
300{
301	u_int val;
302	int err = 0;
303
304	/* Must be called with lock held. */
305	A10_GPIO_LOCK_ASSERT(sc);
306
307	if (pin > sc->padconf->npins)
308		return (EINVAL);
309
310	/* Manage input/output. */
311	if (flags & GPIO_PIN_INPUT) {
312		err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT);
313	} else if (flags & GPIO_PIN_OUTPUT) {
314		if (flags & GPIO_PIN_PRESET_LOW) {
315			a10_gpio_pin_set(sc->sc_dev, pin, 0);
316		} else if (flags & GPIO_PIN_PRESET_HIGH) {
317			a10_gpio_pin_set(sc->sc_dev, pin, 1);
318		} else {
319			/* Read the pin and preset output to current state. */
320			err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT);
321			if (err == 0) {
322				a10_gpio_pin_get(sc->sc_dev, pin, &val);
323				a10_gpio_pin_set(sc->sc_dev, pin, val);
324			}
325		}
326		if (err == 0)
327			err = a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT);
328	}
329
330	if (err)
331		return (err);
332
333	/* Manage Pull-up/pull-down. */
334	if (flags & GPIO_PIN_PULLUP)
335		a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP);
336	else if (flags & GPIO_PIN_PULLDOWN)
337		a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN);
338	else
339		a10_gpio_set_pud(sc, pin, A10_GPIO_NONE);
340
341	return (0);
342}
343
344static device_t
345a10_gpio_get_bus(device_t dev)
346{
347	struct a10_gpio_softc *sc;
348
349	sc = device_get_softc(dev);
350
351	return (sc->sc_busdev);
352}
353
354static int
355a10_gpio_pin_max(device_t dev, int *maxpin)
356{
357	struct a10_gpio_softc *sc;
358
359	sc = device_get_softc(dev);
360
361	*maxpin = sc->padconf->npins - 1;
362	return (0);
363}
364
365static int
366a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
367{
368	struct a10_gpio_softc *sc;
369
370	sc = device_get_softc(dev);
371	if (pin >= sc->padconf->npins)
372		return (EINVAL);
373
374	*caps = A10_GPIO_DEFAULT_CAPS;
375
376	return (0);
377}
378
379static int
380a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
381{
382	struct a10_gpio_softc *sc;
383	uint32_t func;
384	uint32_t pud;
385
386	sc = device_get_softc(dev);
387	if (pin >= sc->padconf->npins)
388		return (EINVAL);
389
390	A10_GPIO_LOCK(sc);
391	func = a10_gpio_get_function(sc, pin);
392	switch (func) {
393	case A10_GPIO_INPUT:
394		*flags = GPIO_PIN_INPUT;
395		break;
396	case A10_GPIO_OUTPUT:
397		*flags = GPIO_PIN_OUTPUT;
398		break;
399	default:
400		*flags = 0;
401		break;
402	}
403
404	pud = a10_gpio_get_pud(sc, pin);
405	switch (pud) {
406	case A10_GPIO_PULLDOWN:
407		*flags |= GPIO_PIN_PULLDOWN;
408		break;
409	case A10_GPIO_PULLUP:
410		*flags |= GPIO_PIN_PULLUP;
411		break;
412	default:
413		break;
414	}
415
416	A10_GPIO_UNLOCK(sc);
417
418	return (0);
419}
420
421static int
422a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
423{
424	struct a10_gpio_softc *sc;
425
426	sc = device_get_softc(dev);
427	if (pin >= sc->padconf->npins)
428		return (EINVAL);
429
430	snprintf(name, GPIOMAXNAME - 1, "%s",
431	    sc->padconf->pins[pin].name);
432	name[GPIOMAXNAME - 1] = '\0';
433
434	return (0);
435}
436
437static int
438a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
439{
440	struct a10_gpio_softc *sc;
441	int err;
442
443	sc = device_get_softc(dev);
444	if (pin > sc->padconf->npins)
445		return (EINVAL);
446
447	A10_GPIO_LOCK(sc);
448	err = a10_gpio_pin_configure(sc, pin, flags);
449	A10_GPIO_UNLOCK(sc);
450
451	return (err);
452}
453
454static int
455a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
456{
457	struct a10_gpio_softc *sc;
458	uint32_t bank, data;
459
460	sc = device_get_softc(dev);
461	if (pin > sc->padconf->npins)
462		return (EINVAL);
463
464	bank = sc->padconf->pins[pin].port;
465	pin = sc->padconf->pins[pin].pin;
466
467	A10_GPIO_LOCK(sc);
468	data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
469	if (value)
470		data |= (1 << pin);
471	else
472		data &= ~(1 << pin);
473	A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
474	A10_GPIO_UNLOCK(sc);
475
476	return (0);
477}
478
479static int
480a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
481{
482	struct a10_gpio_softc *sc;
483	uint32_t bank, reg_data;
484
485	sc = device_get_softc(dev);
486	if (pin > sc->padconf->npins)
487		return (EINVAL);
488
489	bank = sc->padconf->pins[pin].port;
490	pin = sc->padconf->pins[pin].pin;
491
492	A10_GPIO_LOCK(sc);
493	reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
494	A10_GPIO_UNLOCK(sc);
495	*val = (reg_data & (1 << pin)) ? 1 : 0;
496
497	return (0);
498}
499
500static int
501a10_gpio_pin_toggle(device_t dev, uint32_t pin)
502{
503	struct a10_gpio_softc *sc;
504	uint32_t bank, data;
505
506	sc = device_get_softc(dev);
507	if (pin > sc->padconf->npins)
508		return (EINVAL);
509
510	bank = sc->padconf->pins[pin].port;
511	pin = sc->padconf->pins[pin].pin;
512
513	A10_GPIO_LOCK(sc);
514	data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
515	if (data & (1 << pin))
516		data &= ~(1 << pin);
517	else
518		data |= (1 << pin);
519	A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
520	A10_GPIO_UNLOCK(sc);
521
522	return (0);
523}
524
525static int
526a10_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
527    uint32_t change_pins, uint32_t *orig_pins)
528{
529	struct a10_gpio_softc *sc;
530	uint32_t bank, data, pin;
531
532	sc = device_get_softc(dev);
533	if (first_pin > sc->padconf->npins)
534		return (EINVAL);
535
536	/*
537	 * We require that first_pin refers to the first pin in a bank, because
538	 * this API is not about convenience, it's for making a set of pins
539	 * change simultaneously (required) with reasonably high performance
540	 * (desired); we need to do a read-modify-write on a single register.
541	 */
542	bank = sc->padconf->pins[first_pin].port;
543	pin = sc->padconf->pins[first_pin].pin;
544	if (pin != 0)
545		return (EINVAL);
546
547	A10_GPIO_LOCK(sc);
548	data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
549	if ((clear_pins | change_pins) != 0)
550		A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank),
551		    (data & ~clear_pins) ^ change_pins);
552	A10_GPIO_UNLOCK(sc);
553
554	if (orig_pins != NULL)
555		*orig_pins = data;
556
557	return (0);
558}
559
560static int
561a10_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
562    uint32_t *pin_flags)
563{
564	struct a10_gpio_softc *sc;
565	uint32_t bank, pin;
566	int err;
567
568	sc = device_get_softc(dev);
569	if (first_pin > sc->padconf->npins)
570		return (EINVAL);
571
572	bank = sc->padconf->pins[first_pin].port;
573	if (sc->padconf->pins[first_pin].pin != 0)
574		return (EINVAL);
575
576	/*
577	 * The configuration for a bank of pins is scattered among several
578	 * registers; we cannot g'tee to simultaneously change the state of all
579	 * the pins in the flags array.  So just loop through the array
580	 * configuring each pin for now.  If there was a strong need, it might
581	 * be possible to support some limited simultaneous config, such as
582	 * adjacent groups of 8 pins that line up the same as the config regs.
583	 */
584	for (err = 0, pin = first_pin; err == 0 && pin < num_pins; ++pin) {
585		if (pin_flags[pin] & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
586			err = a10_gpio_pin_configure(sc, pin, pin_flags[pin]);
587	}
588
589	return (err);
590}
591
592static int
593aw_find_pinnum_by_name(struct a10_gpio_softc *sc, const char *pinname)
594{
595	int i;
596
597	for (i = 0; i < sc->padconf->npins; i++)
598		if (!strcmp(pinname, sc->padconf->pins[i].name))
599			return i;
600
601	return (-1);
602}
603
604static int
605aw_find_pin_func(struct a10_gpio_softc *sc, int pin, const char *func)
606{
607	int i;
608
609	for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++)
610		if (sc->padconf->pins[pin].functions[i] &&
611		    !strcmp(func, sc->padconf->pins[pin].functions[i]))
612			return (i);
613
614	return (-1);
615}
616
617static int
618aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
619{
620	struct a10_gpio_softc *sc;
621	phandle_t node;
622	const char **pinlist = NULL;
623	char *pin_function = NULL;
624	uint32_t pin_drive, pin_pull;
625	int pins_nb, pin_num, pin_func, i, ret;
626
627	sc = device_get_softc(dev);
628	node = OF_node_from_xref(cfgxref);
629	ret = 0;
630
631	/* Getting all prop for configuring pins */
632	pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", &pinlist);
633	if (pins_nb <= 0)
634		return (ENOENT);
635	if (OF_getprop_alloc(node, "allwinner,function",
636			     sizeof(*pin_function),
637			     (void **)&pin_function) == -1) {
638		ret = ENOENT;
639		goto out;
640	}
641	if (OF_getencprop(node, "allwinner,drive",
642			  &pin_drive, sizeof(pin_drive)) == -1) {
643		ret = ENOENT;
644		goto out;
645	}
646	if (OF_getencprop(node, "allwinner,pull",
647			  &pin_pull, sizeof(pin_pull)) == -1) {
648		ret = ENOENT;
649		goto out;
650	}
651
652	/* Configure each pin to the correct function, drive and pull */
653	for (i = 0; i < pins_nb; i++) {
654		pin_num = aw_find_pinnum_by_name(sc, pinlist[i]);
655		if (pin_num == -1) {
656			ret = ENOENT;
657			goto out;
658		}
659		pin_func = aw_find_pin_func(sc, pin_num, pin_function);
660		if (pin_func == -1) {
661			ret = ENOENT;
662			goto out;
663		}
664
665		A10_GPIO_LOCK(sc);
666
667		if (a10_gpio_get_function(sc, pin_num) != pin_func)
668			a10_gpio_set_function(sc, pin_num, pin_func);
669		if (a10_gpio_get_drv(sc, pin_num) != pin_drive)
670			a10_gpio_set_drv(sc, pin_num, pin_drive);
671		if (a10_gpio_get_pud(sc, pin_num) != pin_pull &&
672			(pin_pull == A10_GPIO_PULLUP ||
673			    pin_pull == A10_GPIO_PULLDOWN))
674			a10_gpio_set_pud(sc, pin_num, pin_pull);
675		A10_GPIO_UNLOCK(sc);
676	}
677
678 out:
679	OF_prop_free(pinlist);
680	OF_prop_free(pin_function);
681	return (ret);
682}
683
684static int
685a10_gpio_probe(device_t dev)
686{
687
688	if (!ofw_bus_status_okay(dev))
689		return (ENXIO);
690
691	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
692		return (ENXIO);
693
694	device_set_desc(dev, "Allwinner GPIO/Pinmux controller");
695	return (BUS_PROBE_DEFAULT);
696}
697
698static int
699a10_gpio_attach(device_t dev)
700{
701	int rid, error;
702	phandle_t gpio;
703	struct a10_gpio_softc *sc;
704	clk_t clk;
705	hwreset_t rst;
706
707	sc = device_get_softc(dev);
708	sc->sc_dev = dev;
709
710	mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN);
711
712	rid = 0;
713	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
714	    RF_ACTIVE);
715	if (!sc->sc_mem_res) {
716		device_printf(dev, "cannot allocate memory window\n");
717		goto fail;
718	}
719
720	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
721	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
722
723	rid = 0;
724	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
725	    RF_ACTIVE);
726	if (!sc->sc_irq_res) {
727		device_printf(dev, "cannot allocate interrupt\n");
728		goto fail;
729	}
730
731	/* Find our node. */
732	gpio = ofw_bus_get_node(sc->sc_dev);
733	if (!OF_hasprop(gpio, "gpio-controller"))
734		/* Node is not a GPIO controller. */
735		goto fail;
736
737	/* Use the right pin data for the current SoC */
738	sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev,
739	    compat_data)->ocd_data;
740
741	if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) {
742		error = hwreset_deassert(rst);
743		if (error != 0) {
744			device_printf(dev, "cannot de-assert reset\n");
745			return (error);
746		}
747	}
748
749	if (clk_get_by_ofw_index(dev, 0, 0, &clk) == 0) {
750		error = clk_enable(clk);
751		if (error != 0) {
752			device_printf(dev, "could not enable clock\n");
753			return (error);
754		}
755	}
756
757	sc->sc_busdev = gpiobus_attach_bus(dev);
758	if (sc->sc_busdev == NULL)
759		goto fail;
760
761	/*
762	 * Register as a pinctrl device
763	 */
764	fdt_pinctrl_register(dev, "allwinner,pins");
765	fdt_pinctrl_configure_tree(dev);
766
767	return (0);
768
769fail:
770	if (sc->sc_irq_res)
771		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
772	if (sc->sc_mem_res)
773		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
774	mtx_destroy(&sc->sc_mtx);
775
776	return (ENXIO);
777}
778
779static int
780a10_gpio_detach(device_t dev)
781{
782
783	return (EBUSY);
784}
785
786static phandle_t
787a10_gpio_get_node(device_t dev, device_t bus)
788{
789
790	/* We only have one child, the GPIO bus, which needs our own node. */
791	return (ofw_bus_get_node(dev));
792}
793
794static int
795a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
796    pcell_t *gpios, uint32_t *pin, uint32_t *flags)
797{
798	struct a10_gpio_softc *sc;
799	int i;
800
801	sc = device_get_softc(bus);
802
803	/* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
804	for (i = 0; i < sc->padconf->npins; i++)
805		if (sc->padconf->pins[i].port == gpios[0] &&
806		    sc->padconf->pins[i].pin == gpios[1]) {
807			*pin = i;
808			break;
809		}
810	*flags = gpios[gcells - 1];
811
812	return (0);
813}
814
815static device_method_t a10_gpio_methods[] = {
816	/* Device interface */
817	DEVMETHOD(device_probe,		a10_gpio_probe),
818	DEVMETHOD(device_attach,	a10_gpio_attach),
819	DEVMETHOD(device_detach,	a10_gpio_detach),
820
821	/* GPIO protocol */
822	DEVMETHOD(gpio_get_bus,		a10_gpio_get_bus),
823	DEVMETHOD(gpio_pin_max,		a10_gpio_pin_max),
824	DEVMETHOD(gpio_pin_getname,	a10_gpio_pin_getname),
825	DEVMETHOD(gpio_pin_getflags,	a10_gpio_pin_getflags),
826	DEVMETHOD(gpio_pin_getcaps,	a10_gpio_pin_getcaps),
827	DEVMETHOD(gpio_pin_setflags,	a10_gpio_pin_setflags),
828	DEVMETHOD(gpio_pin_get,		a10_gpio_pin_get),
829	DEVMETHOD(gpio_pin_set,		a10_gpio_pin_set),
830	DEVMETHOD(gpio_pin_toggle,	a10_gpio_pin_toggle),
831	DEVMETHOD(gpio_pin_access_32,	a10_gpio_pin_access_32),
832	DEVMETHOD(gpio_pin_config_32,	a10_gpio_pin_config_32),
833	DEVMETHOD(gpio_map_gpios,	a10_gpio_map_gpios),
834
835	/* ofw_bus interface */
836	DEVMETHOD(ofw_bus_get_node,	a10_gpio_get_node),
837
838        /* fdt_pinctrl interface */
839	DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins),
840
841	DEVMETHOD_END
842};
843
844static devclass_t a10_gpio_devclass;
845
846static driver_t a10_gpio_driver = {
847	"gpio",
848	a10_gpio_methods,
849	sizeof(struct a10_gpio_softc),
850};
851
852EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0,
853    BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
854