initial commit, pull in sys/arch/armv7/omap
[bbb-pru.git] / omgpio.c
... / ...
CommitLineData
1/* $OpenBSD: omgpio.c,v 1.6 2016/01/31 00:14:50 jsg Exp $ */
2/*
3 * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/param.h>
19#include <sys/systm.h>
20#include <sys/queue.h>
21#include <sys/device.h>
22#include <sys/malloc.h>
23#include <sys/evcount.h>
24#include <sys/gpio.h>
25
26#include <arm/cpufunc.h>
27
28#include <machine/bus.h>
29#include <machine/intr.h>
30
31#include <dev/gpio/gpiovar.h>
32
33#include <armv7/armv7/armv7var.h>
34#include <armv7/omap/prcmvar.h>
35#include <armv7/omap/sitara_cm.h>
36#include <armv7/omap/omgpiovar.h>
37
38#include "gpio.h"
39
40/* OMAP3 registers */
41#define GPIO3_REVISION 0x00
42#define GPIO3_SYSCONFIG 0x10
43#define GPIO3_SYSSTATUS 0x14
44#define GPIO3_IRQSTATUS1 0x18
45#define GPIO3_IRQENABLE1 0x1C
46#define GPIO3_WAKEUPENABLE 0x20
47#define GPIO3_IRQSTATUS2 0x28
48#define GPIO3_IRQENABLE2 0x2C
49#define GPIO3_CTRL 0x30
50#define GPIO3_OE 0x34
51#define GPIO3_DATAIN 0x38
52#define GPIO3_DATAOUT 0x3C
53#define GPIO3_LEVELDETECT0 0x40
54#define GPIO3_LEVELDETECT1 0x44
55#define GPIO3_RISINGDETECT 0x48
56#define GPIO3_FALLINGDETECT 0x4C
57#define GPIO3_DEBOUNCENABLE 0x50
58#define GPIO3_DEBOUNCINGTIME 0x54
59#define GPIO3_CLEARIRQENABLE1 0x60
60#define GPIO3_SETIRQENABLE1 0x64
61#define GPIO3_CLEARIRQENABLE2 0x70
62#define GPIO3_SETIRQENABLE2 0x74
63#define GPIO3_CLEARWKUENA 0x80
64#define GPIO3_SETWKUENA 0x84
65#define GPIO3_CLEARDATAOUT 0x90
66#define GPIO3_SETDATAOUT 0x94
67
68/* OMAP4 registers */
69#define GPIO4_REVISION 0x00
70#define GPIO4_SYSCONFIG 0x10
71#define GPIO4_IRQSTATUS_RAW_0 0x24
72#define GPIO4_IRQSTATUS_RAW_1 0x28
73#define GPIO4_IRQSTATUS_0 0x2C
74#define GPIO4_IRQSTATUS_1 0x30
75#define GPIO4_IRQSTATUS_SET_0 0x34
76#define GPIO4_IRQSTATUS_SET_1 0x38
77#define GPIO4_IRQSTATUS_CLR_0 0x3C
78#define GPIO4_IRQSTATUS_CLR_1 0x40
79#define GPIO4_IRQWAKEN_0 0x44
80#define GPIO4_IRQWAKEN_1 0x48
81#define GPIO4_SYSSTATUS 0x114
82#define GPIO4_WAKEUPENABLE 0x120
83#define GPIO4_CTRL 0x130
84#define GPIO4_OE 0x134
85#define GPIO4_DATAIN 0x138
86#define GPIO4_DATAOUT 0x13C
87#define GPIO4_LEVELDETECT0 0x140
88#define GPIO4_LEVELDETECT1 0x144
89#define GPIO4_RISINGDETECT 0x148
90#define GPIO4_FALLINGDETECT 0x14C
91#define GPIO4_DEBOUNCENABLE 0x150
92#define GPIO4_DEBOUNCINGTIME 0x154
93#define GPIO4_CLEARWKUPENA 0x180
94#define GPIO4_SETWKUENA 0x184
95#define GPIO4_CLEARDATAOUT 0x190
96#define GPIO4_SETDATAOUT 0x194
97
98/* AM335X registers */
99#define GPIO_AM335X_REVISION 0x00
100#define GPIO_AM335X_SYSCONFIG 0x10
101#define GPIO_AM335X_IRQSTATUS_RAW_0 0x24
102#define GPIO_AM335X_IRQSTATUS_RAW_1 0x28
103#define GPIO_AM335X_IRQSTATUS_0 0x2C
104#define GPIO_AM335X_IRQSTATUS_1 0x30
105#define GPIO_AM335X_IRQSTATUS_SET_0 0x34
106#define GPIO_AM335X_IRQSTATUS_SET_1 0x38
107#define GPIO_AM335X_IRQSTATUS_CLR_0 0x3c
108#define GPIO_AM335X_IRQSTATUS_CLR_1 0x40
109#define GPIO_AM335X_IRQWAKEN_0 0x44
110#define GPIO_AM335X_IRQWAKEN_1 0x48
111#define GPIO_AM335X_SYSSTATUS 0x114
112#define GPIO_AM335X_CTRL 0x130
113#define GPIO_AM335X_OE 0x134
114#define GPIO_AM335X_DATAIN 0x138
115#define GPIO_AM335X_DATAOUT 0x13C
116#define GPIO_AM335X_LEVELDETECT0 0x140
117#define GPIO_AM335X_LEVELDETECT1 0x144
118#define GPIO_AM335X_RISINGDETECT 0x148
119#define GPIO_AM335X_FALLINGDETECT 0x14C
120#define GPIO_AM335X_DEBOUNCENABLE 0x150
121#define GPIO_AM335X_DEBOUNCINGTIME 0x154
122#define GPIO_AM335X_CLEARDATAOUT 0x190
123#define GPIO_AM335X_SETDATAOUT 0x194
124
125#define GPIO_NUM_PINS 32
126
127struct intrhand {
128 int (*ih_func)(void *); /* handler */
129 void *ih_arg; /* arg for handler */
130 int ih_ipl; /* IPL_* */
131 int ih_irq; /* IRQ number */
132 int ih_gpio; /* gpio pin */
133 struct evcount ih_count;
134 char *ih_name;
135};
136
137struct omgpio_regs {
138 u_int32_t revision;
139 u_int32_t sysconfig;
140 u_int32_t irqstatus_raw0; /* omap4/am335x only */
141 u_int32_t irqstatus_raw1; /* omap4/am335x only */
142 u_int32_t irqstatus0;
143 u_int32_t irqstatus1;
144 u_int32_t irqstatus_set0;
145 u_int32_t irqstatus_set1;
146 u_int32_t irqstatus_clear0;
147 u_int32_t irqstatus_clear1;
148 u_int32_t irqwaken0;
149 u_int32_t irqwaken1;
150 u_int32_t sysstatus;
151 u_int32_t wakeupenable; /* omap3/omap4 only */
152 u_int32_t ctrl;
153 u_int32_t oe;
154 u_int32_t datain;
155 u_int32_t dataout;
156 u_int32_t leveldetect0;
157 u_int32_t leveldetect1;
158 u_int32_t risingdetect;
159 u_int32_t fallingdetect;
160 u_int32_t debounceenable;
161 u_int32_t debouncingtime;
162 u_int32_t clearwkupena; /* omap3/omap4 only */
163 u_int32_t setwkupena; /* omap3/omap4 only */
164 u_int32_t cleardataout;
165 u_int32_t setdataout;
166};
167
168struct omgpio_softc {
169 struct device sc_dev;
170 bus_space_tag_t sc_iot;
171 bus_space_handle_t sc_ioh;
172 void *sc_ih_h;
173 void *sc_ih_l;
174 int sc_max_il;
175 int sc_min_il;
176 int sc_irq;
177 struct intrhand *sc_handlers[GPIO_NUM_PINS];
178 int sc_omap_ver;
179 struct gpio_chipset_tag sc_gpio_gc;
180 gpio_pin_t sc_gpio_pins[GPIO_NUM_PINS];
181 struct omgpio_regs sc_regs;
182};
183
184#define GPIO_PIN_TO_INST(x) ((x) >> 5)
185#define GPIO_PIN_TO_OFFSET(x) ((x) & 0x1f)
186#define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
187#define READ4(sc, reg) omgpio_read4(sc, reg)
188#define WRITE4(sc, reg, val) omgpio_write4(sc, reg, val)
189
190u_int32_t omgpio_read4(struct omgpio_softc *, u_int32_t);
191void omgpio_write4(struct omgpio_softc *, u_int32_t, u_int32_t);
192int omgpio_match(struct device *, void *, void *);
193void omgpio_attach(struct device *, struct device *, void *);
194void omgpio_recalc_interrupts(struct omgpio_softc *);
195int omgpio_irq(void *);
196int omgpio_irq_dummy(void *);
197int omgpio_pin_dir_read(struct omgpio_softc *, unsigned int);
198void omgpio_pin_dir_write(struct omgpio_softc *, unsigned int, unsigned int);
199
200struct cfattach omgpio_ca = {
201 sizeof (struct omgpio_softc), omgpio_match, omgpio_attach
202};
203
204struct cfdriver omgpio_cd = {
205 NULL, "omgpio", DV_DULL
206};
207
208u_int32_t
209omgpio_read4(struct omgpio_softc *sc, u_int32_t reg)
210{
211 if(reg == -1)
212 panic("%s: Invalid register address", DEVNAME(sc));
213
214 return bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg));
215}
216
217void
218omgpio_write4(struct omgpio_softc *sc, u_int32_t reg, u_int32_t val)
219{
220 if(reg == -1)
221 panic("%s: Invalid register address", DEVNAME(sc));
222
223 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val));
224}
225
226int
227omgpio_match(struct device *parent, void *v, void *aux)
228{
229 switch (board_id) {
230 case BOARD_ID_OMAP3_BEAGLE:
231 case BOARD_ID_OMAP3_OVERO:
232 case BOARD_ID_AM335X_BEAGLEBONE:
233 case BOARD_ID_OMAP4_PANDA:
234 break; /* continue trying */
235 default:
236 return 0; /* unknown */
237 }
238 return (1);
239}
240
241void
242omgpio_attach(struct device *parent, struct device *self, void *args)
243{
244 struct armv7_attach_args *aa = args;
245 struct omgpio_softc *sc = (struct omgpio_softc *) self;
246 struct gpiobus_attach_args gba;
247 u_int32_t rev;
248 int i;
249
250 prcm_enablemodule(PRCM_GPIO0 + aa->aa_dev->unit);
251
252 sc->sc_iot = aa->aa_iot;
253 if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
254 aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
255 panic("%s: bus_space_map failed!", DEVNAME(sc));
256
257 switch (board_id) {
258 case BOARD_ID_OMAP3_BEAGLE:
259 case BOARD_ID_OMAP3_OVERO:
260 sc->sc_regs.revision = GPIO3_REVISION;
261 sc->sc_regs.sysconfig = GPIO3_SYSCONFIG;
262 sc->sc_regs.irqstatus_raw0 = -1;
263 sc->sc_regs.irqstatus_raw1 = -1;
264 sc->sc_regs.irqstatus0 = GPIO3_IRQSTATUS1;
265 sc->sc_regs.irqstatus1 = GPIO3_IRQSTATUS2;
266 sc->sc_regs.irqstatus_set0 = GPIO3_SETIRQENABLE1;
267 sc->sc_regs.irqstatus_set1 = GPIO3_SETIRQENABLE2;
268 sc->sc_regs.irqstatus_clear0 = GPIO3_CLEARIRQENABLE1;
269 sc->sc_regs.irqstatus_clear1 = GPIO3_CLEARIRQENABLE2;
270 sc->sc_regs.irqwaken0 = -1;
271 sc->sc_regs.irqwaken1 = -1;
272 sc->sc_regs.sysstatus = GPIO3_SYSSTATUS;
273 sc->sc_regs.wakeupenable = GPIO3_WAKEUPENABLE;
274 sc->sc_regs.ctrl = GPIO3_CTRL;
275 sc->sc_regs.oe = GPIO3_OE;
276 sc->sc_regs.datain = GPIO3_DATAIN;
277 sc->sc_regs.dataout = GPIO3_DATAOUT;
278 sc->sc_regs.leveldetect0 = GPIO3_LEVELDETECT0;
279 sc->sc_regs.leveldetect1 = GPIO3_LEVELDETECT1;
280 sc->sc_regs.risingdetect = GPIO3_RISINGDETECT;
281 sc->sc_regs.fallingdetect = GPIO3_FALLINGDETECT;
282 sc->sc_regs.debounceenable = GPIO3_DEBOUNCENABLE;
283 sc->sc_regs.debouncingtime = GPIO3_DEBOUNCINGTIME;
284 sc->sc_regs.clearwkupena = GPIO3_CLEARWKUENA;
285 sc->sc_regs.setwkupena = GPIO3_SETWKUENA;
286 sc->sc_regs.cleardataout = GPIO3_CLEARDATAOUT;
287 sc->sc_regs.setdataout = GPIO3_SETDATAOUT;
288 break;
289 case BOARD_ID_OMAP4_PANDA:
290 sc->sc_regs.revision = GPIO4_REVISION;
291 sc->sc_regs.sysconfig = GPIO4_SYSCONFIG;
292 sc->sc_regs.irqstatus_raw0 = GPIO4_IRQSTATUS_RAW_0;
293 sc->sc_regs.irqstatus_raw1 = GPIO4_IRQSTATUS_RAW_1;
294 sc->sc_regs.irqstatus0 = GPIO4_IRQSTATUS_0;
295 sc->sc_regs.irqstatus1 = GPIO4_IRQSTATUS_1;
296 sc->sc_regs.irqstatus_set0 = GPIO4_IRQSTATUS_SET_0;
297 sc->sc_regs.irqstatus_set1 = GPIO4_IRQSTATUS_SET_1;
298 sc->sc_regs.irqstatus_clear0 = GPIO4_IRQSTATUS_CLR_0;
299 sc->sc_regs.irqstatus_clear1 = GPIO4_IRQSTATUS_CLR_1;
300 sc->sc_regs.irqwaken0 = GPIO4_IRQWAKEN_0;
301 sc->sc_regs.irqwaken1 = GPIO4_IRQWAKEN_1;
302 sc->sc_regs.sysstatus = GPIO4_SYSSTATUS;
303 sc->sc_regs.wakeupenable = GPIO4_WAKEUPENABLE;
304 sc->sc_regs.ctrl = GPIO4_CTRL;
305 sc->sc_regs.oe = GPIO4_OE;
306 sc->sc_regs.datain = GPIO4_DATAIN;
307 sc->sc_regs.dataout = GPIO4_DATAOUT;
308 sc->sc_regs.leveldetect0 = GPIO4_LEVELDETECT0;
309 sc->sc_regs.leveldetect1 = GPIO4_LEVELDETECT1;
310 sc->sc_regs.risingdetect = GPIO4_RISINGDETECT;
311 sc->sc_regs.fallingdetect = GPIO4_FALLINGDETECT;
312 sc->sc_regs.debounceenable = GPIO4_DEBOUNCENABLE;
313 sc->sc_regs.debouncingtime = GPIO4_DEBOUNCINGTIME;
314 sc->sc_regs.clearwkupena = GPIO4_CLEARWKUPENA;
315 sc->sc_regs.setwkupena = GPIO4_SETWKUENA;
316 sc->sc_regs.cleardataout = GPIO4_CLEARDATAOUT;
317 sc->sc_regs.setdataout = GPIO4_SETDATAOUT;
318 break;
319 case BOARD_ID_AM335X_BEAGLEBONE:
320 sc->sc_regs.revision = GPIO_AM335X_REVISION;
321 sc->sc_regs.sysconfig = GPIO_AM335X_SYSCONFIG;
322 sc->sc_regs.irqstatus_raw0 = GPIO_AM335X_IRQSTATUS_RAW_0;
323 sc->sc_regs.irqstatus_raw1 = GPIO_AM335X_IRQSTATUS_RAW_1;
324 sc->sc_regs.irqstatus0 = GPIO_AM335X_IRQSTATUS_0;
325 sc->sc_regs.irqstatus1 = GPIO_AM335X_IRQSTATUS_1;
326 sc->sc_regs.irqstatus_set0 = GPIO_AM335X_IRQSTATUS_SET_0;
327 sc->sc_regs.irqstatus_set1 = GPIO_AM335X_IRQSTATUS_SET_1;
328 sc->sc_regs.irqstatus_clear0 = GPIO_AM335X_IRQSTATUS_CLR_0;
329 sc->sc_regs.irqstatus_clear1 = GPIO_AM335X_IRQSTATUS_CLR_1;
330 sc->sc_regs.irqwaken0 = GPIO_AM335X_IRQWAKEN_0;
331 sc->sc_regs.irqwaken1 = GPIO_AM335X_IRQWAKEN_1;
332 sc->sc_regs.sysstatus = GPIO_AM335X_SYSSTATUS;
333 sc->sc_regs.wakeupenable = -1;
334 sc->sc_regs.ctrl = GPIO_AM335X_CTRL;
335 sc->sc_regs.oe = GPIO_AM335X_OE;
336 sc->sc_regs.datain = GPIO_AM335X_DATAIN;
337 sc->sc_regs.dataout = GPIO_AM335X_DATAOUT;
338 sc->sc_regs.leveldetect0 = GPIO_AM335X_LEVELDETECT0;
339 sc->sc_regs.leveldetect1 = GPIO_AM335X_LEVELDETECT1;
340 sc->sc_regs.risingdetect = GPIO_AM335X_RISINGDETECT;
341 sc->sc_regs.fallingdetect = GPIO_AM335X_FALLINGDETECT;
342 sc->sc_regs.debounceenable = GPIO_AM335X_DEBOUNCENABLE;
343 sc->sc_regs.debouncingtime = GPIO_AM335X_DEBOUNCINGTIME;
344 sc->sc_regs.clearwkupena = -1;
345 sc->sc_regs.setwkupena = -1;
346 sc->sc_regs.cleardataout = GPIO_AM335X_CLEARDATAOUT;
347 sc->sc_regs.setdataout = GPIO_AM335X_SETDATAOUT;
348 break;
349 }
350
351 rev = READ4(sc, sc->sc_regs.revision);
352
353 printf(": rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
354
355 sc->sc_irq = aa->aa_dev->irq[0];
356
357 WRITE4(sc, sc->sc_regs.irqstatus_clear0, ~0);
358 WRITE4(sc, sc->sc_regs.irqstatus_clear1, ~0);
359
360 /* XXX - SYSCONFIG */
361 /* XXX - CTRL */
362 /* XXX - DEBOUNCE */
363
364 for (i = 0; i < GPIO_NUM_PINS; i++) {
365 sc->sc_gpio_pins[i].pin_num = i;
366 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
367 GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
368 sc->sc_gpio_pins[i].pin_state = omgpio_pin_read(sc, i) ?
369 GPIO_PIN_HIGH : GPIO_PIN_LOW;
370 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_SET;
371 }
372
373 sc->sc_gpio_gc.gp_cookie = sc;
374 sc->sc_gpio_gc.gp_pin_read = omgpio_pin_read;
375 sc->sc_gpio_gc.gp_pin_write = omgpio_pin_write;
376 sc->sc_gpio_gc.gp_pin_ctl = omgpio_pin_ctl;
377
378 gba.gba_name = "gpio";
379 gba.gba_gc = &sc->sc_gpio_gc;
380 gba.gba_pins = sc->sc_gpio_pins;
381 gba.gba_npins = GPIO_NUM_PINS;
382
383#if NGPIO > 0
384 config_found(&sc->sc_dev, &gba, gpiobus_print);
385#endif
386}
387
388/* XXX - This assumes MCU INTERRUPTS are IRQ1, and DSP are IRQ2 */
389
390#if 0
391/* XXX - FIND THESE REGISTERS !!! */
392unsigned int
393omgpio_get_function(unsigned int gpio, unsigned int fn)
394{
395 return 0;
396}
397
398void
399omgpio_set_function(unsigned int gpio, unsigned int fn)
400{
401}
402#endif
403
404unsigned int
405omgpio_get_bit(unsigned int gpio)
406{
407 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
408
409 return omgpio_pin_read(sc, GPIO_PIN_TO_OFFSET(gpio));
410}
411
412void
413omgpio_set_bit(unsigned int gpio)
414{
415 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
416
417 omgpio_pin_write(sc, GPIO_PIN_TO_OFFSET(gpio), GPIO_PIN_HIGH);
418}
419
420void
421omgpio_clear_bit(unsigned int gpio)
422{
423 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
424
425 omgpio_pin_write(sc, GPIO_PIN_TO_OFFSET(gpio), GPIO_PIN_LOW);
426}
427
428void
429omgpio_set_dir(unsigned int gpio, unsigned int dir)
430{
431 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
432
433 omgpio_pin_dir_write(sc, GPIO_PIN_TO_OFFSET(gpio), dir);
434}
435
436int
437omgpio_pin_read(void *arg, int pin)
438{
439 struct omgpio_softc *sc = arg;
440 u_int32_t reg;
441
442 if(omgpio_pin_dir_read(sc, pin) == OMGPIO_DIR_IN)
443 reg = READ4(sc, sc->sc_regs.datain);
444 else
445 reg = READ4(sc, sc->sc_regs.dataout);
446 return (reg >> GPIO_PIN_TO_OFFSET(pin)) & 0x1;
447}
448
449void
450omgpio_pin_write(void *arg, int pin, int value)
451{
452 struct omgpio_softc *sc = arg;
453
454 if (value)
455 WRITE4(sc, sc->sc_regs.setdataout,
456 1 << GPIO_PIN_TO_OFFSET(pin));
457 else
458 WRITE4(sc, sc->sc_regs.cleardataout,
459 1 << GPIO_PIN_TO_OFFSET(pin));
460}
461
462void
463omgpio_pin_ctl(void *arg, int pin, int flags)
464{
465 struct omgpio_softc *sc = arg;
466
467 if (flags & GPIO_PIN_INPUT)
468 omgpio_pin_dir_write(sc, pin, OMGPIO_DIR_IN);
469 else if (flags & GPIO_PIN_OUTPUT)
470 omgpio_pin_dir_write(sc, pin, OMGPIO_DIR_OUT);
471
472 if (board_id == BOARD_ID_AM335X_BEAGLEBONE)
473 sitara_cm_padconf_set_gpioflags(
474 sc->sc_dev.dv_unit * GPIO_NUM_PINS + pin, flags);
475}
476
477void
478omgpio_pin_dir_write(struct omgpio_softc *sc, unsigned int gpio,
479 unsigned int dir)
480{
481 int s;
482 u_int32_t reg;
483
484 s = splhigh();
485
486 reg = READ4(sc, sc->sc_regs.oe);
487 if (dir == OMGPIO_DIR_IN)
488 reg |= 1 << GPIO_PIN_TO_OFFSET(gpio);
489 else
490 reg &= ~(1 << GPIO_PIN_TO_OFFSET(gpio));
491 WRITE4(sc, sc->sc_regs.oe, reg);
492
493 splx(s);
494}
495
496int
497omgpio_pin_dir_read(struct omgpio_softc *sc, unsigned int gpio)
498{
499 u_int32_t reg;
500 reg = READ4(sc, sc->sc_regs.oe);
501 if (reg & (1 << GPIO_PIN_TO_OFFSET(gpio)))
502 return OMGPIO_DIR_IN;
503 else
504 return OMGPIO_DIR_OUT;
505}
506
507#if 0
508void
509omgpio_clear_intr(struct omgpio_softc *sc, unsigned int gpio)
510{
511 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
512
513 WRITE4(sc, sc->sc_regs.irqstatus0, 1 << GPIO_PIN_TO_OFFSET(gpio));
514}
515
516void
517omgpio_intr_mask(struct omgpio_softc *sc, unsigned int gpio)
518{
519 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
520
521 WRITE4(sc, sc->sc_regs.irqstatus_clear0, 1 << GPIO_PIN_TO_OFFSET(gpio));
522}
523
524void
525omgpio_intr_unmask(struct omgpio_softc *sc, unsigned int gpio)
526{
527 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
528
529 WRITE4(sc, sc->sc_regs.irqstatus_set0, 1 << GPIO_PIN_TO_OFFSET(gpio));
530}
531
532void
533omgpio_intr_level(struct omgpio_softc *sc, unsigned int gpio, unsigned int level)
534{
535 u_int32_t fe, re, l0, l1, bit;
536 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
537 int s;
538
539 s = splhigh();
540
541 fe = READ4(sc, sc->sc_regs.fallingdetect);
542 re = READ4(sc, sc->sc_regs.risingdetect);
543 l0 = READ4(sc, sc->sc_regs.leveldetect0);
544 l1 = READ4(sc, sc->sc_regs.leveldetect1);
545
546 bit = 1 << GPIO_PIN_TO_OFFSET(gpio);
547
548 switch (level) {
549 case IST_NONE:
550 fe &= ~bit;
551 re &= ~bit;
552 l0 &= ~bit;
553 l1 &= ~bit;
554 break;
555 case IST_EDGE_FALLING:
556 fe |= bit;
557 re &= ~bit;
558 l0 &= ~bit;
559 l1 &= ~bit;
560 break;
561 case IST_EDGE_RISING:
562 fe &= ~bit;
563 re |= bit;
564 l0 &= ~bit;
565 l1 &= ~bit;
566 break;
567 case IST_PULSE: /* XXX */
568 /* FALLTHRU */
569 case IST_EDGE_BOTH:
570 fe |= bit;
571 re |= bit;
572 l0 &= ~bit;
573 l1 &= ~bit;
574 break;
575 case IST_LEVEL_LOW:
576 fe &= ~bit;
577 re &= ~bit;
578 l0 |= bit;
579 l1 &= ~bit;
580 break;
581 case IST_LEVEL_HIGH:
582 fe &= ~bit;
583 re &= ~bit;
584 l0 &= ~bit;
585 l1 |= bit;
586 break;
587 default:
588 panic("omgpio_intr_level: bad level: %d", level);
589 break;
590 }
591
592 WRITE4(sc, sc->sc_regs.fallingdetect, fe);
593 WRITE4(sc, sc->sc_regs.risingdetect, re);
594 WRITE4(sc, sc->sc_regs.leveldetect0, l0);
595 WRITE4(sc, sc->sc_regs.leveldetect1, l1);
596
597 splx(s);
598}
599
600void *
601omgpio_intr_establish(struct omgpio_softc *sc, unsigned int gpio, int level, int spl,
602 int (*func)(void *), void *arg, char *name)
603{
604 int psw;
605 struct intrhand *ih;
606 struct omgpio_softc *sc;
607
608 /*
609 * XXX - is gpio here the pin or the interrupt number
610 * which is 96 + gpio pin?
611 */
612
613 if (GPIO_PIN_TO_INST(gpio) > omgpio_cd.cd_ndevs)
614 panic("omgpio_intr_establish: bogus irqnumber %d: %s",
615 gpio, name);
616
617 sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
618
619 if (sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] != NULL)
620 panic("omgpio_intr_establish: gpio pin busy %d old %s new %s",
621 gpio, sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)]->ih_name,
622 name);
623
624 psw = disable_interrupts(PSR_I);
625
626 /* no point in sleeping unless someone can free memory. */
627 ih = (struct intrhand *)malloc( sizeof *ih, M_DEVBUF,
628 cold ? M_NOWAIT : M_WAITOK);
629 if (ih == NULL)
630 panic("intr_establish: can't malloc handler info");
631 ih->ih_func = func;
632 ih->ih_arg = arg;
633 ih->ih_ipl = level;
634 ih->ih_gpio = gpio;
635 ih->ih_irq = gpio + 512;
636 ih->ih_name = name;
637
638 sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] = ih;
639
640 evcount_attach(&ih->ih_count, name, &ih->ih_irq);
641
642 omgpio_intr_level(gpio, level);
643 omgpio_intr_unmask(gpio);
644
645 omgpio_recalc_interrupts(sc);
646
647 restore_interrupts(psw);
648
649 return (ih);
650}
651
652void
653omgpio_intr_disestablish(struct omgpio_softc *sc, void *cookie)
654{
655 int psw;
656 struct intrhand *ih = cookie;
657 struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(ih->ih_gpio)];
658 int gpio = ih->ih_gpio;
659 psw = disable_interrupts(PSR_I);
660
661 ih = sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)];
662 sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] = NULL;
663
664 evcount_detach(&ih->ih_count);
665
666 free(ih, M_DEVBUF, 0);
667
668 omgpio_intr_level(gpio, IST_NONE);
669 omgpio_intr_mask(gpio);
670 omgpio_clear_intr(gpio); /* Just in case */
671
672 omgpio_recalc_interrupts(sc);
673
674 restore_interrupts(psw);
675}
676
677int
678omgpio_irq(void *v)
679{
680 struct omgpio_softc *sc = v;
681 u_int32_t pending;
682 struct intrhand *ih;
683 int bit;
684
685 pending = READ4(sc, omgpio.irqstatus0);
686
687 while (pending != 0) {
688 bit = ffs(pending) - 1;
689 ih = sc->sc_handlers[bit];
690
691 if (ih != NULL) {
692 if (ih->ih_func(ih->ih_arg))
693 ih->ih_count.ec_count++;
694 omgpio_clear_intr(ih->ih_gpio);
695 } else {
696 panic("omgpio: irq fired no handler, gpio %x %x %x",
697 sc->sc_dev.dv_unit * 32 + bit, pending,
698 READ4(sc, omgpio.irqstatus0)
699
700 );
701 }
702 pending &= ~(1 << bit);
703 }
704 return 1;
705}
706
707int
708omgpio_irq_dummy(void *v)
709{
710 return 0;
711}
712
713void
714omgpio_recalc_interrupts(struct omgpio_softc *sc)
715{
716 struct intrhand *ih;
717 int max = IPL_NONE;
718 int min = IPL_HIGH;
719 int i;
720
721 for (i = 0; i < GPIO_NUM_PINS; i++) {
722 ih = sc->sc_handlers[i];
723 if (ih != NULL) {
724 if (ih->ih_ipl > max)
725 max = ih->ih_ipl;
726
727 if (ih->ih_ipl < min)
728 min = ih->ih_ipl;
729 }
730 }
731 if (max == IPL_NONE)
732 min = IPL_NONE;
733
734#if 0
735 if ((max == IPL_NONE || max != sc->sc_max_il) && sc->sc_ih_h != NULL)
736 arm_intr_disestablish(sc->sc_ih_h);
737
738 if (max != IPL_NONE && max != sc->sc_max_il) {
739 sc->sc_ih_h = arm_intr_establish(sc->sc_irq, max, omgpio_irq,
740 sc, NULL);
741 }
742#else
743 if (sc->sc_ih_h != NULL)
744 arm_intr_disestablish(sc->sc_ih_h);
745
746 if (max != IPL_NONE) {
747 sc->sc_ih_h = arm_intr_establish(sc->sc_irq, max, omgpio_irq,
748 sc, NULL);
749 }
750#endif
751
752 sc->sc_max_il = max;
753
754 if (sc->sc_ih_l != NULL)
755 arm_intr_disestablish(sc->sc_ih_l);
756
757 if (max != min) {
758 sc->sc_ih_h = arm_intr_establish(sc->sc_irq, min,
759 omgpio_irq_dummy, sc, NULL);
760 }
761 sc->sc_min_il = min;
762}
763#endif