1*5349a46bSYannickV /*-
2*5349a46bSYannickV * SPDX-License-Identifier: BSD-2-Clause
3*5349a46bSYannickV *
4*5349a46bSYannickV * Copyright (c) 2026 Beckhoff Automation GmbH & Co. KG
5*5349a46bSYannickV */
6*5349a46bSYannickV
7*5349a46bSYannickV #include <sys/param.h>
8*5349a46bSYannickV #include <sys/systm.h>
9*5349a46bSYannickV #include <sys/bus.h>
10*5349a46bSYannickV #include <sys/gpio.h>
11*5349a46bSYannickV #include <sys/kernel.h>
12*5349a46bSYannickV #include <sys/module.h>
13*5349a46bSYannickV #include <sys/rman.h>
14*5349a46bSYannickV
15*5349a46bSYannickV #include <machine/bus.h>
16*5349a46bSYannickV #include <machine/resource.h>
17*5349a46bSYannickV
18*5349a46bSYannickV #include <contrib/dev/acpica/include/acpi.h>
19*5349a46bSYannickV #include <contrib/dev/acpica/include/accommon.h>
20*5349a46bSYannickV
21*5349a46bSYannickV #include <dev/acpica/acpivar.h>
22*5349a46bSYannickV #include <dev/gpio/gpiobusvar.h>
23*5349a46bSYannickV
24*5349a46bSYannickV #include "intelgpio.h"
25*5349a46bSYannickV
26*5349a46bSYannickV #include "gpio_if.h"
27*5349a46bSYannickV #include "opt_acpi.h"
28*5349a46bSYannickV
29*5349a46bSYannickV #define INTELGPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
30*5349a46bSYannickV #define INTELGPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
31*5349a46bSYannickV #define INTELGPIO_LOCK_INIT(_sc) \
32*5349a46bSYannickV mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
33*5349a46bSYannickV "intelgpio", MTX_SPIN)
34*5349a46bSYannickV #define INTELGPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
35*5349a46bSYannickV
36*5349a46bSYannickV static int
intelgpio_gpio_to_pad(struct intelgpio_softc * sc,uint32_t pin,struct resource ** res,bus_size_t * pad_off,const struct intelgpio_padgroup ** pgp)37*5349a46bSYannickV intelgpio_gpio_to_pad(struct intelgpio_softc *sc, uint32_t pin,
38*5349a46bSYannickV struct resource **res, bus_size_t *pad_off,
39*5349a46bSYannickV const struct intelgpio_padgroup **pgp)
40*5349a46bSYannickV {
41*5349a46bSYannickV const struct intelgpio_platform *plat = sc->sc_plat;
42*5349a46bSYannickV const struct intelgpio_community *com;
43*5349a46bSYannickV const struct intelgpio_padgroup *pg;
44*5349a46bSYannickV int i, j, offset, local_pad;
45*5349a46bSYannickV
46*5349a46bSYannickV for (i = 0; i < plat->ncommunities; i++) {
47*5349a46bSYannickV com = &plat->communities[i];
48*5349a46bSYannickV for (j = 0; j < com->ngroups; j++) {
49*5349a46bSYannickV pg = &com->groups[j];
50*5349a46bSYannickV if (pg->gpio_base == INTELGPIO_GPIO_NOMAP)
51*5349a46bSYannickV continue;
52*5349a46bSYannickV if (pin >= pg->gpio_base &&
53*5349a46bSYannickV pin < pg->gpio_base + pg->npads) {
54*5349a46bSYannickV if (res != NULL)
55*5349a46bSYannickV *res = sc->sc_mem_res[i];
56*5349a46bSYannickV if (pad_off != NULL) {
57*5349a46bSYannickV offset = pin - pg->gpio_base;
58*5349a46bSYannickV local_pad = (pg->first_pad + offset) -
59*5349a46bSYannickV com->groups[0].first_pad;
60*5349a46bSYannickV *pad_off = sc->sc_padbar[i] +
61*5349a46bSYannickV (local_pad * INTELGPIO_PAD_SIZE);
62*5349a46bSYannickV }
63*5349a46bSYannickV if (pgp != NULL)
64*5349a46bSYannickV *pgp = pg;
65*5349a46bSYannickV return (0);
66*5349a46bSYannickV }
67*5349a46bSYannickV }
68*5349a46bSYannickV }
69*5349a46bSYannickV return (-1);
70*5349a46bSYannickV }
71*5349a46bSYannickV
72*5349a46bSYannickV static device_t
intelgpio_get_bus(device_t dev)73*5349a46bSYannickV intelgpio_get_bus(device_t dev)
74*5349a46bSYannickV {
75*5349a46bSYannickV struct intelgpio_softc *sc;
76*5349a46bSYannickV
77*5349a46bSYannickV sc = device_get_softc(dev);
78*5349a46bSYannickV return (sc->sc_busdev);
79*5349a46bSYannickV }
80*5349a46bSYannickV
81*5349a46bSYannickV static int
intelgpio_pin_max(device_t dev,int * maxpin)82*5349a46bSYannickV intelgpio_pin_max(device_t dev, int *maxpin)
83*5349a46bSYannickV {
84*5349a46bSYannickV struct intelgpio_softc *sc;
85*5349a46bSYannickV const struct intelgpio_platform *plat;
86*5349a46bSYannickV const struct intelgpio_community *com;
87*5349a46bSYannickV const struct intelgpio_padgroup *pg;
88*5349a46bSYannickV int i, j;
89*5349a46bSYannickV
90*5349a46bSYannickV if (maxpin == NULL)
91*5349a46bSYannickV return (EINVAL);
92*5349a46bSYannickV
93*5349a46bSYannickV sc = device_get_softc(dev);
94*5349a46bSYannickV plat = sc->sc_plat;
95*5349a46bSYannickV
96*5349a46bSYannickV /* Find the last group with a valid gpio_base, skipping NOMAP */
97*5349a46bSYannickV *maxpin = 0;
98*5349a46bSYannickV for (i = 0; i < plat->ncommunities; i++) {
99*5349a46bSYannickV com = &plat->communities[i];
100*5349a46bSYannickV for (j = 0; j < com->ngroups; j++) {
101*5349a46bSYannickV pg = &com->groups[j];
102*5349a46bSYannickV if (pg->gpio_base == INTELGPIO_GPIO_NOMAP)
103*5349a46bSYannickV continue;
104*5349a46bSYannickV *maxpin = pg->gpio_base + (pg->npads - 1);
105*5349a46bSYannickV }
106*5349a46bSYannickV }
107*5349a46bSYannickV return (0);
108*5349a46bSYannickV }
109*5349a46bSYannickV
110*5349a46bSYannickV static int
intelgpio_pin_getname(device_t dev,uint32_t pin,char * name)111*5349a46bSYannickV intelgpio_pin_getname(device_t dev, uint32_t pin, char *name)
112*5349a46bSYannickV {
113*5349a46bSYannickV struct intelgpio_softc *sc;
114*5349a46bSYannickV const struct intelgpio_padgroup *pg;
115*5349a46bSYannickV int offset;
116*5349a46bSYannickV
117*5349a46bSYannickV sc = device_get_softc(dev);
118*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, NULL, NULL, &pg) != 0)
119*5349a46bSYannickV return (EINVAL);
120*5349a46bSYannickV
121*5349a46bSYannickV offset = pin - pg->gpio_base;
122*5349a46bSYannickV snprintf(name, GPIOMAXNAME, "%s%d", pg->name, offset);
123*5349a46bSYannickV return (0);
124*5349a46bSYannickV }
125*5349a46bSYannickV
126*5349a46bSYannickV static int
intelgpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)127*5349a46bSYannickV intelgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
128*5349a46bSYannickV {
129*5349a46bSYannickV struct intelgpio_softc *sc;
130*5349a46bSYannickV
131*5349a46bSYannickV sc = device_get_softc(dev);
132*5349a46bSYannickV
133*5349a46bSYannickV /*
134*5349a46bSYannickV * The getcaps function is expected to return the capabilities
135*5349a46bSYannickV * of the pin. Validate that the pin number maps to an existing
136*5349a46bSYannickV * pad first.
137*5349a46bSYannickV */
138*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, NULL, NULL, NULL) != 0)
139*5349a46bSYannickV return (EINVAL);
140*5349a46bSYannickV
141*5349a46bSYannickV *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
142*5349a46bSYannickV return (0);
143*5349a46bSYannickV }
144*5349a46bSYannickV
145*5349a46bSYannickV static int
intelgpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * flags)146*5349a46bSYannickV intelgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
147*5349a46bSYannickV {
148*5349a46bSYannickV struct intelgpio_softc *sc;
149*5349a46bSYannickV struct resource *res;
150*5349a46bSYannickV bus_size_t pad_off;
151*5349a46bSYannickV uint32_t val;
152*5349a46bSYannickV
153*5349a46bSYannickV sc = device_get_softc(dev);
154*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, &res, &pad_off, NULL) != 0)
155*5349a46bSYannickV return (EINVAL);
156*5349a46bSYannickV if (res == NULL)
157*5349a46bSYannickV return (EINVAL);
158*5349a46bSYannickV
159*5349a46bSYannickV *flags = 0;
160*5349a46bSYannickV
161*5349a46bSYannickV INTELGPIO_LOCK(sc);
162*5349a46bSYannickV val = bus_read_4(res, pad_off);
163*5349a46bSYannickV INTELGPIO_UNLOCK(sc);
164*5349a46bSYannickV
165*5349a46bSYannickV /*
166*5349a46bSYannickV * If the pad is not in GPIO mode (i.e. configured for a native
167*5349a46bSYannickV * function like PCIe, UART, I2C, etc.), report no flags. The pin
168*5349a46bSYannickV * cannot be used as GPIO without first switching it via setflags.
169*5349a46bSYannickV */
170*5349a46bSYannickV if ((val & INTELGPIO_PADCFG0_PMODE_MASK) !=
171*5349a46bSYannickV INTELGPIO_PADCFG0_PMODE_GPIO)
172*5349a46bSYannickV return (0);
173*5349a46bSYannickV
174*5349a46bSYannickV /*
175*5349a46bSYannickV * Report OUTPUT only if TX is explicitly enabled. Default to INPUT
176*5349a46bSYannickV * otherwise: a non-driving pin is considered an input from the user's
177*5349a46bSYannickV * perspective.
178*5349a46bSYannickV */
179*5349a46bSYannickV if (!(val & INTELGPIO_PADCFG0_GPIOTXDIS))
180*5349a46bSYannickV *flags = GPIO_PIN_OUTPUT;
181*5349a46bSYannickV else
182*5349a46bSYannickV *flags = GPIO_PIN_INPUT;
183*5349a46bSYannickV
184*5349a46bSYannickV return (0);
185*5349a46bSYannickV }
186*5349a46bSYannickV
187*5349a46bSYannickV static int
intelgpio_pin_setflags(device_t dev,uint32_t pin,uint32_t flags)188*5349a46bSYannickV intelgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
189*5349a46bSYannickV {
190*5349a46bSYannickV struct intelgpio_softc *sc;
191*5349a46bSYannickV struct resource *res;
192*5349a46bSYannickV bus_size_t pad_off;
193*5349a46bSYannickV uint32_t val;
194*5349a46bSYannickV
195*5349a46bSYannickV sc = device_get_softc(dev);
196*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, &res, &pad_off, NULL) != 0)
197*5349a46bSYannickV return (EINVAL);
198*5349a46bSYannickV if (res == NULL)
199*5349a46bSYannickV return (EINVAL);
200*5349a46bSYannickV
201*5349a46bSYannickV /*
202*5349a46bSYannickV * We currently only support input and output, not both simultaneously
203*5349a46bSYannickV */
204*5349a46bSYannickV if (flags & ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
205*5349a46bSYannickV return (EINVAL);
206*5349a46bSYannickV if ((flags & GPIO_PIN_INPUT) && (flags & GPIO_PIN_OUTPUT))
207*5349a46bSYannickV return (EINVAL);
208*5349a46bSYannickV
209*5349a46bSYannickV INTELGPIO_LOCK(sc);
210*5349a46bSYannickV val = bus_read_4(res, pad_off);
211*5349a46bSYannickV
212*5349a46bSYannickV /*
213*5349a46bSYannickV * Switch the pad to GPIO mode. Intel pads can operate in different
214*5349a46bSYannickV * modes (native function 1-15 or GPIO). Since setflags is only called
215*5349a46bSYannickV * when userspace or a consumer explicitly wants to use the pin as a
216*5349a46bSYannickV * GPIO, we force the pad into GPIO mode here so the direction bits
217*5349a46bSYannickV * (TXDIS/RXDIS) below take effect.
218*5349a46bSYannickV */
219*5349a46bSYannickV val &= ~INTELGPIO_PADCFG0_PMODE_MASK;
220*5349a46bSYannickV val |= INTELGPIO_PADCFG0_PMODE_GPIO;
221*5349a46bSYannickV
222*5349a46bSYannickV if (flags & GPIO_PIN_INPUT)
223*5349a46bSYannickV val &= ~INTELGPIO_PADCFG0_GPIORXDIS;
224*5349a46bSYannickV else
225*5349a46bSYannickV val |= INTELGPIO_PADCFG0_GPIORXDIS;
226*5349a46bSYannickV
227*5349a46bSYannickV if (flags & GPIO_PIN_OUTPUT)
228*5349a46bSYannickV val &= ~INTELGPIO_PADCFG0_GPIOTXDIS;
229*5349a46bSYannickV else
230*5349a46bSYannickV val |= INTELGPIO_PADCFG0_GPIOTXDIS;
231*5349a46bSYannickV
232*5349a46bSYannickV bus_write_4(res, pad_off, val);
233*5349a46bSYannickV INTELGPIO_UNLOCK(sc);
234*5349a46bSYannickV
235*5349a46bSYannickV return (0);
236*5349a46bSYannickV }
237*5349a46bSYannickV
238*5349a46bSYannickV static int
intelgpio_pin_get(device_t dev,uint32_t pin,unsigned int * value)239*5349a46bSYannickV intelgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
240*5349a46bSYannickV {
241*5349a46bSYannickV struct intelgpio_softc *sc;
242*5349a46bSYannickV struct resource *res;
243*5349a46bSYannickV bus_size_t pad_off;
244*5349a46bSYannickV uint32_t val;
245*5349a46bSYannickV
246*5349a46bSYannickV sc = device_get_softc(dev);
247*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, &res, &pad_off, NULL) != 0)
248*5349a46bSYannickV return (EINVAL);
249*5349a46bSYannickV if (res == NULL)
250*5349a46bSYannickV return (EINVAL);
251*5349a46bSYannickV
252*5349a46bSYannickV INTELGPIO_LOCK(sc);
253*5349a46bSYannickV val = bus_read_4(res, pad_off);
254*5349a46bSYannickV INTELGPIO_UNLOCK(sc);
255*5349a46bSYannickV
256*5349a46bSYannickV *value = (val & INTELGPIO_PADCFG0_GPIORXSTATE) ?
257*5349a46bSYannickV GPIO_PIN_HIGH : GPIO_PIN_LOW;
258*5349a46bSYannickV
259*5349a46bSYannickV return (0);
260*5349a46bSYannickV }
261*5349a46bSYannickV
262*5349a46bSYannickV static int
intelgpio_pin_set(device_t dev,uint32_t pin,unsigned int value)263*5349a46bSYannickV intelgpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
264*5349a46bSYannickV {
265*5349a46bSYannickV struct intelgpio_softc *sc;
266*5349a46bSYannickV struct resource *res;
267*5349a46bSYannickV bus_size_t pad_off;
268*5349a46bSYannickV uint32_t val;
269*5349a46bSYannickV
270*5349a46bSYannickV sc = device_get_softc(dev);
271*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, &res, &pad_off, NULL) != 0)
272*5349a46bSYannickV return (EINVAL);
273*5349a46bSYannickV if (res == NULL)
274*5349a46bSYannickV return (EINVAL);
275*5349a46bSYannickV
276*5349a46bSYannickV INTELGPIO_LOCK(sc);
277*5349a46bSYannickV val = bus_read_4(res, pad_off);
278*5349a46bSYannickV if (value == GPIO_PIN_LOW)
279*5349a46bSYannickV val &= ~INTELGPIO_PADCFG0_GPIOTXSTATE;
280*5349a46bSYannickV else
281*5349a46bSYannickV val |= INTELGPIO_PADCFG0_GPIOTXSTATE;
282*5349a46bSYannickV bus_write_4(res, pad_off, val);
283*5349a46bSYannickV INTELGPIO_UNLOCK(sc);
284*5349a46bSYannickV
285*5349a46bSYannickV return (0);
286*5349a46bSYannickV }
287*5349a46bSYannickV
288*5349a46bSYannickV static int
intelgpio_pin_toggle(device_t dev,uint32_t pin)289*5349a46bSYannickV intelgpio_pin_toggle(device_t dev, uint32_t pin)
290*5349a46bSYannickV {
291*5349a46bSYannickV struct intelgpio_softc *sc;
292*5349a46bSYannickV struct resource *res;
293*5349a46bSYannickV bus_size_t pad_off;
294*5349a46bSYannickV uint32_t val;
295*5349a46bSYannickV
296*5349a46bSYannickV sc = device_get_softc(dev);
297*5349a46bSYannickV if (intelgpio_gpio_to_pad(sc, pin, &res, &pad_off, NULL) != 0)
298*5349a46bSYannickV return (EINVAL);
299*5349a46bSYannickV if (res == NULL)
300*5349a46bSYannickV return (EINVAL);
301*5349a46bSYannickV
302*5349a46bSYannickV INTELGPIO_LOCK(sc);
303*5349a46bSYannickV val = bus_read_4(res, pad_off);
304*5349a46bSYannickV val ^= INTELGPIO_PADCFG0_GPIOTXSTATE;
305*5349a46bSYannickV bus_write_4(res, pad_off, val);
306*5349a46bSYannickV INTELGPIO_UNLOCK(sc);
307*5349a46bSYannickV
308*5349a46bSYannickV return (0);
309*5349a46bSYannickV }
310*5349a46bSYannickV
311*5349a46bSYannickV int
intelgpio_probe(device_t dev,const struct intelgpio_platform * plat)312*5349a46bSYannickV intelgpio_probe(device_t dev, const struct intelgpio_platform *plat)
313*5349a46bSYannickV {
314*5349a46bSYannickV int rv;
315*5349a46bSYannickV
316*5349a46bSYannickV if (acpi_disabled("intelgpio"))
317*5349a46bSYannickV return (ENXIO);
318*5349a46bSYannickV
319*5349a46bSYannickV rv = ACPI_ID_PROBE(device_get_parent(dev), dev, plat->hids, NULL);
320*5349a46bSYannickV if (rv <= 0)
321*5349a46bSYannickV device_set_desc(dev, plat->desc);
322*5349a46bSYannickV return (rv);
323*5349a46bSYannickV }
324*5349a46bSYannickV
325*5349a46bSYannickV static int
intelgpio_detach(device_t dev)326*5349a46bSYannickV intelgpio_detach(device_t dev)
327*5349a46bSYannickV {
328*5349a46bSYannickV struct intelgpio_softc *sc;
329*5349a46bSYannickV int i;
330*5349a46bSYannickV
331*5349a46bSYannickV sc = device_get_softc(dev);
332*5349a46bSYannickV
333*5349a46bSYannickV if (sc->sc_busdev != NULL)
334*5349a46bSYannickV gpiobus_detach_bus(dev);
335*5349a46bSYannickV
336*5349a46bSYannickV for (i = 0; i < sc->sc_plat->ncommunities; i++) {
337*5349a46bSYannickV if (sc->sc_mem_res[i] != NULL)
338*5349a46bSYannickV bus_release_resource(dev, SYS_RES_MEMORY, i,
339*5349a46bSYannickV sc->sc_mem_res[i]);
340*5349a46bSYannickV }
341*5349a46bSYannickV
342*5349a46bSYannickV INTELGPIO_LOCK_DESTROY(sc);
343*5349a46bSYannickV return (0);
344*5349a46bSYannickV }
345*5349a46bSYannickV
346*5349a46bSYannickV int
intelgpio_attach(device_t dev,const struct intelgpio_platform * plat)347*5349a46bSYannickV intelgpio_attach(device_t dev, const struct intelgpio_platform *plat)
348*5349a46bSYannickV {
349*5349a46bSYannickV struct intelgpio_softc *sc;
350*5349a46bSYannickV bool have_res;
351*5349a46bSYannickV int i;
352*5349a46bSYannickV
353*5349a46bSYannickV sc = device_get_softc(dev);
354*5349a46bSYannickV sc->sc_dev = dev;
355*5349a46bSYannickV sc->sc_plat = plat;
356*5349a46bSYannickV
357*5349a46bSYannickV KASSERT(plat->ncommunities <= INTELGPIO_MAX_COMMUNITIES,
358*5349a46bSYannickV ("too many communities: %d > %d", plat->ncommunities,
359*5349a46bSYannickV INTELGPIO_MAX_COMMUNITIES));
360*5349a46bSYannickV
361*5349a46bSYannickV INTELGPIO_LOCK_INIT(sc);
362*5349a46bSYannickV
363*5349a46bSYannickV have_res = false;
364*5349a46bSYannickV for (i = 0; i < plat->ncommunities; i++) {
365*5349a46bSYannickV sc->sc_mem_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
366*5349a46bSYannickV &i, RF_ACTIVE);
367*5349a46bSYannickV if (sc->sc_mem_res[i] == NULL) {
368*5349a46bSYannickV device_printf(dev,
369*5349a46bSYannickV "failed to allocate memory resource "
370*5349a46bSYannickV "for community %d\n",
371*5349a46bSYannickV i);
372*5349a46bSYannickV continue;
373*5349a46bSYannickV }
374*5349a46bSYannickV sc->sc_padbar[i] = bus_read_4(sc->sc_mem_res[i],
375*5349a46bSYannickV INTELGPIO_PADBAR_REG);
376*5349a46bSYannickV have_res = true;
377*5349a46bSYannickV }
378*5349a46bSYannickV
379*5349a46bSYannickV if (!have_res) {
380*5349a46bSYannickV device_printf(dev, "no memory resources found\n");
381*5349a46bSYannickV INTELGPIO_LOCK_DESTROY(sc);
382*5349a46bSYannickV return (ENXIO);
383*5349a46bSYannickV }
384*5349a46bSYannickV
385*5349a46bSYannickV sc->sc_busdev = gpiobus_add_bus(dev);
386*5349a46bSYannickV if (sc->sc_busdev == NULL) {
387*5349a46bSYannickV device_printf(dev, "failed to add gpiobus\n");
388*5349a46bSYannickV intelgpio_detach(dev);
389*5349a46bSYannickV return (ENXIO);
390*5349a46bSYannickV }
391*5349a46bSYannickV
392*5349a46bSYannickV bus_attach_children(dev);
393*5349a46bSYannickV
394*5349a46bSYannickV return (0);
395*5349a46bSYannickV }
396*5349a46bSYannickV
397*5349a46bSYannickV
398*5349a46bSYannickV static device_method_t intelgpio_methods[] = {
399*5349a46bSYannickV DEVMETHOD(device_detach, intelgpio_detach),
400*5349a46bSYannickV
401*5349a46bSYannickV DEVMETHOD(gpio_get_bus, intelgpio_get_bus),
402*5349a46bSYannickV DEVMETHOD(gpio_pin_max, intelgpio_pin_max),
403*5349a46bSYannickV DEVMETHOD(gpio_pin_getname, intelgpio_pin_getname),
404*5349a46bSYannickV DEVMETHOD(gpio_pin_getcaps, intelgpio_pin_getcaps),
405*5349a46bSYannickV DEVMETHOD(gpio_pin_getflags, intelgpio_pin_getflags),
406*5349a46bSYannickV DEVMETHOD(gpio_pin_setflags, intelgpio_pin_setflags),
407*5349a46bSYannickV DEVMETHOD(gpio_pin_get, intelgpio_pin_get),
408*5349a46bSYannickV DEVMETHOD(gpio_pin_set, intelgpio_pin_set),
409*5349a46bSYannickV DEVMETHOD(gpio_pin_toggle, intelgpio_pin_toggle),
410*5349a46bSYannickV
411*5349a46bSYannickV DEVMETHOD_END
412*5349a46bSYannickV };
413*5349a46bSYannickV
414*5349a46bSYannickV DEFINE_CLASS_0(intelgpio, intelgpio_driver, intelgpio_methods,
415*5349a46bSYannickV sizeof(struct intelgpio_softc));
416