xref: /freebsd/sys/dev/ftgpio/ftgpio.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2016-2023 Stormshield
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 
33 #include <sys/bus.h>
34 #include <sys/eventhandler.h>
35 #include <sys/gpio.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
40 
41 #include <machine/bus.h>
42 
43 #include <dev/gpio/gpiobusvar.h>
44 #include <dev/superio/superio.h>
45 
46 #include "gpio_if.h"
47 
48 #define GPIO_LOCK_INIT(_sc)	mtx_init(&(_sc)->mtx,	\
49 		device_get_nameunit(dev), NULL, MTX_DEF)
50 #define GPIO_LOCK_DESTROY(_sc)		mtx_destroy(&(_sc)->mtx)
51 #define GPIO_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
52 #define GPIO_UNLOCK(_sc)	mtx_unlock(&(_sc)->mtx)
53 #define GPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_OWNED)
54 #define GPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_NOTOWNED)
55 
56 /* Global register set */
57 #define GPIO4_ENABLE 0x28
58 #define GPIO3_ENABLE 0x29
59 #define FULL_UR5_UR6 0x2A
60 #define GPIO1_ENABLE 0x2B
61 #define GPIO2_ENABLE 0x2C
62 
63 /* Logical Device Numbers. */
64 #define FTGPIO_LDN_GPIO			0x06
65 
66 #define FTGPIO_MAX_GROUP 6
67 #define FTGPIO_MAX_PIN   52
68 
69 #define FTGPIO_IS_VALID_PIN(_p)  ((_p) >= 0 && (_p) <= FTGPIO_MAX_PIN)
70 #define FTGPIO_PIN_GETINDEX(_p) ((_p) & 7)
71 #define FTGPIO_PIN_GETGROUP(_p) ((_p) >> 3)
72 
73 #define FTGPIO_GPIO_CAPS (GPIO_PIN_INPUT  | GPIO_PIN_OUTPUT    | GPIO_PIN_INVIN | \
74                           GPIO_PIN_INVOUT | GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)
75 
76 #define GET_BIT(_v, _b) (((_v) >> (_b)) & 1)
77 
78 #define FTGPIO_VERBOSE_PRINTF(dev, ...)         \
79 	do {                                        \
80 		if (__predict_false(bootverbose))       \
81 			device_printf(dev, __VA_ARGS__);    \
82 	} while (0)
83 
84 /*
85  * Note that the values are important.
86  * They match actual register offsets.
87  * See p71 and p72 of F81865's datasheet.
88  */
89 #define REG_OUTPUT_ENABLE         0 /* Not for GPIO0 */
90 #define REG_OUTPUT_DATA           1
91 #define REG_PIN_STATUS            2
92 #define REG_DRIVE_ENABLE          3
93 #define REG_MODE_SELECT_1         4 /* Only for GPIO0 */
94 #define REG_MODE_SELECT_2         5 /* Only for GPIO0 */
95 #define REG_PULSE_WIDTH_SELECT_1  6 /* Only for GPIO0 */
96 #define REG_PULSE_WIDTH_SELECT_2  7 /* Only for GPIO0 */
97 #define REG_INTERRUPT_ENABLE      8 /* Only for GPIO0 */
98 #define REG_INTERRUPT_STATUS      9 /* Only for GPIO0 */
99 
100 struct ftgpio_device {
101 	uint16_t    devid;
102 	const char *descr;
103 } ftgpio_devices[] = {
104 	{
105 		.devid = 0x0704,
106 		.descr = "Fintek F81865",
107 	},
108 };
109 
110 struct ftgpio_softc {
111 	device_t			dev;
112 	device_t			busdev;
113 	struct mtx			mtx;
114 	struct gpio_pin		pins[FTGPIO_MAX_PIN + 1];
115 };
116 
117 static uint8_t
118 ftgpio_group_get_ioreg(struct ftgpio_softc *sc, uint8_t reg, unsigned group)
119 {
120 	uint8_t ioreg;
121 
122 	KASSERT((group == 0 && REG_OUTPUT_DATA <= reg && reg <= REG_INTERRUPT_STATUS) || \
123 	        (group >= 1 && reg <= REG_DRIVE_ENABLE),
124 		("%s: invalid register %u for group %u", __func__, reg, group));
125 	ioreg = (((0xf - group) << 4) + reg);
126 	return (ioreg);
127 }
128 
129 static uint8_t
130 ftgpio_group_get_output(struct ftgpio_softc *sc, unsigned group)
131 {
132 	uint8_t ioreg, val;
133 
134 	ioreg = ftgpio_group_get_ioreg(sc, REG_OUTPUT_DATA, group);
135 	val   = superio_read(sc->dev, ioreg);
136 	FTGPIO_VERBOSE_PRINTF(sc->dev, "group GPIO%u output is 0x%x (ioreg=0x%x)\n",
137 		group, val, ioreg);
138 	return (val);
139 }
140 
141 static void
142 ftgpio_group_set_output(struct ftgpio_softc *sc, unsigned group, uint8_t group_value)
143 {
144 	uint8_t ioreg;
145 
146 	ioreg = ftgpio_group_get_ioreg(sc, REG_OUTPUT_DATA, group);
147 	superio_write(sc->dev, ioreg, group_value);
148 	FTGPIO_VERBOSE_PRINTF(sc->dev, "set group GPIO%u output to 0x%x (ioreg=0x%x)\n",
149 		group, group_value, ioreg);
150 }
151 
152 static uint8_t
153 ftgpio_group_get_status(struct ftgpio_softc *sc, unsigned group)
154 {
155 	uint8_t ioreg;
156 
157 	ioreg = ftgpio_group_get_ioreg(sc, REG_PIN_STATUS, group);
158 	return (superio_read(sc->dev, ioreg));
159 }
160 
161 static void
162 ftgpio_pin_write(struct ftgpio_softc *sc, uint32_t pin_num, bool pin_value)
163 {
164 	uint32_t pin_flags;
165 	uint8_t  val;
166 	unsigned group, index;
167 
168 	GPIO_ASSERT_LOCKED(sc);
169 	index     = FTGPIO_PIN_GETINDEX(pin_num);
170 	group     = FTGPIO_PIN_GETGROUP(pin_num);
171 	pin_flags = sc->pins[pin_num].gp_flags;
172 	if ((pin_flags & (GPIO_PIN_OUTPUT)) == 0) {
173 		FTGPIO_VERBOSE_PRINTF(sc->dev, "pin %u<GPIO%u%u> is not configured for output\n",
174 			pin_num, group, index);
175 		return;
176 	}
177 
178 	FTGPIO_VERBOSE_PRINTF(sc->dev, "set pin %u<GPIO%u%u> to %s\n",
179 		pin_num, group, index, (pin_value ? "on" : "off"));
180 
181 	val = ftgpio_group_get_output(sc, group);
182 	if (!pin_value != !(pin_flags & GPIO_PIN_INVOUT))
183 		val |=  (1 << index);
184 	else
185 		val &= ~(1 << index);
186 	ftgpio_group_set_output(sc, group, val);
187 }
188 
189 static bool
190 ftgpio_pin_read(struct ftgpio_softc *sc, uint32_t pin_num)
191 {
192 	uint32_t pin_flags;
193 	unsigned group, index;
194 	uint8_t  val;
195 	bool     pin_value;
196 
197 	GPIO_ASSERT_LOCKED(sc);
198 	group     = FTGPIO_PIN_GETGROUP(pin_num);
199 	index     = FTGPIO_PIN_GETINDEX(pin_num);
200 	pin_flags = sc->pins[pin_num].gp_flags;
201 	if ((pin_flags & (GPIO_PIN_OUTPUT | GPIO_PIN_INPUT)) == 0) {
202 		FTGPIO_VERBOSE_PRINTF(sc->dev, "pin %u<GPIO%u%u> is not configured for input or output\n",
203 			pin_num, group, index);
204 		return (false);
205 	}
206 
207 	if (pin_flags & GPIO_PIN_OUTPUT)
208 		val = ftgpio_group_get_output(sc, group);
209 	else
210 		val = ftgpio_group_get_status(sc, group);
211 	pin_value = GET_BIT(val, index);
212 
213 	if (((pin_flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INVOUT)) == (GPIO_PIN_OUTPUT|GPIO_PIN_INVOUT)) ||
214 	    ((pin_flags & (GPIO_PIN_INPUT |GPIO_PIN_INVIN )) == (GPIO_PIN_INPUT |GPIO_PIN_INVIN)))
215 		pin_value = !pin_value;
216 	FTGPIO_VERBOSE_PRINTF(sc->dev, "pin %u<GPIO%u%u> is %s\n",
217 		pin_num, group, index, (pin_value ? "on" : "off"));
218 
219 	return (pin_value);
220 }
221 
222 static void
223 ftgpio_pin_set_drive(struct ftgpio_softc *sc, uint32_t pin_num, bool pin_drive)
224 {
225 	unsigned group, index;
226 	uint8_t  group_drive, ioreg;
227 
228 	index       = FTGPIO_PIN_GETINDEX(pin_num);
229 	group       = FTGPIO_PIN_GETGROUP(pin_num);
230 	ioreg		= ftgpio_group_get_ioreg(sc, REG_DRIVE_ENABLE, group);
231 	group_drive = superio_read(sc->dev, ioreg);
232 	FTGPIO_VERBOSE_PRINTF(sc->dev, "group GPIO%u drive is 0x%x (ioreg=0x%x)\n",
233 		group, group_drive, ioreg);
234 
235 	if (pin_drive)
236 		group_drive |= (1 << index);   /* push pull */
237 	else
238 		group_drive &= ~(1 << index);  /* open drain */
239 	superio_write(sc->dev, ioreg, group_drive);
240 }
241 
242 static bool
243 ftgpio_pin_is_pushpull(struct ftgpio_softc *sc, uint32_t pin_num)
244 {
245 	unsigned group, index;
246 	uint8_t  group_drive, ioreg;
247 	bool is_pushpull;
248 
249 	index       = FTGPIO_PIN_GETINDEX(pin_num);
250 	group       = FTGPIO_PIN_GETGROUP(pin_num);
251 
252 	ioreg		= ftgpio_group_get_ioreg(sc, REG_DRIVE_ENABLE, group);
253 	group_drive = superio_read(sc->dev, ioreg);
254 	FTGPIO_VERBOSE_PRINTF(sc->dev, "group GPIO%u drive is 0x%x (ioreg=0x%x)\n",
255 		group, group_drive, ioreg);
256 
257 	is_pushpull = group_drive & (1 << index);
258 	FTGPIO_VERBOSE_PRINTF(sc->dev, "pin %u<GPIO%u%u> drive is %s\n",
259 		pin_num, group, index, (is_pushpull ? "pushpull" : "opendrain"));
260 
261 	return (is_pushpull);
262 }
263 
264 static void
265 ftgpio_pin_set_io(struct ftgpio_softc *sc, uint32_t pin_num, bool pin_io)
266 {
267 	unsigned group, index;
268 	uint8_t  group_io, ioreg;
269 
270 	index = FTGPIO_PIN_GETINDEX(pin_num);
271 	group = FTGPIO_PIN_GETGROUP(pin_num);
272 	FTGPIO_VERBOSE_PRINTF(sc->dev, "set pin %u<GPIO%u%u> io to %s\n",
273 		pin_num, group, index, (pin_io ? "output" : "input"));
274 
275 	ioreg    = ftgpio_group_get_ioreg(sc, REG_OUTPUT_ENABLE, group);
276 	group_io = superio_read(sc->dev, ioreg);
277 	FTGPIO_VERBOSE_PRINTF(sc->dev, "group GPIO%u io is 0x%x (ioreg=0x%x)\n",
278 		group, group_io, ioreg);
279 	if (pin_io)
280 		group_io |=  (1 << index); /* output */
281 	else
282 		group_io &= ~(1 << index); /* input */
283 	superio_write(sc->dev, ioreg, group_io);
284 	FTGPIO_VERBOSE_PRINTF(sc->dev, "set group GPIO%u io to 0x%x (ioreg=0x%x)\n",
285 		group, group_io, ioreg);
286 }
287 
288 static bool
289 ftgpio_pin_is_output(struct ftgpio_softc *sc, uint32_t pin_num)
290 {
291 	unsigned group, index;
292 	bool is_output;
293 
294 	index = FTGPIO_PIN_GETINDEX(pin_num);
295 	group = FTGPIO_PIN_GETGROUP(pin_num);
296 
297 	is_output = ftgpio_group_get_status(sc, group) & (1 << index);
298 	FTGPIO_VERBOSE_PRINTF(sc->dev, "pin %u<GPIO%u%u> io is %s\n",
299 		pin_num, group, index, (is_output ? "output" : "input"));
300 	return (is_output);
301 }
302 
303 static int
304 ftgpio_pin_setflags(struct ftgpio_softc *sc, uint32_t pin_num, uint32_t pin_flags)
305 {
306 	/* check flags consistency */
307 	if ((pin_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
308 		(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
309 		return (EINVAL);
310 
311 	if ((pin_flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) ==
312 		(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL))
313 		return (EINVAL);
314 
315 	if (pin_flags & GPIO_PIN_OPENDRAIN)
316 		ftgpio_pin_set_drive(sc, pin_num, 0 /* open drain */);
317 	else if (pin_flags & GPIO_PIN_PUSHPULL)
318 		ftgpio_pin_set_drive(sc, pin_num, 1 /* push pull */);
319 
320 	if (pin_flags & GPIO_PIN_INPUT)
321 		ftgpio_pin_set_io(sc, pin_num, 0 /* input */);
322 	else if (pin_flags & GPIO_PIN_OUTPUT)
323 		ftgpio_pin_set_io(sc, pin_num, 1 /* output */);
324 
325 	sc->pins[pin_num].gp_flags = pin_flags;
326 
327 	return (0);
328 }
329 
330 static int
331 ftgpio_probe(device_t dev)
332 {
333 	uint16_t devid;
334 	int      i;
335 
336 	if (superio_vendor(dev) != SUPERIO_VENDOR_FINTEK)
337 		return (ENXIO);
338 	if (superio_get_type(dev) != SUPERIO_DEV_GPIO)
339 		return (ENXIO);
340 
341 	/*
342 	 * There are several GPIO devices, we attach only to one of them
343 	 * and use the rest without attaching.
344 	 */
345 	if (superio_get_ldn(dev) != FTGPIO_LDN_GPIO)
346 		return (ENXIO);
347 
348 	devid = superio_devid(dev);
349 	for (i = 0; i < nitems(ftgpio_devices); i++) {
350 		if (devid == ftgpio_devices[i].devid) {
351 			device_set_desc(dev, ftgpio_devices[i].descr);
352 			return (BUS_PROBE_DEFAULT);
353 		}
354 	}
355 	return (ENXIO);
356 }
357 
358 static int
359 ftgpio_attach(device_t dev)
360 {
361 	struct ftgpio_softc *sc;
362 	int                  i;
363 
364 	sc		= device_get_softc(dev);
365 	sc->dev = dev;
366 
367 	GPIO_LOCK_INIT(sc);
368 	GPIO_LOCK(sc);
369 
370 	for (i = 0; i <= FTGPIO_MAX_PIN; i++) {
371 		struct gpio_pin *pin;
372 
373 		pin           = &sc->pins[i];
374 		pin->gp_pin   = i;
375 		pin->gp_caps  = FTGPIO_GPIO_CAPS;
376 		pin->gp_flags = 0;
377 
378 		if (ftgpio_pin_is_output(sc, i))
379 			pin->gp_flags |= GPIO_PIN_OUTPUT;
380 		else
381 			pin->gp_flags |= GPIO_PIN_INPUT;
382 
383 		if (ftgpio_pin_is_pushpull(sc, i))
384 			pin->gp_flags |= GPIO_PIN_PUSHPULL;
385 		else
386 			pin->gp_flags |= GPIO_PIN_OPENDRAIN;
387 
388 		snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%u%u",
389 			FTGPIO_PIN_GETGROUP(i), FTGPIO_PIN_GETINDEX(i));
390 	}
391 
392 	/* Enable all groups */
393 	superio_write(sc->dev, GPIO1_ENABLE, 0xFF);
394 	superio_write(sc->dev, GPIO2_ENABLE, 0xFF);
395 	superio_write(sc->dev, GPIO3_ENABLE, 0xFF);
396 	superio_write(sc->dev, GPIO4_ENABLE, 0xFF);
397 	superio_write(sc->dev, FULL_UR5_UR6, 0x0A);
398 	FTGPIO_VERBOSE_PRINTF(sc->dev, "groups GPIO1..GPIO6 enabled\n");
399 
400 	GPIO_UNLOCK(sc);
401 	sc->busdev = gpiobus_attach_bus(dev);
402 	if (sc->busdev == NULL) {
403 		GPIO_LOCK_DESTROY(sc);
404 		return (ENXIO);
405 	}
406 
407 	return (0);
408 }
409 
410 static int
411 ftgpio_detach(device_t dev)
412 {
413 	struct ftgpio_softc *sc;
414 
415 	sc = device_get_softc(dev);
416 	gpiobus_detach_bus(dev);
417 	GPIO_ASSERT_UNLOCKED(sc);
418 	GPIO_LOCK_DESTROY(sc);
419 
420 	return (0);
421 }
422 
423 static device_t
424 ftgpio_gpio_get_bus(device_t dev)
425 {
426 	struct ftgpio_softc *sc;
427 
428 	sc = device_get_softc(dev);
429 
430 	return (sc->busdev);
431 }
432 
433 static int
434 ftgpio_gpio_pin_max(device_t dev, int *npins)
435 {
436 	*npins = FTGPIO_MAX_PIN;
437 	return (0);
438 }
439 
440 static int
441 ftgpio_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
442 {
443 	struct ftgpio_softc *sc;
444 
445 	if (!FTGPIO_IS_VALID_PIN(pin_num))
446 		return (EINVAL);
447 
448 	sc = device_get_softc(dev);
449 	GPIO_LOCK(sc);
450 	if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) {
451 		GPIO_UNLOCK(sc);
452 		return (EINVAL);
453 	}
454 	ftgpio_pin_write(sc, pin_num, pin_value);
455 	GPIO_UNLOCK(sc);
456 
457 	return (0);
458 }
459 
460 static int
461 ftgpio_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
462 {
463 	struct ftgpio_softc *sc;
464 
465 	if (!FTGPIO_IS_VALID_PIN(pin_num))
466 		return (EINVAL);
467 
468 	if (pin_value == NULL)
469 		return (EINVAL);
470 
471 	sc = device_get_softc(dev);
472 	GPIO_LOCK(sc);
473 	*pin_value = ftgpio_pin_read(sc, pin_num);
474 	GPIO_UNLOCK(sc);
475 
476 	return (0);
477 }
478 
479 static int
480 ftgpio_gpio_pin_toggle(device_t dev, uint32_t pin_num)
481 {
482 	struct ftgpio_softc *sc;
483 	bool              pin_value;
484 
485 	if (!FTGPIO_IS_VALID_PIN(pin_num))
486 		return (EINVAL);
487 
488 	sc = device_get_softc(dev);
489 	GPIO_LOCK(sc);
490 	pin_value = ftgpio_pin_read(sc, pin_num);
491 	ftgpio_pin_write(sc, pin_num, !pin_value);
492 	GPIO_UNLOCK(sc);
493 
494 	return (0);
495 }
496 
497 static int
498 ftgpio_gpio_pin_getname(device_t dev, uint32_t pin_num, char *pin_name)
499 {
500 	struct ftgpio_softc *sc;
501 
502 	if (pin_name == NULL)
503 		return (EINVAL);
504 
505 	if (!FTGPIO_IS_VALID_PIN(pin_num))
506 		return (EINVAL);
507 
508 	sc = device_get_softc(dev);
509 	strlcpy(pin_name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
510 
511 	return (0);
512 }
513 
514 static int
515 ftgpio_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *pin_caps)
516 {
517 	struct ftgpio_softc *sc;
518 
519 	if (pin_caps == NULL)
520 		return (EINVAL);
521 
522 	if (!FTGPIO_IS_VALID_PIN(pin_num))
523 		return (EINVAL);
524 
525 	sc        = device_get_softc(dev);
526 	*pin_caps = sc->pins[pin_num].gp_caps;
527 
528 	return (0);
529 }
530 
531 static int
532 ftgpio_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *pin_flags)
533 {
534 	struct ftgpio_softc *sc;
535 
536 	if (pin_flags == NULL)
537 		return (EINVAL);
538 
539 	if (!FTGPIO_IS_VALID_PIN(pin_num))
540 		return (EINVAL);
541 
542 	sc         = device_get_softc(dev);
543 	*pin_flags = sc->pins[pin_num].gp_flags;
544 
545 	return (0);
546 }
547 
548 static int
549 ftgpio_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t pin_flags)
550 {
551 	struct ftgpio_softc *sc;
552 	int               ret;
553 
554 	if (!FTGPIO_IS_VALID_PIN(pin_num)) {
555 		FTGPIO_VERBOSE_PRINTF(dev, "invalid pin number: %u\n", pin_num);
556 		return (EINVAL);
557 	}
558 
559 	sc = device_get_softc(dev);
560 
561 	/* Check for unwanted flags. */
562 	if ((pin_flags & sc->pins[pin_num].gp_caps) != pin_flags) {
563 		FTGPIO_VERBOSE_PRINTF(dev, "invalid pin flags 0x%x, vs caps 0x%x\n",
564 			pin_flags, sc->pins[pin_num].gp_caps);
565 		return (EINVAL);
566 	}
567 
568 	GPIO_LOCK(sc);
569 	ret = ftgpio_pin_setflags(sc, pin_num, pin_flags);
570 	GPIO_UNLOCK(sc);
571 
572 	return (ret);
573 }
574 
575 static device_method_t ftgpio_methods[] = {
576 	/* Device interface */
577 	DEVMETHOD(device_probe,     ftgpio_probe),
578 	DEVMETHOD(device_attach,    ftgpio_attach),
579 	DEVMETHOD(device_detach,    ftgpio_detach),
580 
581 	/* GPIO */
582 	DEVMETHOD(gpio_get_bus,         ftgpio_gpio_get_bus),
583 	DEVMETHOD(gpio_pin_max,         ftgpio_gpio_pin_max),
584 	DEVMETHOD(gpio_pin_set,         ftgpio_gpio_pin_set),
585 	DEVMETHOD(gpio_pin_get,         ftgpio_gpio_pin_get),
586 	DEVMETHOD(gpio_pin_toggle,      ftgpio_gpio_pin_toggle),
587 	DEVMETHOD(gpio_pin_getname,     ftgpio_gpio_pin_getname),
588 	DEVMETHOD(gpio_pin_getcaps,     ftgpio_gpio_pin_getcaps),
589 	DEVMETHOD(gpio_pin_getflags,    ftgpio_gpio_pin_getflags),
590 	DEVMETHOD(gpio_pin_setflags,    ftgpio_gpio_pin_setflags),
591 
592 	DEVMETHOD_END
593 };
594 
595 static driver_t ftgpio_driver = {
596 	"gpio",
597 	ftgpio_methods,
598 	sizeof(struct ftgpio_softc)
599 };
600 
601 DRIVER_MODULE(ftgpio, superio, ftgpio_driver, NULL,  NULL);
602 MODULE_DEPEND(ftgpio, gpiobus, 1, 1, 1);
603 MODULE_DEPEND(ftgpio, superio, 1, 1, 1);
604 MODULE_VERSION(ftgpio, 1);
605