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