1 /* $NetBSD: igpio.c,v 1.5 2023/01/07 03:27:01 msaitoh Exp $ */
2
3 /*
4 * Copyright (c) 2021,2022 Emmanuel Dreyfus
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/device.h>
34 #include <sys/intr.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/kmem.h>
38 #include <sys/endian.h>
39 #include <sys/gpio.h>
40
41 #include <dev/gpio/gpiovar.h>
42 #include "gpio.h"
43
44 #include <dev/ic/igpiovar.h>
45 #include <dev/ic/igpioreg.h>
46
47 struct igpio_intr {
48 int (*ii_func)(void *);
49 void *ii_arg;
50 struct igpio_bank *ii_bank;
51 int ii_pin;
52 };
53
54 struct igpio_bank {
55 int ib_barno;
56 int ib_revid;
57 int ib_cap;
58 int ib_padbar;
59 struct igpio_bank_setup *ib_setup;
60 struct igpio_softc *ib_sc;
61 struct igpio_intr *ib_intr;
62 kmutex_t ib_mtx;
63 };
64
65
66 static int igpio_debug = 0;
67 #define DPRINTF(x) if (igpio_debug) printf x;
68
69 static char *
igpio_padcfg0_print(uint32_t val,int idx)70 igpio_padcfg0_print(uint32_t val, int idx)
71 {
72 uint32_t rxev, pmode;
73 static char buf0[256];
74 static char buf1[256];
75 char *buf = (idx % 2) ? &buf0[0] : &buf1[0];
76 size_t len = sizeof(buf0) - 1;
77 size_t wr = 0;
78 uint32_t unknown_bits =
79 __BITS(3,7)|__BITS(14,16)|__BITS(21,22)|__BITS(27,31);
80 int b;
81
82 rxev =
83 (val & IGPIO_PADCFG0_RXEVCFG_MASK) >> IGPIO_PADCFG0_RXEVCFG_SHIFT;
84 wr += snprintf(buf + wr, len - wr, "rxev ");
85 switch (rxev) {
86 case IGPIO_PADCFG0_RXEVCFG_LEVEL:
87 wr += snprintf(buf + wr, len - wr, "level");
88 break;
89 case IGPIO_PADCFG0_RXEVCFG_EDGE:
90 wr += snprintf(buf + wr, len - wr, "edge");
91 break;
92 case IGPIO_PADCFG0_RXEVCFG_DISABLED:
93 wr += snprintf(buf + wr, len - wr, "disabled");
94 break;
95 case IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH:
96 wr += snprintf(buf + wr, len - wr, "edge both");
97 break;
98 default:
99 break;
100 }
101
102 if (val & IGPIO_PADCFG0_PREGFRXSEL)
103 wr += snprintf(buf + wr, len - wr, ", pregfrxsel");
104
105 if (val & IGPIO_PADCFG0_RXINV)
106 wr += snprintf(buf + wr, len - wr, ", rxinv");
107
108 if (val & (IGPIO_PADCFG0_GPIROUTIOXAPIC|IGPIO_PADCFG0_GPIROUTSCI|
109 IGPIO_PADCFG0_GPIROUTSMI|IGPIO_PADCFG0_GPIROUTNMI)) {
110 wr += snprintf(buf + wr, len - wr, ", gpirout");
111
112 if (val & IGPIO_PADCFG0_GPIROUTIOXAPIC)
113 wr += snprintf(buf + wr, len - wr, " ioxapic");
114
115 if (val & IGPIO_PADCFG0_GPIROUTSCI)
116 wr += snprintf(buf + wr, len - wr, " sci");
117
118 if (val & IGPIO_PADCFG0_GPIROUTSMI)
119 wr += snprintf(buf + wr, len - wr, " smi");
120
121 if (val & IGPIO_PADCFG0_GPIROUTNMI)
122 wr += snprintf(buf + wr, len - wr, " nmi");
123 }
124
125 pmode =
126 (val & IGPIO_PADCFG0_PMODE_MASK) >> IGPIO_PADCFG0_PMODE_SHIFT;
127 switch (pmode) {
128 case IGPIO_PADCFG0_PMODE_GPIO:
129 wr += snprintf(buf + wr, len - wr, ", pmode gpio");
130 break;
131 default:
132 wr += snprintf(buf + wr, len - wr, ", pmode %d", pmode);
133 break;
134 }
135
136 if (val & IGPIO_PADCFG0_GPIORXDIS)
137 wr += snprintf(buf + wr, len - wr, ", rx disabled");
138 else
139 wr += snprintf(buf + wr, len - wr, ", rx %d",
140 !!(val & IGPIO_PADCFG0_GPIORXSTATE));
141
142 if (val & IGPIO_PADCFG0_GPIOTXDIS)
143 wr += snprintf(buf + wr, len - wr, ", tx disabled");
144 else
145 wr += snprintf(buf + wr, len - wr, ", tx %d",
146 !!(val & IGPIO_PADCFG0_GPIOTXSTATE));
147
148 if (val & unknown_bits) {
149 wr += snprintf(buf + wr, len - wr, ", unknown bits");
150 for (b = 0; b < 32; b++) {
151 if (!(__BIT(b) & unknown_bits & val))
152 continue;
153 wr += snprintf(buf + wr, len - wr, " %d", b);
154 }
155 }
156
157 return buf;
158 }
159
160
161 static struct igpio_bank_setup *
igpio_find_bank_setup(struct igpio_bank * ib,int barno)162 igpio_find_bank_setup(struct igpio_bank *ib, int barno)
163 {
164 struct igpio_bank_setup *ibs;
165
166 for (ibs = igpio_bank_setup; ibs->ibs_acpi_hid; ibs++) {
167 if (strcmp(ib->ib_sc->sc_acpi_hid, ibs->ibs_acpi_hid) != 0)
168 continue;
169 if (ibs->ibs_barno != barno)
170 continue;
171
172 return ibs;
173 }
174
175 return NULL;
176 }
177
178 static struct igpio_bank *
igpio_find_bank(struct igpio_softc * sc,int pin)179 igpio_find_bank(struct igpio_softc *sc, int pin)
180 {
181 int i;
182 struct igpio_bank *ib;
183
184 for (i = 0; i < sc->sc_nbar; i++) {
185 ib = &sc->sc_banks[i];
186 if (pin >= ib->ib_setup->ibs_first_pin &&
187 pin <= ib->ib_setup->ibs_last_pin)
188 goto out;
189 }
190
191 ib = NULL;
192 out:
193 return ib;
194 }
195
196 static int
igpio_bank_pin(struct igpio_bank * ib,int pin)197 igpio_bank_pin(struct igpio_bank *ib, int pin)
198 {
199 return pin - ib->ib_setup->ibs_first_pin;
200 }
201
202 #if 0
203 static void
204 igpio_hexdump(struct igpio_softc *sc, int n)
205 {
206 int i, j;
207 uint8_t v;
208 size_t len = MIN(sc->sc_length[n], 2048);
209
210 printf("bar %d\n", n);
211 for (j = 0; j < len; j += 16) {
212 printf("%04x ", j);
213 for (i = 0; i < 16 && i + j < len; i++) {
214 v = bus_space_read_1(sc->sc_bst, sc->sc_bsh[n], i + j);
215 printf("%02x ", v);
216 }
217 printf("\n");
218 }
219 }
220 #endif
221
222 void
igpio_attach(struct igpio_softc * sc)223 igpio_attach(struct igpio_softc *sc)
224 {
225 device_t self = sc->sc_dev;
226 int i,j;
227 struct gpiobus_attach_args gba;
228 int success = 0;
229
230 sc->sc_banks =
231 kmem_zalloc(sizeof(*sc->sc_banks) * sc->sc_nbar, KM_SLEEP);
232
233 sc->sc_npins = 0;
234
235 for (i = 0; i < sc->sc_nbar; i++) {
236 struct igpio_bank *ib = &sc->sc_banks[i];
237 struct igpio_bank_setup *ibs;
238 bus_size_t reg;
239 uint32_t val;
240 int error;
241 int npins;
242
243 ib->ib_barno = i;
244 ib->ib_sc = sc;
245
246 mutex_init(&ib->ib_mtx, MUTEX_DEFAULT, IPL_VM);
247
248 error = bus_space_map(sc->sc_bst, sc->sc_base[i],
249 sc->sc_length[i], 0, &sc->sc_bsh[i]);
250 if (error) {
251 aprint_error_dev(self, "couldn't map registers\n");
252 goto out;
253 }
254
255 reg = IGPIO_REVID;
256 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
257 if (val == 0) {
258 aprint_error_dev(self, "couldn't find revid\n");
259 goto out;
260 }
261 ib->ib_revid = val >> 16;
262
263 DPRINTF(("revid[%d] = #%x\n", i, ib->ib_revid));
264
265 if (ib->ib_revid > 0x94) {
266 ib->ib_cap |= IGPIO_PINCTRL_FEATURE_DEBOUNCE;
267 ib->ib_cap |= IGPIO_PINCTRL_FEATURE_1K_PD;
268 }
269
270 reg = IGPIO_CAPLIST;
271 do {
272 /* higher 16 bits: value, lower 16 bits, next reg */
273 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
274
275 reg = val & 0xffff;
276 val = val >> 16;
277
278 switch (val) {
279 case IGPIO_CAPLIST_ID_GPIO_HW_INFO:
280 ib->ib_cap |=
281 IGPIO_PINCTRL_FEATURE_GPIO_HW_INFO;
282 break;
283 case IGPIO_CAPLIST_ID_PWM:
284 ib->ib_cap |= IGPIO_PINCTRL_FEATURE_PWM;
285 break;
286 case IGPIO_CAPLIST_ID_BLINK:
287 ib->ib_cap |= IGPIO_PINCTRL_FEATURE_BLINK;
288 break;
289 case IGPIO_CAPLIST_ID_EXP:
290 ib->ib_cap |= IGPIO_PINCTRL_FEATURE_EXP;
291 break;
292 default:
293 break;
294 }
295 } while (reg);
296 DPRINTF(("cap[%d] = #%x\n", i, ib->ib_cap));
297
298 reg = IGPIO_PADBAR;
299 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
300 ib->ib_padbar = val;
301 DPRINTF(("padbar[%d] = #%x\n", i, ib->ib_padbar));
302 if (ib->ib_padbar > sc->sc_length[i]) {
303 printf("PADBAR = #%x higher than max #%lx\n",
304 ib->ib_padbar, sc->sc_length[i]);
305 goto out;
306 }
307
308 ib->ib_setup = igpio_find_bank_setup(ib, i);
309 if (ib->ib_setup == NULL) {
310 printf("Missing BAR %d\n", i);
311 goto out;
312 }
313
314 ibs = ib->ib_setup;
315
316 DPRINTF(("setup[%d] = "
317 "{ barno = %d, first_pin = %d, last_pin = %d }\n",
318 i, ibs->ibs_barno, ibs->ibs_first_pin, ibs->ibs_last_pin));
319
320 npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin;
321
322 ib->ib_intr =
323 kmem_zalloc(sizeof(*ib->ib_intr) * npins, KM_SLEEP);
324
325 sc->sc_npins += npins;
326 }
327
328 if (sc->sc_npins < 1 || sc->sc_npins > 4096) {
329 printf("Unexpected pin count %d\n", sc->sc_npins);
330 goto out;
331 }
332
333 sc->sc_pins =
334 kmem_zalloc(sizeof(*sc->sc_pins) * sc->sc_npins, KM_SLEEP);
335
336 for (j = 0; j < sc->sc_npins; j++) {
337 sc->sc_pins[j].pin_num = j;
338 sc->sc_pins[j].pin_caps =
339 GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INOUT |
340 GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN;
341 sc->sc_pins[j].pin_intrcaps =
342 GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE |
343 GPIO_INTR_DOUBLE_EDGE | GPIO_INTR_HIGH_LEVEL |
344 GPIO_INTR_LOW_LEVEL | GPIO_INTR_MPSAFE;
345 sc->sc_pins[j].pin_state = igpio_pin_read(sc, j);
346 }
347
348 sc->sc_gc.gp_cookie = sc;
349 sc->sc_gc.gp_pin_read = igpio_pin_read;
350 sc->sc_gc.gp_pin_write = igpio_pin_write;
351 sc->sc_gc.gp_pin_ctl = igpio_pin_ctl;
352 sc->sc_gc.gp_intr_establish = igpio_intr_establish;
353 sc->sc_gc.gp_intr_disestablish = igpio_intr_disestablish;
354 sc->sc_gc.gp_intr_str = igpio_intr_str;
355
356 memset(&gba, 0, sizeof(gba));
357 gba.gba_gc = &sc->sc_gc;
358 gba.gba_pins = sc->sc_pins;
359 gba.gba_npins = sc->sc_npins;
360
361 #if NGPIO > 0
362 config_found(sc->sc_dev, &gba, gpiobus_print, CFARGS_NONE);
363 #endif
364
365 success = 1;
366 out:
367 if (!success)
368 igpio_detach(sc);
369
370 return;
371 }
372
373 void
igpio_detach(struct igpio_softc * sc)374 igpio_detach(struct igpio_softc *sc)
375 {
376 int i;
377
378 for (i = 0; i < sc->sc_nbar; i++) {
379 struct igpio_bank *ib = &sc->sc_banks[i];
380 struct igpio_bank_setup *ibs = ib->ib_setup;
381 int npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin;
382
383 if (ib->ib_intr != NULL) {
384 kmem_free(ib->ib_intr, sizeof(*ib->ib_intr) * npins);
385 ib->ib_intr = NULL;
386 }
387 }
388
389 if (sc->sc_pins != NULL) {
390 kmem_free(sc->sc_pins, sizeof(*sc->sc_pins) * sc->sc_npins);
391 sc->sc_pins = NULL;
392 }
393
394 if (sc->sc_banks != NULL) {
395 kmem_free(sc->sc_banks, sizeof(*sc->sc_banks) * sc->sc_nbar);
396 sc->sc_banks = NULL;
397 }
398
399 return;
400 }
401
402 static bus_addr_t
igpio_pincfg(struct igpio_bank * ib,int pin,int reg)403 igpio_pincfg(struct igpio_bank *ib, int pin, int reg)
404 {
405 int nregs = (ib->ib_cap & IGPIO_PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2;
406 bus_addr_t pincfg;
407
408 pincfg = ib->ib_padbar + reg + (pin * nregs * 4);
409 #if 0
410 DPRINTF(("%s bar %d pin %d reg #%x pincfg = %p\n",
411 __func__, ib->ib_barno, pin, reg, (void *)pincfg));
412 #endif
413 return pincfg;
414 }
415
416 #if notyet
417 static struct igpio_pin_group *
igpio_find_group(struct igpio_bank * ib,int pin)418 igpio_find_group(struct igpio_bank *ib, int pin)
419 {
420 struct igpio_bank_setup *ibs = ib->ib_setup;
421 struct igpio_pin_group *found_ipg = NULL;
422 struct igpio_pin_group *ipg;
423
424 if (pin > ibs->ibs_last_pin) {
425 DPRINTF(("%s: barno %d, pin = %d > past pin = %d\n", __func__,
426 ibs->ibs_barno, pin, ibs->ibs_last_pin));
427 return NULL;
428 }
429
430 for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) {
431 if (strcmp(ipg->ipg_acpi_hid, ibs->ibs_acpi_hid) != 0)
432 continue;
433
434 if (pin > ipg->ipg_first_pin) {
435 found_ipg = ipg;
436 continue;
437 }
438 }
439
440 return found_ipg;
441 }
442
443 static bus_addr_t
igpio_groupcfg(struct igpio_bank * ib,int pin)444 igpio_groupcfg(struct igpio_bank *ib, int pin)
445 {
446 struct igpio_bank_setup *ibs = ib->ib_setup;
447 struct igpio_pin_group *ipg;
448 bus_addr_t groupcfg;
449
450 if ((ipg = igpio_find_group(ib, pin)) == NULL)
451 return (bus_addr_t)NULL;
452
453 groupcfg = ib->ib_padbar
454 + (ipg->ipg_groupno * 4)
455 + (pin - ipg->ipg_first_pin) / 2;
456
457 DPRINTF(("%s: barno %d, pin = %d, found group %d \"%s\", cfg %p\n", \
458 __func__, ibs->ibs_barno, pin, ipg->ipg_groupno, \
459 ipg->ipg_name, (void *)groupcfg));
460
461 return groupcfg;
462 }
463 #endif
464
465
466 int
igpio_pin_read(void * priv,int pin)467 igpio_pin_read(void *priv, int pin)
468 {
469 struct igpio_softc *sc = priv;
470 struct igpio_bank *ib = igpio_find_bank(sc, pin);
471 bus_addr_t cfg0;
472 uint32_t val;
473
474 pin = igpio_bank_pin(ib, pin);
475 cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
476
477 mutex_enter(&ib->ib_mtx);
478
479 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
480 DPRINTF(("%s: bar %d pin %d val #%x (%s)\n", __func__,
481 ib->ib_barno, pin, val, igpio_padcfg0_print(val, 0)));
482
483 if (val & IGPIO_PADCFG0_GPIOTXDIS)
484 val = (val & IGPIO_PADCFG0_GPIORXSTATE) ? 1 : 0;
485 else
486 val = (val & IGPIO_PADCFG0_GPIOTXSTATE) ? 1 : 0;
487
488 mutex_exit(&ib->ib_mtx);
489
490 return val;
491 }
492
493 void
igpio_pin_write(void * priv,int pin,int value)494 igpio_pin_write(void *priv, int pin, int value)
495 {
496 struct igpio_softc *sc = priv;
497 struct igpio_bank *ib = igpio_find_bank(sc, pin);
498 bus_addr_t cfg0;
499 uint32_t val, newval;
500
501 pin = igpio_bank_pin(ib, pin);
502 cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
503
504 mutex_enter(&ib->ib_mtx);
505
506 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
507
508 if (value)
509 newval = val | IGPIO_PADCFG0_GPIOTXSTATE;
510 else
511 newval = val & ~IGPIO_PADCFG0_GPIOTXSTATE;
512
513 DPRINTF(("%s: bar %d pin %d value %d val #%x (%s) -> #%x (%s)\n",
514 __func__, ib->ib_barno, pin, value,
515 val, igpio_padcfg0_print(val, 0),
516 newval, igpio_padcfg0_print(newval, 1)));
517
518 bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
519
520 mutex_exit(&ib->ib_mtx);
521
522 return;
523 }
524
525 void
igpio_pin_ctl(void * priv,int pin,int flags)526 igpio_pin_ctl(void *priv, int pin, int flags)
527 {
528 struct igpio_softc *sc = priv;
529 struct igpio_bank *ib = igpio_find_bank(sc, pin);
530 bus_addr_t cfg0, cfg1;
531 uint32_t val0, newval0;
532 uint32_t val1, newval1;
533
534 pin = igpio_bank_pin(ib, pin);
535 cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
536 cfg1 = igpio_pincfg(ib, pin, IGPIO_PADCFG1);
537
538 mutex_enter(&ib->ib_mtx);
539
540 val0 = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
541 val1 = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg1);
542
543 newval0 = val0;
544 newval1 = val1;
545
546 newval0 &= ~IGPIO_PADCFG0_PMODE_MASK;
547 newval0 |= IGPIO_PADCFG0_PMODE_GPIO;
548
549 newval0 |= IGPIO_PADCFG0_GPIORXDIS;
550 newval0 |= IGPIO_PADCFG0_GPIOTXDIS;
551
552 newval0 &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
553 newval0 &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
554
555 if (flags & GPIO_PIN_INPUT) {
556 newval0 &= ~IGPIO_PADCFG0_GPIORXDIS;
557 newval0 |= IGPIO_PADCFG0_GPIOTXDIS;
558 }
559
560 if (flags & GPIO_PIN_OUTPUT) {
561 newval0 &= ~IGPIO_PADCFG0_GPIOTXDIS;
562 newval0 |= IGPIO_PADCFG0_GPIORXDIS;
563 }
564
565 if (flags & GPIO_PIN_INOUT) {
566 newval0 &= ~IGPIO_PADCFG0_GPIOTXDIS;
567 newval0 &= ~IGPIO_PADCFG0_GPIORXDIS;
568 }
569
570 if (flags & GPIO_PIN_INVIN)
571 newval0 |= IGPIO_PADCFG0_RXINV;
572 else
573 newval0 &= ~IGPIO_PADCFG0_RXINV;
574
575 newval1 &= ~IGPIO_PADCFG1_TERM_MASK;
576 if (flags & GPIO_PIN_PULLUP) {
577 newval1 |= IGPIO_PADCFG1_TERM_UP;
578 newval1 |= IGPIO_PADCFG1_TERM_5K;
579 }
580
581 if (flags & GPIO_PIN_PULLDOWN) {
582 newval1 &= ~IGPIO_PADCFG1_TERM_UP;
583 newval1 |= IGPIO_PADCFG1_TERM_5K;
584 }
585
586 DPRINTF(("%s: bar %d pin %d flags #%x val0 #%x (%s) -> #%x (%s), "
587 "val1 #%x -> #%x\n", __func__, ib->ib_barno, pin, flags,
588 val0, igpio_padcfg0_print(val0, 0),
589 newval0, igpio_padcfg0_print(newval0, 1),
590 val1, newval1));
591
592 bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval0);
593 bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg1, newval1);
594
595 mutex_exit(&ib->ib_mtx);
596
597 return;
598 }
599
600 void *
igpio_intr_establish(void * priv,int pin,int ipl,int irqmode,int (* func)(void *),void * arg)601 igpio_intr_establish(void *priv, int pin, int ipl, int irqmode,
602 int (*func)(void *), void *arg)
603 {
604 struct igpio_softc *sc = priv;
605 struct igpio_bank *ib = igpio_find_bank(sc, pin);
606 bus_addr_t cfg0;
607 uint32_t val, newval;
608 struct igpio_intr *ii;
609
610 pin = igpio_bank_pin(ib, pin);
611 cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
612
613 ii = &ib->ib_intr[pin];
614 ii->ii_func = func;
615 ii->ii_arg = arg;
616 ii->ii_pin = pin;
617 ii->ii_bank = ib;
618
619 mutex_enter(&ib->ib_mtx);
620
621 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
622 newval = val;
623
624 newval &= ~IGPIO_PADCFG0_PMODE_MASK;
625 newval |= IGPIO_PADCFG0_PMODE_GPIO;
626
627 newval &= ~IGPIO_PADCFG0_GPIORXDIS;
628 newval |= IGPIO_PADCFG0_GPIOTXDIS;
629
630 newval |= (IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
631 newval |= (IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
632
633 newval &= ~IGPIO_PADCFG0_RXINV;
634 newval &= ~IGPIO_PADCFG0_RXEVCFG_EDGE;
635 newval &= ~IGPIO_PADCFG0_RXEVCFG_LEVEL;
636 newval &= ~IGPIO_PADCFG0_RXEVCFG_DISABLED;
637
638 switch (irqmode & GPIO_INTR_EDGE_MASK) {
639 case GPIO_INTR_DOUBLE_EDGE:
640 newval |= IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH;
641 break;
642 case GPIO_INTR_NEG_EDGE:
643 newval |= IGPIO_PADCFG0_RXEVCFG_EDGE;
644 newval |= IGPIO_PADCFG0_RXINV;
645 break;
646 case GPIO_INTR_POS_EDGE:
647 newval |= IGPIO_PADCFG0_RXEVCFG_EDGE;
648 break;
649 default:
650 switch (irqmode & GPIO_INTR_LEVEL_MASK) {
651 case GPIO_INTR_HIGH_LEVEL:
652 newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL;
653 break;
654 case GPIO_INTR_LOW_LEVEL:
655 newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL;
656 newval |= IGPIO_PADCFG0_RXINV;
657 break;
658 default:
659 newval |= IGPIO_PADCFG0_RXEVCFG_DISABLED;
660 break;
661 }
662 break;
663 }
664
665
666 DPRINTF(("%s: bar %d pin %d val #%x (%s) -> #%x (%s)\n",
667 __func__, ib->ib_barno, pin,
668 val, igpio_padcfg0_print(val, 0),
669 newval, igpio_padcfg0_print(newval, 1)));
670
671 bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
672
673 mutex_exit(&ib->ib_mtx);
674
675 return ii;
676 }
677
678 void
igpio_intr_disestablish(void * priv,void * ih)679 igpio_intr_disestablish(void *priv, void *ih)
680 {
681 struct igpio_softc *sc = priv;
682 struct igpio_bank *ib;
683 struct igpio_intr *ii = ih;
684 int pin;
685 bus_addr_t cfg0;
686 uint32_t val, newval;
687
688 if (ih == NULL)
689 return;
690
691 pin = ii->ii_pin;
692 ib = igpio_find_bank(sc, pin);
693 pin = igpio_bank_pin(ib, pin);
694 cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
695
696 mutex_enter(&ib->ib_mtx);
697
698 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
699 newval = val;
700
701 newval &= ~IGPIO_PADCFG0_PMODE_MASK;
702 newval |= IGPIO_PADCFG0_PMODE_GPIO;
703
704 newval &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
705 newval &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
706
707 DPRINTF(("%s: bar %d pin %d val #%x (%s) -> #%x (%s)\n", \
708 __func__, ib->ib_barno, pin,
709 val, igpio_padcfg0_print(val, 0),
710 newval, igpio_padcfg0_print(newval, 1)));
711
712 bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
713
714 mutex_exit(&ib->ib_mtx);
715
716 ii->ii_func = NULL;
717 ii->ii_arg = NULL;
718
719 return;
720 }
721
722 bool
igpio_intr_str(void * priv,int pin,int irqmode,char * buf,size_t buflen)723 igpio_intr_str(void *priv, int pin, int irqmode,
724 char *buf, size_t buflen)
725 {
726 struct igpio_softc *sc = priv;
727 const char *name = device_xname(sc->sc_dev);
728 int rv;
729
730 rv = snprintf(buf, buflen, "%s pin %d", name, pin);
731
732 return (rv < buflen);
733 }
734
735 int
igpio_intr(void * priv)736 igpio_intr(void *priv)
737 {
738 struct igpio_softc *sc = priv;
739 int i;
740 int ret = 0;
741
742 for (i = 0; i < sc->sc_nbar; i++) {
743 struct igpio_bank *ib = &sc->sc_banks[i];
744 struct igpio_bank_setup *ibs = ib->ib_setup;
745 bus_space_handle_t bsh = sc->sc_bsh[i];
746 struct igpio_pin_group *ipg;
747
748 mutex_enter(&ib->ib_mtx);
749
750 for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) {
751 int offset;
752 bus_addr_t is_reg;
753 bus_addr_t ie_reg;
754 uint32_t raised;
755 uint32_t pending;
756 uint32_t enabled;
757 int b;
758
759 if (strcmp(ipg->ipg_acpi_hid,
760 ibs->ibs_acpi_hid) != 0)
761 continue;
762
763 offset = ib->ib_padbar + ipg->ipg_groupno * 4;
764 is_reg = offset + ibs->ibs_gpi_is;
765 ie_reg = offset + ibs->ibs_gpi_ie;
766
767 raised = bus_space_read_4(sc->sc_bst, bsh, is_reg);
768 enabled = bus_space_read_4(sc->sc_bst, bsh, ie_reg);
769
770 /*
771 * find pins for which interrupt is pending
772 * and enabled
773 */
774 pending = raised & enabled;
775
776 for (b = 0; b < 32; b++) {
777 int pin;
778 int (*func)(void *);
779 void *arg;
780
781 if ((pending & (1 << b)) == 0)
782 continue;
783
784 pin = ipg->ipg_first_pin + b;
785 func = ib->ib_intr[pin].ii_func;
786 arg = ib->ib_intr[pin].ii_arg;
787
788 /* XXX ack intr, handled or not? */
789 raised &= ~(1 << b);
790
791 if (func == NULL)
792 continue;
793
794 ret |= func(arg);
795 }
796
797 bus_space_write_4(sc->sc_bst, bsh, is_reg, raised);
798
799 }
800
801 mutex_exit(&ib->ib_mtx);
802
803 }
804
805 return ret;
806 }
807