1239281Sgonzo/*-
2239281Sgonzo * Copyright (c) 2011
3239281Sgonzo *	Ben Gray <ben.r.gray@gmail.com>.
4239281Sgonzo * All rights reserved.
5239281Sgonzo *
6239281Sgonzo * Redistribution and use in source and binary forms, with or without
7239281Sgonzo * modification, are permitted provided that the following conditions
8239281Sgonzo * are met:
9239281Sgonzo * 1. Redistributions of source code must retain the above copyright
10239281Sgonzo *    notice, this list of conditions and the following disclaimer.
11239281Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
12239281Sgonzo *    notice, this list of conditions and the following disclaimer in the
13239281Sgonzo *    documentation and/or other materials provided with the distribution.
14239281Sgonzo *
15239281Sgonzo * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16239281Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17239281Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18239281Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19239281Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20239281Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21239281Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22239281Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23239281Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24239281Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25239281Sgonzo * SUCH DAMAGE.
26239281Sgonzo */
27239281Sgonzo
28239281Sgonzo/**
29239281Sgonzo *	Very simple GPIO (general purpose IO) driver module for TI OMAP SoC's.
30239281Sgonzo *
31239281Sgonzo *	Currently this driver only does the basics, get a value on a pin & set a
32239281Sgonzo *	value on a pin. Hopefully over time I'll expand this to be a bit more generic
33239281Sgonzo *	and support interrupts and other various bits on the SoC can do ... in the
34239281Sgonzo *	meantime this is all you get.
35239281Sgonzo *
36239281Sgonzo *	Beware the OMA datasheet(s) lists GPIO banks 1-6, whereas I've used 0-5 here
37239281Sgonzo *	in the code.
38239281Sgonzo *
39239281Sgonzo *
40239281Sgonzo */
41239281Sgonzo
42239281Sgonzo#include <sys/cdefs.h>
43239281Sgonzo__FBSDID("$FreeBSD$");
44239281Sgonzo
45239281Sgonzo#include <sys/param.h>
46239281Sgonzo#include <sys/systm.h>
47239281Sgonzo#include <sys/bus.h>
48239281Sgonzo
49239281Sgonzo#include <sys/kernel.h>
50239281Sgonzo#include <sys/module.h>
51239281Sgonzo#include <sys/rman.h>
52239281Sgonzo#include <sys/lock.h>
53239281Sgonzo#include <sys/mutex.h>
54239281Sgonzo#include <sys/gpio.h>
55239281Sgonzo
56239281Sgonzo#include <machine/bus.h>
57239281Sgonzo#include <machine/resource.h>
58239281Sgonzo
59239281Sgonzo#include <arm/ti/ti_scm.h>
60239281Sgonzo#include <arm/ti/ti_prcm.h>
61239281Sgonzo
62239281Sgonzo#include <dev/fdt/fdt_common.h>
63239281Sgonzo#include <dev/ofw/openfirm.h>
64239281Sgonzo#include <dev/ofw/ofw_bus.h>
65239281Sgonzo#include <dev/ofw/ofw_bus_subr.h>
66239281Sgonzo
67239281Sgonzo#include "gpio_if.h"
68239281Sgonzo
69266148Sloos/* Register definitions */
70266148Sloos#define	TI_GPIO_REVISION		0x0000
71266148Sloos#define	TI_GPIO_SYSCONFIG		0x0010
72239281Sgonzo#if defined(SOC_OMAP3)
73266148Sloos#define	TI_GPIO_SYSSTATUS		0x0014
74266148Sloos#define	TI_GPIO_IRQSTATUS1		0x0018
75266148Sloos#define	TI_GPIO_IRQENABLE1		0x001C
76266148Sloos#define	TI_GPIO_WAKEUPENABLE		0x0020
77266148Sloos#define	TI_GPIO_IRQSTATUS2		0x0028
78266148Sloos#define	TI_GPIO_IRQENABLE2		0x002C
79266148Sloos#define	TI_GPIO_CTRL			0x0030
80266148Sloos#define	TI_GPIO_OE			0x0034
81266148Sloos#define	TI_GPIO_DATAIN			0x0038
82266148Sloos#define	TI_GPIO_DATAOUT			0x003C
83266148Sloos#define	TI_GPIO_LEVELDETECT0		0x0040
84266148Sloos#define	TI_GPIO_LEVELDETECT1		0x0044
85266148Sloos#define	TI_GPIO_RISINGDETECT		0x0048
86266148Sloos#define	TI_GPIO_FALLINGDETECT		0x004C
87266148Sloos#define	TI_GPIO_DEBOUNCENABLE		0x0050
88266148Sloos#define	TI_GPIO_DEBOUNCINGTIME		0x0054
89266148Sloos#define	TI_GPIO_CLEARIRQENABLE1		0x0060
90266148Sloos#define	TI_GPIO_SETIRQENABLE1		0x0064
91266148Sloos#define	TI_GPIO_CLEARIRQENABLE2		0x0070
92266148Sloos#define	TI_GPIO_SETIRQENABLE2		0x0074
93266148Sloos#define	TI_GPIO_CLEARWKUENA		0x0080
94266148Sloos#define	TI_GPIO_SETWKUENA		0x0084
95266148Sloos#define	TI_GPIO_CLEARDATAOUT		0x0090
96266148Sloos#define	TI_GPIO_SETDATAOUT		0x0094
97239281Sgonzo#elif defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
98266148Sloos#define	TI_GPIO_IRQSTATUS_RAW_0		0x0024
99266148Sloos#define	TI_GPIO_IRQSTATUS_RAW_1		0x0028
100266148Sloos#define	TI_GPIO_IRQSTATUS_0		0x002C
101266148Sloos#define	TI_GPIO_IRQSTATUS_1		0x0030
102266148Sloos#define	TI_GPIO_IRQSTATUS_SET_0		0x0034
103266148Sloos#define	TI_GPIO_IRQSTATUS_SET_1		0x0038
104266148Sloos#define	TI_GPIO_IRQSTATUS_CLR_0		0x003C
105266148Sloos#define	TI_GPIO_IRQSTATUS_CLR_1		0x0040
106266148Sloos#define	TI_GPIO_IRQWAKEN_0		0x0044
107266148Sloos#define	TI_GPIO_IRQWAKEN_1		0x0048
108266148Sloos#define	TI_GPIO_SYSSTATUS		0x0114
109266148Sloos#define	TI_GPIO_IRQSTATUS1		0x0118
110266148Sloos#define	TI_GPIO_IRQENABLE1		0x011C
111266148Sloos#define	TI_GPIO_WAKEUPENABLE		0x0120
112266148Sloos#define	TI_GPIO_IRQSTATUS2		0x0128
113266148Sloos#define	TI_GPIO_IRQENABLE2		0x012C
114266148Sloos#define	TI_GPIO_CTRL			0x0130
115266148Sloos#define	TI_GPIO_OE			0x0134
116266148Sloos#define	TI_GPIO_DATAIN			0x0138
117266148Sloos#define	TI_GPIO_DATAOUT			0x013C
118266148Sloos#define	TI_GPIO_LEVELDETECT0		0x0140
119266148Sloos#define	TI_GPIO_LEVELDETECT1		0x0144
120266148Sloos#define	TI_GPIO_RISINGDETECT		0x0148
121266148Sloos#define	TI_GPIO_FALLINGDETECT		0x014C
122266148Sloos#define	TI_GPIO_DEBOUNCENABLE		0x0150
123266148Sloos#define	TI_GPIO_DEBOUNCINGTIME		0x0154
124266148Sloos#define	TI_GPIO_CLEARWKUPENA		0x0180
125266148Sloos#define	TI_GPIO_SETWKUENA		0x0184
126266148Sloos#define	TI_GPIO_CLEARDATAOUT		0x0190
127266148Sloos#define	TI_GPIO_SETDATAOUT		0x0194
128239281Sgonzo#else
129239281Sgonzo#error "Unknown SoC"
130239281Sgonzo#endif
131239281Sgonzo
132266148Sloos/* Other SoC Specific definitions */
133239281Sgonzo#if defined(SOC_OMAP3)
134266148Sloos#define	MAX_GPIO_BANKS			6
135266148Sloos#define	FIRST_GPIO_BANK			1
136266148Sloos#define	INTR_PER_BANK			1
137266148Sloos#define	TI_GPIO_REV			0x00000025
138239281Sgonzo#elif defined(SOC_OMAP4)
139266148Sloos#define	MAX_GPIO_BANKS			6
140266148Sloos#define	FIRST_GPIO_BANK			1
141266148Sloos#define	INTR_PER_BANK			1
142266148Sloos#define	TI_GPIO_REV			0x50600801
143239281Sgonzo#elif defined(SOC_TI_AM335X)
144266148Sloos#define	MAX_GPIO_BANKS			4
145266148Sloos#define	FIRST_GPIO_BANK			0
146266148Sloos#define	INTR_PER_BANK			2
147266148Sloos#define	TI_GPIO_REV			0x50600801
148239281Sgonzo#endif
149266148Sloos#define	PINS_PER_BANK			32
150266148Sloos#define	MAX_GPIO_INTRS			MAX_GPIO_BANKS * INTR_PER_BANK
151239281Sgonzo
152239281Sgonzo/**
153239281Sgonzo *	ti_gpio_mem_spec - Resource specification used when allocating resources
154239281Sgonzo *	ti_gpio_irq_spec - Resource specification used when allocating resources
155239281Sgonzo *
156239281Sgonzo *	This driver module can have up to six independent memory regions, each
157239281Sgonzo *	region typically controls 32 GPIO pins.
158266148Sloos *
159266148Sloos *	On OMAP3 and OMAP4 there is only one physical interrupt line per bank,
160266148Sloos *	but there are two set of registers which control the interrupt delivery
161266148Sloos *	to internal subsystems.  The first set of registers control the
162266148Sloos *	interrupts delivery to the MPU and the second set control the
163266148Sloos *	interrupts delivery to the DSP.
164266148Sloos *
165266148Sloos *	On AM335x there are two physical interrupt lines for each GPIO module.
166266148Sloos *	Each interrupt line is controlled by a set of registers.
167239281Sgonzo */
168239281Sgonzostatic struct resource_spec ti_gpio_mem_spec[] = {
169239281Sgonzo	{ SYS_RES_MEMORY,   0,  RF_ACTIVE },
170239281Sgonzo	{ SYS_RES_MEMORY,   1,  RF_ACTIVE | RF_OPTIONAL },
171239281Sgonzo	{ SYS_RES_MEMORY,   2,  RF_ACTIVE | RF_OPTIONAL },
172239281Sgonzo	{ SYS_RES_MEMORY,   3,  RF_ACTIVE | RF_OPTIONAL },
173239281Sgonzo#if !defined(SOC_TI_AM335X)
174239281Sgonzo	{ SYS_RES_MEMORY,   4,  RF_ACTIVE | RF_OPTIONAL },
175239281Sgonzo	{ SYS_RES_MEMORY,   5,  RF_ACTIVE | RF_OPTIONAL },
176239281Sgonzo#endif
177239281Sgonzo	{ -1,               0,  0 }
178239281Sgonzo};
179239281Sgonzostatic struct resource_spec ti_gpio_irq_spec[] = {
180239281Sgonzo	{ SYS_RES_IRQ,      0,  RF_ACTIVE },
181239281Sgonzo	{ SYS_RES_IRQ,      1,  RF_ACTIVE | RF_OPTIONAL },
182239281Sgonzo	{ SYS_RES_IRQ,      2,  RF_ACTIVE | RF_OPTIONAL },
183239281Sgonzo	{ SYS_RES_IRQ,      3,  RF_ACTIVE | RF_OPTIONAL },
184239281Sgonzo	{ SYS_RES_IRQ,      4,  RF_ACTIVE | RF_OPTIONAL },
185239281Sgonzo	{ SYS_RES_IRQ,      5,  RF_ACTIVE | RF_OPTIONAL },
186266148Sloos#if defined(SOC_TI_AM335X)
187266148Sloos	{ SYS_RES_IRQ,      6,  RF_ACTIVE | RF_OPTIONAL },
188266148Sloos	{ SYS_RES_IRQ,      7,  RF_ACTIVE | RF_OPTIONAL },
189239281Sgonzo#endif
190239281Sgonzo	{ -1,               0,  0 }
191239281Sgonzo};
192239281Sgonzo
193239281Sgonzo/**
194239281Sgonzo *	Structure that stores the driver context.
195239281Sgonzo *
196239281Sgonzo *	This structure is allocated during driver attach.
197239281Sgonzo */
198239281Sgonzostruct ti_gpio_softc {
199266148Sloos	device_t		sc_dev;
200239281Sgonzo
201266148Sloos	/*
202266148Sloos	 * The memory resource(s) for the PRCM register set, when the device is
203266148Sloos	 * created the caller can assign up to 6 memory regions depending on
204266148Sloos	 * the SoC type.
205239281Sgonzo	 */
206266148Sloos	struct resource		*sc_mem_res[MAX_GPIO_BANKS];
207266148Sloos	struct resource		*sc_irq_res[MAX_GPIO_INTRS];
208239281Sgonzo
209266148Sloos	/* The handle for the register IRQ handlers. */
210266148Sloos	void			*sc_irq_hdl[MAX_GPIO_INTRS];
211239281Sgonzo
212266148Sloos	/*
213266148Sloos	 * The following describes the H/W revision of each of the GPIO banks.
214266148Sloos	 */
215266148Sloos	uint32_t		sc_revision[MAX_GPIO_BANKS];
216239281Sgonzo
217266148Sloos	struct mtx		sc_mtx;
218239281Sgonzo};
219239281Sgonzo
220239281Sgonzo/**
221239281Sgonzo *	Macros for driver mutex locking
222239281Sgonzo */
223266148Sloos#define	TI_GPIO_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
224266148Sloos#define	TI_GPIO_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
225266148Sloos#define	TI_GPIO_LOCK_INIT(_sc)		\
226239281Sgonzo	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
227266148Sloos	    "ti_gpio", MTX_DEF)
228266148Sloos#define	TI_GPIO_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx)
229266148Sloos#define	TI_GPIO_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED)
230266148Sloos#define	TI_GPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
231239281Sgonzo
232239281Sgonzo/**
233239281Sgonzo *	ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers
234239281Sgonzo *	@sc: GPIO device context
235239281Sgonzo *	@bank: The bank to read from
236239281Sgonzo *	@off: The offset of a register from the GPIO register address range
237239281Sgonzo *
238239281Sgonzo *
239239281Sgonzo *	RETURNS:
240239281Sgonzo *	32-bit value read from the register.
241239281Sgonzo */
242239281Sgonzostatic inline uint32_t
243239281Sgonzoti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off)
244239281Sgonzo{
245239281Sgonzo	return (bus_read_4(sc->sc_mem_res[bank], off));
246239281Sgonzo}
247239281Sgonzo
248239281Sgonzo/**
249239281Sgonzo *	ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers
250239281Sgonzo *	@sc: GPIO device context
251239281Sgonzo *	@bank: The bank to write to
252239281Sgonzo *	@off: The offset of a register from the GPIO register address range
253239281Sgonzo *	@val: The value to write into the register
254239281Sgonzo *
255239281Sgonzo *	RETURNS:
256239281Sgonzo *	nothing
257239281Sgonzo */
258239281Sgonzostatic inline void
259239281Sgonzoti_gpio_write_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off,
260239281Sgonzo                 uint32_t val)
261239281Sgonzo{
262239281Sgonzo	bus_write_4(sc->sc_mem_res[bank], off, val);
263239281Sgonzo}
264239281Sgonzo
265266148Sloosstatic inline void
266266148Sloosti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
267266148Sloos{
268266148Sloos
269266148Sloos	/* We clear both set of registers. */
270266148Sloos#if defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
271266148Sloos	ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_0, mask);
272266148Sloos	ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_1, mask);
273266148Sloos#else
274266148Sloos	ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE1, mask);
275266148Sloos	ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE2, mask);
276266148Sloos#endif
277266148Sloos}
278266148Sloos
279239281Sgonzo/**
280239281Sgonzo *	ti_gpio_pin_max - Returns the maximum number of GPIO pins
281239281Sgonzo *	@dev: gpio device handle
282239281Sgonzo *	@maxpin: pointer to a value that upon return will contain the maximum number
283239281Sgonzo *	         of pins in the device.
284239281Sgonzo *
285239281Sgonzo *
286239281Sgonzo *	LOCKING:
287239281Sgonzo *	Internally locks the context
288239281Sgonzo *
289239281Sgonzo *	RETURNS:
290239281Sgonzo *	Returns 0 on success otherwise an error code
291239281Sgonzo */
292239281Sgonzostatic int
293239281Sgonzoti_gpio_pin_max(device_t dev, int *maxpin)
294239281Sgonzo{
295239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
296239281Sgonzo	unsigned int i;
297239281Sgonzo	unsigned int banks = 0;
298239281Sgonzo
299239281Sgonzo	TI_GPIO_LOCK(sc);
300239281Sgonzo
301239281Sgonzo	/* Calculate how many valid banks we have and then multiply that by 32 to
302239281Sgonzo	 * give use the total number of pins.
303239281Sgonzo	 */
304239281Sgonzo	for (i = 0; i < MAX_GPIO_BANKS; i++) {
305239281Sgonzo		if (sc->sc_mem_res[i] != NULL)
306239281Sgonzo			banks++;
307239281Sgonzo	}
308239281Sgonzo
309247252Sgonzo	*maxpin = (banks * PINS_PER_BANK) - 1;
310239281Sgonzo
311239281Sgonzo	TI_GPIO_UNLOCK(sc);
312239281Sgonzo
313239281Sgonzo	return (0);
314239281Sgonzo}
315239281Sgonzo
316239281Sgonzo/**
317239281Sgonzo *	ti_gpio_pin_getcaps - Gets the capabilties of a given pin
318239281Sgonzo *	@dev: gpio device handle
319239281Sgonzo *	@pin: the number of the pin
320239281Sgonzo *	@caps: pointer to a value that upon return will contain the capabilities
321239281Sgonzo *
322239281Sgonzo *	Currently all pins have the same capability, notably:
323239281Sgonzo *	  - GPIO_PIN_INPUT
324239281Sgonzo *	  - GPIO_PIN_OUTPUT
325239281Sgonzo *	  - GPIO_PIN_PULLUP
326239281Sgonzo *	  - GPIO_PIN_PULLDOWN
327239281Sgonzo *
328239281Sgonzo *	LOCKING:
329239281Sgonzo *	Internally locks the context
330239281Sgonzo *
331239281Sgonzo *	RETURNS:
332239281Sgonzo *	Returns 0 on success otherwise an error code
333239281Sgonzo */
334239281Sgonzostatic int
335239281Sgonzoti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
336239281Sgonzo{
337239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
338239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
339239281Sgonzo
340239281Sgonzo	TI_GPIO_LOCK(sc);
341239281Sgonzo
342239281Sgonzo	/* Sanity check the pin number is valid */
343247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
344239281Sgonzo		TI_GPIO_UNLOCK(sc);
345239281Sgonzo		return (EINVAL);
346239281Sgonzo	}
347239281Sgonzo
348239281Sgonzo	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP |
349239281Sgonzo	    GPIO_PIN_PULLDOWN);
350239281Sgonzo
351239281Sgonzo	TI_GPIO_UNLOCK(sc);
352239281Sgonzo
353239281Sgonzo	return (0);
354239281Sgonzo}
355239281Sgonzo
356239281Sgonzo/**
357239281Sgonzo *	ti_gpio_pin_getflags - Gets the current flags of a given pin
358239281Sgonzo *	@dev: gpio device handle
359239281Sgonzo *	@pin: the number of the pin
360239281Sgonzo *	@flags: upon return will contain the current flags of the pin
361239281Sgonzo *
362239281Sgonzo *	Reads the current flags of a given pin, here we actually read the H/W
363239281Sgonzo *	registers to determine the flags, rather than storing the value in the
364239281Sgonzo *	setflags call.
365239281Sgonzo *
366239281Sgonzo *	LOCKING:
367239281Sgonzo *	Internally locks the context
368239281Sgonzo *
369239281Sgonzo *	RETURNS:
370239281Sgonzo *	Returns 0 on success otherwise an error code
371239281Sgonzo */
372239281Sgonzostatic int
373239281Sgonzoti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
374239281Sgonzo{
375239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
376239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
377239281Sgonzo
378239281Sgonzo	TI_GPIO_LOCK(sc);
379239281Sgonzo
380239281Sgonzo	/* Sanity check the pin number is valid */
381247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
382239281Sgonzo		TI_GPIO_UNLOCK(sc);
383239281Sgonzo		return (EINVAL);
384239281Sgonzo	}
385239281Sgonzo
386239281Sgonzo	/* Get the current pin state */
387239281Sgonzo	ti_scm_padconf_get_gpioflags(pin, flags);
388239281Sgonzo
389239281Sgonzo	TI_GPIO_UNLOCK(sc);
390239281Sgonzo
391239281Sgonzo	return (0);
392239281Sgonzo}
393239281Sgonzo
394239281Sgonzo/**
395239281Sgonzo *	ti_gpio_pin_getname - Gets the name of a given pin
396239281Sgonzo *	@dev: gpio device handle
397239281Sgonzo *	@pin: the number of the pin
398239281Sgonzo *	@name: buffer to put the name in
399239281Sgonzo *
400239281Sgonzo *	The driver simply calls the pins gpio_n, where 'n' is obviously the number
401239281Sgonzo *	of the pin.
402239281Sgonzo *
403239281Sgonzo *	LOCKING:
404239281Sgonzo *	Internally locks the context
405239281Sgonzo *
406239281Sgonzo *	RETURNS:
407239281Sgonzo *	Returns 0 on success otherwise an error code
408239281Sgonzo */
409239281Sgonzostatic int
410239281Sgonzoti_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
411239281Sgonzo{
412239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
413239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
414239281Sgonzo
415239281Sgonzo	TI_GPIO_LOCK(sc);
416239281Sgonzo
417239281Sgonzo	/* Sanity check the pin number is valid */
418247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
419239281Sgonzo		TI_GPIO_UNLOCK(sc);
420239281Sgonzo		return (EINVAL);
421239281Sgonzo	}
422239281Sgonzo
423239281Sgonzo	/* Set a very simple name */
424239281Sgonzo	snprintf(name, GPIOMAXNAME, "gpio_%u", pin);
425239281Sgonzo	name[GPIOMAXNAME - 1] = '\0';
426239281Sgonzo
427239281Sgonzo	TI_GPIO_UNLOCK(sc);
428239281Sgonzo
429239281Sgonzo	return (0);
430239281Sgonzo}
431239281Sgonzo
432239281Sgonzo/**
433239281Sgonzo *	ti_gpio_pin_setflags - Sets the flags for a given pin
434239281Sgonzo *	@dev: gpio device handle
435239281Sgonzo *	@pin: the number of the pin
436239281Sgonzo *	@flags: the flags to set
437239281Sgonzo *
438239281Sgonzo *	The flags of the pin correspond to things like input/output mode, pull-ups,
439239281Sgonzo *	pull-downs, etc.  This driver doesn't support all flags, only the following:
440239281Sgonzo *	  - GPIO_PIN_INPUT
441239281Sgonzo *	  - GPIO_PIN_OUTPUT
442239281Sgonzo *	  - GPIO_PIN_PULLUP
443239281Sgonzo *	  - GPIO_PIN_PULLDOWN
444239281Sgonzo *
445239281Sgonzo *	LOCKING:
446239281Sgonzo *	Internally locks the context
447239281Sgonzo *
448239281Sgonzo *	RETURNS:
449239281Sgonzo *	Returns 0 on success otherwise an error code
450239281Sgonzo */
451239281Sgonzostatic int
452239281Sgonzoti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
453239281Sgonzo{
454239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
455239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
456239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
457239281Sgonzo	uint32_t reg_val;
458239281Sgonzo
459239281Sgonzo	TI_GPIO_LOCK(sc);
460239281Sgonzo
461239281Sgonzo	/* Sanity check the pin number is valid */
462247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
463239281Sgonzo		TI_GPIO_UNLOCK(sc);
464239281Sgonzo		return (EINVAL);
465239281Sgonzo	}
466239281Sgonzo
467239281Sgonzo	/* Set the GPIO mode and state */
468239281Sgonzo	if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) {
469239281Sgonzo		TI_GPIO_UNLOCK(sc);
470239281Sgonzo		return (EINVAL);
471239281Sgonzo	}
472239281Sgonzo
473239281Sgonzo	/* If configuring as an output set the "output enable" bit */
474239281Sgonzo	reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
475239281Sgonzo	if (flags & GPIO_PIN_INPUT)
476239281Sgonzo		reg_val |= mask;
477239281Sgonzo	else
478239281Sgonzo		reg_val &= ~mask;
479239281Sgonzo	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val);
480239281Sgonzo
481239281Sgonzo	TI_GPIO_UNLOCK(sc);
482239281Sgonzo
483239281Sgonzo	return (0);
484239281Sgonzo}
485239281Sgonzo
486239281Sgonzo/**
487239281Sgonzo *	ti_gpio_pin_set - Sets the current level on a GPIO pin
488239281Sgonzo *	@dev: gpio device handle
489239281Sgonzo *	@pin: the number of the pin
490239281Sgonzo *	@value: non-zero value will drive the pin high, otherwise the pin is
491239281Sgonzo *	        driven low.
492239281Sgonzo *
493239281Sgonzo *
494239281Sgonzo *	LOCKING:
495239281Sgonzo *	Internally locks the context
496239281Sgonzo *
497239281Sgonzo *	RETURNS:
498239281Sgonzo *	Returns 0 on success otherwise a error code
499239281Sgonzo */
500239281Sgonzostatic int
501239281Sgonzoti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
502239281Sgonzo{
503239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
504239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
505239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
506239281Sgonzo
507239281Sgonzo	TI_GPIO_LOCK(sc);
508239281Sgonzo
509239281Sgonzo	/* Sanity check the pin number is valid */
510247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
511239281Sgonzo		TI_GPIO_UNLOCK(sc);
512239281Sgonzo		return (EINVAL);
513239281Sgonzo	}
514239281Sgonzo
515239281Sgonzo	ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT
516239281Sgonzo	    : TI_GPIO_SETDATAOUT, mask);
517239281Sgonzo
518239281Sgonzo	TI_GPIO_UNLOCK(sc);
519239281Sgonzo
520239281Sgonzo	return (0);
521239281Sgonzo}
522239281Sgonzo
523239281Sgonzo/**
524239281Sgonzo *	ti_gpio_pin_get - Gets the current level on a GPIO pin
525239281Sgonzo *	@dev: gpio device handle
526239281Sgonzo *	@pin: the number of the pin
527239281Sgonzo *	@value: pointer to a value that upond return will contain the pin value
528239281Sgonzo *
529239281Sgonzo *	The pin must be configured as an input pin beforehand, otherwise this
530239281Sgonzo *	function will fail.
531239281Sgonzo *
532239281Sgonzo *	LOCKING:
533239281Sgonzo *	Internally locks the context
534239281Sgonzo *
535239281Sgonzo *	RETURNS:
536239281Sgonzo *	Returns 0 on success otherwise a error code
537239281Sgonzo */
538239281Sgonzostatic int
539239281Sgonzoti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
540239281Sgonzo{
541239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
542239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
543239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
544239281Sgonzo	uint32_t val = 0;
545239281Sgonzo
546239281Sgonzo	TI_GPIO_LOCK(sc);
547239281Sgonzo
548239281Sgonzo	/* Sanity check the pin number is valid */
549247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
550239281Sgonzo		TI_GPIO_UNLOCK(sc);
551239281Sgonzo		return (EINVAL);
552239281Sgonzo	}
553239281Sgonzo
554239281Sgonzo	/* Sanity check the pin is not configured as an output */
555239281Sgonzo	val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
556239281Sgonzo
557239281Sgonzo	/* Read the value on the pin */
558247252Sgonzo	if (val & mask)
559266105Sloos		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0;
560266105Sloos	else
561247252Sgonzo		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0;
562239281Sgonzo
563239281Sgonzo	TI_GPIO_UNLOCK(sc);
564239281Sgonzo
565239281Sgonzo	return (0);
566239281Sgonzo}
567239281Sgonzo
568239281Sgonzo/**
569239281Sgonzo *	ti_gpio_pin_toggle - Toggles a given GPIO pin
570239281Sgonzo *	@dev: gpio device handle
571239281Sgonzo *	@pin: the number of the pin
572239281Sgonzo *
573239281Sgonzo *
574239281Sgonzo *	LOCKING:
575239281Sgonzo *	Internally locks the context
576239281Sgonzo *
577239281Sgonzo *	RETURNS:
578239281Sgonzo *	Returns 0 on success otherwise a error code
579239281Sgonzo */
580239281Sgonzostatic int
581239281Sgonzoti_gpio_pin_toggle(device_t dev, uint32_t pin)
582239281Sgonzo{
583239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
584239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
585239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
586239281Sgonzo	uint32_t val;
587239281Sgonzo
588239281Sgonzo	TI_GPIO_LOCK(sc);
589239281Sgonzo
590239281Sgonzo	/* Sanity check the pin number is valid */
591247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
592239281Sgonzo		TI_GPIO_UNLOCK(sc);
593239281Sgonzo		return (EINVAL);
594239281Sgonzo	}
595239281Sgonzo
596239281Sgonzo	/* Toggle the pin */
597239281Sgonzo	val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT);
598239281Sgonzo	if (val & mask)
599239281Sgonzo		ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask);
600239281Sgonzo	else
601239281Sgonzo		ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask);
602239281Sgonzo
603239281Sgonzo	TI_GPIO_UNLOCK(sc);
604239281Sgonzo
605239281Sgonzo	return (0);
606239281Sgonzo}
607239281Sgonzo
608239281Sgonzo/**
609239281Sgonzo *	ti_gpio_intr - ISR for all GPIO modules
610239281Sgonzo *	@arg: the soft context pointer
611239281Sgonzo *
612239281Sgonzo *	Unsused
613239281Sgonzo *
614239281Sgonzo *	LOCKING:
615239281Sgonzo *	Internally locks the context
616239281Sgonzo *
617239281Sgonzo */
618239281Sgonzostatic void
619239281Sgonzoti_gpio_intr(void *arg)
620239281Sgonzo{
621239281Sgonzo	struct ti_gpio_softc *sc = arg;
622239281Sgonzo
623239281Sgonzo	TI_GPIO_LOCK(sc);
624239281Sgonzo	/* TODO: something useful */
625239281Sgonzo	TI_GPIO_UNLOCK(sc);
626239281Sgonzo}
627239281Sgonzo
628239281Sgonzo/**
629239281Sgonzo *	ti_gpio_probe - probe function for the driver
630239281Sgonzo *	@dev: gpio device handle
631239281Sgonzo *
632239281Sgonzo *	Simply sets the name of the driver
633239281Sgonzo *
634239281Sgonzo *	LOCKING:
635239281Sgonzo *	None
636239281Sgonzo *
637239281Sgonzo *	RETURNS:
638239281Sgonzo *	Always returns 0
639239281Sgonzo */
640239281Sgonzostatic int
641239281Sgonzoti_gpio_probe(device_t dev)
642239281Sgonzo{
643266152Sian
644266152Sian	if (!ofw_bus_status_okay(dev))
645266152Sian		return (ENXIO);
646266152Sian
647239281Sgonzo	if (!ofw_bus_is_compatible(dev, "ti,gpio"))
648239281Sgonzo		return (ENXIO);
649239281Sgonzo
650239281Sgonzo	device_set_desc(dev, "TI General Purpose I/O (GPIO)");
651266148Sloos
652239281Sgonzo	return (0);
653239281Sgonzo}
654239281Sgonzo
655266148Sloosstatic int
656266148Sloosti_gpio_attach_intr(device_t dev)
657266148Sloos{
658266148Sloos	int i;
659266148Sloos	struct ti_gpio_softc *sc;
660266148Sloos
661266148Sloos	sc = device_get_softc(dev);
662266148Sloos	for (i = 0; i < MAX_GPIO_INTRS; i++) {
663266148Sloos		if (sc->sc_irq_res[i] == NULL)
664266148Sloos			break;
665266148Sloos
666266148Sloos		/*
667266148Sloos		 * Register our interrupt handler for each of the IRQ resources.
668266148Sloos		 */
669266148Sloos		if (bus_setup_intr(dev, sc->sc_irq_res[i],
670266148Sloos		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc,
671266148Sloos		    &sc->sc_irq_hdl[i]) != 0) {
672266148Sloos			device_printf(dev,
673266148Sloos			    "WARNING: unable to register interrupt handler\n");
674266148Sloos			return (-1);
675266148Sloos		}
676266148Sloos	}
677266148Sloos
678266148Sloos	return (0);
679266148Sloos}
680266148Sloos
681266148Sloosstatic int
682266148Sloosti_gpio_detach_intr(device_t dev)
683266148Sloos{
684266148Sloos	int i;
685266148Sloos	struct ti_gpio_softc *sc;
686266148Sloos
687266148Sloos	/* Teardown our interrupt handlers. */
688266148Sloos	sc = device_get_softc(dev);
689266148Sloos	for (i = 0; i < MAX_GPIO_INTRS; i++) {
690266148Sloos		if (sc->sc_irq_res[i] == NULL)
691266148Sloos			break;
692266148Sloos
693266148Sloos		if (sc->sc_irq_hdl[i]) {
694266148Sloos			bus_teardown_intr(dev, sc->sc_irq_res[i],
695266148Sloos			    sc->sc_irq_hdl[i]);
696266148Sloos		}
697266148Sloos	}
698266148Sloos
699266148Sloos	return (0);
700266148Sloos}
701266148Sloos
702266148Sloosstatic int
703266148Sloosti_gpio_bank_init(device_t dev, int bank)
704266148Sloos{
705266148Sloos	int pin;
706266148Sloos	struct ti_gpio_softc *sc;
707266148Sloos	uint32_t flags, reg_oe;
708266148Sloos
709266148Sloos	sc = device_get_softc(dev);
710266148Sloos
711266148Sloos	/* Enable the interface and functional clocks for the module. */
712266148Sloos	ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank);
713266148Sloos
714266148Sloos	/*
715266148Sloos	 * Read the revision number of the module.  TI don't publish the
716266148Sloos	 * actual revision numbers, so instead the values have been
717266148Sloos	 * determined by experimentation.
718266148Sloos	 */
719266148Sloos	sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION);
720266148Sloos
721266148Sloos	/* Check the revision. */
722266148Sloos	if (sc->sc_revision[bank] != TI_GPIO_REV) {
723266148Sloos		device_printf(dev, "Warning: could not determine the revision "
724266148Sloos		    "of %u GPIO module (revision:0x%08x)\n",
725266148Sloos		    bank, sc->sc_revision[bank]);
726266148Sloos		return (EINVAL);
727266148Sloos	}
728266148Sloos
729266148Sloos	/* Disable interrupts for all pins. */
730266148Sloos	ti_gpio_intr_clr(sc, bank, 0xffffffff);
731266148Sloos
732266148Sloos	/* Init OE register based on pads configuration. */
733266148Sloos	reg_oe = 0xffffffff;
734266148Sloos	for (pin = 0; pin < PINS_PER_BANK; pin++) {
735266148Sloos		ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin,
736266148Sloos		    &flags);
737266148Sloos		if (flags & GPIO_PIN_OUTPUT)
738266148Sloos			reg_oe &= ~(1UL << pin);
739266148Sloos	}
740266148Sloos	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe);
741266148Sloos
742266148Sloos	return (0);
743266148Sloos}
744266148Sloos
745239281Sgonzo/**
746239281Sgonzo *	ti_gpio_attach - attach function for the driver
747239281Sgonzo *	@dev: gpio device handle
748239281Sgonzo *
749239281Sgonzo *	Allocates and sets up the driver context for all GPIO banks.  This function
750239281Sgonzo *	expects the memory ranges and IRQs to already be allocated to the driver.
751239281Sgonzo *
752239281Sgonzo *	LOCKING:
753239281Sgonzo *	None
754239281Sgonzo *
755239281Sgonzo *	RETURNS:
756239281Sgonzo *	Always returns 0
757239281Sgonzo */
758239281Sgonzostatic int
759239281Sgonzoti_gpio_attach(device_t dev)
760239281Sgonzo{
761266148Sloos	struct ti_gpio_softc *sc;
762239281Sgonzo	unsigned int i;
763266148Sloos	int err;
764239281Sgonzo
765266148Sloos 	sc = device_get_softc(dev);
766239281Sgonzo	sc->sc_dev = dev;
767239281Sgonzo
768239281Sgonzo	TI_GPIO_LOCK_INIT(sc);
769239281Sgonzo
770239281Sgonzo	/* There are up to 6 different GPIO register sets located in different
771239281Sgonzo	 * memory areas on the chip.  The memory range should have been set for
772239281Sgonzo	 * the driver when it was added as a child.
773239281Sgonzo	 */
774266148Sloos	if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) {
775239281Sgonzo		device_printf(dev, "Error: could not allocate mem resources\n");
776239281Sgonzo		return (ENXIO);
777239281Sgonzo	}
778239281Sgonzo
779239281Sgonzo	/* Request the IRQ resources */
780266148Sloos	if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) {
781266148Sloos		bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
782239281Sgonzo		device_printf(dev, "Error: could not allocate irq resources\n");
783239281Sgonzo		return (ENXIO);
784239281Sgonzo	}
785239281Sgonzo
786239281Sgonzo	/* Setup the IRQ resources */
787266148Sloos	if (ti_gpio_attach_intr(dev) != 0) {
788266148Sloos		ti_gpio_detach_intr(dev);
789266148Sloos		bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
790266148Sloos		bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
791266148Sloos		return (ENXIO);
792239281Sgonzo	}
793239281Sgonzo
794239281Sgonzo	/* We need to go through each block and ensure the clocks are running and
795239281Sgonzo	 * the module is enabled.  It might be better to do this only when the
796239281Sgonzo	 * pins are configured which would result in less power used if the GPIO
797239281Sgonzo	 * pins weren't used ...
798239281Sgonzo	 */
799266148Sloos	for (i = 0; i < MAX_GPIO_BANKS; i++) {
800239281Sgonzo		if (sc->sc_mem_res[i] != NULL) {
801266148Sloos			/* Initialize the GPIO module. */
802266148Sloos			err = ti_gpio_bank_init(dev, i);
803266148Sloos			if (err != 0) {
804266148Sloos				ti_gpio_detach_intr(dev);
805266148Sloos				bus_release_resources(dev, ti_gpio_irq_spec,
806266148Sloos				    sc->sc_irq_res);
807266148Sloos				bus_release_resources(dev, ti_gpio_mem_spec,
808266148Sloos				    sc->sc_mem_res);
809266148Sloos				return (err);
810239281Sgonzo			}
811239281Sgonzo		}
812239281Sgonzo	}
813239281Sgonzo
814239281Sgonzo	/* Finish of the probe call */
815278782Sloos	device_add_child(dev, "gpioc", -1);
816278782Sloos	device_add_child(dev, "gpiobus", -1);
817247252Sgonzo
818239281Sgonzo	return (bus_generic_attach(dev));
819239281Sgonzo}
820239281Sgonzo
821239281Sgonzo/**
822239281Sgonzo *	ti_gpio_detach - detach function for the driver
823239281Sgonzo *	@dev: scm device handle
824239281Sgonzo *
825239281Sgonzo *	Allocates and sets up the driver context, this simply entails creating a
826239281Sgonzo *	bus mappings for the SCM register set.
827239281Sgonzo *
828239281Sgonzo *	LOCKING:
829239281Sgonzo *	None
830239281Sgonzo *
831239281Sgonzo *	RETURNS:
832239281Sgonzo *	Always returns 0
833239281Sgonzo */
834239281Sgonzostatic int
835239281Sgonzoti_gpio_detach(device_t dev)
836239281Sgonzo{
837239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
838239281Sgonzo	unsigned int i;
839239281Sgonzo
840239281Sgonzo	KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
841239281Sgonzo
842239281Sgonzo	/* Disable all interrupts */
843266148Sloos	for (i = 0; i < MAX_GPIO_BANKS; i++) {
844266148Sloos		if (sc->sc_mem_res[i] != NULL)
845266148Sloos			ti_gpio_intr_clr(sc, i, 0xffffffff);
846239281Sgonzo	}
847239281Sgonzo
848239281Sgonzo	bus_generic_detach(dev);
849239281Sgonzo
850266148Sloos	/* Release the memory and IRQ resources. */
851266148Sloos	ti_gpio_detach_intr(dev);
852266148Sloos	bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
853266148Sloos	bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
854239281Sgonzo
855239281Sgonzo	TI_GPIO_LOCK_DESTROY(sc);
856239281Sgonzo
857266148Sloos	return (0);
858239281Sgonzo}
859239281Sgonzo
860266105Sloosstatic phandle_t
861266105Sloosti_gpio_get_node(device_t bus, device_t dev)
862266105Sloos{
863266105Sloos
864266105Sloos	/* We only have one child, the GPIO bus, which needs our own node. */
865266105Sloos	return (ofw_bus_get_node(bus));
866266105Sloos}
867266105Sloos
868239281Sgonzostatic device_method_t ti_gpio_methods[] = {
869239281Sgonzo	DEVMETHOD(device_probe, ti_gpio_probe),
870239281Sgonzo	DEVMETHOD(device_attach, ti_gpio_attach),
871239281Sgonzo	DEVMETHOD(device_detach, ti_gpio_detach),
872239281Sgonzo
873239281Sgonzo	/* GPIO protocol */
874239281Sgonzo	DEVMETHOD(gpio_pin_max, ti_gpio_pin_max),
875239281Sgonzo	DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname),
876239281Sgonzo	DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags),
877239281Sgonzo	DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps),
878239281Sgonzo	DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags),
879239281Sgonzo	DEVMETHOD(gpio_pin_get, ti_gpio_pin_get),
880239281Sgonzo	DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
881239281Sgonzo	DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
882266105Sloos
883266105Sloos	/* ofw_bus interface */
884266105Sloos	DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
885266105Sloos
886239281Sgonzo	{0, 0},
887239281Sgonzo};
888239281Sgonzo
889239281Sgonzostatic driver_t ti_gpio_driver = {
890239281Sgonzo	"gpio",
891239281Sgonzo	ti_gpio_methods,
892239281Sgonzo	sizeof(struct ti_gpio_softc),
893239281Sgonzo};
894239281Sgonzostatic devclass_t ti_gpio_devclass;
895239281Sgonzo
896239281SgonzoDRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0);
897