pxa2x0_gpio.c revision 1.2 1 /* $NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $ */
2
3 /*
4 * Copyright 2003 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Steve C. Woodford for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $");
40
41 #include "opt_pxa2x0_gpio.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
47
48 #include <machine/intr.h>
49 #include <machine/bus.h>
50
51 #include <arm/xscale/pxa2x0reg.h>
52 #include <arm/xscale/pxa2x0var.h>
53 #include <arm/xscale/pxa2x0_gpio.h>
54
55 #include "locators.h"
56
57 struct gpio_irq_handler {
58 int (*gh_func)(void *);
59 void *gh_arg;
60 int gh_spl;
61 u_int gh_gpio;
62 };
63
64 struct pxagpio_softc {
65 struct device sc_dev;
66 bus_space_tag_t sc_bust;
67 bus_space_handle_t sc_bush;
68 void *sc_irqcookie[3];
69 u_int32_t sc_mask[3];
70 #ifdef PXAGPIO_HAS_GPION_INTRS
71 struct gpio_irq_handler *sc_handlers[GPIO_NPINS];
72 #else
73 struct gpio_irq_handler *sc_handlers[2];
74 #endif
75 };
76
77 static int pxagpio_match(struct device *, struct cfdata *, void *);
78 static void pxagpio_attach(struct device *, struct device *, void *);
79
80 CFATTACH_DECL(pxagpio, sizeof(struct pxagpio_softc),
81 pxagpio_match, pxagpio_attach, NULL, NULL);
82
83 static struct pxagpio_softc *pxagpio_softc;
84 static vaddr_t pxagpio_regs;
85 #define GPIO_BOOTSTRAP_REG(reg) \
86 (*((volatile u_int32_t *)(pxagpio_regs + (reg))))
87
88 static int gpio_intr0(void *);
89 static int gpio_intr1(void *);
90 #ifdef PXAGPIO_HAS_GPION_INTRS
91 static int gpio_dispatch(struct pxagpio_softc *, int);
92 static int gpio_intrN(void *);
93 #endif
94
95 static __inline u_int32_t
96 pxagpio_reg_read(struct pxagpio_softc *sc, int reg)
97 {
98 if (__predict_true(sc != NULL))
99 return (bus_space_read_4(sc->sc_bust, sc->sc_bush, reg));
100 else
101 if (pxagpio_regs)
102 return (GPIO_BOOTSTRAP_REG(reg));
103 panic("pxagpio_reg_read: not bootstrapped");
104 }
105
106 static __inline void
107 pxagpio_reg_write(struct pxagpio_softc *sc, int reg, u_int32_t val)
108 {
109 if (__predict_true(sc != NULL))
110 bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, val);
111 else
112 if (pxagpio_regs)
113 GPIO_BOOTSTRAP_REG(reg) = val;
114 else
115 panic("pxagpio_reg_write: not bootstrapped");
116 return;
117 }
118
119 static int
120 pxagpio_match(struct device *parent, struct cfdata *cf, void *aux)
121 {
122 struct pxaip_attach_args *pxa = aux;
123
124 if (pxagpio_softc != NULL || pxa->pxa_addr != PXA2X0_GPIO_BASE)
125 return (0);
126
127 pxa->pxa_size = PXA2X0_GPIO_SIZE;
128
129 return (1);
130 }
131
132 void
133 pxagpio_attach(struct device *parent, struct device *self, void *aux)
134 {
135 struct pxagpio_softc *sc = (struct pxagpio_softc *)self;
136 struct pxaip_attach_args *pxa = aux;
137
138 sc->sc_bust = pxa->pxa_iot;
139
140 aprint_normal(": GPIO Controller\n");
141
142 if (bus_space_map(sc->sc_bust, pxa->pxa_addr, pxa->pxa_size, 0,
143 &sc->sc_bush)) {
144 aprint_error("%s: Can't map registers!\n", sc->sc_dev.dv_xname);
145 return;
146 }
147
148 memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers));
149
150 /*
151 * Disable all GPIO interrupts
152 */
153 pxagpio_reg_write(sc, GPIO_GRER0, 0);
154 pxagpio_reg_write(sc, GPIO_GRER1, 0);
155 pxagpio_reg_write(sc, GPIO_GRER2, 0);
156 pxagpio_reg_write(sc, GPIO_GFER0, 0);
157 pxagpio_reg_write(sc, GPIO_GFER1, 0);
158 pxagpio_reg_write(sc, GPIO_GFER2, 0);
159 pxagpio_reg_write(sc, GPIO_GEDR0, ~0);
160 pxagpio_reg_write(sc, GPIO_GEDR1, ~0);
161 pxagpio_reg_write(sc, GPIO_GEDR2, ~0);
162
163 #ifdef PXAGPIO_HAS_GPION_INTRS
164 sc->sc_irqcookie[2] = pxa2x0_intr_establish(PXA2X0_INT_GPION, IPL_BIO,
165 gpio_intrN, sc);
166 if (sc->sc_irqcookie[2] == NULL) {
167 aprint_error("%s: failed to hook main GPIO interrupt\n",
168 sc->sc_dev.dv_xname);
169 return;
170 }
171 #endif
172
173 sc->sc_irqcookie[0] = sc->sc_irqcookie[1] = NULL;
174
175 pxagpio_softc = sc;
176 }
177
178 void
179 pxa2x0_gpio_bootstrap(vaddr_t gpio_regs)
180 {
181
182 pxagpio_regs = gpio_regs;
183 }
184
185 void *
186 pxa2x0_gpio_intr_establish(u_int gpio, int level, int spl, int (*func)(void *),
187 void *arg)
188 {
189 struct pxagpio_softc *sc = pxagpio_softc;
190 struct gpio_irq_handler *gh;
191 u_int32_t bit, reg;
192
193 #ifdef DEBUG
194 #ifdef PXAGPIO_HAS_GPION_INTRS
195 if (gpio >= GPIO_NPINS)
196 panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio);
197 #else
198 if (gpio > 1)
199 panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio);
200 #endif
201 #endif
202
203 if (!GPIO_IS_GPIO_IN(pxa2x0_gpio_get_function(gpio)))
204 panic("pxa2x0_gpio_intr_establish: Pin %d not GPIO_IN", gpio);
205
206 switch (level) {
207 case IST_EDGE_FALLING:
208 case IST_EDGE_RISING:
209 case IST_EDGE_BOTH:
210 break;
211
212 default:
213 panic("pxa2x0_gpio_intr_establish: bad level: %d", level);
214 break;
215 }
216
217 if (sc->sc_handlers[gpio] != NULL)
218 panic("pxa2x0_gpio_intr_establish: illegal shared interrupt");
219
220 MALLOC(gh, struct gpio_irq_handler *, sizeof(struct gpio_irq_handler),
221 M_DEVBUF, M_NOWAIT);
222
223 gh->gh_func = func;
224 gh->gh_arg = arg;
225 gh->gh_spl = spl;
226 gh->gh_gpio = gpio;
227 sc->sc_handlers[gpio] = gh;
228
229 if (gpio == 0) {
230 KDASSERT(sc->sc_irqcookie[0] == NULL);
231 sc->sc_irqcookie[0] = pxa2x0_intr_establish(PXA2X0_INT_GPIO0,
232 spl, gpio_intr0, sc);
233 KDASSERT(sc->sc_irqcookie[0]);
234 } else
235 if (gpio == 1) {
236 KDASSERT(sc->sc_irqcookie[1] == NULL);
237 sc->sc_irqcookie[1] = pxa2x0_intr_establish(PXA2X0_INT_GPIO1,
238 spl, gpio_intr1, sc);
239 KDASSERT(sc->sc_irqcookie[1]);
240 }
241
242 bit = GPIO_BIT(gpio);
243 sc->sc_mask[GPIO_BANK(gpio)] |= bit;
244
245 switch (level) {
246 case IST_EDGE_FALLING:
247 reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gpio));
248 pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gpio), reg | bit);
249 break;
250
251 case IST_EDGE_RISING:
252 reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gpio));
253 pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gpio), reg | bit);
254 break;
255
256 case IST_EDGE_BOTH:
257 reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gpio));
258 pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gpio), reg | bit);
259 reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gpio));
260 pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gpio), reg | bit);
261 break;
262 }
263
264 return (gh);
265 }
266
267 void
268 pxa2x0_gpio_intr_disestablish(void *cookie)
269 {
270 struct pxagpio_softc *sc = pxagpio_softc;
271 struct gpio_irq_handler *gh = cookie;
272 u_int32_t bit, reg;
273
274 bit = GPIO_BIT(gh->gh_gpio);
275
276 reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio));
277 reg &= ~bit;
278 pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio), reg);
279 reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio));
280 reg &= ~bit;
281 pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio), reg);
282
283 pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gh->gh_gpio), bit);
284
285 sc->sc_mask[GPIO_BANK(gh->gh_gpio)] &= ~bit;
286 sc->sc_handlers[gh->gh_gpio] = NULL;
287
288 if (gh->gh_gpio == 0) {
289 #if 0
290 pxa2x0_intr_disestablish(sc->sc_irqcookie[0]);
291 sc->sc_irqcookie[0] = NULL;
292 #else
293 panic("pxa2x0_gpio_intr_disestablish: can't unhook GPIO#0");
294 #endif
295 } else
296 if (gh->gh_gpio == 1) {
297 #if 0
298 pxa2x0_intr_disestablish(sc->sc_irqcookie[1]);
299 sc->sc_irqcookie[0] = NULL;
300 #else
301 panic("pxa2x0_gpio_intr_disestablish: can't unhook GPIO#0");
302 #endif
303 }
304
305 FREE(gh, M_DEVBUF);
306 }
307
308 static int
309 gpio_intr0(void *arg)
310 {
311 struct pxagpio_softc *sc = arg;
312
313 #ifdef DIAGNOSTIC
314 if (sc->sc_handlers[0] == NULL) {
315 printf("%s: stray GPIO#0 edge interrupt\n",
316 sc->sc_dev.dv_xname);
317 return (0);
318 }
319 #endif
320
321 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 0),
322 GPIO_BIT(0));
323
324 return ((sc->sc_handlers[0]->gh_func)(sc->sc_handlers[0]->gh_arg));
325 }
326
327 static int
328 gpio_intr1(void *arg)
329 {
330 struct pxagpio_softc *sc = arg;
331
332 #ifdef DIAGNOSTIC
333 if (sc->sc_handlers[1] == NULL) {
334 printf("%s: stray GPIO#1 edge interrupt\n",
335 sc->sc_dev.dv_xname);
336 return (0);
337 }
338 #endif
339
340 bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 1),
341 GPIO_BIT(1));
342
343 return ((sc->sc_handlers[1]->gh_func)(sc->sc_handlers[1]->gh_arg));
344 }
345
346 #ifdef PXAGPIO_HAS_GPION_INTRS
347 static int
348 gpio_dispatch(struct pxagpio_softc *sc, int gpio_base)
349 {
350 struct gpio_irq_handler **ghp, *gh;
351 int i, s, handled, pins;
352 u_int32_t gedr, mask;
353 int bank;
354
355 /* Fetch bitmap of pending interrupts on this GPIO bank */
356 gedr = pxagpio_reg_read(sc, GPIO_REG(GPIO_GEDR0, gpio_base));
357
358 /* Don't handle GPIO 0/1 here */
359 if (gpio_base == 0)
360 gedr &= ~(GPIO_BIT(0) | GPIO_BIT(1));
361
362 /* Bail early if there are no pending interrupts in this bank */
363 if (gedr == 0)
364 return (0);
365
366 /* Acknowledge pending interrupts. */
367 pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gpio_base), gedr);
368
369 bank = GPIO_BANK(gpio_base);
370
371 /*
372 * We're only interested in those for which we have a handler
373 * registered
374 */
375 #ifdef DEBUG
376 if ((gedr & sc->sc_mask[bank]) == 0) {
377 printf("%s: stray GPIO interrupt. Bank %d, GEDR 0x%08x, mask 0x%08x\n",
378 sc->sc_dev.dv_xname, bank, gedr, sc->sc_mask[bank]);
379 return (1); /* XXX: Pretend we dealt with it */
380 }
381 #endif
382
383 gedr &= sc->sc_mask[bank];
384 ghp = &sc->sc_handlers[gpio_base];
385 pins = (gpio_base < 64) ? 32 : 17;
386 handled = 0;
387
388 for (i = 0, mask = 1; i < pins && gedr; i++, ghp++, mask <<= 1) {
389 if ((gedr & mask) == 0)
390 continue;
391 gedr &= ~mask;
392
393 if ((gh = *ghp) == NULL) {
394 printf("%s: unhandled GPIO interrupt. GPIO#%d\n",
395 sc->sc_dev.dv_xname, gpio_base + i);
396 continue;
397 }
398
399 s = _splraise(gh->gh_spl);
400 handled |= (gh->gh_func)(gh->gh_arg);
401 splx(s);
402 }
403
404 return (handled);
405 }
406
407 static int
408 gpio_intrN(void *arg)
409 {
410 struct pxagpio_softc *sc = arg;
411 int handled;
412
413 handled = gpio_dispatch(sc, 0);
414 handled |= gpio_dispatch(sc, 32);
415 handled |= gpio_dispatch(sc, 64);
416
417 return (handled);
418 }
419 #endif /* PXAGPIO_HAS_GPION_INTRS */
420
421 u_int
422 pxa2x0_gpio_get_function(u_int gpio)
423 {
424 struct pxagpio_softc *sc = pxagpio_softc;
425 u_int32_t rv, io;
426
427 KDASSERT(gpio < GPIO_NPINS);
428
429 rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
430 rv = GPIO_FN(rv);
431
432 io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio));
433 if (io & GPIO_BIT(gpio))
434 rv |= GPIO_OUT;
435
436 io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPLR0, gpio));
437 if (io & GPIO_BIT(gpio))
438 rv |= GPIO_SET;
439
440 return (rv);
441 }
442
443 u_int
444 pxa2x0_gpio_set_function(u_int gpio, u_int fn)
445 {
446 struct pxagpio_softc *sc = pxagpio_softc;
447 u_int32_t rv, bit;
448 u_int oldfn;
449
450 KDASSERT(gpio < GPIO_NPINS);
451
452 oldfn = pxa2x0_gpio_get_function(gpio);
453
454 if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
455 GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
456 /*
457 * The pin's function is not changing.
458 * For Alternate Functions and GPIO input, we can just
459 * return now.
460 * For GPIO output pins, check the initial state is
461 * the same.
462 *
463 * Return 'fn' instead of 'oldfn' so the caller can
464 * reliably detect that we didn't change anything.
465 * (The initial state might be different for non-
466 * GPIO output pins).
467 */
468 if (!GPIO_IS_GPIO_OUT(fn) ||
469 GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
470 return (fn);
471 }
472
473 /*
474 * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
475 * the correct procedure for changing GPIO pin functions.
476 */
477
478 bit = GPIO_BIT(gpio);
479
480 /*
481 * 1. Configure the correct set/clear state of the pin
482 */
483 if (GPIO_FN_IS_SET(fn))
484 pxagpio_reg_write(sc, GPIO_REG(GPIO_GPSR0, gpio), bit);
485 else
486 pxagpio_reg_write(sc, GPIO_REG(GPIO_GPCR0, gpio), bit);
487
488 /*
489 * 2. Configure the pin as an input or output as appropriate
490 */
491 rv = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
492 if (GPIO_FN_IS_OUT(fn))
493 rv |= bit;
494 pxagpio_reg_write(sc, GPIO_REG(GPIO_GPDR0, gpio), rv);
495
496 /*
497 * 3. Configure the pin's function
498 */
499 bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
500 fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
501 rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
502 pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
503
504 return (oldfn);
505 }
506