a10_gpio.c revision 305436
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 305436 2016-09-05 20:17:18Z manu $");
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/cpu.h>
45#include <machine/cpufunc.h>
46#include <machine/resource.h>
47#include <machine/intr.h>
48
49#include <dev/fdt/fdt_common.h>
50#include <dev/fdt/fdt_pinctrl.h>
51#include <dev/gpio/gpiobusvar.h>
52#include <dev/ofw/ofw_bus.h>
53#include <dev/ofw/ofw_bus_subr.h>
54
55#include <arm/allwinner/allwinner_machdep.h>
56#include <arm/allwinner/allwinner_pinctrl.h>
57#include <dev/extres/clk/clk.h>
58#include <dev/extres/hwreset/hwreset.h>
59
60#include "gpio_if.h"
61
62#define	A10_GPIO_DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |	\
63    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
64
65#define	A10_GPIO_NONE		0
66#define	A10_GPIO_PULLUP		1
67#define	A10_GPIO_PULLDOWN	2
68
69#define	A10_GPIO_INPUT		0
70#define	A10_GPIO_OUTPUT		1
71
72#define	AW_GPIO_DRV_MASK	0x3
73#define	AW_GPIO_PUD_MASK	0x3
74
75#define	AW_PINCTRL	1
76#define	AW_R_PINCTRL	2
77
78/* Defined in a10_padconf.c */
79#ifdef SOC_ALLWINNER_A10
80extern const struct allwinner_padconf a10_padconf;
81#endif
82
83/* Defined in a13_padconf.c */
84#ifdef SOC_ALLWINNER_A13
85extern const struct allwinner_padconf a13_padconf;
86#endif
87
88/* Defined in a20_padconf.c */
89#ifdef SOC_ALLWINNER_A20
90extern const struct allwinner_padconf a20_padconf;
91#endif
92
93/* Defined in a31_padconf.c */
94#ifdef SOC_ALLWINNER_A31
95extern const struct allwinner_padconf a31_padconf;
96#endif
97
98/* Defined in a31s_padconf.c */
99#ifdef SOC_ALLWINNER_A31S
100extern const struct allwinner_padconf a31s_padconf;
101#endif
102
103#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
104extern const struct allwinner_padconf a31_r_padconf;
105#endif
106
107/* Defined in h3_padconf.c */
108#ifdef SOC_ALLWINNER_H3
109extern const struct allwinner_padconf h3_padconf;
110extern const struct allwinner_padconf h3_r_padconf;
111#endif
112
113/* Defined in a83t_padconf.c */
114#ifdef SOC_ALLWINNER_A83T
115extern const struct allwinner_padconf a83t_padconf;
116extern const struct allwinner_padconf a83t_r_padconf;
117#endif
118
119static struct ofw_compat_data compat_data[] = {
120#ifdef SOC_ALLWINNER_A10
121	{"allwinner,sun4i-a10-pinctrl",		(uintptr_t)&a10_padconf},
122#endif
123#ifdef SOC_ALLWINNER_A13
124	{"allwinner,sun5i-a13-pinctrl",		(uintptr_t)&a13_padconf},
125#endif
126#ifdef SOC_ALLWINNER_A20
127	{"allwinner,sun7i-a20-pinctrl",		(uintptr_t)&a20_padconf},
128#endif
129#ifdef SOC_ALLWINNER_A31
130	{"allwinner,sun6i-a31-pinctrl",		(uintptr_t)&a31_padconf},
131#endif
132#ifdef SOC_ALLWINNER_A31S
133	{"allwinner,sun6i-a31s-pinctrl",	(uintptr_t)&a31s_padconf},
134#endif
135#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
136	{"allwinner,sun6i-a31-r-pinctrl",	(uintptr_t)&a31_r_padconf},
137#endif
138#ifdef SOC_ALLWINNER_A83T
139	{"allwinner,sun8i-a83t-pinctrl",	(uintptr_t)&a83t_padconf},
140	{"allwinner,sun8i-a83t-r-pinctrl",	(uintptr_t)&a83t_r_padconf},
141#endif
142#ifdef SOC_ALLWINNER_H3
143	{"allwinner,sun8i-h3-pinctrl",		(uintptr_t)&h3_padconf},
144	{"allwinner,sun8i-h3-r-pinctrl",	(uintptr_t)&h3_r_padconf},
145#endif
146	{NULL,	0}
147};
148
149struct a10_gpio_softc {
150	device_t		sc_dev;
151	device_t		sc_busdev;
152	struct mtx		sc_mtx;
153	struct resource *	sc_mem_res;
154	struct resource *	sc_irq_res;
155	bus_space_tag_t		sc_bst;
156	bus_space_handle_t	sc_bsh;
157	void *			sc_intrhand;
158	const struct allwinner_padconf *	padconf;
159};
160
161#define	A10_GPIO_LOCK(_sc)		mtx_lock_spin(&(_sc)->sc_mtx)
162#define	A10_GPIO_UNLOCK(_sc)		mtx_unlock_spin(&(_sc)->sc_mtx)
163#define	A10_GPIO_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
164
165#define	A10_GPIO_GP_CFG(_bank, _idx)	0x00 + ((_bank) * 0x24) + ((_idx) << 2)
166#define	A10_GPIO_GP_DAT(_bank)		0x10 + ((_bank) * 0x24)
167#define	A10_GPIO_GP_DRV(_bank, _idx)	0x14 + ((_bank) * 0x24) + ((_idx) << 2)
168#define	A10_GPIO_GP_PUL(_bank, _idx)	0x1c + ((_bank) * 0x24) + ((_idx) << 2)
169
170#define	A10_GPIO_GP_INT_CFG0		0x200
171#define	A10_GPIO_GP_INT_CFG1		0x204
172#define	A10_GPIO_GP_INT_CFG2		0x208
173#define	A10_GPIO_GP_INT_CFG3		0x20c
174
175#define	A10_GPIO_GP_INT_CTL		0x210
176#define	A10_GPIO_GP_INT_STA		0x214
177#define	A10_GPIO_GP_INT_DEB		0x218
178
179#define	A10_GPIO_WRITE(_sc, _off, _val)		\
180    bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
181#define	A10_GPIO_READ(_sc, _off)		\
182    bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
183
184static uint32_t
185a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin)
186{
187	uint32_t bank, func, offset;
188
189	/* Must be called with lock held. */
190	A10_GPIO_LOCK_ASSERT(sc);
191
192	if (pin > sc->padconf->npins)
193		return (0);
194	bank = sc->padconf->pins[pin].port;
195	pin = sc->padconf->pins[pin].pin;
196	offset = ((pin & 0x07) << 2);
197
198	func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
199	switch ((func >> offset) & 0x7) {
200	case A10_GPIO_INPUT:
201		return (GPIO_PIN_INPUT);
202	case A10_GPIO_OUTPUT:
203		return (GPIO_PIN_OUTPUT);
204	}
205
206	return (0);
207}
208
209static int
210a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
211{
212	uint32_t bank, data, offset;
213
214	/* Check if the function exists in the padconf data */
215	if (sc->padconf->pins[pin].functions[f] == NULL)
216		return (EINVAL);
217
218	/* Must be called with lock held. */
219	A10_GPIO_LOCK_ASSERT(sc);
220
221	bank = sc->padconf->pins[pin].port;
222	pin = sc->padconf->pins[pin].pin;
223	offset = ((pin & 0x07) << 2);
224
225	data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
226	data &= ~(7 << offset);
227	data |= (f << offset);
228	A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data);
229
230	return (0);
231}
232
233static uint32_t
234a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin)
235{
236	uint32_t bank, offset, val;
237
238	/* Must be called with lock held. */
239	A10_GPIO_LOCK_ASSERT(sc);
240
241	bank = sc->padconf->pins[pin].port;
242	pin = sc->padconf->pins[pin].pin;
243	offset = ((pin & 0x0f) << 1);
244
245	val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
246	switch ((val >> offset) & 0x3) {
247	case A10_GPIO_PULLDOWN:
248		return (GPIO_PIN_PULLDOWN);
249	case A10_GPIO_PULLUP:
250		return (GPIO_PIN_PULLUP);
251	}
252
253	return (0);
254}
255
256static void
257a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
258{
259	uint32_t bank, offset, val;
260
261	/* Must be called with lock held. */
262	A10_GPIO_LOCK_ASSERT(sc);
263
264	bank = sc->padconf->pins[pin].port;
265	pin = sc->padconf->pins[pin].pin;
266	offset = ((pin & 0x0f) << 1);
267
268	val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
269	val &= ~(AW_GPIO_PUD_MASK << offset);
270	val |= (state << offset);
271	A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val);
272}
273
274static void
275a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive)
276{
277	uint32_t bank, offset, val;
278
279	/* Must be called with lock held. */
280	A10_GPIO_LOCK_ASSERT(sc);
281
282	bank = sc->padconf->pins[pin].port;
283	pin = sc->padconf->pins[pin].pin;
284	offset = ((pin & 0x0f) << 1);
285
286	val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4));
287	val &= ~(AW_GPIO_DRV_MASK << offset);
288	val |= (drive << offset);
289	A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val);
290}
291
292static int
293a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
294{
295	int err = 0;
296
297	/* Must be called with lock held. */
298	A10_GPIO_LOCK_ASSERT(sc);
299
300	/* Manage input/output. */
301	if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
302		if (flags & GPIO_PIN_OUTPUT)
303			err = a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT);
304		else
305			err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT);
306	}
307
308	if (err)
309		return (err);
310
311	/* Manage Pull-up/pull-down. */
312	if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) {
313		if (flags & GPIO_PIN_PULLUP)
314			a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP);
315		else
316			a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN);
317	} else
318		a10_gpio_set_pud(sc, pin, A10_GPIO_NONE);
319
320	return (0);
321}
322
323static device_t
324a10_gpio_get_bus(device_t dev)
325{
326	struct a10_gpio_softc *sc;
327
328	sc = device_get_softc(dev);
329
330	return (sc->sc_busdev);
331}
332
333static int
334a10_gpio_pin_max(device_t dev, int *maxpin)
335{
336	struct a10_gpio_softc *sc;
337
338	sc = device_get_softc(dev);
339
340	*maxpin = sc->padconf->npins - 1;
341	return (0);
342}
343
344static int
345a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
346{
347	struct a10_gpio_softc *sc;
348
349	sc = device_get_softc(dev);
350	if (pin >= sc->padconf->npins)
351		return (EINVAL);
352
353	*caps = A10_GPIO_DEFAULT_CAPS;
354
355	return (0);
356}
357
358static int
359a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
360{
361	struct a10_gpio_softc *sc;
362
363	sc = device_get_softc(dev);
364	if (pin >= sc->padconf->npins)
365		return (EINVAL);
366
367	A10_GPIO_LOCK(sc);
368	*flags = a10_gpio_get_function(sc, pin);
369	*flags |= a10_gpio_get_pud(sc, pin);
370	A10_GPIO_UNLOCK(sc);
371
372	return (0);
373}
374
375static int
376a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
377{
378	struct a10_gpio_softc *sc;
379
380	sc = device_get_softc(dev);
381	if (pin >= sc->padconf->npins)
382		return (EINVAL);
383
384	snprintf(name, GPIOMAXNAME - 1, "%s",
385	    sc->padconf->pins[pin].name);
386	name[GPIOMAXNAME - 1] = '\0';
387
388	return (0);
389}
390
391static int
392a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
393{
394	struct a10_gpio_softc *sc;
395	int err;
396
397	sc = device_get_softc(dev);
398	if (pin > sc->padconf->npins)
399		return (EINVAL);
400
401	A10_GPIO_LOCK(sc);
402	err = a10_gpio_pin_configure(sc, pin, flags);
403	A10_GPIO_UNLOCK(sc);
404
405	return (err);
406}
407
408static int
409a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
410{
411	struct a10_gpio_softc *sc;
412	uint32_t bank, data;
413
414	sc = device_get_softc(dev);
415	if (pin > sc->padconf->npins)
416		return (EINVAL);
417
418	bank = sc->padconf->pins[pin].port;
419	pin = sc->padconf->pins[pin].pin;
420
421	A10_GPIO_LOCK(sc);
422	data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
423	if (value)
424		data |= (1 << pin);
425	else
426		data &= ~(1 << pin);
427	A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
428	A10_GPIO_UNLOCK(sc);
429
430	return (0);
431}
432
433static int
434a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
435{
436	struct a10_gpio_softc *sc;
437	uint32_t bank, reg_data;
438
439	sc = device_get_softc(dev);
440	if (pin > sc->padconf->npins)
441		return (EINVAL);
442
443	bank = sc->padconf->pins[pin].port;
444	pin = sc->padconf->pins[pin].pin;
445
446	A10_GPIO_LOCK(sc);
447	reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
448	A10_GPIO_UNLOCK(sc);
449	*val = (reg_data & (1 << pin)) ? 1 : 0;
450
451	return (0);
452}
453
454static int
455a10_gpio_pin_toggle(device_t dev, uint32_t pin)
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 (data & (1 << pin))
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
480aw_find_pinnum_by_name(struct a10_gpio_softc *sc, const char *pinname)
481{
482	int i;
483
484	for (i = 0; i < sc->padconf->npins; i++)
485		if (!strcmp(pinname, sc->padconf->pins[i].name))
486			return i;
487
488	return (-1);
489}
490
491static int
492aw_find_pin_func(struct a10_gpio_softc *sc, int pin, const char *func)
493{
494	int i;
495
496	for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++)
497		if (sc->padconf->pins[pin].functions[i] &&
498		    !strcmp(func, sc->padconf->pins[pin].functions[i]))
499			return (i);
500
501	return (-1);
502}
503
504static int
505aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
506{
507	struct a10_gpio_softc *sc;
508	phandle_t node;
509	const char **pinlist = NULL;
510	char *pin_function = NULL;
511	uint32_t pin_drive, pin_pull;
512	int pins_nb, pin_num, pin_func, i, ret;
513
514	sc = device_get_softc(dev);
515	node = OF_node_from_xref(cfgxref);
516	ret = 0;
517
518	/* Getting all prop for configuring pins */
519	pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", &pinlist);
520	if (pins_nb <= 0)
521		return (ENOENT);
522	if (OF_getprop_alloc(node, "allwinner,function",
523			     sizeof(*pin_function),
524			     (void **)&pin_function) == -1) {
525		ret = ENOENT;
526		goto out;
527	}
528	if (OF_getencprop(node, "allwinner,drive",
529			  &pin_drive, sizeof(pin_drive)) == -1) {
530		ret = ENOENT;
531		goto out;
532	}
533	if (OF_getencprop(node, "allwinner,pull",
534			  &pin_pull, sizeof(pin_pull)) == -1) {
535		ret = ENOENT;
536		goto out;
537	}
538
539	/* Configure each pin to the correct function, drive and pull */
540	for (i = 0; i < pins_nb; i++) {
541		pin_num = aw_find_pinnum_by_name(sc, pinlist[i]);
542		if (pin_num == -1) {
543			ret = ENOENT;
544			goto out;
545		}
546		pin_func = aw_find_pin_func(sc, pin_num, pin_function);
547		if (pin_func == -1) {
548			ret = ENOENT;
549			goto out;
550		}
551
552		A10_GPIO_LOCK(sc);
553		a10_gpio_set_function(sc, pin_num, pin_func);
554		a10_gpio_set_drv(sc, pin_num, pin_drive);
555		a10_gpio_set_pud(sc, pin_num, pin_pull);
556		A10_GPIO_UNLOCK(sc);
557	}
558
559 out:
560	OF_prop_free(pinlist);
561	OF_prop_free(pin_function);
562	return (ret);
563}
564
565static int
566a10_gpio_probe(device_t dev)
567{
568
569	if (!ofw_bus_status_okay(dev))
570		return (ENXIO);
571
572	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
573		return (ENXIO);
574
575	device_set_desc(dev, "Allwinner GPIO/Pinmux controller");
576	return (BUS_PROBE_DEFAULT);
577}
578
579static int
580a10_gpio_attach(device_t dev)
581{
582	int rid, error;
583	phandle_t gpio;
584	struct a10_gpio_softc *sc;
585	clk_t clk;
586	hwreset_t rst;
587
588	sc = device_get_softc(dev);
589	sc->sc_dev = dev;
590
591	mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN);
592
593	rid = 0;
594	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
595	    RF_ACTIVE);
596	if (!sc->sc_mem_res) {
597		device_printf(dev, "cannot allocate memory window\n");
598		goto fail;
599	}
600
601	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
602	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
603
604	rid = 0;
605	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
606	    RF_ACTIVE);
607	if (!sc->sc_irq_res) {
608		device_printf(dev, "cannot allocate interrupt\n");
609		goto fail;
610	}
611
612	/* Find our node. */
613	gpio = ofw_bus_get_node(sc->sc_dev);
614	if (!OF_hasprop(gpio, "gpio-controller"))
615		/* Node is not a GPIO controller. */
616		goto fail;
617
618	/* Use the right pin data for the current SoC */
619	sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev,
620	    compat_data)->ocd_data;
621
622	if (hwreset_get_by_ofw_idx(dev, 0, &rst) == 0) {
623		error = hwreset_deassert(rst);
624		if (error != 0) {
625			device_printf(dev, "cannot de-assert reset\n");
626			return (error);
627		}
628	}
629
630	if (clk_get_by_ofw_index(dev, 0, &clk) == 0) {
631		error = clk_enable(clk);
632		if (error != 0) {
633			device_printf(dev, "could not enable clock\n");
634			return (error);
635		}
636	}
637
638	sc->sc_busdev = gpiobus_attach_bus(dev);
639	if (sc->sc_busdev == NULL)
640		goto fail;
641
642	/*
643	 * Register as a pinctrl device
644	 */
645	fdt_pinctrl_register(dev, "allwinner,pins");
646	fdt_pinctrl_configure_tree(dev);
647
648	return (0);
649
650fail:
651	if (sc->sc_irq_res)
652		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
653	if (sc->sc_mem_res)
654		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
655	mtx_destroy(&sc->sc_mtx);
656
657	return (ENXIO);
658}
659
660static int
661a10_gpio_detach(device_t dev)
662{
663
664	return (EBUSY);
665}
666
667static phandle_t
668a10_gpio_get_node(device_t dev, device_t bus)
669{
670
671	/* We only have one child, the GPIO bus, which needs our own node. */
672	return (ofw_bus_get_node(dev));
673}
674
675static int
676a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
677    pcell_t *gpios, uint32_t *pin, uint32_t *flags)
678{
679	struct a10_gpio_softc *sc;
680	int i;
681
682	sc = device_get_softc(bus);
683
684	/* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
685	for (i = 0; i < sc->padconf->npins; i++)
686		if (sc->padconf->pins[i].port == gpios[0] &&
687		    sc->padconf->pins[i].pin == gpios[1]) {
688			*pin = i;
689			break;
690		}
691	*flags = gpios[gcells - 1];
692
693	return (0);
694}
695
696static device_method_t a10_gpio_methods[] = {
697	/* Device interface */
698	DEVMETHOD(device_probe,		a10_gpio_probe),
699	DEVMETHOD(device_attach,	a10_gpio_attach),
700	DEVMETHOD(device_detach,	a10_gpio_detach),
701
702	/* GPIO protocol */
703	DEVMETHOD(gpio_get_bus,		a10_gpio_get_bus),
704	DEVMETHOD(gpio_pin_max,		a10_gpio_pin_max),
705	DEVMETHOD(gpio_pin_getname,	a10_gpio_pin_getname),
706	DEVMETHOD(gpio_pin_getflags,	a10_gpio_pin_getflags),
707	DEVMETHOD(gpio_pin_getcaps,	a10_gpio_pin_getcaps),
708	DEVMETHOD(gpio_pin_setflags,	a10_gpio_pin_setflags),
709	DEVMETHOD(gpio_pin_get,		a10_gpio_pin_get),
710	DEVMETHOD(gpio_pin_set,		a10_gpio_pin_set),
711	DEVMETHOD(gpio_pin_toggle,	a10_gpio_pin_toggle),
712	DEVMETHOD(gpio_map_gpios,	a10_gpio_map_gpios),
713
714	/* ofw_bus interface */
715	DEVMETHOD(ofw_bus_get_node,	a10_gpio_get_node),
716
717        /* fdt_pinctrl interface */
718	DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins),
719
720	DEVMETHOD_END
721};
722
723static devclass_t a10_gpio_devclass;
724
725static driver_t a10_gpio_driver = {
726	"gpio",
727	a10_gpio_methods,
728	sizeof(struct a10_gpio_softc),
729};
730
731EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0,
732    BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
733