ti_gpio.c revision 247252
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: head/sys/arm/ti/ti_gpio.c 247252 2013-02-25 08:04:47Z gonzo $");
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
69239281Sgonzo /* Register definitions */
70239281Sgonzo#define TI_GPIO_REVISION		0x0000
71239281Sgonzo#define TI_GPIO_SYSCONFIG		0x0010
72239281Sgonzo#if defined(SOC_OMAP3)
73239281Sgonzo#define TI_GPIO_REVISION		0x0000
74239281Sgonzo#define TI_GPIO_SYSCONFIG		0x0010
75239281Sgonzo#define TI_GPIO_SYSSTATUS		0x0014
76239281Sgonzo#define TI_GPIO_IRQSTATUS1		0x0018
77239281Sgonzo#define TI_GPIO_IRQENABLE1		0x001C
78239281Sgonzo#define TI_GPIO_WAKEUPENABLE		0x0020
79239281Sgonzo#define TI_GPIO_IRQSTATUS2		0x0028
80239281Sgonzo#define TI_GPIO_IRQENABLE2		0x002C
81239281Sgonzo#define TI_GPIO_CTRL			0x0030
82239281Sgonzo#define TI_GPIO_OE			0x0034
83239281Sgonzo#define TI_GPIO_DATAIN			0x0038
84239281Sgonzo#define TI_GPIO_DATAOUT			0x003C
85239281Sgonzo#define TI_GPIO_LEVELDETECT0		0x0040
86239281Sgonzo#define TI_GPIO_LEVELDETECT1		0x0044
87239281Sgonzo#define TI_GPIO_RISINGDETECT		0x0048
88239281Sgonzo#define TI_GPIO_FALLINGDETECT		0x004C
89239281Sgonzo#define TI_GPIO_DEBOUNCENABLE		0x0050
90239281Sgonzo#define TI_GPIO_DEBOUNCINGTIME		0x0054
91239281Sgonzo#define TI_GPIO_CLEARIRQENABLE1		0x0060
92239281Sgonzo#define TI_GPIO_SETIRQENABLE1		0x0064
93239281Sgonzo#define TI_GPIO_CLEARIRQENABLE2		0x0070
94239281Sgonzo#define TI_GPIO_SETIRQENABLE2		0x0074
95239281Sgonzo#define TI_GPIO_CLEARWKUENA		0x0080
96239281Sgonzo#define TI_GPIO_SETWKUENA		0x0084
97239281Sgonzo#define TI_GPIO_CLEARDATAOUT		0x0090
98239281Sgonzo#define TI_GPIO_SETDATAOUT		0x0094
99239281Sgonzo#elif defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
100239281Sgonzo#define TI_GPIO_IRQSTATUS_RAW_0		0x0024
101239281Sgonzo#define TI_GPIO_IRQSTATUS_RAW_1		0x0028
102239281Sgonzo#define TI_GPIO_IRQSTATUS_0		0x002C
103239281Sgonzo#define TI_GPIO_IRQSTATUS_1		0x0030
104239281Sgonzo#define TI_GPIO_IRQSTATUS_SET_0		0x0034
105239281Sgonzo#define TI_GPIO_IRQSTATUS_SET_1		0x0038
106239281Sgonzo#define TI_GPIO_IRQSTATUS_CLR_0		0x003C
107239281Sgonzo#define TI_GPIO_IRQSTATUS_CLR_1		0x0040
108239281Sgonzo#define TI_GPIO_IRQWAKEN_0		0x0044
109239281Sgonzo#define TI_GPIO_IRQWAKEN_1		0x0048
110239281Sgonzo#define TI_GPIO_SYSSTATUS		0x0114
111239281Sgonzo#define TI_GPIO_IRQSTATUS1		0x0118
112239281Sgonzo#define TI_GPIO_IRQENABLE1		0x011C
113239281Sgonzo#define TI_GPIO_WAKEUPENABLE		0x0120
114239281Sgonzo#define TI_GPIO_IRQSTATUS2		0x0128
115239281Sgonzo#define TI_GPIO_IRQENABLE2		0x012C
116239281Sgonzo#define TI_GPIO_CTRL			0x0130
117239281Sgonzo#define TI_GPIO_OE			0x0134
118239281Sgonzo#define TI_GPIO_DATAIN			0x0138
119239281Sgonzo#define TI_GPIO_DATAOUT			0x013C
120239281Sgonzo#define TI_GPIO_LEVELDETECT0		0x0140
121239281Sgonzo#define TI_GPIO_LEVELDETECT1		0x0144
122239281Sgonzo#define TI_GPIO_RISINGDETECT		0x0148
123239281Sgonzo#define TI_GPIO_FALLINGDETECT		0x014C
124239281Sgonzo#define TI_GPIO_DEBOUNCENABLE		0x0150
125239281Sgonzo#define TI_GPIO_DEBOUNCINGTIME		0x0154
126239281Sgonzo#define TI_GPIO_CLEARIRQENABLE1		0x0160
127239281Sgonzo#define TI_GPIO_SETIRQENABLE1		0x0164
128239281Sgonzo#define TI_GPIO_CLEARIRQENABLE2		0x0170
129239281Sgonzo#define TI_GPIO_SETIRQENABLE2		0x0174
130239281Sgonzo#define TI_GPIO_CLEARWKUPENA		0x0180
131239281Sgonzo#define TI_GPIO_SETWKUENA		0x0184
132239281Sgonzo#define TI_GPIO_CLEARDATAOUT		0x0190
133239281Sgonzo#define TI_GPIO_SETDATAOUT		0x0194
134239281Sgonzo#else
135239281Sgonzo#error "Unknown SoC"
136239281Sgonzo#endif
137239281Sgonzo
138239281Sgonzo /*Other SoC Specific definitions*/
139239281Sgonzo#if defined(SOC_OMAP3)
140239281Sgonzo#define MAX_GPIO_BANKS			6
141239281Sgonzo#define FIRST_GPIO_BANK			1
142239281Sgonzo#define PINS_PER_BANK			32
143239281Sgonzo#define TI_GPIO_REV			0x00000025
144239281Sgonzo#elif defined(SOC_OMAP4)
145239281Sgonzo#define MAX_GPIO_BANKS			6
146239281Sgonzo#define FIRST_GPIO_BANK			1
147239281Sgonzo#define PINS_PER_BANK			32
148239281Sgonzo#define TI_GPIO_REV			0x50600801
149239281Sgonzo#elif defined(SOC_TI_AM335X)
150239281Sgonzo#define MAX_GPIO_BANKS			4
151239281Sgonzo#define FIRST_GPIO_BANK			0
152239281Sgonzo#define PINS_PER_BANK			32
153239281Sgonzo#define TI_GPIO_REV			0x50600801
154239281Sgonzo#endif
155239281Sgonzo
156239281Sgonzo/**
157239281Sgonzo *	ti_gpio_mem_spec - Resource specification used when allocating resources
158239281Sgonzo *	ti_gpio_irq_spec - Resource specification used when allocating resources
159239281Sgonzo *
160239281Sgonzo *	This driver module can have up to six independent memory regions, each
161239281Sgonzo *	region typically controls 32 GPIO pins.
162239281Sgonzo */
163239281Sgonzostatic struct resource_spec ti_gpio_mem_spec[] = {
164239281Sgonzo	{ SYS_RES_MEMORY,   0,  RF_ACTIVE },
165239281Sgonzo	{ SYS_RES_MEMORY,   1,  RF_ACTIVE | RF_OPTIONAL },
166239281Sgonzo	{ SYS_RES_MEMORY,   2,  RF_ACTIVE | RF_OPTIONAL },
167239281Sgonzo	{ SYS_RES_MEMORY,   3,  RF_ACTIVE | RF_OPTIONAL },
168239281Sgonzo#if !defined(SOC_TI_AM335X)
169239281Sgonzo	{ SYS_RES_MEMORY,   4,  RF_ACTIVE | RF_OPTIONAL },
170239281Sgonzo	{ SYS_RES_MEMORY,   5,  RF_ACTIVE | RF_OPTIONAL },
171239281Sgonzo#endif
172239281Sgonzo	{ -1,               0,  0 }
173239281Sgonzo};
174239281Sgonzostatic struct resource_spec ti_gpio_irq_spec[] = {
175239281Sgonzo	{ SYS_RES_IRQ,      0,  RF_ACTIVE },
176239281Sgonzo	{ SYS_RES_IRQ,      1,  RF_ACTIVE | RF_OPTIONAL },
177239281Sgonzo	{ SYS_RES_IRQ,      2,  RF_ACTIVE | RF_OPTIONAL },
178239281Sgonzo	{ SYS_RES_IRQ,      3,  RF_ACTIVE | RF_OPTIONAL },
179239281Sgonzo#if !defined(SOC_TI_AM335X)
180239281Sgonzo	{ SYS_RES_IRQ,      4,  RF_ACTIVE | RF_OPTIONAL },
181239281Sgonzo	{ SYS_RES_IRQ,      5,  RF_ACTIVE | RF_OPTIONAL },
182239281Sgonzo#endif
183239281Sgonzo	{ -1,               0,  0 }
184239281Sgonzo};
185239281Sgonzo
186239281Sgonzo/**
187239281Sgonzo *	Structure that stores the driver context.
188239281Sgonzo *
189239281Sgonzo *	This structure is allocated during driver attach.
190239281Sgonzo */
191239281Sgonzostruct ti_gpio_softc {
192239281Sgonzo	device_t			sc_dev;
193239281Sgonzo
194239281Sgonzo	/* The memory resource(s) for the PRCM register set, when the device is
195239281Sgonzo	 * created the caller can assign up to 4 memory regions.
196239281Sgonzo	 */
197239281Sgonzo	struct resource*    sc_mem_res[MAX_GPIO_BANKS];
198239281Sgonzo	struct resource*    sc_irq_res[MAX_GPIO_BANKS];
199239281Sgonzo
200239281Sgonzo	/* The handle for the register IRQ handlers */
201239281Sgonzo	void*               sc_irq_hdl[MAX_GPIO_BANKS];
202239281Sgonzo
203239281Sgonzo	/* The following describes the H/W revision of each of the GPIO banks */
204239281Sgonzo	uint32_t            sc_revision[MAX_GPIO_BANKS];
205239281Sgonzo
206239281Sgonzo	struct mtx			sc_mtx;
207239281Sgonzo};
208239281Sgonzo
209239281Sgonzo/**
210239281Sgonzo *	Macros for driver mutex locking
211239281Sgonzo */
212239281Sgonzo#define TI_GPIO_LOCK(_sc)             mtx_lock(&(_sc)->sc_mtx)
213239281Sgonzo#define	TI_GPIO_UNLOCK(_sc)           mtx_unlock(&(_sc)->sc_mtx)
214239281Sgonzo#define TI_GPIO_LOCK_INIT(_sc) \
215239281Sgonzo	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
216239281Sgonzo	         "ti_gpio", MTX_DEF)
217239281Sgonzo#define TI_GPIO_LOCK_DESTROY(_sc)     mtx_destroy(&_sc->sc_mtx);
218239281Sgonzo#define TI_GPIO_ASSERT_LOCKED(_sc)    mtx_assert(&_sc->sc_mtx, MA_OWNED);
219239281Sgonzo#define TI_GPIO_ASSERT_UNLOCKED(_sc)  mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
220239281Sgonzo
221239281Sgonzo/**
222239281Sgonzo *	ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers
223239281Sgonzo *	@sc: GPIO device context
224239281Sgonzo *	@bank: The bank to read from
225239281Sgonzo *	@off: The offset of a register from the GPIO register address range
226239281Sgonzo *
227239281Sgonzo *
228239281Sgonzo *	RETURNS:
229239281Sgonzo *	32-bit value read from the register.
230239281Sgonzo */
231239281Sgonzostatic inline uint32_t
232239281Sgonzoti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off)
233239281Sgonzo{
234239281Sgonzo	return (bus_read_4(sc->sc_mem_res[bank], off));
235239281Sgonzo}
236239281Sgonzo
237239281Sgonzo/**
238239281Sgonzo *	ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers
239239281Sgonzo *	@sc: GPIO device context
240239281Sgonzo *	@bank: The bank to write to
241239281Sgonzo *	@off: The offset of a register from the GPIO register address range
242239281Sgonzo *	@val: The value to write into the register
243239281Sgonzo *
244239281Sgonzo *	RETURNS:
245239281Sgonzo *	nothing
246239281Sgonzo */
247239281Sgonzostatic inline void
248239281Sgonzoti_gpio_write_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off,
249239281Sgonzo                 uint32_t val)
250239281Sgonzo{
251239281Sgonzo	bus_write_4(sc->sc_mem_res[bank], off, val);
252239281Sgonzo}
253239281Sgonzo
254239281Sgonzo/**
255239281Sgonzo *	ti_gpio_pin_max - Returns the maximum number of GPIO pins
256239281Sgonzo *	@dev: gpio device handle
257239281Sgonzo *	@maxpin: pointer to a value that upon return will contain the maximum number
258239281Sgonzo *	         of pins in the device.
259239281Sgonzo *
260239281Sgonzo *
261239281Sgonzo *	LOCKING:
262239281Sgonzo *	Internally locks the context
263239281Sgonzo *
264239281Sgonzo *	RETURNS:
265239281Sgonzo *	Returns 0 on success otherwise an error code
266239281Sgonzo */
267239281Sgonzostatic int
268239281Sgonzoti_gpio_pin_max(device_t dev, int *maxpin)
269239281Sgonzo{
270239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
271239281Sgonzo	unsigned int i;
272239281Sgonzo	unsigned int banks = 0;
273239281Sgonzo
274239281Sgonzo	TI_GPIO_LOCK(sc);
275239281Sgonzo
276239281Sgonzo	/* Calculate how many valid banks we have and then multiply that by 32 to
277239281Sgonzo	 * give use the total number of pins.
278239281Sgonzo	 */
279239281Sgonzo	for (i = 0; i < MAX_GPIO_BANKS; i++) {
280239281Sgonzo		if (sc->sc_mem_res[i] != NULL)
281239281Sgonzo			banks++;
282239281Sgonzo	}
283239281Sgonzo
284247252Sgonzo	*maxpin = (banks * PINS_PER_BANK) - 1;
285239281Sgonzo
286239281Sgonzo	TI_GPIO_UNLOCK(sc);
287239281Sgonzo
288239281Sgonzo	return (0);
289239281Sgonzo}
290239281Sgonzo
291239281Sgonzo/**
292239281Sgonzo *	ti_gpio_pin_getcaps - Gets the capabilties of a given pin
293239281Sgonzo *	@dev: gpio device handle
294239281Sgonzo *	@pin: the number of the pin
295239281Sgonzo *	@caps: pointer to a value that upon return will contain the capabilities
296239281Sgonzo *
297239281Sgonzo *	Currently all pins have the same capability, notably:
298239281Sgonzo *	  - GPIO_PIN_INPUT
299239281Sgonzo *	  - GPIO_PIN_OUTPUT
300239281Sgonzo *	  - GPIO_PIN_PULLUP
301239281Sgonzo *	  - GPIO_PIN_PULLDOWN
302239281Sgonzo *
303239281Sgonzo *	LOCKING:
304239281Sgonzo *	Internally locks the context
305239281Sgonzo *
306239281Sgonzo *	RETURNS:
307239281Sgonzo *	Returns 0 on success otherwise an error code
308239281Sgonzo */
309239281Sgonzostatic int
310239281Sgonzoti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
311239281Sgonzo{
312239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
313239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
314239281Sgonzo
315239281Sgonzo	TI_GPIO_LOCK(sc);
316239281Sgonzo
317239281Sgonzo	/* Sanity check the pin number is valid */
318239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
319239281Sgonzo		TI_GPIO_UNLOCK(sc);
320239281Sgonzo		return (EINVAL);
321239281Sgonzo	}
322239281Sgonzo
323239281Sgonzo	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP |
324239281Sgonzo	    GPIO_PIN_PULLDOWN);
325239281Sgonzo
326239281Sgonzo	TI_GPIO_UNLOCK(sc);
327239281Sgonzo
328239281Sgonzo	return (0);
329239281Sgonzo}
330239281Sgonzo
331239281Sgonzo/**
332239281Sgonzo *	ti_gpio_pin_getflags - Gets the current flags of a given pin
333239281Sgonzo *	@dev: gpio device handle
334239281Sgonzo *	@pin: the number of the pin
335239281Sgonzo *	@flags: upon return will contain the current flags of the pin
336239281Sgonzo *
337239281Sgonzo *	Reads the current flags of a given pin, here we actually read the H/W
338239281Sgonzo *	registers to determine the flags, rather than storing the value in the
339239281Sgonzo *	setflags call.
340239281Sgonzo *
341239281Sgonzo *	LOCKING:
342239281Sgonzo *	Internally locks the context
343239281Sgonzo *
344239281Sgonzo *	RETURNS:
345239281Sgonzo *	Returns 0 on success otherwise an error code
346239281Sgonzo */
347239281Sgonzostatic int
348239281Sgonzoti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
349239281Sgonzo{
350239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
351239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
352239281Sgonzo
353239281Sgonzo	TI_GPIO_LOCK(sc);
354239281Sgonzo
355239281Sgonzo	/* Sanity check the pin number is valid */
356239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
357239281Sgonzo		TI_GPIO_UNLOCK(sc);
358239281Sgonzo		return (EINVAL);
359239281Sgonzo	}
360239281Sgonzo
361239281Sgonzo	/* Get the current pin state */
362239281Sgonzo	ti_scm_padconf_get_gpioflags(pin, flags);
363239281Sgonzo
364239281Sgonzo	TI_GPIO_UNLOCK(sc);
365239281Sgonzo
366239281Sgonzo	return (0);
367239281Sgonzo}
368239281Sgonzo
369239281Sgonzo/**
370239281Sgonzo *	ti_gpio_pin_getname - Gets the name of a given pin
371239281Sgonzo *	@dev: gpio device handle
372239281Sgonzo *	@pin: the number of the pin
373239281Sgonzo *	@name: buffer to put the name in
374239281Sgonzo *
375239281Sgonzo *	The driver simply calls the pins gpio_n, where 'n' is obviously the number
376239281Sgonzo *	of the pin.
377239281Sgonzo *
378239281Sgonzo *	LOCKING:
379239281Sgonzo *	Internally locks the context
380239281Sgonzo *
381239281Sgonzo *	RETURNS:
382239281Sgonzo *	Returns 0 on success otherwise an error code
383239281Sgonzo */
384239281Sgonzostatic int
385239281Sgonzoti_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
386239281Sgonzo{
387239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
388239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
389239281Sgonzo
390239281Sgonzo	TI_GPIO_LOCK(sc);
391239281Sgonzo
392239281Sgonzo	/* Sanity check the pin number is valid */
393239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
394239281Sgonzo		TI_GPIO_UNLOCK(sc);
395239281Sgonzo		return (EINVAL);
396239281Sgonzo	}
397239281Sgonzo
398239281Sgonzo	/* Set a very simple name */
399239281Sgonzo	snprintf(name, GPIOMAXNAME, "gpio_%u", pin);
400239281Sgonzo	name[GPIOMAXNAME - 1] = '\0';
401239281Sgonzo
402239281Sgonzo	TI_GPIO_UNLOCK(sc);
403239281Sgonzo
404239281Sgonzo	return (0);
405239281Sgonzo}
406239281Sgonzo
407239281Sgonzo/**
408239281Sgonzo *	ti_gpio_pin_setflags - Sets the flags for a given pin
409239281Sgonzo *	@dev: gpio device handle
410239281Sgonzo *	@pin: the number of the pin
411239281Sgonzo *	@flags: the flags to set
412239281Sgonzo *
413239281Sgonzo *	The flags of the pin correspond to things like input/output mode, pull-ups,
414239281Sgonzo *	pull-downs, etc.  This driver doesn't support all flags, only the following:
415239281Sgonzo *	  - GPIO_PIN_INPUT
416239281Sgonzo *	  - GPIO_PIN_OUTPUT
417239281Sgonzo *	  - GPIO_PIN_PULLUP
418239281Sgonzo *	  - GPIO_PIN_PULLDOWN
419239281Sgonzo *
420239281Sgonzo *	LOCKING:
421239281Sgonzo *	Internally locks the context
422239281Sgonzo *
423239281Sgonzo *	RETURNS:
424239281Sgonzo *	Returns 0 on success otherwise an error code
425239281Sgonzo */
426239281Sgonzostatic int
427239281Sgonzoti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
428239281Sgonzo{
429239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
430239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
431239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
432239281Sgonzo	uint32_t reg_val;
433239281Sgonzo
434239281Sgonzo	/* Sanity check the flags supplied are valid, i.e. not input and output */
435239281Sgonzo	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 0x0000)
436239281Sgonzo		return (EINVAL);
437239281Sgonzo	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
438239281Sgonzo	    (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
439239281Sgonzo		return (EINVAL);
440239281Sgonzo	if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) ==
441239281Sgonzo	    (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN))
442239281Sgonzo		return (EINVAL);
443239281Sgonzo
444239281Sgonzo
445239281Sgonzo	TI_GPIO_LOCK(sc);
446239281Sgonzo
447239281Sgonzo	/* Sanity check the pin number is valid */
448239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
449239281Sgonzo		TI_GPIO_UNLOCK(sc);
450239281Sgonzo		return (EINVAL);
451239281Sgonzo	}
452239281Sgonzo
453239281Sgonzo	/* Set the GPIO mode and state */
454239281Sgonzo	if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) {
455239281Sgonzo		TI_GPIO_UNLOCK(sc);
456239281Sgonzo		return (EINVAL);
457239281Sgonzo	}
458239281Sgonzo
459239281Sgonzo	/* If configuring as an output set the "output enable" bit */
460239281Sgonzo	reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
461239281Sgonzo	if (flags & GPIO_PIN_INPUT)
462239281Sgonzo		reg_val |= mask;
463239281Sgonzo	else
464239281Sgonzo		reg_val &= ~mask;
465239281Sgonzo	ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val);
466239281Sgonzo
467239281Sgonzo
468239281Sgonzo	TI_GPIO_UNLOCK(sc);
469239281Sgonzo
470239281Sgonzo	return (0);
471239281Sgonzo}
472239281Sgonzo
473239281Sgonzo/**
474239281Sgonzo *	ti_gpio_pin_set - Sets the current level on a GPIO pin
475239281Sgonzo *	@dev: gpio device handle
476239281Sgonzo *	@pin: the number of the pin
477239281Sgonzo *	@value: non-zero value will drive the pin high, otherwise the pin is
478239281Sgonzo *	        driven low.
479239281Sgonzo *
480239281Sgonzo *
481239281Sgonzo *	LOCKING:
482239281Sgonzo *	Internally locks the context
483239281Sgonzo *
484239281Sgonzo *	RETURNS:
485239281Sgonzo *	Returns 0 on success otherwise a error code
486239281Sgonzo */
487239281Sgonzostatic int
488239281Sgonzoti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
489239281Sgonzo{
490239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
491239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
492239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
493239281Sgonzo
494239281Sgonzo	TI_GPIO_LOCK(sc);
495239281Sgonzo
496239281Sgonzo	/* Sanity check the pin number is valid */
497239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
498239281Sgonzo		TI_GPIO_UNLOCK(sc);
499239281Sgonzo		return (EINVAL);
500239281Sgonzo	}
501239281Sgonzo
502239281Sgonzo	ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT
503239281Sgonzo	    : TI_GPIO_SETDATAOUT, mask);
504239281Sgonzo
505239281Sgonzo	TI_GPIO_UNLOCK(sc);
506239281Sgonzo
507239281Sgonzo	return (0);
508239281Sgonzo}
509239281Sgonzo
510239281Sgonzo/**
511239281Sgonzo *	ti_gpio_pin_get - Gets the current level on a GPIO pin
512239281Sgonzo *	@dev: gpio device handle
513239281Sgonzo *	@pin: the number of the pin
514239281Sgonzo *	@value: pointer to a value that upond return will contain the pin value
515239281Sgonzo *
516239281Sgonzo *	The pin must be configured as an input pin beforehand, otherwise this
517239281Sgonzo *	function will fail.
518239281Sgonzo *
519239281Sgonzo *	LOCKING:
520239281Sgonzo *	Internally locks the context
521239281Sgonzo *
522239281Sgonzo *	RETURNS:
523239281Sgonzo *	Returns 0 on success otherwise a error code
524239281Sgonzo */
525239281Sgonzostatic int
526239281Sgonzoti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
527239281Sgonzo{
528239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
529239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
530239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
531239281Sgonzo	uint32_t val = 0;
532239281Sgonzo
533239281Sgonzo	TI_GPIO_LOCK(sc);
534239281Sgonzo
535239281Sgonzo	/* Sanity check the pin number is valid */
536239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
537239281Sgonzo		TI_GPIO_UNLOCK(sc);
538239281Sgonzo		return (EINVAL);
539239281Sgonzo	}
540239281Sgonzo
541239281Sgonzo	/* Sanity check the pin is not configured as an output */
542239281Sgonzo	val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
543239281Sgonzo
544239281Sgonzo	/* Read the value on the pin */
545247252Sgonzo	if (val & mask)
546247252Sgonzo		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0;
547247252Sgonzo	else
548247252Sgonzo		*value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0;
549239281Sgonzo
550239281Sgonzo	TI_GPIO_UNLOCK(sc);
551239281Sgonzo
552239281Sgonzo	return (0);
553239281Sgonzo}
554239281Sgonzo
555239281Sgonzo/**
556239281Sgonzo *	ti_gpio_pin_toggle - Toggles a given GPIO pin
557239281Sgonzo *	@dev: gpio device handle
558239281Sgonzo *	@pin: the number of the pin
559239281Sgonzo *
560239281Sgonzo *
561239281Sgonzo *	LOCKING:
562239281Sgonzo *	Internally locks the context
563239281Sgonzo *
564239281Sgonzo *	RETURNS:
565239281Sgonzo *	Returns 0 on success otherwise a error code
566239281Sgonzo */
567239281Sgonzostatic int
568239281Sgonzoti_gpio_pin_toggle(device_t dev, uint32_t pin)
569239281Sgonzo{
570239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
571239281Sgonzo	uint32_t bank = (pin / PINS_PER_BANK);
572239281Sgonzo	uint32_t mask = (1UL << (pin % PINS_PER_BANK));
573239281Sgonzo	uint32_t val;
574239281Sgonzo
575239281Sgonzo	TI_GPIO_LOCK(sc);
576239281Sgonzo
577239281Sgonzo	/* Sanity check the pin number is valid */
578239281Sgonzo	if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
579239281Sgonzo		TI_GPIO_UNLOCK(sc);
580239281Sgonzo		return (EINVAL);
581239281Sgonzo	}
582239281Sgonzo
583239281Sgonzo	/* Toggle the pin */
584239281Sgonzo	val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT);
585239281Sgonzo	if (val & mask)
586239281Sgonzo		ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask);
587239281Sgonzo	else
588239281Sgonzo		ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask);
589239281Sgonzo
590239281Sgonzo	TI_GPIO_UNLOCK(sc);
591239281Sgonzo
592239281Sgonzo	return (0);
593239281Sgonzo}
594239281Sgonzo
595239281Sgonzo/**
596239281Sgonzo *	ti_gpio_intr - ISR for all GPIO modules
597239281Sgonzo *	@arg: the soft context pointer
598239281Sgonzo *
599239281Sgonzo *	Unsused
600239281Sgonzo *
601239281Sgonzo *	LOCKING:
602239281Sgonzo *	Internally locks the context
603239281Sgonzo *
604239281Sgonzo */
605239281Sgonzostatic void
606239281Sgonzoti_gpio_intr(void *arg)
607239281Sgonzo{
608239281Sgonzo	struct ti_gpio_softc *sc = arg;
609239281Sgonzo
610239281Sgonzo	TI_GPIO_LOCK(sc);
611239281Sgonzo	/* TODO: something useful */
612239281Sgonzo	TI_GPIO_UNLOCK(sc);
613239281Sgonzo}
614239281Sgonzo
615239281Sgonzo/**
616239281Sgonzo *	ti_gpio_probe - probe function for the driver
617239281Sgonzo *	@dev: gpio device handle
618239281Sgonzo *
619239281Sgonzo *	Simply sets the name of the driver
620239281Sgonzo *
621239281Sgonzo *	LOCKING:
622239281Sgonzo *	None
623239281Sgonzo *
624239281Sgonzo *	RETURNS:
625239281Sgonzo *	Always returns 0
626239281Sgonzo */
627239281Sgonzostatic int
628239281Sgonzoti_gpio_probe(device_t dev)
629239281Sgonzo{
630239281Sgonzo	if (!ofw_bus_is_compatible(dev, "ti,gpio"))
631239281Sgonzo		return (ENXIO);
632239281Sgonzo
633239281Sgonzo	device_set_desc(dev, "TI General Purpose I/O (GPIO)");
634239281Sgonzo	return (0);
635239281Sgonzo}
636239281Sgonzo
637239281Sgonzo/**
638239281Sgonzo *	ti_gpio_attach - attach function for the driver
639239281Sgonzo *	@dev: gpio device handle
640239281Sgonzo *
641239281Sgonzo *	Allocates and sets up the driver context for all GPIO banks.  This function
642239281Sgonzo *	expects the memory ranges and IRQs to already be allocated to the driver.
643239281Sgonzo *
644239281Sgonzo *	LOCKING:
645239281Sgonzo *	None
646239281Sgonzo *
647239281Sgonzo *	RETURNS:
648239281Sgonzo *	Always returns 0
649239281Sgonzo */
650239281Sgonzostatic int
651239281Sgonzoti_gpio_attach(device_t dev)
652239281Sgonzo{
653239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
654239281Sgonzo	unsigned int i;
655239281Sgonzo	int err = 0;
656239281Sgonzo
657239281Sgonzo	sc->sc_dev = dev;
658239281Sgonzo
659239281Sgonzo	TI_GPIO_LOCK_INIT(sc);
660239281Sgonzo
661239281Sgonzo
662239281Sgonzo	/* There are up to 6 different GPIO register sets located in different
663239281Sgonzo	 * memory areas on the chip.  The memory range should have been set for
664239281Sgonzo	 * the driver when it was added as a child.
665239281Sgonzo	 */
666239281Sgonzo	err = bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
667239281Sgonzo	if (err) {
668239281Sgonzo		device_printf(dev, "Error: could not allocate mem resources\n");
669239281Sgonzo		return (ENXIO);
670239281Sgonzo	}
671239281Sgonzo
672239281Sgonzo	/* Request the IRQ resources */
673239281Sgonzo	err = bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
674239281Sgonzo	if (err) {
675239281Sgonzo		device_printf(dev, "Error: could not allocate irq resources\n");
676239281Sgonzo		return (ENXIO);
677239281Sgonzo	}
678239281Sgonzo
679239281Sgonzo	/* Setup the IRQ resources */
680239281Sgonzo	for (i = 0;  i < MAX_GPIO_BANKS; i++) {
681239281Sgonzo		if (sc->sc_irq_res[i] == NULL)
682239281Sgonzo			break;
683239281Sgonzo
684239281Sgonzo		/* Register an interrupt handler for each of the IRQ resources */
685239281Sgonzo		if ((bus_setup_intr(dev, sc->sc_irq_res[i], INTR_TYPE_MISC | INTR_MPSAFE,
686239281Sgonzo		                    NULL, ti_gpio_intr, sc, &(sc->sc_irq_hdl[i])))) {
687239281Sgonzo			device_printf(dev, "WARNING: unable to register interrupt handler\n");
688239281Sgonzo			return (ENXIO);
689239281Sgonzo		}
690239281Sgonzo	}
691239281Sgonzo
692239281Sgonzo	/* Store the device handle back in the sc */
693239281Sgonzo	sc->sc_dev = dev;
694239281Sgonzo
695239281Sgonzo	/* We need to go through each block and ensure the clocks are running and
696239281Sgonzo	 * the module is enabled.  It might be better to do this only when the
697239281Sgonzo	 * pins are configured which would result in less power used if the GPIO
698239281Sgonzo	 * pins weren't used ...
699239281Sgonzo	 */
700239281Sgonzo	for (i = 0;  i < MAX_GPIO_BANKS; i++) {
701239281Sgonzo		if (sc->sc_mem_res[i] != NULL) {
702239281Sgonzo
703239281Sgonzo			/* Enable the interface and functional clocks for the module */
704239281Sgonzo			ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + i);
705239281Sgonzo
706239281Sgonzo			/* Read the revision number of the module. TI don't publish the
707239281Sgonzo			 * actual revision numbers, so instead the values have been
708239281Sgonzo			 * determined by experimentation.
709239281Sgonzo			 */
710239281Sgonzo			sc->sc_revision[i] = ti_gpio_read_4(sc, i, TI_GPIO_REVISION);
711239281Sgonzo
712239281Sgonzo			/* Check the revision */
713239281Sgonzo			if (sc->sc_revision[i] != TI_GPIO_REV) {
714239281Sgonzo				device_printf(dev, "Warning: could not determine the revision"
715239281Sgonzo				              "of %u GPIO module (revision:0x%08x)\n",
716239281Sgonzo				              i, sc->sc_revision[i]);
717239281Sgonzo				continue;
718239281Sgonzo			}
719239281Sgonzo
720239281Sgonzo			/* Disable interrupts for all pins */
721239281Sgonzo			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff);
722239281Sgonzo			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff);
723239281Sgonzo		}
724239281Sgonzo	}
725239281Sgonzo
726239281Sgonzo	/* Finish of the probe call */
727239281Sgonzo	device_add_child(dev, "gpioc", device_get_unit(dev));
728239281Sgonzo	device_add_child(dev, "gpiobus", device_get_unit(dev));
729247252Sgonzo
730239281Sgonzo	return (bus_generic_attach(dev));
731239281Sgonzo}
732239281Sgonzo
733239281Sgonzo/**
734239281Sgonzo *	ti_gpio_detach - detach function for the driver
735239281Sgonzo *	@dev: scm device handle
736239281Sgonzo *
737239281Sgonzo *	Allocates and sets up the driver context, this simply entails creating a
738239281Sgonzo *	bus mappings for the SCM register set.
739239281Sgonzo *
740239281Sgonzo *	LOCKING:
741239281Sgonzo *	None
742239281Sgonzo *
743239281Sgonzo *	RETURNS:
744239281Sgonzo *	Always returns 0
745239281Sgonzo */
746239281Sgonzostatic int
747239281Sgonzoti_gpio_detach(device_t dev)
748239281Sgonzo{
749239281Sgonzo	struct ti_gpio_softc *sc = device_get_softc(dev);
750239281Sgonzo	unsigned int i;
751239281Sgonzo
752239281Sgonzo	KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
753239281Sgonzo
754239281Sgonzo	/* Disable all interrupts */
755239281Sgonzo	for (i = 0;  i < MAX_GPIO_BANKS; i++) {
756239281Sgonzo		if (sc->sc_mem_res[i] != NULL) {
757239281Sgonzo			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff);
758239281Sgonzo			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff);
759239281Sgonzo		}
760239281Sgonzo	}
761239281Sgonzo
762239281Sgonzo	bus_generic_detach(dev);
763239281Sgonzo
764239281Sgonzo	/* Release the memory and IRQ resources */
765239281Sgonzo	for (i = 0;  i < MAX_GPIO_BANKS; i++) {
766239281Sgonzo		if (sc->sc_mem_res[i] != NULL)
767239281Sgonzo			bus_release_resource(dev, SYS_RES_MEMORY, i, sc->sc_mem_res[i]);
768239281Sgonzo		if (sc->sc_irq_res[i] != NULL)
769239281Sgonzo			bus_release_resource(dev, SYS_RES_IRQ, i, sc->sc_irq_res[i]);
770239281Sgonzo	}
771239281Sgonzo
772239281Sgonzo	TI_GPIO_LOCK_DESTROY(sc);
773239281Sgonzo
774239281Sgonzo	return(0);
775239281Sgonzo}
776239281Sgonzo
777239281Sgonzostatic device_method_t ti_gpio_methods[] = {
778239281Sgonzo	DEVMETHOD(device_probe, ti_gpio_probe),
779239281Sgonzo	DEVMETHOD(device_attach, ti_gpio_attach),
780239281Sgonzo	DEVMETHOD(device_detach, ti_gpio_detach),
781239281Sgonzo
782239281Sgonzo	/* GPIO protocol */
783239281Sgonzo	DEVMETHOD(gpio_pin_max, ti_gpio_pin_max),
784239281Sgonzo	DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname),
785239281Sgonzo	DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags),
786239281Sgonzo	DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps),
787239281Sgonzo	DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags),
788239281Sgonzo	DEVMETHOD(gpio_pin_get, ti_gpio_pin_get),
789239281Sgonzo	DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
790239281Sgonzo	DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
791239281Sgonzo	{0, 0},
792239281Sgonzo};
793239281Sgonzo
794239281Sgonzostatic driver_t ti_gpio_driver = {
795239281Sgonzo	"gpio",
796239281Sgonzo	ti_gpio_methods,
797239281Sgonzo	sizeof(struct ti_gpio_softc),
798239281Sgonzo};
799239281Sgonzostatic devclass_t ti_gpio_devclass;
800239281Sgonzo
801239281SgonzoDRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0);
802