File: | dev/acpi/pchgpio.c |
Warning: | line 640, column 2 Value stored to 'pad' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: pchgpio.c,v 1.15 2023/11/27 00:39:42 jsg Exp $ */ |
2 | /* |
3 | * Copyright (c) 2020 Mark Kettenis |
4 | * Copyright (c) 2020 James Hastings |
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/malloc.h> |
21 | #include <sys/systm.h> |
22 | |
23 | #include <dev/acpi/acpireg.h> |
24 | #include <dev/acpi/acpivar.h> |
25 | #include <dev/acpi/acpidev.h> |
26 | #include <dev/acpi/amltypes.h> |
27 | #include <dev/acpi/dsdt.h> |
28 | |
29 | #define PCHGPIO_MAXCOM5 5 |
30 | |
31 | #define PCHGPIO_CONF_TXSTATE0x00000001 0x00000001 |
32 | #define PCHGPIO_CONF_RXSTATE0x00000002 0x00000002 |
33 | #define PCHGPIO_CONF_RXINV0x00800000 0x00800000 |
34 | #define PCHGPIO_CONF_RXEV_EDGE0x02000000 0x02000000 |
35 | #define PCHGPIO_CONF_RXEV_ZERO0x04000000 0x04000000 |
36 | #define PCHGPIO_CONF_RXEV_MASK0x06000000 0x06000000 |
37 | #define PCHGPIO_CONF_PADRSTCFG_MASK0xc0000000 0xc0000000 |
38 | |
39 | #define PCHGPIO_PADBAR0x00c 0x00c |
40 | |
41 | struct pchgpio_group { |
42 | uint8_t bar; |
43 | uint8_t bank; |
44 | uint16_t base; |
45 | uint16_t limit; |
46 | int16_t gpiobase; |
47 | }; |
48 | |
49 | struct pchgpio_device { |
50 | uint16_t pad_size; |
51 | uint16_t gpi_is; |
52 | uint16_t gpi_ie; |
53 | const struct pchgpio_group *groups; |
54 | int ngroups; |
55 | int npins; |
56 | }; |
57 | |
58 | struct pchgpio_match { |
59 | const char *hid; |
60 | const struct pchgpio_device *device; |
61 | }; |
62 | |
63 | struct pchgpio_pincfg { |
64 | uint32_t pad_cfg_dw0; |
65 | uint32_t pad_cfg_dw1; |
66 | int gpi_ie; |
67 | }; |
68 | |
69 | struct pchgpio_intrhand { |
70 | int (*ih_func)(void *); |
71 | void *ih_arg; |
72 | }; |
73 | |
74 | struct pchgpio_softc { |
75 | struct device sc_dev; |
76 | struct acpi_softc *sc_acpi; |
77 | struct aml_node *sc_node; |
78 | |
79 | bus_space_tag_t sc_memt[PCHGPIO_MAXCOM5]; |
80 | bus_space_handle_t sc_memh[PCHGPIO_MAXCOM5]; |
81 | void *sc_ih; |
82 | int sc_naddr; |
83 | |
84 | const struct pchgpio_device *sc_device; |
85 | uint16_t sc_padbar[PCHGPIO_MAXCOM5]; |
86 | uint16_t sc_padbase[PCHGPIO_MAXCOM5]; |
87 | int sc_padsize; |
88 | |
89 | int sc_npins; |
90 | struct pchgpio_pincfg *sc_pin_cfg; |
91 | struct pchgpio_intrhand *sc_pin_ih; |
92 | |
93 | struct acpi_gpio sc_gpio; |
94 | }; |
95 | |
96 | int pchgpio_match(struct device *, void *, void *); |
97 | void pchgpio_attach(struct device *, struct device *, void *); |
98 | int pchgpio_activate(struct device *, int); |
99 | |
100 | const struct cfattach pchgpio_ca = { |
101 | sizeof(struct pchgpio_softc), pchgpio_match, pchgpio_attach, |
102 | NULL((void *)0), pchgpio_activate |
103 | }; |
104 | |
105 | struct cfdriver pchgpio_cd = { |
106 | NULL((void *)0), "pchgpio", DV_DULL |
107 | }; |
108 | |
109 | const char *pchgpio_hids[] = { |
110 | "INT344B", |
111 | "INT3450", |
112 | "INT3451", |
113 | "INT345D", |
114 | "INT34BB", |
115 | "INT34C5", |
116 | "INT34C6", |
117 | "INTC1055", |
118 | "INTC1056", |
119 | "INTC1057", |
120 | "INTC1085", |
121 | NULL((void *)0) |
122 | }; |
123 | |
124 | /* Sunrisepoint-LP */ |
125 | |
126 | const struct pchgpio_group spt_lp_groups[] = |
127 | { |
128 | /* Community 0 */ |
129 | { 0, 0, 0, 23, 0 }, /* GPP_A */ |
130 | { 0, 1, 24, 47, 24 }, /* GPP_B */ |
131 | |
132 | /* Community 1 */ |
133 | { 1, 0, 48, 71, 48 }, /* GPP_C */ |
134 | { 1, 1, 72, 95, 72 }, /* GPP_D */ |
135 | { 1, 2, 96, 119, 96 }, /* GPP_E */ |
136 | |
137 | /* Community 3 */ |
138 | { 2, 0, 120, 143, 120 }, /* GPP_F */ |
139 | { 2, 1, 144, 151, 144 }, /* GPP_G */ |
140 | }; |
141 | |
142 | const struct pchgpio_device spt_lp_device = |
143 | { |
144 | .pad_size = 8, |
145 | .gpi_is = 0x100, |
146 | .gpi_ie = 0x120, |
147 | .groups = spt_lp_groups, |
148 | .ngroups = nitems(spt_lp_groups)(sizeof((spt_lp_groups)) / sizeof((spt_lp_groups)[0])), |
149 | .npins = 176, |
150 | }; |
151 | |
152 | /* Sunrisepoint-H */ |
153 | |
154 | const struct pchgpio_group spt_h_groups[] = |
155 | { |
156 | /* Community 0 */ |
157 | { 0, 0, 0, 23, 0 }, /* GPP_A */ |
158 | { 0, 1, 24, 47, 24 }, /* GPP_B */ |
159 | |
160 | /* Community 1 */ |
161 | { 1, 0, 48, 71, 48 }, /* GPP_C */ |
162 | { 1, 1, 72, 95, 72 }, /* GPP_D */ |
163 | { 1, 2, 96, 108, 96 }, /* GPP_E */ |
164 | { 1, 3, 109, 132, 120 }, /* GPP_F */ |
165 | { 1, 4, 133, 156, 144 }, /* GPP_G */ |
166 | { 1, 5, 157, 180, 168 }, /* GPP_H */ |
167 | |
168 | /* Community 3 */ |
169 | { 2, 0, 181, 191, 192 }, /* GPP_I */ |
170 | }; |
171 | |
172 | const struct pchgpio_device spt_h_device = |
173 | { |
174 | .pad_size = 8, |
175 | .gpi_is = 0x100, |
176 | .gpi_ie = 0x120, |
177 | .groups = spt_h_groups, |
178 | .ngroups = nitems(spt_h_groups)(sizeof((spt_h_groups)) / sizeof((spt_h_groups)[0])), |
179 | .npins = 224, |
180 | }; |
181 | |
182 | /* Cannon Lake-H */ |
183 | |
184 | const struct pchgpio_group cnl_h_groups[] = |
185 | { |
186 | /* Community 0 */ |
187 | { 0, 0, 0, 24, 0 }, /* GPP_A */ |
188 | { 0, 1, 25, 50, 32 }, /* GPP_B */ |
189 | |
190 | /* Community 1 */ |
191 | { 1, 0, 51, 74, 64 }, /* GPP_C */ |
192 | { 1, 1, 75, 98, 96 }, /* GPP_D */ |
193 | { 1, 2, 99, 106, 128 }, /* GPP_G */ |
194 | |
195 | /* Community 3 */ |
196 | { 2, 0, 155, 178, 192 }, /* GPP_K */ |
197 | { 2, 1, 179, 202, 224 }, /* GPP_H */ |
198 | { 2, 2, 203, 215, 256 }, /* GPP_E */ |
199 | { 2, 3, 216, 239, 288 }, /* GPP_F */ |
200 | |
201 | /* Community 4 */ |
202 | { 3, 2, 269, 286, 320 }, /* GPP_I */ |
203 | { 3, 3, 287, 298, 352 }, /* GPP_J */ |
204 | }; |
205 | |
206 | const struct pchgpio_device cnl_h_device = |
207 | { |
208 | .pad_size = 16, |
209 | .gpi_is = 0x100, |
210 | .gpi_ie = 0x120, |
211 | .groups = cnl_h_groups, |
212 | .ngroups = nitems(cnl_h_groups)(sizeof((cnl_h_groups)) / sizeof((cnl_h_groups)[0])), |
213 | .npins = 384, |
214 | }; |
215 | |
216 | /* Cannon Lake-LP */ |
217 | |
218 | const struct pchgpio_group cnl_lp_groups[] = |
219 | { |
220 | /* Community 0 */ |
221 | { 0, 0, 0, 24, 0 }, /* GPP_A */ |
222 | { 0, 1, 25, 50, 32 }, /* GPP_B */ |
223 | { 0, 2, 51, 58, 64 }, /* GPP_G */ |
224 | |
225 | /* Community 1 */ |
226 | { 1, 0, 68, 92, 96 }, /* GPP_D */ |
227 | { 1, 1, 93, 116, 128 }, /* GPP_F */ |
228 | { 1, 2, 117, 140, 160 }, /* GPP_H */ |
229 | |
230 | /* Community 4 */ |
231 | { 2, 0, 181, 204, 256 }, /* GPP_C */ |
232 | { 2, 1, 205, 228, 288 }, /* GPP_E */ |
233 | }; |
234 | |
235 | const struct pchgpio_device cnl_lp_device = |
236 | { |
237 | .pad_size = 16, |
238 | .gpi_is = 0x100, |
239 | .gpi_ie = 0x120, |
240 | .groups = cnl_lp_groups, |
241 | .ngroups = nitems(cnl_lp_groups)(sizeof((cnl_lp_groups)) / sizeof((cnl_lp_groups)[0])), |
242 | .npins = 320, |
243 | }; |
244 | |
245 | /* Tiger Lake-LP */ |
246 | |
247 | const struct pchgpio_group tgl_lp_groups[] = |
248 | { |
249 | /* Community 0 */ |
250 | { 0, 0, 0, 25, 0 }, /* GPP_B */ |
251 | { 0, 1, 26, 41, 32 }, /* GPP_T */ |
252 | { 0, 2, 42, 66, 64 }, /* GPP_A */ |
253 | |
254 | /* Community 1 */ |
255 | { 1, 0, 67, 74, 96 }, /* GPP_S */ |
256 | { 1, 1, 75, 98, 128 }, /* GPP_H */ |
257 | { 1, 2, 99, 119, 160 }, /* GPP_D */ |
258 | { 1, 3, 120, 143, 192 }, /* GPP_U */ |
259 | |
260 | /* Community 4 */ |
261 | { 2, 0, 171, 194, 256 }, /* GPP_C */ |
262 | { 2, 1, 195, 219, 288 }, /* GPP_F */ |
263 | { 2, 3, 226, 250, 320 }, /* GPP_E */ |
264 | |
265 | /* Community 5 */ |
266 | { 3, 0, 260, 267, 352 }, /* GPP_R */ |
267 | }; |
268 | |
269 | const struct pchgpio_device tgl_lp_device = |
270 | { |
271 | .pad_size = 16, |
272 | .gpi_is = 0x100, |
273 | .gpi_ie = 0x120, |
274 | .groups = tgl_lp_groups, |
275 | .ngroups = nitems(tgl_lp_groups)(sizeof((tgl_lp_groups)) / sizeof((tgl_lp_groups)[0])), |
276 | .npins = 360, |
277 | }; |
278 | |
279 | /* Tiger Lake-H */ |
280 | |
281 | const struct pchgpio_group tgl_h_groups[] = |
282 | { |
283 | /* Community 0 */ |
284 | { 0, 0, 0, 24, 0 }, /* GPP_A */ |
285 | { 0, 1, 25, 44, 32 }, /* GPP_R */ |
286 | { 0, 2, 45, 70, 64 }, /* GPP_B */ |
287 | |
288 | /* Community 1 */ |
289 | { 1, 0, 79, 104, 128 }, /* GPP_D */ |
290 | { 1, 1, 105, 128, 160 }, /* GPP_C */ |
291 | { 1, 2, 129, 136, 192 }, /* GPP_S */ |
292 | { 1, 3, 137, 153, 224 }, /* GPP_G */ |
293 | |
294 | /* Community 3 */ |
295 | { 2, 0, 181, 193, 288 }, /* GPP_E */ |
296 | { 2, 1, 194, 217, 320 }, /* GPP_F */ |
297 | |
298 | /* Community 4 */ |
299 | { 2, 0, 218, 241, 352 }, /* GPP_H */ |
300 | { 2, 1, 242, 251, 384 }, /* GPP_J */ |
301 | { 2, 2, 252, 266, 416 }, /* GPP_K */ |
302 | |
303 | /* Community 5 */ |
304 | { 3, 0, 267, 281, 448 }, /* GPP_I */ |
305 | }; |
306 | |
307 | const struct pchgpio_device tgl_h_device = |
308 | { |
309 | .pad_size = 16, |
310 | .gpi_is = 0x100, |
311 | .gpi_ie = 0x120, |
312 | .groups = tgl_h_groups, |
313 | .ngroups = nitems(tgl_h_groups)(sizeof((tgl_h_groups)) / sizeof((tgl_h_groups)[0])), |
314 | .npins = 480, |
315 | }; |
316 | |
317 | /* Alder Lake-S */ |
318 | |
319 | const struct pchgpio_group adl_s_groups[] = |
320 | { |
321 | /* Community 0 */ |
322 | { 0, 0, 0, 24, 0 }, /* GPP_I */ |
323 | { 0, 1, 25, 47, 32 }, /* GPP_R */ |
324 | { 0, 2, 48, 59, 64 }, /* GPP_J */ |
325 | |
326 | /* Community 1 */ |
327 | { 1, 0, 95, 118, 160 }, /* GPP_B */ |
328 | { 1, 1, 119, 126, 192 }, /* GPP_G */ |
329 | { 1, 2, 127, 150, 224 }, /* GPP_H */ |
330 | |
331 | /* Community 3 */ |
332 | { 2, 1, 160, 175, 256 }, /* GPP_A */ |
333 | { 2, 2, 176, 199, 288 }, /* GPP_C */ |
334 | |
335 | /* Community 4 */ |
336 | { 3, 0, 200, 207, 320 }, /* GPP_S */ |
337 | { 3, 1, 208, 230, 352 }, /* GPP_E */ |
338 | { 3, 2, 231, 245, 384 }, /* GPP_K */ |
339 | { 3, 3, 246, 269, 416 }, /* GPP_F */ |
340 | |
341 | /* Community 5 */ |
342 | { 4, 0, 270, 294, 448 }, /* GPP_D */ |
343 | }; |
344 | |
345 | const struct pchgpio_device adl_s_device = |
346 | { |
347 | .pad_size = 16, |
348 | .gpi_is = 0x200, |
349 | .gpi_ie = 0x220, |
350 | .groups = adl_s_groups, |
351 | .ngroups = nitems(adl_s_groups)(sizeof((adl_s_groups)) / sizeof((adl_s_groups)[0])), |
352 | .npins = 480, |
353 | }; |
354 | |
355 | /* Alder Lake-N */ |
356 | |
357 | const struct pchgpio_group adl_n_groups[] = |
358 | { |
359 | /* Community 0 */ |
360 | { 0, 0, 0, 25, 0 }, /* GPP_B */ |
361 | { 0, 1, 26, 41, 32 }, /* GPP_T */ |
362 | { 0, 2, 42, 66, 64 }, /* GPP_A */ |
363 | |
364 | /* Community 1 */ |
365 | { 1, 0, 67, 74, 96 }, /* GPP_S */ |
366 | { 1, 1, 75, 94, 128 }, /* GPP_I */ |
367 | { 1, 2, 95, 118, 160 }, /* GPP_H */ |
368 | { 1, 3, 119, 139, 192 }, /* GPP_D */ |
369 | |
370 | /* Community 4 */ |
371 | { 2, 0, 169, 192, 256 }, /* GPP_C */ |
372 | { 2, 1, 193, 217, 288 }, /* GPP_F */ |
373 | { 2, 3, 224, 248, 320 }, /* GPP_E */ |
374 | |
375 | /* Community 5 */ |
376 | { 3, 0, 249, 256, 352 }, /* GPP_R */ |
377 | }; |
378 | |
379 | const struct pchgpio_device adl_n_device = |
380 | { |
381 | .pad_size = 16, |
382 | .gpi_is = 0x100, |
383 | .gpi_ie = 0x120, |
384 | .groups = adl_n_groups, |
385 | .ngroups = nitems(adl_n_groups)(sizeof((adl_n_groups)) / sizeof((adl_n_groups)[0])), |
386 | .npins = 384, |
387 | }; |
388 | |
389 | struct pchgpio_match pchgpio_devices[] = { |
390 | { "INT344B", &spt_lp_device }, |
391 | { "INT3450", &cnl_h_device }, |
392 | { "INT3451", &spt_h_device }, |
393 | { "INT345D", &spt_h_device }, |
394 | { "INT34BB", &cnl_lp_device }, |
395 | { "INT34C5", &tgl_lp_device }, |
396 | { "INT34C6", &tgl_h_device }, |
397 | { "INTC1055", &tgl_lp_device }, |
398 | { "INTC1056", &adl_s_device }, |
399 | { "INTC1057", &adl_n_device }, |
400 | { "INTC1085", &adl_s_device }, |
401 | }; |
402 | |
403 | int pchgpio_read_pin(void *, int); |
404 | void pchgpio_write_pin(void *, int, int); |
405 | void pchgpio_intr_establish(void *, int, int, int (*)(void *), void *); |
406 | void pchgpio_intr_enable(void *, int); |
407 | void pchgpio_intr_disable(void *, int); |
408 | int pchgpio_intr(void *); |
409 | void pchgpio_save(struct pchgpio_softc *); |
410 | void pchgpio_restore(struct pchgpio_softc *); |
411 | |
412 | int |
413 | pchgpio_match(struct device *parent, void *match, void *aux) |
414 | { |
415 | struct acpi_attach_args *aaa = aux; |
416 | struct cfdata *cf = match; |
417 | |
418 | if (aaa->aaa_naddr < 1 || aaa->aaa_nirq < 1) |
419 | return 0; |
420 | return acpi_matchhids(aaa, pchgpio_hids, cf->cf_driver->cd_name); |
421 | } |
422 | |
423 | void |
424 | pchgpio_attach(struct device *parent, struct device *self, void *aux) |
425 | { |
426 | struct pchgpio_softc *sc = (struct pchgpio_softc *)self; |
427 | struct acpi_attach_args *aaa = aux; |
428 | uint16_t bar; |
429 | int i; |
430 | |
431 | sc->sc_acpi = (struct acpi_softc *)parent; |
432 | sc->sc_node = aaa->aaa_node; |
433 | printf(" %s", sc->sc_node->name); |
434 | |
435 | printf(" addr"); |
436 | |
437 | for (i = 0; i < aaa->aaa_naddr; i++) { |
438 | printf(" 0x%llx/0x%llx", aaa->aaa_addr[i], aaa->aaa_size[i]); |
439 | |
440 | sc->sc_memt[i] = aaa->aaa_bst[i]; |
441 | if (bus_space_map(sc->sc_memt[i], aaa->aaa_addr[i], |
442 | aaa->aaa_size[i], 0, &sc->sc_memh[i])) { |
443 | printf(": can't map registers\n"); |
444 | goto unmap; |
445 | } |
446 | |
447 | sc->sc_padbar[i] = bus_space_read_4(sc->sc_memt[i],((sc->sc_memt[i])->read_4((sc->sc_memh[i]), (0x00c)) ) |
448 | sc->sc_memh[i], PCHGPIO_PADBAR)((sc->sc_memt[i])->read_4((sc->sc_memh[i]), (0x00c)) ); |
449 | sc->sc_naddr++; |
450 | } |
451 | |
452 | printf(" irq %d", aaa->aaa_irq[0]); |
453 | |
454 | for (i = 0; i < nitems(pchgpio_devices)(sizeof((pchgpio_devices)) / sizeof((pchgpio_devices)[0])); i++) { |
455 | if (strcmp(pchgpio_devices[i].hid, aaa->aaa_dev) == 0) { |
456 | sc->sc_device = pchgpio_devices[i].device; |
457 | break; |
458 | } |
459 | } |
460 | KASSERT(sc->sc_device)((sc->sc_device) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/acpi/pchgpio.c" , 460, "sc->sc_device")); |
461 | |
462 | /* Figure out the first pin for each community. */ |
463 | bar = -1; |
464 | for (i = 0; i < sc->sc_device->ngroups; i++) { |
465 | if (sc->sc_device->groups[i].bar != bar) { |
466 | bar = sc->sc_device->groups[i].bar; |
467 | sc->sc_padbase[bar] = sc->sc_device->groups[i].base; |
468 | } |
469 | } |
470 | |
471 | sc->sc_padsize = sc->sc_device->pad_size; |
472 | sc->sc_npins = sc->sc_device->npins; |
473 | sc->sc_pin_cfg = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_cfg), |
474 | M_DEVBUF2, M_WAITOK0x0001); |
475 | sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih), |
476 | M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
477 | |
478 | sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], |
479 | IPL_BIO0x3, pchgpio_intr, sc, sc->sc_dev.dv_xname); |
480 | if (sc->sc_ih == NULL((void *)0)) { |
481 | printf(": can't establish interrupt\n"); |
482 | goto unmap; |
483 | } |
484 | |
485 | sc->sc_gpio.cookie = sc; |
486 | sc->sc_gpio.read_pin = pchgpio_read_pin; |
487 | sc->sc_gpio.write_pin = pchgpio_write_pin; |
488 | sc->sc_gpio.intr_establish = pchgpio_intr_establish; |
489 | sc->sc_gpio.intr_enable = pchgpio_intr_enable; |
490 | sc->sc_gpio.intr_disable = pchgpio_intr_disable; |
491 | sc->sc_node->gpio = &sc->sc_gpio; |
492 | |
493 | printf(", %d pins\n", sc->sc_npins); |
494 | |
495 | acpi_register_gpio(sc->sc_acpi, sc->sc_node); |
496 | return; |
497 | |
498 | unmap: |
499 | free(sc->sc_pin_ih, M_DEVBUF2, sc->sc_npins * sizeof(*sc->sc_pin_ih)); |
500 | free(sc->sc_pin_cfg, M_DEVBUF2, sc->sc_npins * sizeof(*sc->sc_pin_cfg)); |
501 | for (i = 0; i < sc->sc_naddr; i++) |
502 | bus_space_unmap(sc->sc_memt[i], sc->sc_memh[i], |
503 | aaa->aaa_size[i]); |
504 | } |
505 | |
506 | int |
507 | pchgpio_activate(struct device *self, int act) |
508 | { |
509 | struct pchgpio_softc *sc = (struct pchgpio_softc *)self; |
510 | |
511 | switch (act) { |
512 | case DVACT_SUSPEND3: |
513 | pchgpio_save(sc); |
514 | break; |
515 | case DVACT_RESUME4: |
516 | pchgpio_restore(sc); |
517 | break; |
518 | } |
519 | |
520 | return 0; |
521 | } |
522 | |
523 | const struct pchgpio_group * |
524 | pchgpio_find_group(struct pchgpio_softc *sc, int pin) |
525 | { |
526 | int i, npads; |
527 | |
528 | for (i = 0; i < sc->sc_device->ngroups; i++) { |
529 | npads = 1 + sc->sc_device->groups[i].limit - |
530 | sc->sc_device->groups[i].base; |
531 | |
532 | if (pin >= sc->sc_device->groups[i].gpiobase && |
533 | pin < sc->sc_device->groups[i].gpiobase + npads) |
534 | return &sc->sc_device->groups[i]; |
535 | } |
536 | return NULL((void *)0); |
537 | } |
538 | |
539 | int |
540 | pchgpio_read_pin(void *cookie, int pin) |
541 | { |
542 | struct pchgpio_softc *sc = cookie; |
543 | const struct pchgpio_group *group; |
544 | uint32_t reg; |
545 | uint16_t pad; |
546 | uint8_t bar; |
547 | |
548 | group = pchgpio_find_group(sc, pin); |
549 | bar = group->bar; |
550 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
551 | |
552 | reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))) |
553 | sc->sc_padbar[bar] + pad * sc->sc_padsize)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))); |
554 | |
555 | return !!(reg & PCHGPIO_CONF_RXSTATE0x00000002); |
556 | } |
557 | |
558 | void |
559 | pchgpio_write_pin(void *cookie, int pin, int value) |
560 | { |
561 | struct pchgpio_softc *sc = cookie; |
562 | const struct pchgpio_group *group; |
563 | uint32_t reg; |
564 | uint16_t pad; |
565 | uint8_t bar; |
566 | |
567 | group = pchgpio_find_group(sc, pin); |
568 | bar = group->bar; |
569 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
570 | |
571 | reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))) |
572 | sc->sc_padbar[bar] + pad * sc->sc_padsize)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))); |
573 | if (value) |
574 | reg |= PCHGPIO_CONF_TXSTATE0x00000001; |
575 | else |
576 | reg &= ~PCHGPIO_CONF_TXSTATE0x00000001; |
577 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (reg))) |
578 | sc->sc_padbar[bar] + pad * sc->sc_padsize, reg)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (reg))); |
579 | } |
580 | |
581 | void |
582 | pchgpio_intr_establish(void *cookie, int pin, int flags, |
583 | int (*func)(void *), void *arg) |
584 | { |
585 | struct pchgpio_softc *sc = cookie; |
586 | const struct pchgpio_group *group; |
587 | uint32_t reg; |
588 | uint16_t pad; |
589 | uint8_t bank, bar; |
590 | |
591 | KASSERT(pin >= 0)((pin >= 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/acpi/pchgpio.c" , 591, "pin >= 0")); |
592 | |
593 | group = pchgpio_find_group(sc, pin); |
594 | if (group == NULL((void *)0)) |
595 | return; |
596 | |
597 | bar = group->bar; |
598 | bank = group->bank; |
599 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
600 | |
601 | sc->sc_pin_ih[pin].ih_func = func; |
602 | sc->sc_pin_ih[pin].ih_arg = arg; |
603 | |
604 | reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))) |
605 | sc->sc_padbar[bar] + pad * sc->sc_padsize)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))); |
606 | reg &= ~(PCHGPIO_CONF_RXEV_MASK0x06000000 | PCHGPIO_CONF_RXINV0x00800000); |
607 | if ((flags & LR_GPIO_MODE(1L << 0)) == 1) |
608 | reg |= PCHGPIO_CONF_RXEV_EDGE0x02000000; |
609 | if ((flags & LR_GPIO_POLARITY(3L << 1)) == LR_GPIO_ACTLO(1L << 1)) |
610 | reg |= PCHGPIO_CONF_RXINV0x00800000; |
611 | if ((flags & LR_GPIO_POLARITY(3L << 1)) == LR_GPIO_ACTBOTH(2L << 1)) |
612 | reg |= PCHGPIO_CONF_RXEV_EDGE0x02000000 | PCHGPIO_CONF_RXEV_ZERO0x04000000; |
613 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (reg))) |
614 | sc->sc_padbar[bar] + pad * sc->sc_padsize, reg)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (reg))); |
615 | |
616 | reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
617 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
618 | reg |= (1 << (pin - group->gpiobase)); |
619 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (reg))) |
620 | sc->sc_device->gpi_ie + bank * 4, reg)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (reg))); |
621 | } |
622 | |
623 | void |
624 | pchgpio_intr_enable(void *cookie, int pin) |
625 | { |
626 | struct pchgpio_softc *sc = cookie; |
627 | const struct pchgpio_group *group; |
628 | uint32_t reg; |
629 | uint16_t pad; |
630 | uint8_t bank, bar; |
631 | |
632 | KASSERT(pin >= 0)((pin >= 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/acpi/pchgpio.c" , 632, "pin >= 0")); |
633 | |
634 | group = pchgpio_find_group(sc, pin); |
635 | if (group == NULL((void *)0)) |
636 | return; |
637 | |
638 | bar = group->bar; |
639 | bank = group->bank; |
640 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
Value stored to 'pad' is never read | |
641 | |
642 | reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
643 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
644 | reg |= (1 << (pin - group->gpiobase)); |
645 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (reg))) |
646 | sc->sc_device->gpi_ie + bank * 4, reg)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (reg))); |
647 | } |
648 | |
649 | void |
650 | pchgpio_intr_disable(void *cookie, int pin) |
651 | { |
652 | struct pchgpio_softc *sc = cookie; |
653 | const struct pchgpio_group *group; |
654 | uint32_t reg; |
655 | uint16_t pad; |
656 | uint8_t bank, bar; |
657 | |
658 | KASSERT(pin >= 0)((pin >= 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/acpi/pchgpio.c" , 658, "pin >= 0")); |
659 | |
660 | group = pchgpio_find_group(sc, pin); |
661 | if (group == NULL((void *)0)) |
662 | return; |
663 | |
664 | bar = group->bar; |
665 | bank = group->bank; |
666 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
667 | |
668 | reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
669 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
670 | reg &= ~(1 << (pin - group->gpiobase)); |
671 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (reg))) |
672 | sc->sc_device->gpi_ie + bank * 4, reg)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (reg))); |
673 | } |
674 | |
675 | int |
676 | pchgpio_intr_handle(struct pchgpio_softc *sc, int group, int bit) |
677 | { |
678 | uint32_t enable; |
679 | int gpiobase, pin, handled = 0; |
680 | uint8_t bank, bar; |
681 | |
682 | bar = sc->sc_device->groups[group].bar; |
683 | bank = sc->sc_device->groups[group].bank; |
684 | gpiobase = sc->sc_device->groups[group].gpiobase; |
685 | |
686 | pin = gpiobase + bit; |
687 | if (sc->sc_pin_ih[pin].ih_func) { |
688 | sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg); |
689 | handled = 1; |
690 | } else { |
691 | /* Mask unhandled interrupt */ |
692 | enable = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
693 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
694 | enable &= ~(1 << bit); |
695 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (enable))) |
696 | sc->sc_device->gpi_ie + bank * 4, enable)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (enable))); |
697 | } |
698 | |
699 | return handled; |
700 | } |
701 | |
702 | int |
703 | pchgpio_intr(void *arg) |
704 | { |
705 | struct pchgpio_softc *sc = arg; |
706 | uint32_t status, enable; |
707 | int group, bit, handled = 0; |
708 | uint16_t base, limit; |
709 | uint8_t bank, bar; |
710 | |
711 | for (group = 0; group < sc->sc_device->ngroups; group++) { |
712 | bar = sc->sc_device->groups[group].bar; |
713 | bank = sc->sc_device->groups[group].bank; |
714 | base = sc->sc_device->groups[group].base; |
715 | limit = sc->sc_device->groups[group].limit; |
716 | |
717 | status = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_is + bank * 4))) |
718 | sc->sc_device->gpi_is + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_is + bank * 4))); |
719 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_is + bank * 4), (status))) |
720 | sc->sc_device->gpi_is + bank * 4, status)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_is + bank * 4), (status))); |
721 | enable = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
722 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
723 | status &= enable; |
724 | if (status == 0) |
725 | continue; |
726 | |
727 | for (bit = 0; bit <= (limit - base); bit++) { |
728 | if (status & (1 << bit)) |
729 | handled |= pchgpio_intr_handle(sc, group, bit); |
730 | } |
731 | } |
732 | |
733 | return handled; |
734 | } |
735 | |
736 | void |
737 | pchgpio_save_pin(struct pchgpio_softc *sc, int pin) |
738 | { |
739 | const struct pchgpio_group *group; |
740 | uint32_t gpi_ie; |
741 | uint16_t pad; |
742 | uint8_t bank, bar; |
743 | |
744 | group = pchgpio_find_group(sc, pin); |
745 | if (group == NULL((void *)0)) |
746 | return; |
747 | |
748 | bar = group->bar; |
749 | bank = group->bank; |
750 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
751 | |
752 | sc->sc_pin_cfg[pin].pad_cfg_dw0 = |
753 | bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))) |
754 | sc->sc_padbar[bar] + pad * sc->sc_padsize)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))); |
755 | sc->sc_pin_cfg[pin].pad_cfg_dw1 = |
756 | bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize + 4))) |
757 | sc->sc_padbar[bar] + pad * sc->sc_padsize + 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize + 4))); |
758 | |
759 | gpi_ie = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
760 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
761 | sc->sc_pin_cfg[pin].gpi_ie = (gpi_ie & (1 << (pin - group->gpiobase))); |
762 | } |
763 | |
764 | void |
765 | pchgpio_save(struct pchgpio_softc *sc) |
766 | { |
767 | int pin; |
768 | |
769 | for (pin = 0; pin < sc->sc_npins; pin++) |
770 | pchgpio_save_pin(sc, pin); |
771 | } |
772 | |
773 | void |
774 | pchgpio_restore_pin(struct pchgpio_softc *sc, int pin) |
775 | { |
776 | const struct pchgpio_group *group; |
777 | int restore = 0; |
778 | uint32_t pad_cfg_dw0, gpi_ie; |
779 | uint16_t pad; |
780 | uint8_t bank, bar; |
781 | |
782 | group = pchgpio_find_group(sc, pin); |
783 | if (group == NULL((void *)0)) |
784 | return; |
785 | |
786 | bar = group->bar; |
787 | bank = group->bank; |
788 | pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar]; |
789 | |
790 | pad_cfg_dw0 = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))) |
791 | sc->sc_padbar[bar] + pad * sc->sc_padsize)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_padbar[bar] + pad * sc->sc_padsize))); |
792 | |
793 | if (sc->sc_pin_ih[pin].ih_func) |
794 | restore = 1; |
795 | |
796 | /* |
797 | * The BIOS on Lenovo Thinkpads based on Intel's Tiger Lake |
798 | * platform have a bug where the GPIO pin that is used for the |
799 | * touchpad interrupt gets reset when entering S3 and isn't |
800 | * properly restored upon resume. We detect this issue by |
801 | * comparing the bits in the PAD_CFG_DW0 register PADRSTCFG |
802 | * field before suspend and after resume and restore the pin |
803 | * configuration if the bits don't match. |
804 | */ |
805 | if ((sc->sc_pin_cfg[pin].pad_cfg_dw0 & PCHGPIO_CONF_PADRSTCFG_MASK0xc0000000) != |
806 | (pad_cfg_dw0 & PCHGPIO_CONF_PADRSTCFG_MASK0xc0000000)) |
807 | restore = 1; |
808 | |
809 | if (restore) { |
810 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (sc->sc_pin_cfg [pin].pad_cfg_dw0))) |
811 | sc->sc_padbar[bar] + pad * sc->sc_padsize,((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (sc->sc_pin_cfg [pin].pad_cfg_dw0))) |
812 | sc->sc_pin_cfg[pin].pad_cfg_dw0)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize), (sc->sc_pin_cfg [pin].pad_cfg_dw0))); |
813 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize + 4), (sc->sc_pin_cfg [pin].pad_cfg_dw1))) |
814 | sc->sc_padbar[bar] + pad * sc->sc_padsize + 4,((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize + 4), (sc->sc_pin_cfg [pin].pad_cfg_dw1))) |
815 | sc->sc_pin_cfg[pin].pad_cfg_dw1)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_padbar[bar] + pad * sc->sc_padsize + 4), (sc->sc_pin_cfg [pin].pad_cfg_dw1))); |
816 | |
817 | gpi_ie = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))) |
818 | sc->sc_device->gpi_ie + bank * 4)((sc->sc_memt[bar])->read_4((sc->sc_memh[bar]), (sc-> sc_device->gpi_ie + bank * 4))); |
819 | if (sc->sc_pin_cfg[pin].gpi_ie) |
820 | gpi_ie |= (1 << (pin - group->gpiobase)); |
821 | else |
822 | gpi_ie &= ~(1 << (pin - group->gpiobase)); |
823 | bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (gpi_ie))) |
824 | sc->sc_device->gpi_ie + bank * 4, gpi_ie)((sc->sc_memt[bar])->write_4((sc->sc_memh[bar]), (sc ->sc_device->gpi_ie + bank * 4), (gpi_ie))); |
825 | } |
826 | } |
827 | |
828 | void |
829 | pchgpio_restore(struct pchgpio_softc *sc) |
830 | { |
831 | int pin; |
832 | |
833 | for (pin = 0; pin < sc->sc_npins; pin++) |
834 | pchgpio_restore_pin(sc, pin); |
835 | } |