ti_gpio.c revision 266148
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: stable/10/sys/arm/ti/ti_gpio.c 266148 2014-05-15 15:47:52Z loos $");
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	/* Sanity check the flags supplied are valid, i.e. not input and output */
460239281Sgonzo	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 0x0000)
461239281Sgonzo		return (EINVAL);
462239281Sgonzo	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
463239281Sgonzo	    (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
464239281Sgonzo		return (EINVAL);
465239281Sgonzo	if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) ==
466239281Sgonzo	    (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN))
467239281Sgonzo		return (EINVAL);
468239281Sgonzo
469239281Sgonzo	TI_GPIO_LOCK(sc);
470239281Sgonzo
471239281Sgonzo	/* Sanity check the pin number is valid */
472247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
473239281Sgonzo		TI_GPIO_UNLOCK(sc);
474239281Sgonzo		return (EINVAL);
475239281Sgonzo	}
476239281Sgonzo
477239281Sgonzo	/* Set the GPIO mode and state */
478239281Sgonzo	if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) {
479239281Sgonzo		TI_GPIO_UNLOCK(sc);
480239281Sgonzo		return (EINVAL);
481239281Sgonzo	}
482239281Sgonzo
483239281Sgonzo	/* If configuring as an output set the "output enable" bit */
484239281Sgonzo	reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
485239281Sgonzo	if (flags & GPIO_PIN_INPUT)
486239281Sgonzo		reg_val |= mask;
487239281Sgonzo	else
488239281Sgonzo		reg_val &= ~mask;
489239281Sgonzo	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val);
490239281Sgonzo
491239281Sgonzo	TI_GPIO_UNLOCK(sc);
492239281Sgonzo
493239281Sgonzo	return (0);
494239281Sgonzo}
495239281Sgonzo
496239281Sgonzo/**
497239281Sgonzo *	ti_gpio_pin_set - Sets the current level on a GPIO pin
498239281Sgonzo *	@dev: gpio device handle
499239281Sgonzo *	@pin: the number of the pin
500239281Sgonzo *	@value: non-zero value will drive the pin high, otherwise the pin is
501239281Sgonzo *	        driven low.
502239281Sgonzo *
503239281Sgonzo *
504239281Sgonzo *	LOCKING:
505239281Sgonzo *	Internally locks the context
506239281Sgonzo *
507239281Sgonzo *	RETURNS:
508239281Sgonzo *	Returns 0 on success otherwise a error code
509239281Sgonzo */
510239281Sgonzostatic int
511239281Sgonzoti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
512239281Sgonzo{
513239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
514239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
515239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
516239281Sgonzo
517239281Sgonzo	TI_GPIO_LOCK(sc);
518239281Sgonzo
519239281Sgonzo	/* Sanity check the pin number is valid */
520247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
521239281Sgonzo		TI_GPIO_UNLOCK(sc);
522239281Sgonzo		return (EINVAL);
523239281Sgonzo	}
524239281Sgonzo
525239281Sgonzo	ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT
526239281Sgonzo	    : TI_GPIO_SETDATAOUT, mask);
527239281Sgonzo
528239281Sgonzo	TI_GPIO_UNLOCK(sc);
529239281Sgonzo
530239281Sgonzo	return (0);
531239281Sgonzo}
532239281Sgonzo
533239281Sgonzo/**
534239281Sgonzo *	ti_gpio_pin_get - Gets the current level on a GPIO pin
535239281Sgonzo *	@dev: gpio device handle
536239281Sgonzo *	@pin: the number of the pin
537239281Sgonzo *	@value: pointer to a value that upond return will contain the pin value
538239281Sgonzo *
539239281Sgonzo *	The pin must be configured as an input pin beforehand, otherwise this
540239281Sgonzo *	function will fail.
541239281Sgonzo *
542239281Sgonzo *	LOCKING:
543239281Sgonzo *	Internally locks the context
544239281Sgonzo *
545239281Sgonzo *	RETURNS:
546239281Sgonzo *	Returns 0 on success otherwise a error code
547239281Sgonzo */
548239281Sgonzostatic int
549239281Sgonzoti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
550239281Sgonzo{
551239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
552239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
553239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
554239281Sgonzo	uint32_t val = 0;
555239281Sgonzo
556239281Sgonzo	TI_GPIO_LOCK(sc);
557239281Sgonzo
558239281Sgonzo	/* Sanity check the pin number is valid */
559247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
560239281Sgonzo		TI_GPIO_UNLOCK(sc);
561239281Sgonzo		return (EINVAL);
562239281Sgonzo	}
563239281Sgonzo
564239281Sgonzo	/* Sanity check the pin is not configured as an output */
565239281Sgonzo	val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
566239281Sgonzo
567239281Sgonzo	/* Read the value on the pin */
568247252Sgonzo	if (val & mask)
569266105Sloos		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0;
570266105Sloos	else
571247252Sgonzo		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0;
572239281Sgonzo
573239281Sgonzo	TI_GPIO_UNLOCK(sc);
574239281Sgonzo
575239281Sgonzo	return (0);
576239281Sgonzo}
577239281Sgonzo
578239281Sgonzo/**
579239281Sgonzo *	ti_gpio_pin_toggle - Toggles a given GPIO pin
580239281Sgonzo *	@dev: gpio device handle
581239281Sgonzo *	@pin: the number of the pin
582239281Sgonzo *
583239281Sgonzo *
584239281Sgonzo *	LOCKING:
585239281Sgonzo *	Internally locks the context
586239281Sgonzo *
587239281Sgonzo *	RETURNS:
588239281Sgonzo *	Returns 0 on success otherwise a error code
589239281Sgonzo */
590239281Sgonzostatic int
591239281Sgonzoti_gpio_pin_toggle(device_t dev, uint32_t pin)
592239281Sgonzo{
593239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
594239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
595239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
596239281Sgonzo	uint32_t val;
597239281Sgonzo
598239281Sgonzo	TI_GPIO_LOCK(sc);
599239281Sgonzo
600239281Sgonzo	/* Sanity check the pin number is valid */
601247259Sgonzo	if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
602239281Sgonzo		TI_GPIO_UNLOCK(sc);
603239281Sgonzo		return (EINVAL);
604239281Sgonzo	}
605239281Sgonzo
606239281Sgonzo	/* Toggle the pin */
607239281Sgonzo	val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT);
608239281Sgonzo	if (val & mask)
609239281Sgonzo		ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask);
610239281Sgonzo	else
611239281Sgonzo		ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask);
612239281Sgonzo
613239281Sgonzo	TI_GPIO_UNLOCK(sc);
614239281Sgonzo
615239281Sgonzo	return (0);
616239281Sgonzo}
617239281Sgonzo
618239281Sgonzo/**
619239281Sgonzo *	ti_gpio_intr - ISR for all GPIO modules
620239281Sgonzo *	@arg: the soft context pointer
621239281Sgonzo *
622239281Sgonzo *	Unsused
623239281Sgonzo *
624239281Sgonzo *	LOCKING:
625239281Sgonzo *	Internally locks the context
626239281Sgonzo *
627239281Sgonzo */
628239281Sgonzostatic void
629239281Sgonzoti_gpio_intr(void *arg)
630239281Sgonzo{
631239281Sgonzo	struct ti_gpio_softc *sc = arg;
632239281Sgonzo
633239281Sgonzo	TI_GPIO_LOCK(sc);
634239281Sgonzo	/* TODO: something useful */
635239281Sgonzo	TI_GPIO_UNLOCK(sc);
636239281Sgonzo}
637239281Sgonzo
638239281Sgonzo/**
639239281Sgonzo *	ti_gpio_probe - probe function for the driver
640239281Sgonzo *	@dev: gpio device handle
641239281Sgonzo *
642239281Sgonzo *	Simply sets the name of the driver
643239281Sgonzo *
644239281Sgonzo *	LOCKING:
645239281Sgonzo *	None
646239281Sgonzo *
647239281Sgonzo *	RETURNS:
648239281Sgonzo *	Always returns 0
649239281Sgonzo */
650239281Sgonzostatic int
651239281Sgonzoti_gpio_probe(device_t dev)
652239281Sgonzo{
653239281Sgonzo	if (!ofw_bus_is_compatible(dev, "ti,gpio"))
654239281Sgonzo		return (ENXIO);
655239281Sgonzo
656239281Sgonzo	device_set_desc(dev, "TI General Purpose I/O (GPIO)");
657266148Sloos
658239281Sgonzo	return (0);
659239281Sgonzo}
660239281Sgonzo
661266148Sloosstatic int
662266148Sloosti_gpio_attach_intr(device_t dev)
663266148Sloos{
664266148Sloos	int i;
665266148Sloos	struct ti_gpio_softc *sc;
666266148Sloos
667266148Sloos	sc = device_get_softc(dev);
668266148Sloos	for (i = 0; i < MAX_GPIO_INTRS; i++) {
669266148Sloos		if (sc->sc_irq_res[i] == NULL)
670266148Sloos			break;
671266148Sloos
672266148Sloos		/*
673266148Sloos		 * Register our interrupt handler for each of the IRQ resources.
674266148Sloos		 */
675266148Sloos		if (bus_setup_intr(dev, sc->sc_irq_res[i],
676266148Sloos		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc,
677266148Sloos		    &sc->sc_irq_hdl[i]) != 0) {
678266148Sloos			device_printf(dev,
679266148Sloos			    "WARNING: unable to register interrupt handler\n");
680266148Sloos			return (-1);
681266148Sloos		}
682266148Sloos	}
683266148Sloos
684266148Sloos	return (0);
685266148Sloos}
686266148Sloos
687266148Sloosstatic int
688266148Sloosti_gpio_detach_intr(device_t dev)
689266148Sloos{
690266148Sloos	int i;
691266148Sloos	struct ti_gpio_softc *sc;
692266148Sloos
693266148Sloos	/* Teardown our interrupt handlers. */
694266148Sloos	sc = device_get_softc(dev);
695266148Sloos	for (i = 0; i < MAX_GPIO_INTRS; i++) {
696266148Sloos		if (sc->sc_irq_res[i] == NULL)
697266148Sloos			break;
698266148Sloos
699266148Sloos		if (sc->sc_irq_hdl[i]) {
700266148Sloos			bus_teardown_intr(dev, sc->sc_irq_res[i],
701266148Sloos			    sc->sc_irq_hdl[i]);
702266148Sloos		}
703266148Sloos	}
704266148Sloos
705266148Sloos	return (0);
706266148Sloos}
707266148Sloos
708266148Sloosstatic int
709266148Sloosti_gpio_bank_init(device_t dev, int bank)
710266148Sloos{
711266148Sloos	int pin;
712266148Sloos	struct ti_gpio_softc *sc;
713266148Sloos	uint32_t flags, reg_oe;
714266148Sloos
715266148Sloos	sc = device_get_softc(dev);
716266148Sloos
717266148Sloos	/* Enable the interface and functional clocks for the module. */
718266148Sloos	ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank);
719266148Sloos
720266148Sloos	/*
721266148Sloos	 * Read the revision number of the module.  TI don't publish the
722266148Sloos	 * actual revision numbers, so instead the values have been
723266148Sloos	 * determined by experimentation.
724266148Sloos	 */
725266148Sloos	sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION);
726266148Sloos
727266148Sloos	/* Check the revision. */
728266148Sloos	if (sc->sc_revision[bank] != TI_GPIO_REV) {
729266148Sloos		device_printf(dev, "Warning: could not determine the revision "
730266148Sloos		    "of %u GPIO module (revision:0x%08x)\n",
731266148Sloos		    bank, sc->sc_revision[bank]);
732266148Sloos		return (EINVAL);
733266148Sloos	}
734266148Sloos
735266148Sloos	/* Disable interrupts for all pins. */
736266148Sloos	ti_gpio_intr_clr(sc, bank, 0xffffffff);
737266148Sloos
738266148Sloos	/* Init OE register based on pads configuration. */
739266148Sloos	reg_oe = 0xffffffff;
740266148Sloos	for (pin = 0; pin < PINS_PER_BANK; pin++) {
741266148Sloos		ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin,
742266148Sloos		    &flags);
743266148Sloos		if (flags & GPIO_PIN_OUTPUT)
744266148Sloos			reg_oe &= ~(1UL << pin);
745266148Sloos	}
746266148Sloos	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe);
747266148Sloos
748266148Sloos	return (0);
749266148Sloos}
750266148Sloos
751239281Sgonzo/**
752239281Sgonzo *	ti_gpio_attach - attach function for the driver
753239281Sgonzo *	@dev: gpio device handle
754239281Sgonzo *
755239281Sgonzo *	Allocates and sets up the driver context for all GPIO banks.  This function
756239281Sgonzo *	expects the memory ranges and IRQs to already be allocated to the driver.
757239281Sgonzo *
758239281Sgonzo *	LOCKING:
759239281Sgonzo *	None
760239281Sgonzo *
761239281Sgonzo *	RETURNS:
762239281Sgonzo *	Always returns 0
763239281Sgonzo */
764239281Sgonzostatic int
765239281Sgonzoti_gpio_attach(device_t dev)
766239281Sgonzo{
767266148Sloos	struct ti_gpio_softc *sc;
768239281Sgonzo	unsigned int i;
769266148Sloos	int err;
770239281Sgonzo
771266148Sloos 	sc = device_get_softc(dev);
772239281Sgonzo	sc->sc_dev = dev;
773239281Sgonzo
774239281Sgonzo	TI_GPIO_LOCK_INIT(sc);
775239281Sgonzo
776239281Sgonzo	/* There are up to 6 different GPIO register sets located in different
777239281Sgonzo	 * memory areas on the chip.  The memory range should have been set for
778239281Sgonzo	 * the driver when it was added as a child.
779239281Sgonzo	 */
780266148Sloos	if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) {
781239281Sgonzo		device_printf(dev, "Error: could not allocate mem resources\n");
782239281Sgonzo		return (ENXIO);
783239281Sgonzo	}
784239281Sgonzo
785239281Sgonzo	/* Request the IRQ resources */
786266148Sloos	if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) {
787266148Sloos		bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
788239281Sgonzo		device_printf(dev, "Error: could not allocate irq resources\n");
789239281Sgonzo		return (ENXIO);
790239281Sgonzo	}
791239281Sgonzo
792239281Sgonzo	/* Setup the IRQ resources */
793266148Sloos	if (ti_gpio_attach_intr(dev) != 0) {
794266148Sloos		ti_gpio_detach_intr(dev);
795266148Sloos		bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
796266148Sloos		bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
797266148Sloos		return (ENXIO);
798239281Sgonzo	}
799239281Sgonzo
800239281Sgonzo	/* We need to go through each block and ensure the clocks are running and
801239281Sgonzo	 * the module is enabled.  It might be better to do this only when the
802239281Sgonzo	 * pins are configured which would result in less power used if the GPIO
803239281Sgonzo	 * pins weren't used ...
804239281Sgonzo	 */
805266148Sloos	for (i = 0; i < MAX_GPIO_BANKS; i++) {
806239281Sgonzo		if (sc->sc_mem_res[i] != NULL) {
807266148Sloos			/* Initialize the GPIO module. */
808266148Sloos			err = ti_gpio_bank_init(dev, i);
809266148Sloos			if (err != 0) {
810266148Sloos				ti_gpio_detach_intr(dev);
811266148Sloos				bus_release_resources(dev, ti_gpio_irq_spec,
812266148Sloos				    sc->sc_irq_res);
813266148Sloos				bus_release_resources(dev, ti_gpio_mem_spec,
814266148Sloos				    sc->sc_mem_res);
815266148Sloos				return (err);
816239281Sgonzo			}
817239281Sgonzo		}
818239281Sgonzo	}
819239281Sgonzo
820239281Sgonzo	/* Finish of the probe call */
821239281Sgonzo	device_add_child(dev, "gpioc", device_get_unit(dev));
822239281Sgonzo	device_add_child(dev, "gpiobus", device_get_unit(dev));
823247252Sgonzo
824239281Sgonzo	return (bus_generic_attach(dev));
825239281Sgonzo}
826239281Sgonzo
827239281Sgonzo/**
828239281Sgonzo *	ti_gpio_detach - detach function for the driver
829239281Sgonzo *	@dev: scm device handle
830239281Sgonzo *
831239281Sgonzo *	Allocates and sets up the driver context, this simply entails creating a
832239281Sgonzo *	bus mappings for the SCM register set.
833239281Sgonzo *
834239281Sgonzo *	LOCKING:
835239281Sgonzo *	None
836239281Sgonzo *
837239281Sgonzo *	RETURNS:
838239281Sgonzo *	Always returns 0
839239281Sgonzo */
840239281Sgonzostatic int
841239281Sgonzoti_gpio_detach(device_t dev)
842239281Sgonzo{
843239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
844239281Sgonzo	unsigned int i;
845239281Sgonzo
846239281Sgonzo	KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
847239281Sgonzo
848239281Sgonzo	/* Disable all interrupts */
849266148Sloos	for (i = 0; i < MAX_GPIO_BANKS; i++) {
850266148Sloos		if (sc->sc_mem_res[i] != NULL)
851266148Sloos			ti_gpio_intr_clr(sc, i, 0xffffffff);
852239281Sgonzo	}
853239281Sgonzo
854239281Sgonzo	bus_generic_detach(dev);
855239281Sgonzo
856266148Sloos	/* Release the memory and IRQ resources. */
857266148Sloos	ti_gpio_detach_intr(dev);
858266148Sloos	bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
859266148Sloos	bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
860239281Sgonzo
861239281Sgonzo	TI_GPIO_LOCK_DESTROY(sc);
862239281Sgonzo
863266148Sloos	return (0);
864239281Sgonzo}
865239281Sgonzo
866266105Sloosstatic phandle_t
867266105Sloosti_gpio_get_node(device_t bus, device_t dev)
868266105Sloos{
869266105Sloos
870266105Sloos	/* We only have one child, the GPIO bus, which needs our own node. */
871266105Sloos	return (ofw_bus_get_node(bus));
872266105Sloos}
873266105Sloos
874239281Sgonzostatic device_method_t ti_gpio_methods[] = {
875239281Sgonzo	DEVMETHOD(device_probe, ti_gpio_probe),
876239281Sgonzo	DEVMETHOD(device_attach, ti_gpio_attach),
877239281Sgonzo	DEVMETHOD(device_detach, ti_gpio_detach),
878239281Sgonzo
879239281Sgonzo	/* GPIO protocol */
880239281Sgonzo	DEVMETHOD(gpio_pin_max, ti_gpio_pin_max),
881239281Sgonzo	DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname),
882239281Sgonzo	DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags),
883239281Sgonzo	DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps),
884239281Sgonzo	DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags),
885239281Sgonzo	DEVMETHOD(gpio_pin_get, ti_gpio_pin_get),
886239281Sgonzo	DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
887239281Sgonzo	DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
888266105Sloos
889266105Sloos	/* ofw_bus interface */
890266105Sloos	DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
891266105Sloos
892239281Sgonzo	{0, 0},
893239281Sgonzo};
894239281Sgonzo
895239281Sgonzostatic driver_t ti_gpio_driver = {
896239281Sgonzo	"gpio",
897239281Sgonzo	ti_gpio_methods,
898239281Sgonzo	sizeof(struct ti_gpio_softc),
899239281Sgonzo};
900239281Sgonzostatic devclass_t ti_gpio_devclass;
901239281Sgonzo
902239281SgonzoDRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0);
903