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