xref: /freebsd/sys/arm/ti/ti_gpio.c (revision 1f1e8f1681be2ec7262ed9951508b843041f6231)
1e53470feSOleksandr Tymoshenko /*-
2e53470feSOleksandr Tymoshenko  * Copyright (c) 2011
3e53470feSOleksandr Tymoshenko  *	Ben Gray <ben.r.gray@gmail.com>.
4e53470feSOleksandr Tymoshenko  * All rights reserved.
5e53470feSOleksandr Tymoshenko  *
6e53470feSOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
7e53470feSOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
8e53470feSOleksandr Tymoshenko  * are met:
9e53470feSOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
10e53470feSOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer.
11e53470feSOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
12e53470feSOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
13e53470feSOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
14e53470feSOleksandr Tymoshenko  *
15e53470feSOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e53470feSOleksandr Tymoshenko  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e53470feSOleksandr Tymoshenko  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e53470feSOleksandr Tymoshenko  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19e53470feSOleksandr Tymoshenko  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e53470feSOleksandr Tymoshenko  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e53470feSOleksandr Tymoshenko  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e53470feSOleksandr Tymoshenko  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e53470feSOleksandr Tymoshenko  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e53470feSOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e53470feSOleksandr Tymoshenko  * SUCH DAMAGE.
26e53470feSOleksandr Tymoshenko  */
27e53470feSOleksandr Tymoshenko 
28e53470feSOleksandr Tymoshenko /**
29e53470feSOleksandr Tymoshenko  *	Very simple GPIO (general purpose IO) driver module for TI OMAP SoC's.
30e53470feSOleksandr Tymoshenko  *
31e53470feSOleksandr Tymoshenko  *	Currently this driver only does the basics, get a value on a pin & set a
32e53470feSOleksandr Tymoshenko  *	value on a pin. Hopefully over time I'll expand this to be a bit more generic
33e53470feSOleksandr Tymoshenko  *	and support interrupts and other various bits on the SoC can do ... in the
34e53470feSOleksandr Tymoshenko  *	meantime this is all you get.
35e53470feSOleksandr Tymoshenko  *
36e53470feSOleksandr Tymoshenko  *	Beware the OMA datasheet(s) lists GPIO banks 1-6, whereas I've used 0-5 here
37e53470feSOleksandr Tymoshenko  *	in the code.
38e53470feSOleksandr Tymoshenko  *
39e53470feSOleksandr Tymoshenko  *
40e53470feSOleksandr Tymoshenko  */
41e53470feSOleksandr Tymoshenko 
42e53470feSOleksandr Tymoshenko #include <sys/cdefs.h>
43e53470feSOleksandr Tymoshenko __FBSDID("$FreeBSD$");
44e53470feSOleksandr Tymoshenko 
45e53470feSOleksandr Tymoshenko #include <sys/param.h>
46e53470feSOleksandr Tymoshenko #include <sys/systm.h>
47e53470feSOleksandr Tymoshenko #include <sys/bus.h>
48e53470feSOleksandr Tymoshenko 
49e53470feSOleksandr Tymoshenko #include <sys/kernel.h>
50e53470feSOleksandr Tymoshenko #include <sys/module.h>
51e53470feSOleksandr Tymoshenko #include <sys/rman.h>
52e53470feSOleksandr Tymoshenko #include <sys/lock.h>
53e53470feSOleksandr Tymoshenko #include <sys/mutex.h>
54e53470feSOleksandr Tymoshenko #include <sys/gpio.h>
55e53470feSOleksandr Tymoshenko 
56e53470feSOleksandr Tymoshenko #include <machine/bus.h>
57e53470feSOleksandr Tymoshenko #include <machine/resource.h>
58e53470feSOleksandr Tymoshenko 
59e53470feSOleksandr Tymoshenko #include <arm/ti/ti_scm.h>
60e53470feSOleksandr Tymoshenko #include <arm/ti/ti_prcm.h>
61e53470feSOleksandr Tymoshenko 
62e53470feSOleksandr Tymoshenko #include <dev/fdt/fdt_common.h>
63e53470feSOleksandr Tymoshenko #include <dev/ofw/openfirm.h>
64e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h>
65e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h>
66e53470feSOleksandr Tymoshenko 
67e53470feSOleksandr Tymoshenko #include "gpio_if.h"
68e53470feSOleksandr Tymoshenko 
69e53470feSOleksandr Tymoshenko /* Register definitions */
70e53470feSOleksandr Tymoshenko #define	TI_GPIO_REVISION		0x0000
71e53470feSOleksandr Tymoshenko #define	TI_GPIO_SYSCONFIG		0x0010
72e53470feSOleksandr Tymoshenko #if defined(SOC_OMAP3)
73e53470feSOleksandr Tymoshenko #define	TI_GPIO_SYSSTATUS		0x0014
74e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS1		0x0018
75e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQENABLE1		0x001C
76e53470feSOleksandr Tymoshenko #define	TI_GPIO_WAKEUPENABLE		0x0020
77e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS2		0x0028
78e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQENABLE2		0x002C
79e53470feSOleksandr Tymoshenko #define	TI_GPIO_CTRL			0x0030
80e53470feSOleksandr Tymoshenko #define	TI_GPIO_OE			0x0034
81e53470feSOleksandr Tymoshenko #define	TI_GPIO_DATAIN			0x0038
82e53470feSOleksandr Tymoshenko #define	TI_GPIO_DATAOUT			0x003C
83e53470feSOleksandr Tymoshenko #define	TI_GPIO_LEVELDETECT0		0x0040
84e53470feSOleksandr Tymoshenko #define	TI_GPIO_LEVELDETECT1		0x0044
85e53470feSOleksandr Tymoshenko #define	TI_GPIO_RISINGDETECT		0x0048
86e53470feSOleksandr Tymoshenko #define	TI_GPIO_FALLINGDETECT		0x004C
87e53470feSOleksandr Tymoshenko #define	TI_GPIO_DEBOUNCENABLE		0x0050
88e53470feSOleksandr Tymoshenko #define	TI_GPIO_DEBOUNCINGTIME		0x0054
89e53470feSOleksandr Tymoshenko #define	TI_GPIO_CLEARIRQENABLE1		0x0060
90e53470feSOleksandr Tymoshenko #define	TI_GPIO_SETIRQENABLE1		0x0064
91e53470feSOleksandr Tymoshenko #define	TI_GPIO_CLEARIRQENABLE2		0x0070
92e53470feSOleksandr Tymoshenko #define	TI_GPIO_SETIRQENABLE2		0x0074
93e53470feSOleksandr Tymoshenko #define	TI_GPIO_CLEARWKUENA		0x0080
94e53470feSOleksandr Tymoshenko #define	TI_GPIO_SETWKUENA		0x0084
95e53470feSOleksandr Tymoshenko #define	TI_GPIO_CLEARDATAOUT		0x0090
96e53470feSOleksandr Tymoshenko #define	TI_GPIO_SETDATAOUT		0x0094
97e53470feSOleksandr Tymoshenko #elif defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
98e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_RAW_0		0x0024
99e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_RAW_1		0x0028
100e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_0		0x002C
101e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_1		0x0030
102e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_SET_0		0x0034
103e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_SET_1		0x0038
104e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_CLR_0		0x003C
105e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS_CLR_1		0x0040
106e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQWAKEN_0		0x0044
107e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQWAKEN_1		0x0048
108e53470feSOleksandr Tymoshenko #define	TI_GPIO_SYSSTATUS		0x0114
109e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS1		0x0118
110e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQENABLE1		0x011C
111e53470feSOleksandr Tymoshenko #define	TI_GPIO_WAKEUPENABLE		0x0120
112e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQSTATUS2		0x0128
113e53470feSOleksandr Tymoshenko #define	TI_GPIO_IRQENABLE2		0x012C
114e53470feSOleksandr Tymoshenko #define	TI_GPIO_CTRL			0x0130
115e53470feSOleksandr Tymoshenko #define	TI_GPIO_OE			0x0134
116e53470feSOleksandr Tymoshenko #define	TI_GPIO_DATAIN			0x0138
117e53470feSOleksandr Tymoshenko #define	TI_GPIO_DATAOUT			0x013C
118e53470feSOleksandr Tymoshenko #define	TI_GPIO_LEVELDETECT0		0x0140
119e53470feSOleksandr Tymoshenko #define	TI_GPIO_LEVELDETECT1		0x0144
120e53470feSOleksandr Tymoshenko #define	TI_GPIO_RISINGDETECT		0x0148
121e53470feSOleksandr Tymoshenko #define	TI_GPIO_FALLINGDETECT		0x014C
122e53470feSOleksandr Tymoshenko #define	TI_GPIO_DEBOUNCENABLE		0x0150
123e53470feSOleksandr Tymoshenko #define	TI_GPIO_DEBOUNCINGTIME		0x0154
124e53470feSOleksandr Tymoshenko #define	TI_GPIO_CLEARWKUPENA		0x0180
125e53470feSOleksandr Tymoshenko #define	TI_GPIO_SETWKUENA		0x0184
126e53470feSOleksandr Tymoshenko #define	TI_GPIO_CLEARDATAOUT		0x0190
127e53470feSOleksandr Tymoshenko #define	TI_GPIO_SETDATAOUT		0x0194
128e53470feSOleksandr Tymoshenko #else
129e53470feSOleksandr Tymoshenko #error "Unknown SoC"
130e53470feSOleksandr Tymoshenko #endif
131e53470feSOleksandr Tymoshenko 
132e53470feSOleksandr Tymoshenko /* Other SoC Specific definitions */
133e53470feSOleksandr Tymoshenko #if defined(SOC_OMAP3)
134e53470feSOleksandr Tymoshenko #define	MAX_GPIO_BANKS			6
135e53470feSOleksandr Tymoshenko #define	FIRST_GPIO_BANK			1
136db8a14ecSLuiz Otavio O Souza #define	INTR_PER_BANK			1
137e53470feSOleksandr Tymoshenko #define	TI_GPIO_REV			0x00000025
138e53470feSOleksandr Tymoshenko #elif defined(SOC_OMAP4)
139e53470feSOleksandr Tymoshenko #define	MAX_GPIO_BANKS			6
140e53470feSOleksandr Tymoshenko #define	FIRST_GPIO_BANK			1
141db8a14ecSLuiz Otavio O Souza #define	INTR_PER_BANK			1
142e53470feSOleksandr Tymoshenko #define	TI_GPIO_REV			0x50600801
143e53470feSOleksandr Tymoshenko #elif defined(SOC_TI_AM335X)
144e53470feSOleksandr Tymoshenko #define	MAX_GPIO_BANKS			4
145e53470feSOleksandr Tymoshenko #define	FIRST_GPIO_BANK			0
146db8a14ecSLuiz Otavio O Souza #define	INTR_PER_BANK			2
147e53470feSOleksandr Tymoshenko #define	TI_GPIO_REV			0x50600801
148e53470feSOleksandr Tymoshenko #endif
149ff5823beSLuiz Otavio O Souza #define	PINS_PER_BANK			32
150db8a14ecSLuiz Otavio O Souza #define	MAX_GPIO_INTRS			MAX_GPIO_BANKS * INTR_PER_BANK
151e53470feSOleksandr Tymoshenko 
152e53470feSOleksandr Tymoshenko /**
153e53470feSOleksandr Tymoshenko  *	ti_gpio_mem_spec - Resource specification used when allocating resources
154e53470feSOleksandr Tymoshenko  *	ti_gpio_irq_spec - Resource specification used when allocating resources
155e53470feSOleksandr Tymoshenko  *
156e53470feSOleksandr Tymoshenko  *	This driver module can have up to six independent memory regions, each
157e53470feSOleksandr Tymoshenko  *	region typically controls 32 GPIO pins.
158db8a14ecSLuiz Otavio O Souza  *
159db8a14ecSLuiz Otavio O Souza  *	On OMAP3 and OMAP4 there is only one physical interrupt line per bank,
160db8a14ecSLuiz Otavio O Souza  *	but there are two set of registers which control the interrupt delivery
161db8a14ecSLuiz Otavio O Souza  *	to internal subsystems.  The first set of registers control the
162db8a14ecSLuiz Otavio O Souza  *	interrupts delivery to the MPU and the second set control the
163db8a14ecSLuiz Otavio O Souza  *	interrupts delivery to the DSP.
164db8a14ecSLuiz Otavio O Souza  *
165db8a14ecSLuiz Otavio O Souza  *	On AM335x there are two physical interrupt lines for each GPIO module.
166db8a14ecSLuiz Otavio O Souza  *	Each interrupt line is controlled by a set of registers.
167e53470feSOleksandr Tymoshenko  */
168e53470feSOleksandr Tymoshenko static struct resource_spec ti_gpio_mem_spec[] = {
169e53470feSOleksandr Tymoshenko 	{ SYS_RES_MEMORY,   0,  RF_ACTIVE },
170e53470feSOleksandr Tymoshenko 	{ SYS_RES_MEMORY,   1,  RF_ACTIVE | RF_OPTIONAL },
171e53470feSOleksandr Tymoshenko 	{ SYS_RES_MEMORY,   2,  RF_ACTIVE | RF_OPTIONAL },
172e53470feSOleksandr Tymoshenko 	{ SYS_RES_MEMORY,   3,  RF_ACTIVE | RF_OPTIONAL },
173e53470feSOleksandr Tymoshenko #if !defined(SOC_TI_AM335X)
174e53470feSOleksandr Tymoshenko 	{ SYS_RES_MEMORY,   4,  RF_ACTIVE | RF_OPTIONAL },
175e53470feSOleksandr Tymoshenko 	{ SYS_RES_MEMORY,   5,  RF_ACTIVE | RF_OPTIONAL },
176e53470feSOleksandr Tymoshenko #endif
177e53470feSOleksandr Tymoshenko 	{ -1,               0,  0 }
178e53470feSOleksandr Tymoshenko };
179e53470feSOleksandr Tymoshenko static struct resource_spec ti_gpio_irq_spec[] = {
180e53470feSOleksandr Tymoshenko 	{ SYS_RES_IRQ,      0,  RF_ACTIVE },
181e53470feSOleksandr Tymoshenko 	{ SYS_RES_IRQ,      1,  RF_ACTIVE | RF_OPTIONAL },
182e53470feSOleksandr Tymoshenko 	{ SYS_RES_IRQ,      2,  RF_ACTIVE | RF_OPTIONAL },
183e53470feSOleksandr Tymoshenko 	{ SYS_RES_IRQ,      3,  RF_ACTIVE | RF_OPTIONAL },
184e53470feSOleksandr Tymoshenko 	{ SYS_RES_IRQ,      4,  RF_ACTIVE | RF_OPTIONAL },
185e53470feSOleksandr Tymoshenko 	{ SYS_RES_IRQ,      5,  RF_ACTIVE | RF_OPTIONAL },
186db8a14ecSLuiz Otavio O Souza #if defined(SOC_TI_AM335X)
187db8a14ecSLuiz Otavio O Souza 	{ SYS_RES_IRQ,      6,  RF_ACTIVE | RF_OPTIONAL },
188db8a14ecSLuiz Otavio O Souza 	{ SYS_RES_IRQ,      7,  RF_ACTIVE | RF_OPTIONAL },
189e53470feSOleksandr Tymoshenko #endif
190e53470feSOleksandr Tymoshenko 	{ -1,               0,  0 }
191e53470feSOleksandr Tymoshenko };
192e53470feSOleksandr Tymoshenko 
193e53470feSOleksandr Tymoshenko /**
194e53470feSOleksandr Tymoshenko  *	Structure that stores the driver context.
195e53470feSOleksandr Tymoshenko  *
196e53470feSOleksandr Tymoshenko  *	This structure is allocated during driver attach.
197e53470feSOleksandr Tymoshenko  */
198e53470feSOleksandr Tymoshenko struct ti_gpio_softc {
199e53470feSOleksandr Tymoshenko 	device_t		sc_dev;
200e53470feSOleksandr Tymoshenko 
201ff5823beSLuiz Otavio O Souza 	/*
202ff5823beSLuiz Otavio O Souza 	 * The memory resource(s) for the PRCM register set, when the device is
203ff5823beSLuiz Otavio O Souza 	 * created the caller can assign up to 6 memory regions depending on
204ff5823beSLuiz Otavio O Souza 	 * the SoC type.
205e53470feSOleksandr Tymoshenko 	 */
206e53470feSOleksandr Tymoshenko 	struct resource		*sc_mem_res[MAX_GPIO_BANKS];
207db8a14ecSLuiz Otavio O Souza 	struct resource		*sc_irq_res[MAX_GPIO_INTRS];
208e53470feSOleksandr Tymoshenko 
209ff5823beSLuiz Otavio O Souza 	/* The handle for the register IRQ handlers. */
210db8a14ecSLuiz Otavio O Souza 	void			*sc_irq_hdl[MAX_GPIO_INTRS];
211e53470feSOleksandr Tymoshenko 
212ff5823beSLuiz Otavio O Souza 	/*
213ff5823beSLuiz Otavio O Souza 	 * The following describes the H/W revision of each of the GPIO banks.
214ff5823beSLuiz Otavio O Souza 	 */
215e53470feSOleksandr Tymoshenko 	uint32_t		sc_revision[MAX_GPIO_BANKS];
216e53470feSOleksandr Tymoshenko 
217e53470feSOleksandr Tymoshenko 	struct mtx		sc_mtx;
218e53470feSOleksandr Tymoshenko };
219e53470feSOleksandr Tymoshenko 
220e53470feSOleksandr Tymoshenko /**
221e53470feSOleksandr Tymoshenko  *	Macros for driver mutex locking
222e53470feSOleksandr Tymoshenko  */
223e53470feSOleksandr Tymoshenko #define	TI_GPIO_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
224e53470feSOleksandr Tymoshenko #define	TI_GPIO_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
225e53470feSOleksandr Tymoshenko #define	TI_GPIO_LOCK_INIT(_sc)		\
226e53470feSOleksandr Tymoshenko 	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
227e53470feSOleksandr Tymoshenko 	    "ti_gpio", MTX_DEF)
228ff5823beSLuiz Otavio O Souza #define	TI_GPIO_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx)
229ff5823beSLuiz Otavio O Souza #define	TI_GPIO_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED)
230ff5823beSLuiz Otavio O Souza #define	TI_GPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
231e53470feSOleksandr Tymoshenko 
232e53470feSOleksandr Tymoshenko /**
233e53470feSOleksandr Tymoshenko  *	ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers
234e53470feSOleksandr Tymoshenko  *	@sc: GPIO device context
235e53470feSOleksandr Tymoshenko  *	@bank: The bank to read from
236e53470feSOleksandr Tymoshenko  *	@off: The offset of a register from the GPIO register address range
237e53470feSOleksandr Tymoshenko  *
238e53470feSOleksandr Tymoshenko  *
239e53470feSOleksandr Tymoshenko  *	RETURNS:
240e53470feSOleksandr Tymoshenko  *	32-bit value read from the register.
241e53470feSOleksandr Tymoshenko  */
242e53470feSOleksandr Tymoshenko static inline uint32_t
243e53470feSOleksandr Tymoshenko ti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off)
244e53470feSOleksandr Tymoshenko {
245e53470feSOleksandr Tymoshenko 	return (bus_read_4(sc->sc_mem_res[bank], off));
246e53470feSOleksandr Tymoshenko }
247e53470feSOleksandr Tymoshenko 
248e53470feSOleksandr Tymoshenko /**
249e53470feSOleksandr Tymoshenko  *	ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers
250e53470feSOleksandr Tymoshenko  *	@sc: GPIO device context
251e53470feSOleksandr Tymoshenko  *	@bank: The bank to write to
252e53470feSOleksandr Tymoshenko  *	@off: The offset of a register from the GPIO register address range
253e53470feSOleksandr Tymoshenko  *	@val: The value to write into the register
254e53470feSOleksandr Tymoshenko  *
255e53470feSOleksandr Tymoshenko  *	RETURNS:
256e53470feSOleksandr Tymoshenko  *	nothing
257e53470feSOleksandr Tymoshenko  */
258e53470feSOleksandr Tymoshenko static inline void
259e53470feSOleksandr Tymoshenko ti_gpio_write_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off,
260e53470feSOleksandr Tymoshenko                  uint32_t val)
261e53470feSOleksandr Tymoshenko {
262e53470feSOleksandr Tymoshenko 	bus_write_4(sc->sc_mem_res[bank], off, val);
263e53470feSOleksandr Tymoshenko }
264e53470feSOleksandr Tymoshenko 
265db8a14ecSLuiz Otavio O Souza static inline void
266db8a14ecSLuiz Otavio O Souza ti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
267db8a14ecSLuiz Otavio O Souza {
268db8a14ecSLuiz Otavio O Souza 
269db8a14ecSLuiz Otavio O Souza 	/* We clear both set of registers. */
270db8a14ecSLuiz Otavio O Souza #if defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
271db8a14ecSLuiz Otavio O Souza 	ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_0, mask);
272db8a14ecSLuiz Otavio O Souza 	ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_1, mask);
273db8a14ecSLuiz Otavio O Souza #else
274db8a14ecSLuiz Otavio O Souza 	ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE1, mask);
275db8a14ecSLuiz Otavio O Souza 	ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE2, mask);
276db8a14ecSLuiz Otavio O Souza #endif
277db8a14ecSLuiz Otavio O Souza }
278db8a14ecSLuiz Otavio O Souza 
279e53470feSOleksandr Tymoshenko /**
280e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_max - Returns the maximum number of GPIO pins
281e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
282e53470feSOleksandr Tymoshenko  *	@maxpin: pointer to a value that upon return will contain the maximum number
283e53470feSOleksandr Tymoshenko  *	         of pins in the device.
284e53470feSOleksandr Tymoshenko  *
285e53470feSOleksandr Tymoshenko  *
286e53470feSOleksandr Tymoshenko  *	LOCKING:
287e53470feSOleksandr Tymoshenko  *	Internally locks the context
288e53470feSOleksandr Tymoshenko  *
289e53470feSOleksandr Tymoshenko  *	RETURNS:
290e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise an error code
291e53470feSOleksandr Tymoshenko  */
292e53470feSOleksandr Tymoshenko static int
293e53470feSOleksandr Tymoshenko ti_gpio_pin_max(device_t dev, int *maxpin)
294e53470feSOleksandr Tymoshenko {
295e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
296e53470feSOleksandr Tymoshenko 	unsigned int i;
297e53470feSOleksandr Tymoshenko 	unsigned int banks = 0;
298e53470feSOleksandr Tymoshenko 
299e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
300e53470feSOleksandr Tymoshenko 
301e53470feSOleksandr Tymoshenko 	/* Calculate how many valid banks we have and then multiply that by 32 to
302e53470feSOleksandr Tymoshenko 	 * give use the total number of pins.
303e53470feSOleksandr Tymoshenko 	 */
304e53470feSOleksandr Tymoshenko 	for (i = 0; i < MAX_GPIO_BANKS; i++) {
305e53470feSOleksandr Tymoshenko 		if (sc->sc_mem_res[i] != NULL)
306e53470feSOleksandr Tymoshenko 			banks++;
307e53470feSOleksandr Tymoshenko 	}
308e53470feSOleksandr Tymoshenko 
30997b405f1SOleksandr Tymoshenko 	*maxpin = (banks * PINS_PER_BANK) - 1;
310e53470feSOleksandr Tymoshenko 
311e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
312e53470feSOleksandr Tymoshenko 
313e53470feSOleksandr Tymoshenko 	return (0);
314e53470feSOleksandr Tymoshenko }
315e53470feSOleksandr Tymoshenko 
316e53470feSOleksandr Tymoshenko /**
317e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_getcaps - Gets the capabilties of a given pin
318e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
319e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
320e53470feSOleksandr Tymoshenko  *	@caps: pointer to a value that upon return will contain the capabilities
321e53470feSOleksandr Tymoshenko  *
322e53470feSOleksandr Tymoshenko  *	Currently all pins have the same capability, notably:
323e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_INPUT
324e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_OUTPUT
325e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_PULLUP
326e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_PULLDOWN
327e53470feSOleksandr Tymoshenko  *
328e53470feSOleksandr Tymoshenko  *	LOCKING:
329e53470feSOleksandr Tymoshenko  *	Internally locks the context
330e53470feSOleksandr Tymoshenko  *
331e53470feSOleksandr Tymoshenko  *	RETURNS:
332e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise an error code
333e53470feSOleksandr Tymoshenko  */
334e53470feSOleksandr Tymoshenko static int
335e53470feSOleksandr Tymoshenko ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
336e53470feSOleksandr Tymoshenko {
337e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
338e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
339e53470feSOleksandr Tymoshenko 
340e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
341e53470feSOleksandr Tymoshenko 
342e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
3438f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
344e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
345e53470feSOleksandr Tymoshenko 		return (EINVAL);
346e53470feSOleksandr Tymoshenko 	}
347e53470feSOleksandr Tymoshenko 
348e53470feSOleksandr Tymoshenko 	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP |
349e53470feSOleksandr Tymoshenko 	    GPIO_PIN_PULLDOWN);
350e53470feSOleksandr Tymoshenko 
351e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
352e53470feSOleksandr Tymoshenko 
353e53470feSOleksandr Tymoshenko 	return (0);
354e53470feSOleksandr Tymoshenko }
355e53470feSOleksandr Tymoshenko 
356e53470feSOleksandr Tymoshenko /**
357e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_getflags - Gets the current flags of a given pin
358e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
359e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
360e53470feSOleksandr Tymoshenko  *	@flags: upon return will contain the current flags of the pin
361e53470feSOleksandr Tymoshenko  *
362e53470feSOleksandr Tymoshenko  *	Reads the current flags of a given pin, here we actually read the H/W
363e53470feSOleksandr Tymoshenko  *	registers to determine the flags, rather than storing the value in the
364e53470feSOleksandr Tymoshenko  *	setflags call.
365e53470feSOleksandr Tymoshenko  *
366e53470feSOleksandr Tymoshenko  *	LOCKING:
367e53470feSOleksandr Tymoshenko  *	Internally locks the context
368e53470feSOleksandr Tymoshenko  *
369e53470feSOleksandr Tymoshenko  *	RETURNS:
370e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise an error code
371e53470feSOleksandr Tymoshenko  */
372e53470feSOleksandr Tymoshenko static int
373e53470feSOleksandr Tymoshenko ti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
374e53470feSOleksandr Tymoshenko {
375e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
376e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
377e53470feSOleksandr Tymoshenko 
378e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
379e53470feSOleksandr Tymoshenko 
380e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
3818f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
382e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
383e53470feSOleksandr Tymoshenko 		return (EINVAL);
384e53470feSOleksandr Tymoshenko 	}
385e53470feSOleksandr Tymoshenko 
386e53470feSOleksandr Tymoshenko 	/* Get the current pin state */
387e53470feSOleksandr Tymoshenko 	ti_scm_padconf_get_gpioflags(pin, flags);
388e53470feSOleksandr Tymoshenko 
389e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
390e53470feSOleksandr Tymoshenko 
391e53470feSOleksandr Tymoshenko 	return (0);
392e53470feSOleksandr Tymoshenko }
393e53470feSOleksandr Tymoshenko 
394e53470feSOleksandr Tymoshenko /**
395e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_getname - Gets the name of a given pin
396e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
397e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
398e53470feSOleksandr Tymoshenko  *	@name: buffer to put the name in
399e53470feSOleksandr Tymoshenko  *
400e53470feSOleksandr Tymoshenko  *	The driver simply calls the pins gpio_n, where 'n' is obviously the number
401e53470feSOleksandr Tymoshenko  *	of the pin.
402e53470feSOleksandr Tymoshenko  *
403e53470feSOleksandr Tymoshenko  *	LOCKING:
404e53470feSOleksandr Tymoshenko  *	Internally locks the context
405e53470feSOleksandr Tymoshenko  *
406e53470feSOleksandr Tymoshenko  *	RETURNS:
407e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise an error code
408e53470feSOleksandr Tymoshenko  */
409e53470feSOleksandr Tymoshenko static int
410e53470feSOleksandr Tymoshenko ti_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
411e53470feSOleksandr Tymoshenko {
412e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
413e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
414e53470feSOleksandr Tymoshenko 
415e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
416e53470feSOleksandr Tymoshenko 
417e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
4188f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
419e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
420e53470feSOleksandr Tymoshenko 		return (EINVAL);
421e53470feSOleksandr Tymoshenko 	}
422e53470feSOleksandr Tymoshenko 
423e53470feSOleksandr Tymoshenko 	/* Set a very simple name */
424e53470feSOleksandr Tymoshenko 	snprintf(name, GPIOMAXNAME, "gpio_%u", pin);
425e53470feSOleksandr Tymoshenko 	name[GPIOMAXNAME - 1] = '\0';
426e53470feSOleksandr Tymoshenko 
427e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
428e53470feSOleksandr Tymoshenko 
429e53470feSOleksandr Tymoshenko 	return (0);
430e53470feSOleksandr Tymoshenko }
431e53470feSOleksandr Tymoshenko 
432e53470feSOleksandr Tymoshenko /**
433e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_setflags - Sets the flags for a given pin
434e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
435e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
436e53470feSOleksandr Tymoshenko  *	@flags: the flags to set
437e53470feSOleksandr Tymoshenko  *
438e53470feSOleksandr Tymoshenko  *	The flags of the pin correspond to things like input/output mode, pull-ups,
439e53470feSOleksandr Tymoshenko  *	pull-downs, etc.  This driver doesn't support all flags, only the following:
440e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_INPUT
441e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_OUTPUT
442e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_PULLUP
443e53470feSOleksandr Tymoshenko  *	  - GPIO_PIN_PULLDOWN
444e53470feSOleksandr Tymoshenko  *
445e53470feSOleksandr Tymoshenko  *	LOCKING:
446e53470feSOleksandr Tymoshenko  *	Internally locks the context
447e53470feSOleksandr Tymoshenko  *
448e53470feSOleksandr Tymoshenko  *	RETURNS:
449e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise an error code
450e53470feSOleksandr Tymoshenko  */
451e53470feSOleksandr Tymoshenko static int
452e53470feSOleksandr Tymoshenko ti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
453e53470feSOleksandr Tymoshenko {
454e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
455e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
456e53470feSOleksandr Tymoshenko 	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
457e53470feSOleksandr Tymoshenko 	uint32_t reg_val;
458e53470feSOleksandr Tymoshenko 
459e53470feSOleksandr Tymoshenko 	/* Sanity check the flags supplied are valid, i.e. not input and output */
460e53470feSOleksandr Tymoshenko 	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 0x0000)
461e53470feSOleksandr Tymoshenko 		return (EINVAL);
462e53470feSOleksandr Tymoshenko 	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
463e53470feSOleksandr Tymoshenko 	    (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
464e53470feSOleksandr Tymoshenko 		return (EINVAL);
465e53470feSOleksandr Tymoshenko 	if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) ==
466e53470feSOleksandr Tymoshenko 	    (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN))
467e53470feSOleksandr Tymoshenko 		return (EINVAL);
468e53470feSOleksandr Tymoshenko 
469e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
470e53470feSOleksandr Tymoshenko 
471e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
4728f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
473e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
474e53470feSOleksandr Tymoshenko 		return (EINVAL);
475e53470feSOleksandr Tymoshenko 	}
476e53470feSOleksandr Tymoshenko 
477e53470feSOleksandr Tymoshenko 	/* Set the GPIO mode and state */
478e53470feSOleksandr Tymoshenko 	if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) {
479e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
480e53470feSOleksandr Tymoshenko 		return (EINVAL);
481e53470feSOleksandr Tymoshenko 	}
482e53470feSOleksandr Tymoshenko 
483e53470feSOleksandr Tymoshenko 	/* If configuring as an output set the "output enable" bit */
484e53470feSOleksandr Tymoshenko 	reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
485e53470feSOleksandr Tymoshenko 	if (flags & GPIO_PIN_INPUT)
486e53470feSOleksandr Tymoshenko 		reg_val |= mask;
487e53470feSOleksandr Tymoshenko 	else
488e53470feSOleksandr Tymoshenko 		reg_val &= ~mask;
489e53470feSOleksandr Tymoshenko 	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val);
490e53470feSOleksandr Tymoshenko 
491e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
492e53470feSOleksandr Tymoshenko 
493e53470feSOleksandr Tymoshenko 	return (0);
494e53470feSOleksandr Tymoshenko }
495e53470feSOleksandr Tymoshenko 
496e53470feSOleksandr Tymoshenko /**
497e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_set - Sets the current level on a GPIO pin
498e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
499e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
500e53470feSOleksandr Tymoshenko  *	@value: non-zero value will drive the pin high, otherwise the pin is
501e53470feSOleksandr Tymoshenko  *	        driven low.
502e53470feSOleksandr Tymoshenko  *
503e53470feSOleksandr Tymoshenko  *
504e53470feSOleksandr Tymoshenko  *	LOCKING:
505e53470feSOleksandr Tymoshenko  *	Internally locks the context
506e53470feSOleksandr Tymoshenko  *
507e53470feSOleksandr Tymoshenko  *	RETURNS:
508e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise a error code
509e53470feSOleksandr Tymoshenko  */
510e53470feSOleksandr Tymoshenko static int
511e53470feSOleksandr Tymoshenko ti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
512e53470feSOleksandr Tymoshenko {
513e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
514e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
515e53470feSOleksandr Tymoshenko 	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
516e53470feSOleksandr Tymoshenko 
517e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
518e53470feSOleksandr Tymoshenko 
519e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
5208f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
521e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
522e53470feSOleksandr Tymoshenko 		return (EINVAL);
523e53470feSOleksandr Tymoshenko 	}
524e53470feSOleksandr Tymoshenko 
525e53470feSOleksandr Tymoshenko 	ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT
526e53470feSOleksandr Tymoshenko 	    : TI_GPIO_SETDATAOUT, mask);
527e53470feSOleksandr Tymoshenko 
528e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
529e53470feSOleksandr Tymoshenko 
530e53470feSOleksandr Tymoshenko 	return (0);
531e53470feSOleksandr Tymoshenko }
532e53470feSOleksandr Tymoshenko 
533e53470feSOleksandr Tymoshenko /**
534e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_get - Gets the current level on a GPIO pin
535e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
536e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
537e53470feSOleksandr Tymoshenko  *	@value: pointer to a value that upond return will contain the pin value
538e53470feSOleksandr Tymoshenko  *
539e53470feSOleksandr Tymoshenko  *	The pin must be configured as an input pin beforehand, otherwise this
540e53470feSOleksandr Tymoshenko  *	function will fail.
541e53470feSOleksandr Tymoshenko  *
542e53470feSOleksandr Tymoshenko  *	LOCKING:
543e53470feSOleksandr Tymoshenko  *	Internally locks the context
544e53470feSOleksandr Tymoshenko  *
545e53470feSOleksandr Tymoshenko  *	RETURNS:
546e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise a error code
547e53470feSOleksandr Tymoshenko  */
548e53470feSOleksandr Tymoshenko static int
549e53470feSOleksandr Tymoshenko ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
550e53470feSOleksandr Tymoshenko {
551e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
552e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
553e53470feSOleksandr Tymoshenko 	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
554e53470feSOleksandr Tymoshenko 	uint32_t val = 0;
555e53470feSOleksandr Tymoshenko 
556e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
557e53470feSOleksandr Tymoshenko 
558e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
5598f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
560e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
561e53470feSOleksandr Tymoshenko 		return (EINVAL);
562e53470feSOleksandr Tymoshenko 	}
563e53470feSOleksandr Tymoshenko 
564e53470feSOleksandr Tymoshenko 	/* Sanity check the pin is not configured as an output */
565e53470feSOleksandr Tymoshenko 	val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
566e53470feSOleksandr Tymoshenko 
567e53470feSOleksandr Tymoshenko 	/* Read the value on the pin */
56897b405f1SOleksandr Tymoshenko 	if (val & mask)
569e53470feSOleksandr Tymoshenko 		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0;
5709f165184SLuiz Otavio O Souza 	else
5719f165184SLuiz Otavio O Souza 		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0;
572e53470feSOleksandr Tymoshenko 
573e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
574e53470feSOleksandr Tymoshenko 
575e53470feSOleksandr Tymoshenko 	return (0);
576e53470feSOleksandr Tymoshenko }
577e53470feSOleksandr Tymoshenko 
578e53470feSOleksandr Tymoshenko /**
579e53470feSOleksandr Tymoshenko  *	ti_gpio_pin_toggle - Toggles a given GPIO pin
580e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
581e53470feSOleksandr Tymoshenko  *	@pin: the number of the pin
582e53470feSOleksandr Tymoshenko  *
583e53470feSOleksandr Tymoshenko  *
584e53470feSOleksandr Tymoshenko  *	LOCKING:
585e53470feSOleksandr Tymoshenko  *	Internally locks the context
586e53470feSOleksandr Tymoshenko  *
587e53470feSOleksandr Tymoshenko  *	RETURNS:
588e53470feSOleksandr Tymoshenko  *	Returns 0 on success otherwise a error code
589e53470feSOleksandr Tymoshenko  */
590e53470feSOleksandr Tymoshenko static int
591e53470feSOleksandr Tymoshenko ti_gpio_pin_toggle(device_t dev, uint32_t pin)
592e53470feSOleksandr Tymoshenko {
593e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
594e53470feSOleksandr Tymoshenko 	uint32_t bank = (pin / PINS_PER_BANK);
595e53470feSOleksandr Tymoshenko 	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
596e53470feSOleksandr Tymoshenko 	uint32_t val;
597e53470feSOleksandr Tymoshenko 
598e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
599e53470feSOleksandr Tymoshenko 
600e53470feSOleksandr Tymoshenko 	/* Sanity check the pin number is valid */
6018f80e4e1SOleksandr Tymoshenko 	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
602e53470feSOleksandr Tymoshenko 		TI_GPIO_UNLOCK(sc);
603e53470feSOleksandr Tymoshenko 		return (EINVAL);
604e53470feSOleksandr Tymoshenko 	}
605e53470feSOleksandr Tymoshenko 
606e53470feSOleksandr Tymoshenko 	/* Toggle the pin */
607e53470feSOleksandr Tymoshenko 	val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT);
608e53470feSOleksandr Tymoshenko 	if (val & mask)
609e53470feSOleksandr Tymoshenko 		ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask);
610e53470feSOleksandr Tymoshenko 	else
611e53470feSOleksandr Tymoshenko 		ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask);
612e53470feSOleksandr Tymoshenko 
613e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
614e53470feSOleksandr Tymoshenko 
615e53470feSOleksandr Tymoshenko 	return (0);
616e53470feSOleksandr Tymoshenko }
617e53470feSOleksandr Tymoshenko 
618e53470feSOleksandr Tymoshenko /**
619e53470feSOleksandr Tymoshenko  *	ti_gpio_intr - ISR for all GPIO modules
620e53470feSOleksandr Tymoshenko  *	@arg: the soft context pointer
621e53470feSOleksandr Tymoshenko  *
622e53470feSOleksandr Tymoshenko  *	Unsused
623e53470feSOleksandr Tymoshenko  *
624e53470feSOleksandr Tymoshenko  *	LOCKING:
625e53470feSOleksandr Tymoshenko  *	Internally locks the context
626e53470feSOleksandr Tymoshenko  *
627e53470feSOleksandr Tymoshenko  */
628e53470feSOleksandr Tymoshenko static void
629e53470feSOleksandr Tymoshenko ti_gpio_intr(void *arg)
630e53470feSOleksandr Tymoshenko {
631e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = arg;
632e53470feSOleksandr Tymoshenko 
633e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK(sc);
634e53470feSOleksandr Tymoshenko 	/* TODO: something useful */
635e53470feSOleksandr Tymoshenko 	TI_GPIO_UNLOCK(sc);
636e53470feSOleksandr Tymoshenko }
637e53470feSOleksandr Tymoshenko 
638e53470feSOleksandr Tymoshenko /**
639e53470feSOleksandr Tymoshenko  *	ti_gpio_probe - probe function for the driver
640e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
641e53470feSOleksandr Tymoshenko  *
642e53470feSOleksandr Tymoshenko  *	Simply sets the name of the driver
643e53470feSOleksandr Tymoshenko  *
644e53470feSOleksandr Tymoshenko  *	LOCKING:
645e53470feSOleksandr Tymoshenko  *	None
646e53470feSOleksandr Tymoshenko  *
647e53470feSOleksandr Tymoshenko  *	RETURNS:
648e53470feSOleksandr Tymoshenko  *	Always returns 0
649e53470feSOleksandr Tymoshenko  */
650e53470feSOleksandr Tymoshenko static int
651e53470feSOleksandr Tymoshenko ti_gpio_probe(device_t dev)
652e53470feSOleksandr Tymoshenko {
653add35ed5SIan Lepore 
654add35ed5SIan Lepore 	if (!ofw_bus_status_okay(dev))
655add35ed5SIan Lepore 		return (ENXIO);
656add35ed5SIan Lepore 
657e53470feSOleksandr Tymoshenko 	if (!ofw_bus_is_compatible(dev, "ti,gpio"))
658e53470feSOleksandr Tymoshenko 		return (ENXIO);
659e53470feSOleksandr Tymoshenko 
660e53470feSOleksandr Tymoshenko 	device_set_desc(dev, "TI General Purpose I/O (GPIO)");
661ff5823beSLuiz Otavio O Souza 
662e53470feSOleksandr Tymoshenko 	return (0);
663e53470feSOleksandr Tymoshenko }
664e53470feSOleksandr Tymoshenko 
6659b1cba84SLuiz Otavio O Souza static int
6669b1cba84SLuiz Otavio O Souza ti_gpio_attach_intr(device_t dev)
6679b1cba84SLuiz Otavio O Souza {
6689b1cba84SLuiz Otavio O Souza 	int i;
6699b1cba84SLuiz Otavio O Souza 	struct ti_gpio_softc *sc;
6709b1cba84SLuiz Otavio O Souza 
6719b1cba84SLuiz Otavio O Souza 	sc = device_get_softc(dev);
672db8a14ecSLuiz Otavio O Souza 	for (i = 0; i < MAX_GPIO_INTRS; i++) {
6739b1cba84SLuiz Otavio O Souza 		if (sc->sc_irq_res[i] == NULL)
6749b1cba84SLuiz Otavio O Souza 			break;
6759b1cba84SLuiz Otavio O Souza 
6769b1cba84SLuiz Otavio O Souza 		/*
6779b1cba84SLuiz Otavio O Souza 		 * Register our interrupt handler for each of the IRQ resources.
6789b1cba84SLuiz Otavio O Souza 		 */
6799b1cba84SLuiz Otavio O Souza 		if (bus_setup_intr(dev, sc->sc_irq_res[i],
6809b1cba84SLuiz Otavio O Souza 		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc,
6819b1cba84SLuiz Otavio O Souza 		    &sc->sc_irq_hdl[i]) != 0) {
6829b1cba84SLuiz Otavio O Souza 			device_printf(dev,
6839b1cba84SLuiz Otavio O Souza 			    "WARNING: unable to register interrupt handler\n");
6849b1cba84SLuiz Otavio O Souza 			return (-1);
6859b1cba84SLuiz Otavio O Souza 		}
6869b1cba84SLuiz Otavio O Souza 	}
6879b1cba84SLuiz Otavio O Souza 
6889b1cba84SLuiz Otavio O Souza 	return (0);
6899b1cba84SLuiz Otavio O Souza }
6909b1cba84SLuiz Otavio O Souza 
6919b1cba84SLuiz Otavio O Souza static int
6929b1cba84SLuiz Otavio O Souza ti_gpio_detach_intr(device_t dev)
6939b1cba84SLuiz Otavio O Souza {
6949b1cba84SLuiz Otavio O Souza 	int i;
6959b1cba84SLuiz Otavio O Souza 	struct ti_gpio_softc *sc;
6969b1cba84SLuiz Otavio O Souza 
6979b1cba84SLuiz Otavio O Souza 	/* Teardown our interrupt handlers. */
6989b1cba84SLuiz Otavio O Souza 	sc = device_get_softc(dev);
699db8a14ecSLuiz Otavio O Souza 	for (i = 0; i < MAX_GPIO_INTRS; i++) {
7009b1cba84SLuiz Otavio O Souza 		if (sc->sc_irq_res[i] == NULL)
7019b1cba84SLuiz Otavio O Souza 			break;
7029b1cba84SLuiz Otavio O Souza 
7039b1cba84SLuiz Otavio O Souza 		if (sc->sc_irq_hdl[i]) {
7049b1cba84SLuiz Otavio O Souza 			bus_teardown_intr(dev, sc->sc_irq_res[i],
7059b1cba84SLuiz Otavio O Souza 			    sc->sc_irq_hdl[i]);
7069b1cba84SLuiz Otavio O Souza 		}
7079b1cba84SLuiz Otavio O Souza 	}
7089b1cba84SLuiz Otavio O Souza 
7099b1cba84SLuiz Otavio O Souza 	return (0);
7109b1cba84SLuiz Otavio O Souza }
7119b1cba84SLuiz Otavio O Souza 
7129b1cba84SLuiz Otavio O Souza static int
7139b1cba84SLuiz Otavio O Souza ti_gpio_bank_init(device_t dev, int bank)
7149b1cba84SLuiz Otavio O Souza {
715*1f1e8f16SLuiz Otavio O Souza 	int pin;
7169b1cba84SLuiz Otavio O Souza 	struct ti_gpio_softc *sc;
7179b1cba84SLuiz Otavio O Souza 	uint32_t flags, reg_oe;
7189b1cba84SLuiz Otavio O Souza 
7199b1cba84SLuiz Otavio O Souza 	sc = device_get_softc(dev);
7209b1cba84SLuiz Otavio O Souza 
7219b1cba84SLuiz Otavio O Souza 	/* Enable the interface and functional clocks for the module. */
7229b1cba84SLuiz Otavio O Souza 	ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank);
7239b1cba84SLuiz Otavio O Souza 
7249b1cba84SLuiz Otavio O Souza 	/*
7259b1cba84SLuiz Otavio O Souza 	 * Read the revision number of the module.  TI don't publish the
7269b1cba84SLuiz Otavio O Souza 	 * actual revision numbers, so instead the values have been
7279b1cba84SLuiz Otavio O Souza 	 * determined by experimentation.
7289b1cba84SLuiz Otavio O Souza 	 */
7299b1cba84SLuiz Otavio O Souza 	sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION);
7309b1cba84SLuiz Otavio O Souza 
7319b1cba84SLuiz Otavio O Souza 	/* Check the revision. */
7329b1cba84SLuiz Otavio O Souza 	if (sc->sc_revision[bank] != TI_GPIO_REV) {
7339b1cba84SLuiz Otavio O Souza 		device_printf(dev, "Warning: could not determine the revision "
7349b1cba84SLuiz Otavio O Souza 		    "of %u GPIO module (revision:0x%08x)\n",
7359b1cba84SLuiz Otavio O Souza 		    bank, sc->sc_revision[bank]);
7369b1cba84SLuiz Otavio O Souza 		return (EINVAL);
7379b1cba84SLuiz Otavio O Souza 	}
7389b1cba84SLuiz Otavio O Souza 
7399b1cba84SLuiz Otavio O Souza 	/* Disable interrupts for all pins. */
740db8a14ecSLuiz Otavio O Souza 	ti_gpio_intr_clr(sc, bank, 0xffffffff);
7419b1cba84SLuiz Otavio O Souza 
7429b1cba84SLuiz Otavio O Souza 	/* Init OE register based on pads configuration. */
7439b1cba84SLuiz Otavio O Souza 	reg_oe = 0xffffffff;
7449b1cba84SLuiz Otavio O Souza 	for (pin = 0; pin < PINS_PER_BANK; pin++) {
7459b1cba84SLuiz Otavio O Souza 		ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin,
7469b1cba84SLuiz Otavio O Souza 		    &flags);
7479b1cba84SLuiz Otavio O Souza 		if (flags & GPIO_PIN_OUTPUT)
7489b1cba84SLuiz Otavio O Souza 			reg_oe &= ~(1UL << pin);
7499b1cba84SLuiz Otavio O Souza 	}
7509b1cba84SLuiz Otavio O Souza 	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe);
7519b1cba84SLuiz Otavio O Souza 
7529b1cba84SLuiz Otavio O Souza 	return (0);
7539b1cba84SLuiz Otavio O Souza }
7549b1cba84SLuiz Otavio O Souza 
755e53470feSOleksandr Tymoshenko /**
756e53470feSOleksandr Tymoshenko  *	ti_gpio_attach - attach function for the driver
757e53470feSOleksandr Tymoshenko  *	@dev: gpio device handle
758e53470feSOleksandr Tymoshenko  *
759e53470feSOleksandr Tymoshenko  *	Allocates and sets up the driver context for all GPIO banks.  This function
760e53470feSOleksandr Tymoshenko  *	expects the memory ranges and IRQs to already be allocated to the driver.
761e53470feSOleksandr Tymoshenko  *
762e53470feSOleksandr Tymoshenko  *	LOCKING:
763e53470feSOleksandr Tymoshenko  *	None
764e53470feSOleksandr Tymoshenko  *
765e53470feSOleksandr Tymoshenko  *	RETURNS:
766e53470feSOleksandr Tymoshenko  *	Always returns 0
767e53470feSOleksandr Tymoshenko  */
768e53470feSOleksandr Tymoshenko static int
769e53470feSOleksandr Tymoshenko ti_gpio_attach(device_t dev)
770e53470feSOleksandr Tymoshenko {
7719b1cba84SLuiz Otavio O Souza 	struct ti_gpio_softc *sc;
772e53470feSOleksandr Tymoshenko 	unsigned int i;
7739b1cba84SLuiz Otavio O Souza 	int err;
774e53470feSOleksandr Tymoshenko 
7759b1cba84SLuiz Otavio O Souza  	sc = device_get_softc(dev);
776e53470feSOleksandr Tymoshenko 	sc->sc_dev = dev;
777e53470feSOleksandr Tymoshenko 
778e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK_INIT(sc);
779e53470feSOleksandr Tymoshenko 
780e53470feSOleksandr Tymoshenko 	/* There are up to 6 different GPIO register sets located in different
781e53470feSOleksandr Tymoshenko 	 * memory areas on the chip.  The memory range should have been set for
782e53470feSOleksandr Tymoshenko 	 * the driver when it was added as a child.
783e53470feSOleksandr Tymoshenko 	 */
7849b1cba84SLuiz Otavio O Souza 	if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) {
785e53470feSOleksandr Tymoshenko 		device_printf(dev, "Error: could not allocate mem resources\n");
786e53470feSOleksandr Tymoshenko 		return (ENXIO);
787e53470feSOleksandr Tymoshenko 	}
788e53470feSOleksandr Tymoshenko 
789e53470feSOleksandr Tymoshenko 	/* Request the IRQ resources */
7909b1cba84SLuiz Otavio O Souza 	if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) {
7919b1cba84SLuiz Otavio O Souza 		bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
792e53470feSOleksandr Tymoshenko 		device_printf(dev, "Error: could not allocate irq resources\n");
793e53470feSOleksandr Tymoshenko 		return (ENXIO);
794e53470feSOleksandr Tymoshenko 	}
795e53470feSOleksandr Tymoshenko 
796e53470feSOleksandr Tymoshenko 	/* Setup the IRQ resources */
7979b1cba84SLuiz Otavio O Souza 	if (ti_gpio_attach_intr(dev) != 0) {
7989b1cba84SLuiz Otavio O Souza 		ti_gpio_detach_intr(dev);
7999b1cba84SLuiz Otavio O Souza 		bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
8009b1cba84SLuiz Otavio O Souza 		bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
801e53470feSOleksandr Tymoshenko 		return (ENXIO);
802e53470feSOleksandr Tymoshenko 	}
803e53470feSOleksandr Tymoshenko 
804e53470feSOleksandr Tymoshenko 	/* We need to go through each block and ensure the clocks are running and
805e53470feSOleksandr Tymoshenko 	 * the module is enabled.  It might be better to do this only when the
806e53470feSOleksandr Tymoshenko 	 * pins are configured which would result in less power used if the GPIO
807e53470feSOleksandr Tymoshenko 	 * pins weren't used ...
808e53470feSOleksandr Tymoshenko 	 */
809e53470feSOleksandr Tymoshenko 	for (i = 0; i < MAX_GPIO_BANKS; i++) {
810e53470feSOleksandr Tymoshenko 		if (sc->sc_mem_res[i] != NULL) {
811*1f1e8f16SLuiz Otavio O Souza 			/* Initialize the GPIO module. */
8129b1cba84SLuiz Otavio O Souza 			err = ti_gpio_bank_init(dev, i);
8139b1cba84SLuiz Otavio O Souza 			if (err != 0) {
8149b1cba84SLuiz Otavio O Souza 				ti_gpio_detach_intr(dev);
8159b1cba84SLuiz Otavio O Souza 				bus_release_resources(dev, ti_gpio_irq_spec,
8169b1cba84SLuiz Otavio O Souza 				    sc->sc_irq_res);
8179b1cba84SLuiz Otavio O Souza 				bus_release_resources(dev, ti_gpio_mem_spec,
8189b1cba84SLuiz Otavio O Souza 				    sc->sc_mem_res);
8199b1cba84SLuiz Otavio O Souza 				return (err);
820e53470feSOleksandr Tymoshenko 			}
821e53470feSOleksandr Tymoshenko 		}
822e53470feSOleksandr Tymoshenko 	}
823e53470feSOleksandr Tymoshenko 
824e53470feSOleksandr Tymoshenko 	/* Finish of the probe call */
825e53470feSOleksandr Tymoshenko 	device_add_child(dev, "gpioc", device_get_unit(dev));
826e53470feSOleksandr Tymoshenko 	device_add_child(dev, "gpiobus", device_get_unit(dev));
82797b405f1SOleksandr Tymoshenko 
828e53470feSOleksandr Tymoshenko 	return (bus_generic_attach(dev));
829e53470feSOleksandr Tymoshenko }
830e53470feSOleksandr Tymoshenko 
831e53470feSOleksandr Tymoshenko /**
832e53470feSOleksandr Tymoshenko  *	ti_gpio_detach - detach function for the driver
833e53470feSOleksandr Tymoshenko  *	@dev: scm device handle
834e53470feSOleksandr Tymoshenko  *
835e53470feSOleksandr Tymoshenko  *	Allocates and sets up the driver context, this simply entails creating a
836e53470feSOleksandr Tymoshenko  *	bus mappings for the SCM register set.
837e53470feSOleksandr Tymoshenko  *
838e53470feSOleksandr Tymoshenko  *	LOCKING:
839e53470feSOleksandr Tymoshenko  *	None
840e53470feSOleksandr Tymoshenko  *
841e53470feSOleksandr Tymoshenko  *	RETURNS:
842e53470feSOleksandr Tymoshenko  *	Always returns 0
843e53470feSOleksandr Tymoshenko  */
844e53470feSOleksandr Tymoshenko static int
845e53470feSOleksandr Tymoshenko ti_gpio_detach(device_t dev)
846e53470feSOleksandr Tymoshenko {
847e53470feSOleksandr Tymoshenko 	struct ti_gpio_softc *sc = device_get_softc(dev);
848e53470feSOleksandr Tymoshenko 	unsigned int i;
849e53470feSOleksandr Tymoshenko 
850e53470feSOleksandr Tymoshenko 	KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
851e53470feSOleksandr Tymoshenko 
852e53470feSOleksandr Tymoshenko 	/* Disable all interrupts */
853e53470feSOleksandr Tymoshenko 	for (i = 0; i < MAX_GPIO_BANKS; i++) {
854db8a14ecSLuiz Otavio O Souza 		if (sc->sc_mem_res[i] != NULL)
855db8a14ecSLuiz Otavio O Souza 			ti_gpio_intr_clr(sc, i, 0xffffffff);
856e53470feSOleksandr Tymoshenko 	}
857e53470feSOleksandr Tymoshenko 
858e53470feSOleksandr Tymoshenko 	bus_generic_detach(dev);
859e53470feSOleksandr Tymoshenko 
8609b1cba84SLuiz Otavio O Souza 	/* Release the memory and IRQ resources. */
8619b1cba84SLuiz Otavio O Souza 	ti_gpio_detach_intr(dev);
8629b1cba84SLuiz Otavio O Souza 	bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
8639b1cba84SLuiz Otavio O Souza 	bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
864e53470feSOleksandr Tymoshenko 
865e53470feSOleksandr Tymoshenko 	TI_GPIO_LOCK_DESTROY(sc);
866e53470feSOleksandr Tymoshenko 
867e53470feSOleksandr Tymoshenko 	return (0);
868e53470feSOleksandr Tymoshenko }
869e53470feSOleksandr Tymoshenko 
8708c705c2cSLuiz Otavio O Souza static phandle_t
8718c705c2cSLuiz Otavio O Souza ti_gpio_get_node(device_t bus, device_t dev)
8728c705c2cSLuiz Otavio O Souza {
8738c705c2cSLuiz Otavio O Souza 
8748c705c2cSLuiz Otavio O Souza 	/* We only have one child, the GPIO bus, which needs our own node. */
8758c705c2cSLuiz Otavio O Souza 	return (ofw_bus_get_node(bus));
8768c705c2cSLuiz Otavio O Souza }
8778c705c2cSLuiz Otavio O Souza 
878e53470feSOleksandr Tymoshenko static device_method_t ti_gpio_methods[] = {
879e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_probe, ti_gpio_probe),
880e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_attach, ti_gpio_attach),
881e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_detach, ti_gpio_detach),
882e53470feSOleksandr Tymoshenko 
883e53470feSOleksandr Tymoshenko 	/* GPIO protocol */
884e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_max, ti_gpio_pin_max),
885e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname),
886e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags),
887e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps),
888e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags),
889e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_get, ti_gpio_pin_get),
890e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
891e53470feSOleksandr Tymoshenko 	DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
8928c705c2cSLuiz Otavio O Souza 
8938c705c2cSLuiz Otavio O Souza 	/* ofw_bus interface */
8948c705c2cSLuiz Otavio O Souza 	DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
8958c705c2cSLuiz Otavio O Souza 
896e53470feSOleksandr Tymoshenko 	{0, 0},
897e53470feSOleksandr Tymoshenko };
898e53470feSOleksandr Tymoshenko 
899e53470feSOleksandr Tymoshenko static driver_t ti_gpio_driver = {
900e53470feSOleksandr Tymoshenko 	"gpio",
901e53470feSOleksandr Tymoshenko 	ti_gpio_methods,
902e53470feSOleksandr Tymoshenko 	sizeof(struct ti_gpio_softc),
903e53470feSOleksandr Tymoshenko };
904e53470feSOleksandr Tymoshenko static devclass_t ti_gpio_devclass;
905e53470feSOleksandr Tymoshenko 
906e53470feSOleksandr Tymoshenko DRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0);
907