xref: /openbsd-src/sys/dev/acpi/pchgpio.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /*	$OpenBSD: pchgpio.c,v 1.9 2021/12/07 18:06:08 kettenis 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_MAXCOM		5
30 
31 #define PCHGPIO_CONF_TXSTATE		0x00000001
32 #define PCHGPIO_CONF_RXSTATE		0x00000002
33 #define PCHGPIO_CONF_RXINV		0x00800000
34 #define PCHGPIO_CONF_RXEV_EDGE		0x02000000
35 #define PCHGPIO_CONF_RXEV_ZERO		0x04000000
36 #define PCHGPIO_CONF_RXEV_MASK		0x06000000
37 #define PCHGPIO_CONF_PADRSTCFG_MASK	0xc0000000
38 
39 #define PCHGPIO_PADBAR		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_MAXCOM];
80 	bus_space_handle_t sc_memh[PCHGPIO_MAXCOM];
81 	void *sc_ih;
82 	int sc_naddr;
83 
84 	const struct pchgpio_device *sc_device;
85 	uint16_t sc_padbar[PCHGPIO_MAXCOM];
86 	uint16_t sc_padbase[PCHGPIO_MAXCOM];
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 struct cfattach pchgpio_ca = {
101 	sizeof(struct pchgpio_softc), pchgpio_match, pchgpio_attach,
102 	NULL, pchgpio_activate
103 };
104 
105 struct cfdriver pchgpio_cd = {
106 	NULL, "pchgpio", DV_DULL
107 };
108 
109 const char *pchgpio_hids[] = {
110 	"INT3450",
111 	"INT34BB",
112 	"INT34C5",
113 	"INT34C6",
114 	NULL
115 };
116 
117 const struct pchgpio_group cnl_h_groups[] =
118 {
119 	/* Community 0 */
120 	{ 0, 0, 0, 24, 0 },		/* GPP_A */
121 	{ 0, 1, 25, 50, 32 },		/* GPP_B */
122 
123 	/* Community 1 */
124 	{ 1, 0, 51, 74, 64 },		/* GPP_C */
125 	{ 1, 1, 75, 98, 96 },		/* GPP_D */
126 	{ 1, 2, 99, 106, 128 },		/* GPP_G */
127 
128 	/* Community 3 */
129 	{ 2, 0, 155, 178, 192 },	/* GPP_K */
130 	{ 2, 1, 179, 202, 224 },	/* GPP_H */
131 	{ 2, 2, 203, 215, 256 },	/* GPP_E */
132 	{ 2, 3, 216, 239, 288 },	/* GPP_F */
133 
134 	/* Community 4 */
135 	{ 3, 2, 269, 286, 320 },	/* GPP_I */
136 	{ 3, 3, 287, 298, 352 },	/* GPP_J */
137 };
138 
139 const struct pchgpio_device cnl_h_device =
140 {
141 	.pad_size = 16,
142 	.gpi_is = 0x100,
143 	.gpi_ie = 0x120,
144 	.groups = cnl_h_groups,
145 	.ngroups = nitems(cnl_h_groups),
146 	.npins = 384,
147 };
148 
149 const struct pchgpio_group cnl_lp_groups[] =
150 {
151 	/* Community 0 */
152 	{ 0, 0, 0, 24, 0 },		/* GPP_A */
153 	{ 0, 1, 25, 50, 32 },		/* GPP_B */
154 	{ 0, 2, 51, 58, 64 },		/* GPP_G */
155 
156 	/* Community 1 */
157 	{ 1, 0, 68, 92, 96 },		/* GPP_D */
158 	{ 1, 1, 93, 116, 128 },		/* GPP_F */
159 	{ 1, 2, 117, 140, 160 },	/* GPP_H */
160 
161 	/* Community 4 */
162 	{ 2, 0, 181, 204, 256 },	/* GPP_C */
163 	{ 2, 1, 205, 228, 288 },	/* GPP_E */
164 };
165 
166 const struct pchgpio_device cnl_lp_device =
167 {
168 	.pad_size = 16,
169 	.gpi_is = 0x100,
170 	.gpi_ie = 0x120,
171 	.groups = cnl_lp_groups,
172 	.ngroups = nitems(cnl_lp_groups),
173 	.npins = 320,
174 };
175 
176 const struct pchgpio_group tgl_lp_groups[] =
177 {
178 	/* Community 0 */
179 	{ 0, 0, 0, 25, 0 },		/* GPP_B */
180 	{ 0, 1, 26, 41, 32 },		/* GPP_T */
181 	{ 0, 2, 42, 66, 64 },		/* GPP_A */
182 
183 	/* Community 1 */
184 	{ 1, 0, 67, 74, 96 },		/* GPP_S */
185 	{ 1, 1, 75, 98, 128 },		/* GPP_H */
186 	{ 1, 2, 99, 119, 160 },		/* GPP_D */
187 	{ 1, 3, 120, 143, 192 },	/* GPP_U */
188 
189 	/* Community 4 */
190 	{ 2, 0, 171, 194, 256 },	/* GPP_C */
191 	{ 2, 1, 195, 219, 288 },	/* GPP_F */
192 	{ 2, 3, 226, 250, 320 },	/* GPP_E */
193 
194 	/* Community 5 */
195 	{ 3, 0, 260, 267, 352 },	/* GPP_R */
196 };
197 
198 const struct pchgpio_device tgl_lp_device =
199 {
200 	.pad_size = 16,
201 	.gpi_is = 0x100,
202 	.gpi_ie = 0x120,
203 	.groups = tgl_lp_groups,
204 	.ngroups = nitems(tgl_lp_groups),
205 	.npins = 360,
206 };
207 
208 const struct pchgpio_group tgl_h_groups[] =
209 {
210 	/* Community 0 */
211 	{ 0, 0, 0, 24, 0 },		/* GPP_A */
212 	{ 0, 1, 25, 44, 32 },		/* GPP_R */
213 	{ 0, 2, 45, 70, 64 },		/* GPP_B */
214 
215 	/* Community 1 */
216 	{ 1, 0, 79, 104, 128 },		/* GPP_D */
217 	{ 1, 1, 105, 128, 160 },	/* GPP_C */
218 	{ 1, 2, 129, 136, 192 },	/* GPP_S */
219 	{ 1, 3, 137, 153, 224 },	/* GPP_G */
220 
221 	/* Community 3 */
222 	{ 2, 0, 181, 193, 288 },	/* GPP_E */
223 	{ 2, 1, 194, 217, 320 },	/* GPP_F */
224 
225 	/* Community 4 */
226 	{ 2, 0, 218, 241, 352 },	/* GPP_H */
227 	{ 2, 1, 242, 251, 384 },	/* GPP_J */
228 	{ 2, 2, 252, 266, 416 },	/* GPP_K */
229 
230 	/* Community 5 */
231 	{ 3, 0, 267, 281, 448 },	/* GPP_I */
232 };
233 
234 const struct pchgpio_device tgl_h_device =
235 {
236 	.pad_size = 16,
237 	.gpi_is = 0x100,
238 	.gpi_ie = 0x120,
239 	.groups = tgl_h_groups,
240 	.ngroups = nitems(tgl_h_groups),
241 	.npins = 480,
242 };
243 
244 struct pchgpio_match pchgpio_devices[] = {
245 	{ "INT3450", &cnl_h_device },
246 	{ "INT34BB", &cnl_lp_device },
247 	{ "INT34C5", &tgl_lp_device },
248 	{ "INT34C6", &tgl_h_device },
249 };
250 
251 int	pchgpio_read_pin(void *, int);
252 void	pchgpio_write_pin(void *, int, int);
253 void	pchgpio_intr_establish(void *, int, int, int (*)(void *), void *);
254 int	pchgpio_intr(void *);
255 void	pchgpio_save(struct pchgpio_softc *);
256 void	pchgpio_restore(struct pchgpio_softc *);
257 
258 int
259 pchgpio_match(struct device *parent, void *match, void *aux)
260 {
261 	struct acpi_attach_args *aaa = aux;
262 	struct cfdata *cf = match;
263 
264 	return acpi_matchhids(aaa, pchgpio_hids, cf->cf_driver->cd_name);
265 }
266 
267 void
268 pchgpio_attach(struct device *parent, struct device *self, void *aux)
269 {
270 	struct pchgpio_softc *sc = (struct pchgpio_softc *)self;
271 	struct acpi_attach_args *aaa = aux;
272 	uint16_t bar;
273 	int i;
274 
275 	sc->sc_acpi = (struct acpi_softc *)parent;
276 	sc->sc_node = aaa->aaa_node;
277 	printf(" %s", sc->sc_node->name);
278 
279 	if (aaa->aaa_naddr < 1) {
280 		printf(": no registers\n");
281 		return;
282 	}
283 
284 	if (aaa->aaa_nirq < 1) {
285 		printf(": no interrupt\n");
286 		return;
287 	}
288 
289 	printf(" addr");
290 
291 	for (i = 0; i < aaa->aaa_naddr; i++) {
292 		printf(" 0x%llx/0x%llx", aaa->aaa_addr[i], aaa->aaa_size[i]);
293 
294 		sc->sc_memt[i] = aaa->aaa_bst[i];
295 		if (bus_space_map(sc->sc_memt[i], aaa->aaa_addr[i],
296 		    aaa->aaa_size[i], 0, &sc->sc_memh[i])) {
297 			printf(": can't map registers\n");
298 			goto unmap;
299 		}
300 
301 		sc->sc_padbar[i] = bus_space_read_4(sc->sc_memt[i],
302 		    sc->sc_memh[i], PCHGPIO_PADBAR);
303 		sc->sc_naddr++;
304 	}
305 
306 	printf(" irq %d", aaa->aaa_irq[0]);
307 
308 	for (i = 0; i < nitems(pchgpio_devices); i++) {
309 		if (strcmp(pchgpio_devices[i].hid, aaa->aaa_dev) == 0) {
310 			sc->sc_device = pchgpio_devices[i].device;
311 			break;
312 		}
313 	}
314 	KASSERT(sc->sc_device);
315 
316 	/* Figure out the first pin for each community. */
317 	bar = -1;
318 	for (i = 0; i < sc->sc_device->ngroups; i++) {
319 		if (sc->sc_device->groups[i].bar != bar) {
320 			bar = sc->sc_device->groups[i].bar;
321 			sc->sc_padbase[bar] = sc->sc_device->groups[i].base;
322 		}
323 	}
324 
325 	sc->sc_padsize = sc->sc_device->pad_size;
326 	sc->sc_npins = sc->sc_device->npins;
327 	sc->sc_pin_cfg = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_cfg),
328 	    M_DEVBUF, M_WAITOK);
329 	sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih),
330 	    M_DEVBUF, M_WAITOK | M_ZERO);
331 
332 	sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0],
333 	    IPL_BIO, pchgpio_intr, sc, sc->sc_dev.dv_xname);
334 	if (sc->sc_ih == NULL) {
335 		printf(": can't establish interrupt\n");
336 		goto unmap;
337 	}
338 
339 	sc->sc_gpio.cookie = sc;
340 	sc->sc_gpio.read_pin = pchgpio_read_pin;
341 	sc->sc_gpio.write_pin = pchgpio_write_pin;
342 	sc->sc_gpio.intr_establish = pchgpio_intr_establish;
343 	sc->sc_node->gpio = &sc->sc_gpio;
344 
345 	printf(", %d pins\n", sc->sc_npins);
346 
347 	acpi_register_gpio(sc->sc_acpi, sc->sc_node);
348 	return;
349 
350 unmap:
351 	free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih));
352 	free(sc->sc_pin_cfg, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_cfg));
353 	for (i = 0; i < sc->sc_naddr; i++)
354 		bus_space_unmap(sc->sc_memt[i], sc->sc_memh[i],
355 		    aaa->aaa_size[i]);
356 }
357 
358 int
359 pchgpio_activate(struct device *self, int act)
360 {
361 	struct pchgpio_softc *sc = (struct pchgpio_softc *)self;
362 
363 	switch (act) {
364 	case DVACT_SUSPEND:
365 		pchgpio_save(sc);
366 		break;
367 	case DVACT_RESUME:
368 		pchgpio_restore(sc);
369 		break;
370 	}
371 
372 	return 0;
373 }
374 
375 const struct pchgpio_group *
376 pchgpio_find_group(struct pchgpio_softc *sc, int pin)
377 {
378 	int i, npads;
379 
380 	for (i = 0; i < sc->sc_device->ngroups; i++) {
381 		npads = 1 + sc->sc_device->groups[i].limit -
382 		    sc->sc_device->groups[i].base;
383 
384 		if (pin >= sc->sc_device->groups[i].gpiobase &&
385 		    pin < sc->sc_device->groups[i].gpiobase + npads)
386 			return &sc->sc_device->groups[i];
387 	}
388 	return NULL;
389 }
390 
391 int
392 pchgpio_read_pin(void *cookie, int pin)
393 {
394 	struct pchgpio_softc *sc = cookie;
395 	const struct pchgpio_group *group;
396 	uint32_t reg;
397 	uint16_t pad;
398 	uint8_t bar;
399 
400 	group = pchgpio_find_group(sc, pin);
401 	bar = group->bar;
402 	pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
403 
404 	reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
405 	    sc->sc_padbar[bar] + pad * sc->sc_padsize);
406 
407 	return !!(reg & PCHGPIO_CONF_RXSTATE);
408 }
409 
410 void
411 pchgpio_write_pin(void *cookie, int pin, int value)
412 {
413 	struct pchgpio_softc *sc = cookie;
414 	const struct pchgpio_group *group;
415 	uint32_t reg;
416 	uint16_t pad;
417 	uint8_t bar;
418 
419 	group = pchgpio_find_group(sc, pin);
420 	bar = group->bar;
421 	pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
422 
423 	reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
424 	    sc->sc_padbar[bar] + pad * sc->sc_padsize);
425 	if (value)
426 		reg |= PCHGPIO_CONF_TXSTATE;
427 	else
428 		reg &= ~PCHGPIO_CONF_TXSTATE;
429 	bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
430 	    sc->sc_padbar[bar] + pad * sc->sc_padsize, reg);
431 }
432 
433 void
434 pchgpio_intr_establish(void *cookie, int pin, int flags,
435     int (*func)(void *), void *arg)
436 {
437 	struct pchgpio_softc *sc = cookie;
438 	const struct pchgpio_group *group;
439 	uint32_t reg;
440 	uint16_t pad;
441 	uint8_t bank, bar;
442 
443 	KASSERT(pin >= 0);
444 
445 	group = pchgpio_find_group(sc, pin);
446 	if (group == NULL)
447 		return;
448 
449 	bar = group->bar;
450 	bank = group->bank;
451 	pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
452 
453 	sc->sc_pin_ih[pin].ih_func = func;
454 	sc->sc_pin_ih[pin].ih_arg = arg;
455 
456 	reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
457 	    sc->sc_padbar[bar] + pad * sc->sc_padsize);
458 	reg &= ~(PCHGPIO_CONF_RXEV_MASK | PCHGPIO_CONF_RXINV);
459 	if ((flags & LR_GPIO_MODE) == 1)
460 		reg |= PCHGPIO_CONF_RXEV_EDGE;
461 	if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO)
462 		reg |= PCHGPIO_CONF_RXINV;
463 	if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH)
464 		reg |= PCHGPIO_CONF_RXEV_EDGE | PCHGPIO_CONF_RXEV_ZERO;
465 	bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
466 	    sc->sc_padbar[bar] + pad * sc->sc_padsize, reg);
467 
468 	reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
469 	    sc->sc_device->gpi_ie + bank * 4);
470 	reg |= (1 << (pin - group->gpiobase));
471 	bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
472 	    sc->sc_device->gpi_ie + bank * 4, reg);
473 }
474 
475 int
476 pchgpio_intr(void *arg)
477 {
478 	struct pchgpio_softc *sc = arg;
479 	uint32_t status, enable;
480 	int gpiobase, group, bit, pin, handled = 0;
481 	uint16_t base, limit;
482 	uint8_t bank, bar;
483 
484 	for (group = 0; group < sc->sc_device->ngroups; group++) {
485 		bar = sc->sc_device->groups[group].bar;
486 		bank = sc->sc_device->groups[group].bank;
487 		base = sc->sc_device->groups[group].base;
488 		limit = sc->sc_device->groups[group].limit;
489 		gpiobase = sc->sc_device->groups[group].gpiobase;
490 
491 		status = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
492 		    sc->sc_device->gpi_is + bank * 4);
493 		bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
494 		    sc->sc_device->gpi_is + bank * 4, status);
495 		enable = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
496 		    sc->sc_device->gpi_ie + bank * 4);
497 		status &= enable;
498 		if (status == 0)
499 			continue;
500 
501 		for (bit = 0; bit <= (limit - base); bit++) {
502 			pin = gpiobase + bit;
503 			if (status & (1 << bit) && sc->sc_pin_ih[pin].ih_func)
504 				sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg);
505 			handled = 1;
506 		}
507 	}
508 
509 	return handled;
510 }
511 
512 void
513 pchgpio_save_pin(struct pchgpio_softc *sc, int pin)
514 {
515 	const struct pchgpio_group *group;
516 	uint32_t gpi_ie;
517 	uint16_t pad;
518 	uint8_t bank, bar;
519 
520 	group = pchgpio_find_group(sc, pin);
521 	if (group == NULL)
522 		return;
523 
524 	bar = group->bar;
525 	bank = group->bank;
526 	pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
527 
528 	sc->sc_pin_cfg[pin].pad_cfg_dw0 =
529 	    bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
530 		sc->sc_padbar[bar] + pad * sc->sc_padsize);
531 	sc->sc_pin_cfg[pin].pad_cfg_dw1 =
532 	    bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
533 		sc->sc_padbar[bar] + pad * sc->sc_padsize + 4);
534 
535 	gpi_ie = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
536 	    sc->sc_device->gpi_ie + bank * 4);
537 	sc->sc_pin_cfg[pin].gpi_ie = (gpi_ie & (1 << (pin - group->gpiobase)));
538 }
539 
540 void
541 pchgpio_save(struct pchgpio_softc *sc)
542 {
543 	int pin;
544 
545 	for (pin = 0; pin < sc->sc_npins; pin++)
546 		pchgpio_save_pin(sc, pin);
547 }
548 
549 void
550 pchgpio_restore_pin(struct pchgpio_softc *sc, int pin)
551 {
552 	const struct pchgpio_group *group;
553 	int restore = 0;
554 	uint32_t pad_cfg_dw0, gpi_ie;
555 	uint16_t pad;
556 	uint8_t bank, bar;
557 
558 	group = pchgpio_find_group(sc, pin);
559 	if (group == NULL)
560 		return;
561 
562 	bar = group->bar;
563 	bank = group->bank;
564 	pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
565 
566 	pad_cfg_dw0 = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
567 	    sc->sc_padbar[bar] + pad * sc->sc_padsize);
568 
569 	if (sc->sc_pin_ih[pin].ih_func)
570 		restore = 1;
571 
572 	/*
573 	 * The BIOS on Lenovo Thinkpads based on Intel's Tiger Lake
574 	 * platform have a bug where the GPIO pin that is used for the
575 	 * touchpad interrupt gets reset when entering S3 and isn't
576 	 * properly restored upon resume.  We detect this issue by
577 	 * comparing the bits in the PAD_CFG_DW0 register PADRSTCFG
578 	 * field before suspend and after resume and restore the pin
579 	 * configuration if the bits don't match.
580 	 */
581 	if ((sc->sc_pin_cfg[pin].pad_cfg_dw0 & PCHGPIO_CONF_PADRSTCFG_MASK) !=
582 	    (pad_cfg_dw0 & PCHGPIO_CONF_PADRSTCFG_MASK))
583 		restore = 1;
584 
585 	if (restore) {
586 		bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
587 		    sc->sc_padbar[bar] + pad * sc->sc_padsize,
588 		    sc->sc_pin_cfg[pin].pad_cfg_dw0);
589 		bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
590 		    sc->sc_padbar[bar] + pad * sc->sc_padsize + 4,
591 		    sc->sc_pin_cfg[pin].pad_cfg_dw1);
592 
593 		gpi_ie = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
594 		    sc->sc_device->gpi_ie + bank * 4);
595 		if (sc->sc_pin_cfg[pin].gpi_ie)
596 			gpi_ie |= (1 << (pin - group->gpiobase));
597 		else
598 			gpi_ie &= ~(1 << (pin - group->gpiobase));
599 		bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
600 		    sc->sc_device->gpi_ie + bank * 4, gpi_ie);
601 	}
602 }
603 
604 void
605 pchgpio_restore(struct pchgpio_softc *sc)
606 {
607 	int pin;
608 
609 	for (pin = 0; pin < sc->sc_npins; pin++)
610 		pchgpio_restore_pin(sc, pin);
611 }
612