Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / arm / omap / omap_gpio.c
blobb9f47e67566220ea7fa81b1ada8ebfdf863535c6
1 /* $NetBSD: omap_gpio.c,v 1.4 2008/12/12 17:36:14 matt Exp $ */
3 /*
4 * The OMAP GPIO Controller interface is inspired by pxa2x0_gpio.c
6 * Copyright 2003 Wasabi Systems, Inc.
7 * All rights reserved.
9 * Written by Steve C. Woodford for Wasabi Systems, Inc.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed for the NetBSD Project by
22 * Wasabi Systems, Inc.
23 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
24 * or promote products derived from this software without specific prior
25 * written permission.
27 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: omap_gpio.c,v 1.4 2008/12/12 17:36:14 matt Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
48 #include <machine/intr.h>
49 #include <machine/bus.h>
51 #include <arm/omap/omap_tipb.h>
52 #include <arm/omap/omap_gpio.h>
53 #include <arm/omap/omap_gpioreg.h>
55 #include "omapgpio.h"
57 #define GPIOEVNAMESZ 25
59 struct gpio_irq_handler {
60 int (*gh_func)(void *);
61 void *gh_arg;
62 int gh_spl;
63 u_int gh_gpio;
64 char name[GPIOEVNAMESZ];
65 struct evcnt ev;
68 struct omapgpio_softc {
69 device_t sc_dev;
70 bus_space_tag_t sc_bust;
71 bus_space_handle_t sc_bush;
72 void *sc_irqcookie;
73 u_int16_t sc_mask;
74 struct gpio_irq_handler *sc_handlers[GPIO_NPINS];
77 static int omapgpio_match(device_t, cfdata_t, void *);
78 static void omapgpio_attach(device_t, device_t, void *);
80 extern struct cfdriver omapgpio_cd;
82 CFATTACH_DECL_NEW(omapgpio, sizeof(struct omapgpio_softc),
83 omapgpio_match, omapgpio_attach, NULL, NULL);
85 static int omapgpio_intr(void *);
87 static int
88 omapgpio_match(device_t parent, cfdata_t cf, void *aux)
90 struct tipb_attach_args *tipb = aux;
92 if (tipb->tipb_addr == -1 || tipb->tipb_intr == -1) {
93 panic("omapgpio must have addr and intr specified in config.");
96 tipb->tipb_size = OMAP_GPIO_SIZE;
98 return (1);
101 void
102 omapgpio_attach(device_t parent, device_t self, void *aux)
104 struct omapgpio_softc *sc = device_private(self);
105 struct tipb_attach_args *tipb = aux;
106 uint32_t reg;
108 sc->sc_dev = self;
109 sc->sc_bust = tipb->tipb_iot;
111 aprint_normal(": GPIO Controller\n");
113 if (device_unit(self) > NOMAPGPIO - 1) {
114 aprint_error("%s: Unsupported GPIO module unit number.\n",
115 device_xname(sc->sc_dev));
116 return;
119 if (bus_space_map(sc->sc_bust, tipb->tipb_addr, tipb->tipb_size, 0,
120 &sc->sc_bush)) {
121 aprint_error("%s: Failed to map registers.\n",
122 device_xname(sc->sc_dev));
123 return;
126 sc->sc_mask = 0;
127 memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers));
129 /* Reset the module and wait for it to come back online. */
130 reg = bus_space_read_4(sc->sc_bust, sc->sc_bush, GPIO_SYSCONFIG);
131 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_SYSCONFIG,
132 reg | (1 << GPIO_SYSCONFIG_SOFTRESET));
133 do {
134 reg = bus_space_read_4(sc->sc_bust, sc->sc_bush,
135 GPIO_SYSSTATUS);
136 } while ((reg & 1) == 0);
138 /* Enable sleep wakeups, and need "smart idle" mode for that, plus
139 autoidle the OCP interface clock. */
141 reg = bus_space_read_4(sc->sc_bust, sc->sc_bush, GPIO_SYSCONFIG);
142 reg &= ~(GPIO_SYSCONFIG_IDLEMODE_MASK << GPIO_SYSCONFIG_IDLEMODE);
143 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_SYSCONFIG,
144 reg | (1 << GPIO_SYSCONFIG_ENAWAKEUP) |
145 (GPIO_SYSCONFIG_SMARTIDLE <<
146 GPIO_SYSCONFIG_IDLEMODE) |
147 (1 << GPIO_SYSCONFIG_AUTOIDLE));
149 /* Install our ISR. */
150 sc->sc_irqcookie = omap_intr_establish(tipb->tipb_intr, IPL_BIO,
151 device_xname(sc->sc_dev), omapgpio_intr, sc);
152 if (sc->sc_irqcookie == NULL) {
153 aprint_error("%s: Failed to install interrupt handler.\n",
154 device_xname(sc->sc_dev));
155 return;
159 u_int
160 omap_gpio_get_direction(u_int gpio)
162 struct omapgpio_softc *sc;
163 uint32_t reg, bit;
164 u_int rval;
166 KDASSERT(gpio < NOMAPGPIO * GPIO_NPINS);
168 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
169 if (sc == NULL) {
170 panic("omapgpio: GPIO Module for pin %d not configured.\n", gpio);
173 rval = 0;
174 bit = GPIO_BIT(gpio);
175 reg = bus_space_read_4(sc->sc_bust, sc->sc_bush, GPIO_DIRECTION);
177 if ((reg & bit) == 0)
178 /* Output. */
179 rval |= GPIO_OUT;
181 return (rval);
184 void
185 omap_gpio_set_direction(u_int gpio, u_int dir)
187 struct omapgpio_softc *sc;
188 uint32_t reg, bit;
190 KDASSERT(gpio < NOMAPGPIO * GPIO_NPINS);
192 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
193 if (sc == NULL) {
194 panic("omapgpio: GPIO Module for pin %d not configured.\n", gpio);
197 bit = GPIO_BIT(gpio);
198 reg = bus_space_read_4(sc->sc_bust, sc->sc_bush,
199 GPIO_DIRECTION);
201 if (GPIO_IS_IN(dir)) {
202 /* Input. */
203 bus_space_write_4(sc->sc_bust, sc->sc_bush,
204 GPIO_DIRECTION, reg | bit);
205 } else {
206 /* Output. */
207 bus_space_write_4(sc->sc_bust, sc->sc_bush,
208 GPIO_DIRECTION, (reg & ~bit));
212 u_int omap_gpio_read(u_int gpio)
214 struct omapgpio_softc *sc;
215 u_int bit;
217 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
218 if (sc == NULL)
219 panic("omapgpio: GPIO Module for pin %d not configured.",
220 gpio);
222 bit = GPIO_BIT(gpio);
224 return (bus_space_read_4(sc->sc_bust, sc->sc_bush,
225 GPIO_DATAIN) & bit) ? 1 : 0;
228 void omap_gpio_write(u_int gpio, u_int value)
230 struct omapgpio_softc *sc;
231 u_int bit;
233 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
234 if (sc == NULL)
235 panic("omapgpio: GPIO Module for pin %d not configured.",
236 gpio);
238 bit = GPIO_BIT(gpio);
240 if (value) {
241 bus_space_write_4(sc->sc_bust, sc->sc_bush,
242 GPIO_SET_DATAOUT, bit);
243 } else {
244 bus_space_write_4(sc->sc_bust, sc->sc_bush,
245 GPIO_CLEAR_DATAOUT, bit);
249 void *
250 omap_gpio_intr_establish(u_int gpio, int level, int spl,
251 const char *name, int (*func)(void *), void *arg)
253 struct omapgpio_softc *sc;
254 struct gpio_irq_handler *gh;
255 uint32_t bit, levelreg;
256 u_int dir, relnum, off, reg;
257 int levelctrl;
259 KDASSERT(gpio < NOMAPGPIO * GPIO_NPINS);
261 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
262 if (sc == NULL) {
263 panic("omapgpio: GPIO Module for pin %d not configured.", gpio);
266 dir = omap_gpio_get_direction(gpio);
267 if (!GPIO_IS_IN(dir)) {
268 panic("omapgpio: GPIO pin %d not an input.", gpio);
271 relnum = GPIO_RELNUM(gpio);
272 bit = GPIO_BIT(gpio);
274 if (sc->sc_handlers[relnum] != NULL) {
275 panic("omapgpio: Illegal shared interrupt on pin %d", gpio);
278 gh = malloc(sizeof(struct gpio_irq_handler), M_DEVBUF, M_NOWAIT);
279 if (gh == NULL)
280 return gh;
282 gh->gh_func = func;
283 gh->gh_arg = arg;
284 gh->gh_spl = spl;
285 gh->gh_gpio = gpio;
286 sc->sc_handlers[relnum] = gh;
287 sc->sc_mask |= bit;
288 snprintf(gh->name, GPIOEVNAMESZ, "#%d %s", gpio, name);
289 evcnt_attach_dynamic(&gh->ev, EVCNT_TYPE_INTR, NULL,
290 "omap gpio", gh->name);
293 * Set up the level control.
295 * Note: Pins 0->7 on a module use EDGE_CTRL1, pins 8->15 use
296 * EDGE_CTRL2.
298 levelctrl = 0;
299 switch (level) {
300 case IST_EDGE_FALLING:
301 case IST_LEVEL_LOW: /* emulation */
302 levelctrl = 1;
303 break;
304 case IST_EDGE_RISING:
305 case IST_LEVEL_HIGH: /* emulation */
306 levelctrl = 2;
307 break;
308 case IST_EDGE_BOTH:
309 levelctrl = 3;
310 break;
311 default:
312 panic("omapgpio: Unknown level %d.", level);
313 /* NOTREACHED */
316 off = 2 * (relnum & 7);
317 if (relnum < 8) {
318 reg = GPIO_EDGE_CTRL1;
319 } else {
320 reg = GPIO_EDGE_CTRL2;
323 /* Temporarily set the level control to no trigger. */
324 levelreg = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
325 levelreg &= ~(0x3 << off);
326 bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, levelreg);
328 /* Clear the IRQSTATUS bit for the pin we're about to change. */
329 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_IRQSTATUS, bit);
331 /* Set the new level control value. */
332 levelreg |= levelctrl << off;
333 bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, levelreg);
335 /* Disable sleep wakeups for this pin unless enabled later. */
336 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_CLEAR_WAKEUPENA,
337 bit);
339 /* Enable interrupt generation for that pin. */
340 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_SET_IRQENABLE,
341 bit);
343 return (gh);
346 void
347 omap_gpio_intr_disestablish(void *cookie)
349 struct omapgpio_softc *sc;
350 struct gpio_irq_handler *gh = cookie;
351 uint32_t bit;
352 u_int gpio, relnum;
354 KDASSERT(cookie != NULL);
356 gpio = gh->gh_gpio;
357 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
358 bit = GPIO_BIT(gpio);
359 relnum = GPIO_RELNUM(gpio);
360 evcnt_detach(&gh->ev);
362 /* Disable Wakeup enable for this gpio. */
363 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_CLEAR_WAKEUPENA,
364 bit);
366 /* Disable interrupt generation for that gpio. */
367 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_CLEAR_IRQENABLE,
368 bit);
370 sc->sc_mask &= ~bit;
371 sc->sc_handlers[relnum] = NULL;
374 free(gh, M_DEVBUF);
377 void
378 omap_gpio_intr_mask(void *cookie)
380 struct omapgpio_softc *sc;
381 struct gpio_irq_handler *gh = cookie;
382 uint32_t bit;
383 u_int gpio, relnum;
385 KDASSERT(cookie != NULL);
387 gpio = gh->gh_gpio;
388 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
389 bit = GPIO_BIT(gpio);
390 relnum = GPIO_RELNUM(gpio);
392 /* Disable interrupt generation for that gpio. */
393 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_CLEAR_IRQENABLE,
394 bit);
396 sc->sc_mask &= ~bit;
399 void
400 omap_gpio_intr_unmask(void *cookie)
402 struct omapgpio_softc *sc;
403 struct gpio_irq_handler *gh = cookie;
404 uint32_t bit;
405 u_int gpio, relnum;
407 KDASSERT(cookie != NULL);
409 gpio = gh->gh_gpio;
410 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
411 bit = GPIO_BIT(gpio);
412 relnum = GPIO_RELNUM(gpio);
414 /* Enable interrupt generation for that pin. */
415 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_SET_IRQENABLE,
416 bit);
418 sc->sc_mask |= bit;
421 void
422 omap_gpio_intr_wakeup(void *cookie, int enable)
424 struct omapgpio_softc *sc;
425 struct gpio_irq_handler *gh = cookie;
426 uint32_t bit;
427 u_int gpio, relnum;
429 KDASSERT(cookie != NULL);
431 gpio = gh->gh_gpio;
432 sc = device_lookup_private(&omapgpio_cd, GPIO_MODULE(gpio));
433 bit = GPIO_BIT(gpio);
434 relnum = GPIO_RELNUM(gpio);
436 if (enable)
437 bus_space_write_4(sc->sc_bust, sc->sc_bush,
438 GPIO_SET_WAKEUPENA, bit);
439 else
440 bus_space_write_4(sc->sc_bust, sc->sc_bush,
441 GPIO_CLEAR_WAKEUPENA, bit);
444 static int
445 omapgpio_intr(void *arg)
447 struct omapgpio_softc *sc = arg;
448 struct gpio_irq_handler *gh;
449 uint32_t irqs;
450 int idx, handled, s, nattempts;
452 /* Fetch the GPIO interrupts pending. */
453 irqs = bus_space_read_4(sc->sc_bust, sc->sc_bush, GPIO_IRQSTATUS);
454 irqs &= GPIO_REG_MASK;
455 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_IRQSTATUS, irqs);
458 * Since IRQSTATUS can change out from under us while we are busy
459 * servicing everything, keep on doing things until the IRQSTATUS
460 * register is clear.
462 for (nattempts = 0, handled = 0;;) {
464 * Note: Apparently the GPIO block will set the bits in IRQSTATUS if
465 * the level trigger for that pin is set to anything other than NONE
466 * regardless of the IRQENABLE status. Just mask off the ones that we
467 * care about when processing the ISR.
469 irqs &= sc->sc_mask;
470 if (irqs == 0) {
471 /* Pretend that we handled everything. */
472 return (1);
475 for (idx = 0; idx < GPIO_NPINS; idx++, irqs >>= 1) {
476 if ((irqs & 1) == 0)
477 continue;
479 if ((gh = sc->sc_handlers[idx]) == NULL) {
480 printf("%s: unhandled GPIO interrupt. GPIO# %d\n",
481 device_xname(sc->sc_dev), idx);
482 continue;
485 gh->ev.ev_count++;
486 s = _splraise(gh->gh_spl);
487 handled |= (gh->gh_func)(gh->gh_arg);
488 splx(s);
491 /* Check IRQSTATUS again. */
492 irqs = bus_space_read_4(sc->sc_bust, sc->sc_bush, GPIO_IRQSTATUS);
493 irqs &= GPIO_REG_MASK;
494 if (irqs == 0) {
495 /* Done servicing interrupts. */
496 break;
497 } else if (nattempts++ == 10000) {
498 /* TODO: Fix up the # of attempts and this logic after
499 some experimentation. */
501 /* Ensure that we don't get stuck here. */
502 panic("%s: Stuck in GPIO interrupt service routine.",
503 device_xname(sc->sc_dev));
505 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_IRQSTATUS, irqs);
508 return (handled);