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