1 /* $OpenBSD: rkgpio.c,v 1.11 2023/07/10 13:48:02 patrick Exp $ */
2 /*
3 * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
4 * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/malloc.h>
23 #include <sys/evcount.h>
24
25 #include <machine/intr.h>
26 #include <machine/bus.h>
27 #include <machine/fdt.h>
28
29 #include <dev/ofw/openfirm.h>
30 #include <dev/ofw/ofw_gpio.h>
31 #include <dev/ofw/fdt.h>
32
33 /* Registers. */
34
35 #define GPIO_SWPORTA_DR 0x0000
36 #define GPIO_SWPORTA_DDR 0x0004
37 #define GPIO_INTEN 0x0030
38 #define GPIO_INTMASK 0x0034
39 #define GPIO_INTTYPE_LEVEL 0x0038
40 #define GPIO_INT_POLARITY 0x003c
41 #define GPIO_INT_STATUS 0x0040
42 #define GPIO_INT_RAWSTATUS 0x0044
43 #define GPIO_DEBOUNCE 0x0048
44 #define GPIO_PORTS_EOI 0x004c
45 #define GPIO_EXT_PORTA 0x0050
46
47 #define GPIO_SWPORT_DR_L 0x0000
48 #define GPIO_SWPORT_DR_H 0x0004
49 #define GPIO_SWPORT_DDR_L 0x0008
50 #define GPIO_SWPORT_DDR_H 0x000c
51 #define GPIO_INT_EN_L 0x0010
52 #define GPIO_INT_EN_H 0x0014
53 #define GPIO_INT_MASK_L 0x0018
54 #define GPIO_INT_MASK_H 0x001c
55 #define GPIO_INT_TYPE_L 0x0020
56 #define GPIO_INT_TYPE_H 0x0024
57 #define GPIO_INT_POLARITY_L 0x0028
58 #define GPIO_INT_POLARITY_H 0x002c
59 #define GPIO_INT_STATUS_V2 0x0050
60 #define GPIO_PORT_EOI_L 0x0060
61 #define GPIO_PORT_EOI_H 0x0064
62 #define GPIO_EXT_PORT 0x0070
63 #define GPIO_VER_ID 0x0078
64 #define GPIO_VER_ID_1_0 0x00000000
65 #define GPIO_VER_ID_2_0 0x01000c2b
66 #define GPIO_VER_ID_2_1 0x0101157c
67
68 #define GPIO_NUM_PINS 32
69
70 #define HREAD4(sc, reg) \
71 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
72 #define HWRITE4(sc, reg, val) \
73 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
74 #define HSET4(sc, reg, bits) \
75 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
76 #define HCLR4(sc, reg, bits) \
77 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
78
79 struct intrhand {
80 int (*ih_func)(void *); /* handler */
81 void *ih_arg; /* arg for handler */
82 int ih_ipl; /* IPL_* */
83 int ih_irq; /* IRQ number */
84 int ih_level; /* GPIO level */
85 struct evcount ih_count;
86 char *ih_name;
87 void *ih_sc;
88 };
89
90 struct rkgpio_softc {
91 struct device sc_dev;
92 bus_space_tag_t sc_iot;
93 bus_space_handle_t sc_ioh;
94 int sc_node;
95 int sc_version;
96
97 void *sc_ih;
98 int sc_ipl;
99 int sc_irq;
100 struct intrhand *sc_handlers[GPIO_NUM_PINS];
101 struct interrupt_controller sc_ic;
102
103 struct gpio_controller sc_gc;
104 };
105
106 int rkgpio_match(struct device *, void *, void *);
107 void rkgpio_attach(struct device *, struct device *, void *);
108
109 const struct cfattach rkgpio_ca = {
110 sizeof (struct rkgpio_softc), rkgpio_match, rkgpio_attach
111 };
112
113 struct cfdriver rkgpio_cd = {
114 NULL, "rkgpio", DV_DULL
115 };
116
117 void rkgpio_config_pin(void *, uint32_t *, int);
118 int rkgpio_get_pin(void *, uint32_t *);
119 void rkgpio_set_pin(void *, uint32_t *, int);
120
121 int rkgpio_intr(void *);
122 void *rkgpio_intr_establish(void *, int *, int, struct cpu_info *,
123 int (*)(void *), void *, char *);
124 void rkgpio_intr_disestablish(void *);
125 void rkgpio_recalc_ipl(struct rkgpio_softc *);
126 void rkgpio_intr_enable(void *);
127 void rkgpio_intr_disable(void *);
128 void rkgpio_intr_barrier(void *);
129
130 int
rkgpio_match(struct device * parent,void * match,void * aux)131 rkgpio_match(struct device *parent, void *match, void *aux)
132 {
133 struct fdt_attach_args *faa = aux;
134
135 return OF_is_compatible(faa->fa_node, "rockchip,gpio-bank");
136 }
137
138 void
rkgpio_attach(struct device * parent,struct device * self,void * aux)139 rkgpio_attach(struct device *parent, struct device *self, void *aux)
140 {
141 struct rkgpio_softc *sc = (struct rkgpio_softc *)self;
142 struct fdt_attach_args *faa = aux;
143 uint32_t ver_id;
144
145 if (faa->fa_nreg < 1) {
146 printf(": no registers\n");
147 return;
148 }
149
150 sc->sc_node = faa->fa_node;
151 sc->sc_iot = faa->fa_iot;
152
153 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
154 faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
155 printf(": can't map registers\n");
156 return;
157 }
158
159 ver_id = HREAD4(sc, GPIO_VER_ID);
160 switch (ver_id) {
161 case GPIO_VER_ID_1_0:
162 sc->sc_version = 1;
163 break;
164 case GPIO_VER_ID_2_0:
165 case GPIO_VER_ID_2_1:
166 sc->sc_version = 2;
167 break;
168 default:
169 printf(": unknown version 0x%08x\n", ver_id);
170 return;
171 }
172
173 sc->sc_gc.gc_node = faa->fa_node;
174 sc->sc_gc.gc_cookie = sc;
175 sc->sc_gc.gc_config_pin = rkgpio_config_pin;
176 sc->sc_gc.gc_get_pin = rkgpio_get_pin;
177 sc->sc_gc.gc_set_pin = rkgpio_set_pin;
178 gpio_controller_register(&sc->sc_gc);
179
180 sc->sc_ipl = IPL_NONE;
181 if (sc->sc_version == 2) {
182 HWRITE4(sc, GPIO_INT_MASK_L, ~0);
183 HWRITE4(sc, GPIO_INT_MASK_H, ~0);
184 HWRITE4(sc, GPIO_INT_EN_L, ~0);
185 HWRITE4(sc, GPIO_INT_EN_H, ~0);
186 } else {
187 HWRITE4(sc, GPIO_INTMASK, ~0);
188 HWRITE4(sc, GPIO_INTEN, ~0);
189 }
190
191 sc->sc_ic.ic_node = faa->fa_node;
192 sc->sc_ic.ic_cookie = sc;
193 sc->sc_ic.ic_establish = rkgpio_intr_establish;
194 sc->sc_ic.ic_disestablish = rkgpio_intr_disestablish;
195 sc->sc_ic.ic_enable = rkgpio_intr_enable;
196 sc->sc_ic.ic_disable = rkgpio_intr_disable;
197 sc->sc_ic.ic_barrier = rkgpio_intr_barrier;
198 fdt_intr_register(&sc->sc_ic);
199
200 printf("\n");
201 }
202
203 void
rkgpio_config_pin(void * cookie,uint32_t * cells,int config)204 rkgpio_config_pin(void *cookie, uint32_t *cells, int config)
205 {
206 struct rkgpio_softc *sc = cookie;
207 uint32_t pin = cells[0];
208 uint32_t reg;
209
210 if (pin >= GPIO_NUM_PINS)
211 return;
212
213 if (sc->sc_version == 2) {
214 reg = (1 << (pin % 16)) << 16;
215 if (config & GPIO_CONFIG_OUTPUT)
216 reg |= (1 << (pin % 16));
217 HWRITE4(sc, GPIO_SWPORT_DDR_L + (pin / 16) * 4, reg);
218 } else {
219 if (config & GPIO_CONFIG_OUTPUT)
220 HSET4(sc, GPIO_SWPORTA_DDR, (1 << pin));
221 else
222 HCLR4(sc, GPIO_SWPORTA_DDR, (1 << pin));
223 }
224 }
225
226 int
rkgpio_get_pin(void * cookie,uint32_t * cells)227 rkgpio_get_pin(void *cookie, uint32_t *cells)
228 {
229 struct rkgpio_softc *sc = cookie;
230 uint32_t pin = cells[0];
231 uint32_t flags = cells[1];
232 uint32_t reg;
233 int val;
234
235 if (pin >= GPIO_NUM_PINS)
236 return 0;
237
238 if (sc->sc_version == 2)
239 reg = HREAD4(sc, GPIO_EXT_PORT);
240 else
241 reg = HREAD4(sc, GPIO_EXT_PORTA);
242 val = (reg >> pin) & 1;
243 if (flags & GPIO_ACTIVE_LOW)
244 val = !val;
245 return val;
246 }
247
248 void
rkgpio_set_pin(void * cookie,uint32_t * cells,int val)249 rkgpio_set_pin(void *cookie, uint32_t *cells, int val)
250 {
251 struct rkgpio_softc *sc = cookie;
252 uint32_t pin = cells[0];
253 uint32_t flags = cells[1];
254 uint32_t reg;
255
256 if (pin >= GPIO_NUM_PINS)
257 return;
258
259 if (flags & GPIO_ACTIVE_LOW)
260 val = !val;
261 if (sc->sc_version == 2) {
262 reg = (1 << (pin % 16)) << 16;
263 if (val)
264 reg |= (1 << (pin % 16));
265 HWRITE4(sc, GPIO_SWPORT_DR_L + (pin / 16) * 4, reg);
266 } else {
267 if (val)
268 HSET4(sc, GPIO_SWPORTA_DR, (1 << pin));
269 else
270 HCLR4(sc, GPIO_SWPORTA_DR, (1 << pin));
271 }
272 }
273
274 int
rkgpio_intr(void * cookie)275 rkgpio_intr(void *cookie)
276 {
277 struct rkgpio_softc *sc = (struct rkgpio_softc *)cookie;
278 struct intrhand *ih;
279 uint32_t status, pending;
280 int pin, s;
281
282 if (sc->sc_version == 2)
283 status = HREAD4(sc, GPIO_INT_STATUS_V2);
284 else
285 status = HREAD4(sc, GPIO_INT_STATUS);
286 pending = status;
287
288 while (pending) {
289 pin = ffs(pending) - 1;
290
291 if ((ih = sc->sc_handlers[pin]) != NULL) {
292 s = splraise(ih->ih_ipl);
293 if (ih->ih_func(ih->ih_arg))
294 ih->ih_count.ec_count++;
295 splx(s);
296 }
297
298 pending &= ~(1 << pin);
299 }
300
301 if (sc->sc_version == 2) {
302 HWRITE4(sc, GPIO_PORT_EOI_L,
303 (status & 0xffff) << 16 | (status & 0xffff));
304 HWRITE4(sc, GPIO_PORT_EOI_H,
305 status >> 16 | (status & 0xffff0000));
306 } else
307 HWRITE4(sc, GPIO_PORTS_EOI, status);
308
309 return 1;
310 }
311
312 void *
rkgpio_intr_establish(void * cookie,int * cells,int ipl,struct cpu_info * ci,int (* func)(void *),void * arg,char * name)313 rkgpio_intr_establish(void *cookie, int *cells, int ipl,
314 struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
315 {
316 struct rkgpio_softc *sc = (struct rkgpio_softc *)cookie;
317 struct intrhand *ih;
318 int irqno = cells[0];
319 int level = cells[1];
320 int s;
321
322 if (irqno < 0 || irqno >= GPIO_NUM_PINS)
323 panic("%s: bogus irqnumber %d: %s", __func__,
324 irqno, name);
325
326 if (sc->sc_handlers[irqno] != NULL)
327 panic("%s: irqnumber %d reused: %s", __func__,
328 irqno, name);
329
330 if (ci != NULL && !CPU_IS_PRIMARY(ci))
331 return NULL;
332
333 ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK);
334 ih->ih_func = func;
335 ih->ih_arg = arg;
336 ih->ih_ipl = ipl & IPL_IRQMASK;
337 ih->ih_irq = irqno;
338 ih->ih_name = name;
339 ih->ih_level = level;
340 ih->ih_sc = sc;
341
342 s = splhigh();
343
344 sc->sc_handlers[irqno] = ih;
345
346 if (name != NULL)
347 evcount_attach(&ih->ih_count, name, &ih->ih_irq);
348
349 #ifdef DEBUG_INTC
350 printf("%s: irq %d ipl %d [%s]\n", __func__, ih->ih_irq, ih->ih_ipl,
351 ih->ih_name);
352 #endif
353
354 rkgpio_recalc_ipl(sc);
355
356 if (sc->sc_version == 2) {
357 uint32_t bit = (1 << (irqno % 16));
358 uint32_t mask = bit << 16;
359 bus_size_t off = (irqno / 16) * 4;
360
361 switch (level) {
362 case 1: /* rising */
363 HWRITE4(sc, GPIO_INT_TYPE_L + off * 4, mask | bit);
364 HWRITE4(sc, GPIO_INT_POLARITY_L + off * 4, mask | bit);
365 break;
366 case 2: /* falling */
367 HWRITE4(sc, GPIO_INT_TYPE_L + off * 4, mask | bit);
368 HWRITE4(sc, GPIO_INT_POLARITY_L + off * 4, mask);
369 break;
370 case 4: /* high */
371 HWRITE4(sc, GPIO_INT_TYPE_L + off * 4, mask);
372 HWRITE4(sc, GPIO_INT_POLARITY_L + off * 4, mask | bit);
373 break;
374 case 8: /* low */
375 HWRITE4(sc, GPIO_INT_TYPE_L + off * 4, mask);
376 HWRITE4(sc, GPIO_INT_POLARITY_L + off * 4, mask);
377 break;
378 default:
379 panic("%s: unsupported trigger type", __func__);
380 }
381
382 HWRITE4(sc, GPIO_SWPORT_DDR_L + off, mask);
383 HWRITE4(sc, GPIO_INT_MASK_L + off, mask);
384 } else {
385 switch (level) {
386 case 1: /* rising */
387 HSET4(sc, GPIO_INTTYPE_LEVEL, 1 << irqno);
388 HSET4(sc, GPIO_INT_POLARITY, 1 << irqno);
389 break;
390 case 2: /* falling */
391 HSET4(sc, GPIO_INTTYPE_LEVEL, 1 << irqno);
392 HCLR4(sc, GPIO_INT_POLARITY, 1 << irqno);
393 break;
394 case 4: /* high */
395 HCLR4(sc, GPIO_INTTYPE_LEVEL, 1 << irqno);
396 HSET4(sc, GPIO_INT_POLARITY, 1 << irqno);
397 break;
398 case 8: /* low */
399 HCLR4(sc, GPIO_INTTYPE_LEVEL, 1 << irqno);
400 HCLR4(sc, GPIO_INT_POLARITY, 1 << irqno);
401 break;
402 default:
403 panic("%s: unsupported trigger type", __func__);
404 }
405
406 HCLR4(sc, GPIO_SWPORTA_DDR, 1 << irqno);
407 HCLR4(sc, GPIO_INTMASK, 1 << irqno);
408 }
409
410 splx(s);
411 return (ih);
412 }
413
414 void
rkgpio_intr_disestablish(void * cookie)415 rkgpio_intr_disestablish(void *cookie)
416 {
417 struct intrhand *ih = cookie;
418 struct rkgpio_softc *sc = ih->ih_sc;
419 uint32_t bit = (1 << (ih->ih_irq % 16));
420 uint32_t mask = bit << 16;
421 bus_size_t off = (ih->ih_irq / 16) * 4;
422 int s;
423
424 s = splhigh();
425
426 #ifdef DEBUG_INTC
427 printf("%s: irq %d ipl %d [%s]\n", __func__, ih->ih_irq, ih->ih_ipl,
428 ih->ih_name);
429 #endif
430
431 if (sc->sc_version == 2)
432 HWRITE4(sc, GPIO_INT_MASK_L + off, mask | bit);
433 else
434 HSET4(sc, GPIO_INTMASK, 1 << ih->ih_irq);
435
436 sc->sc_handlers[ih->ih_irq] = NULL;
437 if (ih->ih_name != NULL)
438 evcount_detach(&ih->ih_count);
439 free(ih, M_DEVBUF, sizeof(*ih));
440
441 rkgpio_recalc_ipl(sc);
442
443 splx(s);
444 }
445
446 void
rkgpio_recalc_ipl(struct rkgpio_softc * sc)447 rkgpio_recalc_ipl(struct rkgpio_softc *sc)
448 {
449 struct intrhand *ih;
450 int max = IPL_NONE;
451 int min = IPL_HIGH;
452 int pin;
453
454 for (pin = 0; pin < GPIO_NUM_PINS; pin++) {
455 ih = sc->sc_handlers[pin];
456 if (ih == NULL)
457 continue;
458
459 if (ih->ih_ipl > max)
460 max = ih->ih_ipl;
461
462 if (ih->ih_ipl < min)
463 min = ih->ih_ipl;
464 }
465
466 if (max == IPL_NONE)
467 min = IPL_NONE;
468
469 if (sc->sc_ipl != max) {
470 sc->sc_ipl = max;
471
472 if (sc->sc_ih != NULL)
473 fdt_intr_disestablish(sc->sc_ih);
474
475 if (sc->sc_ipl != IPL_NONE)
476 sc->sc_ih = fdt_intr_establish(sc->sc_node,
477 sc->sc_ipl, rkgpio_intr, sc, sc->sc_dev.dv_xname);
478 }
479 }
480
481 void
rkgpio_intr_enable(void * cookie)482 rkgpio_intr_enable(void *cookie)
483 {
484 struct intrhand *ih = cookie;
485 struct rkgpio_softc *sc = ih->ih_sc;
486 uint32_t bit = (1 << (ih->ih_irq % 16));
487 uint32_t mask = bit << 16;
488 bus_size_t off = (ih->ih_irq / 16) * 4;
489 int s;
490
491 s = splhigh();
492 if (sc->sc_version == 2)
493 HWRITE4(sc, GPIO_INT_MASK_L + off, mask);
494 else
495 HCLR4(sc, GPIO_INTMASK, 1 << ih->ih_irq);
496 splx(s);
497 }
498
499 void
rkgpio_intr_disable(void * cookie)500 rkgpio_intr_disable(void *cookie)
501 {
502 struct intrhand *ih = cookie;
503 struct rkgpio_softc *sc = ih->ih_sc;
504 uint32_t bit = (1 << (ih->ih_irq % 16));
505 uint32_t mask = bit << 16;
506 bus_size_t off = (ih->ih_irq / 16) * 4;
507 int s;
508
509 s = splhigh();
510 if (sc->sc_version == 2)
511 HWRITE4(sc, GPIO_INT_MASK_L + off, mask | bit);
512 else
513 HSET4(sc, GPIO_INTMASK, 1 << ih->ih_irq);
514 splx(s);
515 }
516
517 void
rkgpio_intr_barrier(void * cookie)518 rkgpio_intr_barrier(void *cookie)
519 {
520 struct intrhand *ih = cookie;
521 struct rkgpio_softc *sc = ih->ih_sc;
522
523 intr_barrier(sc->sc_ih);
524 }
525