ar71xx_gpio.c revision 228518
1/*-
2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
3 * Copyright (c) 2009, Luiz Otavio O Souza.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice unmodified, this list of conditions, and the following
11 *    disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * GPIO driver for AR71xx
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/mips/atheros/ar71xx_gpio.c 228518 2011-12-15 01:03:49Z adrian $");
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/bus.h>
39
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/rman.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/gpio.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49#include <mips/atheros/ar71xxreg.h>
50#include <mips/atheros/ar71xx_setup.h>
51#include <mips/atheros/ar71xx_gpiovar.h>
52
53#include "gpio_if.h"
54
55#define	DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
56
57/*
58 * Helpers
59 */
60static void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc,
61    uint32_t mask);
62static void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc,
63    uint32_t mask);
64static void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc,
65    struct gpio_pin *pin, uint32_t flags);
66
67/*
68 * Driver stuff
69 */
70static int ar71xx_gpio_probe(device_t dev);
71static int ar71xx_gpio_attach(device_t dev);
72static int ar71xx_gpio_detach(device_t dev);
73static int ar71xx_gpio_filter(void *arg);
74static void ar71xx_gpio_intr(void *arg);
75
76/*
77 * GPIO interface
78 */
79static int ar71xx_gpio_pin_max(device_t dev, int *maxpin);
80static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
81static int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
82    *flags);
83static int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
84static int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
85static int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
86static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
87static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin);
88
89static void
90ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask)
91{
92	GPIO_LOCK(sc);
93	GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
94	GPIO_UNLOCK(sc);
95}
96
97static void
98ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask)
99{
100	GPIO_LOCK(sc);
101	GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
102	GPIO_UNLOCK(sc);
103}
104
105static void
106ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
107    unsigned int flags)
108{
109	uint32_t mask;
110
111	mask = 1 << pin->gp_pin;
112	GPIO_LOCK(sc);
113
114	/*
115	 * Manage input/output
116	 */
117	if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
118		pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
119		if (flags & GPIO_PIN_OUTPUT) {
120			pin->gp_flags |= GPIO_PIN_OUTPUT;
121			GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
122		}
123		else {
124			pin->gp_flags |= GPIO_PIN_INPUT;
125			GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
126		}
127	}
128
129	GPIO_UNLOCK(sc);
130}
131
132static int
133ar71xx_gpio_pin_max(device_t dev, int *maxpin)
134{
135
136	switch (ar71xx_soc) {
137		case AR71XX_SOC_AR9130:
138		case AR71XX_SOC_AR9132:
139			*maxpin = AR91XX_GPIO_PINS - 1;
140			break;
141		case AR71XX_SOC_AR7240:
142		case AR71XX_SOC_AR7241:
143		case AR71XX_SOC_AR7242:
144			*maxpin = AR724X_GPIO_PINS - 1;
145			break;
146		default:
147			*maxpin = AR71XX_GPIO_PINS - 1;
148	}
149	return (0);
150}
151
152static int
153ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
154{
155	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
156	int i;
157
158	for (i = 0; i < sc->gpio_npins; i++) {
159		if (sc->gpio_pins[i].gp_pin == pin)
160			break;
161	}
162
163	if (i >= sc->gpio_npins)
164		return (EINVAL);
165
166	GPIO_LOCK(sc);
167	*caps = sc->gpio_pins[i].gp_caps;
168	GPIO_UNLOCK(sc);
169
170	return (0);
171}
172
173static int
174ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
175{
176	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
177	int i;
178
179	for (i = 0; i < sc->gpio_npins; i++) {
180		if (sc->gpio_pins[i].gp_pin == pin)
181			break;
182	}
183
184	if (i >= sc->gpio_npins)
185		return (EINVAL);
186
187	GPIO_LOCK(sc);
188	*flags = sc->gpio_pins[i].gp_flags;
189	GPIO_UNLOCK(sc);
190
191	return (0);
192}
193
194static int
195ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
196{
197	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
198	int i;
199
200	for (i = 0; i < sc->gpio_npins; i++) {
201		if (sc->gpio_pins[i].gp_pin == pin)
202			break;
203	}
204
205	if (i >= sc->gpio_npins)
206		return (EINVAL);
207
208	GPIO_LOCK(sc);
209	memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
210	GPIO_UNLOCK(sc);
211
212	return (0);
213}
214
215static int
216ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
217{
218	int i;
219	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
220
221	for (i = 0; i < sc->gpio_npins; i++) {
222		if (sc->gpio_pins[i].gp_pin == pin)
223			break;
224	}
225
226	if (i >= sc->gpio_npins)
227		return (EINVAL);
228
229	/* Filter out unwanted flags */
230	if ((flags &= sc->gpio_pins[i].gp_caps) != flags)
231		return (EINVAL);
232
233	/* Can't mix input/output together */
234	if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
235	    (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
236		return (EINVAL);
237
238	ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
239	return (0);
240}
241
242static int
243ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
244{
245	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
246	int i;
247
248	for (i = 0; i < sc->gpio_npins; i++) {
249		if (sc->gpio_pins[i].gp_pin == pin)
250			break;
251	}
252
253	if (i >= sc->gpio_npins)
254		return (EINVAL);
255
256	GPIO_LOCK(sc);
257	if (value)
258		GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
259	else
260		GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
261	GPIO_UNLOCK(sc);
262
263	return (0);
264}
265
266static int
267ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
268{
269	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
270	int i;
271
272	for (i = 0; i < sc->gpio_npins; i++) {
273		if (sc->gpio_pins[i].gp_pin == pin)
274			break;
275	}
276
277	if (i >= sc->gpio_npins)
278		return (EINVAL);
279
280	GPIO_LOCK(sc);
281	*val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
282	GPIO_UNLOCK(sc);
283
284	return (0);
285}
286
287static int
288ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin)
289{
290	int res, i;
291	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
292
293	for (i = 0; i < sc->gpio_npins; i++) {
294		if (sc->gpio_pins[i].gp_pin == pin)
295			break;
296	}
297
298	if (i >= sc->gpio_npins)
299		return (EINVAL);
300
301	GPIO_LOCK(sc);
302	res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
303	if (res)
304		GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
305	else
306		GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
307	GPIO_UNLOCK(sc);
308
309	return (0);
310}
311
312static int
313ar71xx_gpio_filter(void *arg)
314{
315
316	/* TODO: something useful */
317	return (FILTER_STRAY);
318}
319
320
321
322static void
323ar71xx_gpio_intr(void *arg)
324{
325	struct ar71xx_gpio_softc *sc = arg;
326	GPIO_LOCK(sc);
327	/* TODO: something useful */
328	GPIO_UNLOCK(sc);
329}
330
331static int
332ar71xx_gpio_probe(device_t dev)
333{
334
335	device_set_desc(dev, "Atheros AR71XX GPIO driver");
336	return (0);
337}
338
339static int
340ar71xx_gpio_attach(device_t dev)
341{
342	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
343	int error = 0;
344	int i, j, maxpin;
345	int mask;
346	int old = 0;
347
348	KASSERT((device_get_unit(dev) == 0),
349	    ("ar71xx_gpio: Only one gpio module supported"));
350
351	mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
352	    MTX_DEF);
353
354	/* Map control/status registers. */
355	sc->gpio_mem_rid = 0;
356	sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
357	    &sc->gpio_mem_rid, RF_ACTIVE);
358
359	if (sc->gpio_mem_res == NULL) {
360		device_printf(dev, "couldn't map memory\n");
361		error = ENXIO;
362		ar71xx_gpio_detach(dev);
363		return(error);
364	}
365
366	if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
367	    &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
368		device_printf(dev, "unable to allocate IRQ resource\n");
369		return (ENXIO);
370	}
371
372	if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC,
373	    ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) {
374		device_printf(dev,
375		    "WARNING: unable to register interrupt handler\n");
376		return (ENXIO);
377	}
378
379	sc->dev = dev;
380
381	/* Enable function bits that are required */
382	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
383	    "function_set", &mask) == 0) {
384		device_printf(dev, "function_set: 0x%x\n", mask);
385		ar71xx_gpio_function_enable(sc, mask);
386		old = 1;
387	}
388	/* Disable function bits that are required */
389	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
390	    "function_clear", &mask) == 0) {
391		device_printf(dev, "function_clear: 0x%x\n", mask);
392		ar71xx_gpio_function_disable(sc, mask);
393		old = 1;
394	}
395	/* Handle previous behaviour */
396	if (old == 0) {
397		ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN);
398		ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN);
399	}
400
401	/* Configure all pins as input */
402	/* disable interrupts for all pins */
403	GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
404
405	/* Initialise all pins specified in the mask, up to the pin count */
406	(void) ar71xx_gpio_pin_max(dev, &maxpin);
407	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
408	    "pinmask", &mask) != 0)
409		mask = 0;
410	device_printf(dev, "gpio pinmask=0x%x\n", mask);
411	for (i = 0, j = 0; j < maxpin; j++) {
412		if ((mask & (1 << j)) == 0)
413			continue;
414		snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
415		    "pin %d", j);
416		sc->gpio_pins[i].gp_pin = j;
417		sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
418		sc->gpio_pins[i].gp_flags = 0;
419		ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS);
420		i++;
421	}
422	sc->gpio_npins = i;
423	device_add_child(dev, "gpioc", device_get_unit(dev));
424	device_add_child(dev, "gpiobus", device_get_unit(dev));
425	return (bus_generic_attach(dev));
426}
427
428static int
429ar71xx_gpio_detach(device_t dev)
430{
431	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
432
433	KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
434
435	ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN);
436	ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN);
437	bus_generic_detach(dev);
438
439	if (sc->gpio_mem_res)
440		bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
441		    sc->gpio_mem_res);
442
443	mtx_destroy(&sc->gpio_mtx);
444
445	return(0);
446}
447
448static device_method_t ar71xx_gpio_methods[] = {
449	DEVMETHOD(device_probe, ar71xx_gpio_probe),
450	DEVMETHOD(device_attach, ar71xx_gpio_attach),
451	DEVMETHOD(device_detach, ar71xx_gpio_detach),
452
453	/* GPIO protocol */
454	DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max),
455	DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname),
456	DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags),
457	DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps),
458	DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags),
459	DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
460	DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
461	DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
462	{0, 0},
463};
464
465static driver_t ar71xx_gpio_driver = {
466	"gpio",
467	ar71xx_gpio_methods,
468	sizeof(struct ar71xx_gpio_softc),
469};
470static devclass_t ar71xx_gpio_devclass;
471
472DRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0);
473