xref: /freebsd/sys/dev/nctgpio/nctgpio.c (revision 6be3386466ab79a84b48429ae66244f21526d3df)
1 /*-
2  * Copyright (c) 2016 Daniel Wyatt <Daniel.Wyatt@gmail.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
29 
30 /*
31  * Nuvoton GPIO driver.
32  *
33  */
34 
35 #include <sys/cdefs.h>
36 
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/bus.h>
41 #include <sys/eventhandler.h>
42 #include <sys/lock.h>
43 
44 #include <sys/module.h>
45 #include <sys/gpio.h>
46 
47 #include <machine/bus.h>
48 
49 #include <dev/gpio/gpiobusvar.h>
50 #include <dev/superio/superio.h>
51 
52 #include "gpio_if.h"
53 
54 /* Logical Device Numbers. */
55 #define NCT_LDN_GPIO			0x07
56 #define NCT_LDN_GPIO_MODE		0x0f
57 
58 /* Logical Device 7 */
59 #define NCT_LD7_GPIO0_IOR		0xe0
60 #define NCT_LD7_GPIO0_DAT		0xe1
61 #define NCT_LD7_GPIO0_INV		0xe2
62 #define NCT_LD7_GPIO0_DST		0xe3
63 #define NCT_LD7_GPIO1_IOR		0xe4
64 #define NCT_LD7_GPIO1_DAT		0xe5
65 #define NCT_LD7_GPIO1_INV		0xe6
66 #define NCT_LD7_GPIO1_DST		0xe7
67 
68 /* Logical Device F */
69 #define NCT_LDF_GPIO0_OUTCFG		0xe0
70 #define NCT_LDF_GPIO1_OUTCFG		0xe1
71 
72 /* Direct I/O port access. */
73 #define	NCT_IO_GSR			0
74 #define	NCT_IO_IOR			1
75 #define	NCT_IO_DAT			2
76 #define	NCT_IO_INV			3
77 
78 #define NCT_MAX_PIN			15
79 #define NCT_IS_VALID_PIN(_p)	((_p) >= 0 && (_p) <= NCT_MAX_PIN)
80 
81 #define NCT_PIN_BIT(_p)         (1 << ((_p) & 7))
82 
83 #define NCT_GPIO_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
84 	GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \
85 	GPIO_PIN_INVIN | GPIO_PIN_INVOUT)
86 
87 /*
88  * Note that the values are important.
89  * They match actual register offsets.
90  */
91 typedef enum {
92 	REG_IOR = 0,
93 	REG_DAT = 1,
94 	REG_INV = 2,
95 } reg_t;
96 
97 struct nct_softc {
98 	device_t			dev;
99 	device_t			dev_f;
100 	device_t			busdev;
101 	struct mtx			mtx;
102 	struct resource			*iores;
103 	int				iorid;
104 	int				curgrp;
105 	struct {
106 		/* direction, 1: pin is input */
107 		uint8_t			ior[2];
108 		/* output value */
109 		uint8_t			out[2];
110 		/* whether out is valid */
111 		uint8_t			out_known[2];
112 		/* inversion, 1: pin is inverted */
113 		uint8_t			inv[2];
114 	} 				cache;
115 	struct gpio_pin			pins[NCT_MAX_PIN + 1];
116 };
117 
118 #define GPIO_LOCK_INIT(_sc)	mtx_init(&(_sc)->mtx,		\
119 		device_get_nameunit(dev), NULL, MTX_DEF)
120 #define GPIO_LOCK_DESTROY(_sc)		mtx_destroy(&(_sc)->mtx)
121 #define GPIO_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
122 #define GPIO_UNLOCK(_sc)	mtx_unlock(&(_sc)->mtx)
123 #define GPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_OWNED)
124 #define GPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_NOTOWNED)
125 
126 struct nuvoton_vendor_device_id {
127 	uint16_t		chip_id;
128 	const char *		descr;
129 } nct_devs[] = {
130 	{
131 		.chip_id	= 0x1061,
132 		.descr		= "Nuvoton NCT5104D",
133 	},
134 	{
135 		.chip_id	= 0xc452,
136 		.descr		= "Nuvoton NCT5104D (PC-Engines APU)",
137 	},
138 	{
139 		.chip_id	= 0xc453,
140 		.descr		= "Nuvoton NCT5104D (PC-Engines APU3)",
141 	},
142 };
143 
144 static void
145 nct_io_set_group(struct nct_softc *sc, int group)
146 {
147 
148 	GPIO_ASSERT_LOCKED(sc);
149 	if (group != sc->curgrp) {
150 		bus_write_1(sc->iores, NCT_IO_GSR, group);
151 		sc->curgrp = group;
152 	}
153 }
154 
155 static uint8_t
156 nct_io_read(struct nct_softc *sc, int group, uint8_t reg)
157 {
158 	nct_io_set_group(sc, group);
159 	return (bus_read_1(sc->iores, reg));
160 }
161 
162 static void
163 nct_io_write(struct nct_softc *sc, int group, uint8_t reg, uint8_t val)
164 {
165 	nct_io_set_group(sc, group);
166 	return (bus_write_1(sc->iores, reg, val));
167 }
168 
169 static uint8_t
170 nct_get_ioreg(struct nct_softc *sc, reg_t reg, int group)
171 {
172 	uint8_t ioreg;
173 
174 	if (sc->iores != NULL)
175 		ioreg = NCT_IO_IOR + reg;
176 	else if (group == 0)
177 		ioreg = NCT_LD7_GPIO0_IOR + reg;
178 	else
179 		ioreg = NCT_LD7_GPIO1_IOR + reg;
180 	return (ioreg);
181 }
182 
183 static uint8_t
184 nct_read_reg(struct nct_softc *sc, reg_t reg, int group)
185 {
186 	uint8_t ioreg;
187 	uint8_t val;
188 
189 	ioreg = nct_get_ioreg(sc, reg, group);
190 	if (sc->iores != NULL)
191 		val = nct_io_read(sc, group, ioreg);
192 	else
193 		val = superio_read(sc->dev, ioreg);
194 
195 	return (val);
196 }
197 
198 #define GET_BIT(v, b)	(((v) >> (b)) & 1)
199 static bool
200 nct_get_pin_reg(struct nct_softc *sc, reg_t reg, uint32_t pin_num)
201 {
202 	uint8_t bit;
203 	uint8_t group;
204 	uint8_t val;
205 
206 	KASSERT(NCT_IS_VALID_PIN(pin_num), ("%s: invalid pin number %d",
207 	    __func__, pin_num));
208 
209 	group = pin_num >> 3;
210 	bit = pin_num & 7;
211 	val = nct_read_reg(sc, reg, group);
212 	return (GET_BIT(val, bit));
213 }
214 
215 static int
216 nct_get_pin_cache(struct nct_softc *sc, uint32_t pin_num, uint8_t *cache)
217 {
218 	uint8_t bit;
219 	uint8_t group;
220 	uint8_t val;
221 
222 	KASSERT(NCT_IS_VALID_PIN(pin_num), ("%s: invalid pin number %d",
223 	    __func__, pin_num));
224 
225 	group = pin_num >> 3;
226 	bit = pin_num & 7;
227 	val = cache[group];
228 	return (GET_BIT(val, bit));
229 }
230 
231 static void
232 nct_write_reg(struct nct_softc *sc, reg_t reg, int group, uint8_t val)
233 {
234 	uint8_t ioreg;
235 
236 	ioreg = nct_get_ioreg(sc, reg, group);
237 	if (sc->iores != NULL)
238 		nct_io_write(sc, group, ioreg, val);
239 	else
240 		superio_write(sc->dev, ioreg, val);
241 }
242 
243 static void
244 nct_set_pin_reg(struct nct_softc *sc, reg_t reg, uint32_t pin_num, bool val)
245 {
246 	uint8_t *cache;
247 	uint8_t bit;
248 	uint8_t bitval;
249 	uint8_t group;
250 	uint8_t mask;
251 
252 	KASSERT(NCT_IS_VALID_PIN(pin_num),
253 	    ("%s: invalid pin number %d", __func__, pin_num));
254 	KASSERT(reg == REG_IOR || reg == REG_INV,
255 	    ("%s: unsupported register %d", __func__, reg));
256 
257 	group = pin_num >> 3;
258 	bit = pin_num & 7;
259 	mask = (uint8_t)1 << bit;
260 	bitval = (uint8_t)val << bit;
261 
262 	if (reg == REG_IOR)
263 		cache = &sc->cache.ior[group];
264 	else
265 		cache = &sc->cache.inv[group];
266 	if ((*cache & mask) == bitval)
267 		return;
268 	*cache &= ~mask;
269 	*cache |= bitval;
270 	nct_write_reg(sc, reg, group, *cache);
271 }
272 
273 /*
274  * Set a pin to input (val is true) or output (val is false) mode.
275  */
276 static void
277 nct_set_pin_input(struct nct_softc *sc, uint32_t pin_num, bool val)
278 {
279 	nct_set_pin_reg(sc, REG_IOR, pin_num, val);
280 }
281 
282 /*
283  * Check whether a pin is configured as an input.
284  */
285 static bool
286 nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
287 {
288 	return (nct_get_pin_cache(sc, pin_num, sc->cache.ior));
289 }
290 
291 /*
292  * Set a pin to inverted (val is true) or normal (val is false) mode.
293  */
294 static void
295 nct_set_pin_inverted(struct nct_softc *sc, uint32_t pin_num, bool val)
296 {
297 	nct_set_pin_reg(sc, REG_INV, pin_num, val);
298 }
299 
300 static bool
301 nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
302 {
303 	return (nct_get_pin_cache(sc, pin_num, sc->cache.inv));
304 }
305 
306 /*
307  * Write a value to an output pin.
308  * NB: the hardware remembers last output value across switching from
309  * output mode to input mode and back.
310  * Writes to a pin in input mode are not allowed here as they cannot
311  * have any effect and would corrupt the output value cache.
312  */
313 static void
314 nct_write_pin(struct nct_softc *sc, uint32_t pin_num, bool val)
315 {
316 	uint8_t bit;
317 	uint8_t group;
318 
319 	KASSERT(!nct_pin_is_input(sc, pin_num), ("attempt to write input pin"));
320 	group = pin_num >> 3;
321 	bit = pin_num & 7;
322 	if (GET_BIT(sc->cache.out_known[group], bit) &&
323 	    GET_BIT(sc->cache.out[group], bit) == val) {
324 		/* The pin is already in requested state. */
325 		return;
326 	}
327 	sc->cache.out_known[group] |= 1 << bit;
328 	if (val)
329 		sc->cache.out[group] |= 1 << bit;
330 	else
331 		sc->cache.out[group] &= ~(1 << bit);
332 	nct_write_reg(sc, REG_DAT, group, sc->cache.out[group]);
333 }
334 
335 /*
336  * NB: state of an input pin cannot be cached, of course.
337  * For an output we can either take the value from the cache if it's valid
338  * or read the state from the hadrware and cache it.
339  */
340 static bool
341 nct_read_pin(struct nct_softc *sc, uint32_t pin_num)
342 {
343 	uint8_t bit;
344 	uint8_t group;
345 	bool val;
346 
347 	if (nct_pin_is_input(sc, pin_num))
348 		return (nct_get_pin_reg(sc, REG_DAT, pin_num));
349 
350 	group = pin_num >> 3;
351 	bit = pin_num & 7;
352 	if (GET_BIT(sc->cache.out_known[group], bit))
353 		return (GET_BIT(sc->cache.out[group], bit));
354 
355 	val = nct_get_pin_reg(sc, REG_DAT, pin_num);
356 	sc->cache.out_known[group] |= 1 << bit;
357 	if (val)
358 		sc->cache.out[group] |= 1 << bit;
359 	else
360 		sc->cache.out[group] &= ~(1 << bit);
361 	return (val);
362 }
363 
364 static uint8_t
365 nct_outcfg_addr(uint32_t pin_num)
366 {
367 	KASSERT(NCT_IS_VALID_PIN(pin_num), ("%s: invalid pin number %d",
368 	    __func__, pin_num));
369 	if ((pin_num >> 3) == 0)
370 		return (NCT_LDF_GPIO0_OUTCFG);
371 	else
372 		return (NCT_LDF_GPIO1_OUTCFG);
373 }
374 
375 /*
376  * NB: PP/OD can be configured only via configuration registers.
377  * Also, the registers are in a different logical device.
378  * So, this is a special case.  No caching too.
379  */
380 static void
381 nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num)
382 {
383 	uint8_t reg;
384 	uint8_t outcfg;
385 
386 	reg = nct_outcfg_addr(pin_num);
387 	outcfg = superio_read(sc->dev_f, reg);
388 	outcfg |= NCT_PIN_BIT(pin_num);
389 	superio_write(sc->dev_f, reg, outcfg);
390 }
391 
392 static void
393 nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num)
394 {
395 	uint8_t reg;
396 	uint8_t outcfg;
397 
398 	reg = nct_outcfg_addr(pin_num);
399 	outcfg = superio_read(sc->dev_f, reg);
400 	outcfg &= ~NCT_PIN_BIT(pin_num);
401 	superio_write(sc->dev_f, reg, outcfg);
402 }
403 
404 static bool
405 nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num)
406 {
407 	uint8_t reg;
408 	uint8_t outcfg;
409 
410 	reg = nct_outcfg_addr(pin_num);
411 	outcfg = superio_read(sc->dev_f, reg);
412 	return (outcfg & NCT_PIN_BIT(pin_num));
413 }
414 
415 static int
416 nct_probe(device_t dev)
417 {
418 	int j;
419 	uint16_t chipid;
420 
421 	if (superio_vendor(dev) != SUPERIO_VENDOR_NUVOTON)
422 		return (ENXIO);
423 	if (superio_get_type(dev) != SUPERIO_DEV_GPIO)
424 		return (ENXIO);
425 
426 	/*
427 	 * There are several GPIO devices, we attach only to one of them
428 	 * and use the rest without attaching.
429 	 */
430 	if (superio_get_ldn(dev) != NCT_LDN_GPIO)
431 		return (ENXIO);
432 
433 	chipid = superio_devid(dev);
434 	for (j = 0; j < nitems(nct_devs); j++) {
435 		if (chipid == nct_devs[j].chip_id) {
436 			device_set_desc(dev, "Nuvoton GPIO controller");
437 			return (BUS_PROBE_DEFAULT);
438 		}
439 	}
440 	return (ENXIO);
441 }
442 
443 static int
444 nct_attach(device_t dev)
445 {
446 	struct nct_softc *sc;
447 	device_t dev_8;
448 	uint16_t iobase;
449 	int err;
450 	int i;
451 
452 	sc = device_get_softc(dev);
453 	sc->dev = dev;
454 	sc->dev_f = superio_find_dev(device_get_parent(dev), SUPERIO_DEV_GPIO,
455 	    NCT_LDN_GPIO_MODE);
456 	if (sc->dev_f == NULL) {
457 		device_printf(dev, "failed to find LDN F\n");
458 		return (ENXIO);
459 	}
460 
461 	/*
462 	 * As strange as it may seem, I/O port base is configured in the
463 	 * Logical Device 8 which is primarily used for WDT, but also plays
464 	 * a role in GPIO configuration.
465 	 */
466 	iobase = 0;
467 	dev_8 = superio_find_dev(device_get_parent(dev), SUPERIO_DEV_WDT, 8);
468 	if (dev_8 != NULL)
469 		iobase = superio_get_iobase(dev_8);
470 	if (iobase != 0 && iobase != 0xffff) {
471 		sc->curgrp = -1;
472 		sc->iorid = 0;
473 		err = bus_set_resource(dev, SYS_RES_IOPORT, sc->iorid,
474 		    iobase, 7);
475 		if (err == 0) {
476 			sc->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
477 			    &sc->iorid, RF_ACTIVE);
478 			if (sc->iores == NULL) {
479 				device_printf(dev, "can't map i/o space, "
480 				    "iobase=0x%04x\n", iobase);
481 			}
482 		} else {
483 			device_printf(dev,
484 			    "failed to set io port resource at 0x%x\n", iobase);
485 		}
486 	}
487 
488 	/* Enable gpio0 and gpio1. */
489 	superio_dev_enable(dev, 0x03);
490 
491 	GPIO_LOCK_INIT(sc);
492 	GPIO_LOCK(sc);
493 
494 	sc->cache.inv[0] = nct_read_reg(sc, REG_INV, 0);
495 	sc->cache.inv[1] = nct_read_reg(sc, REG_INV, 1);
496 	sc->cache.ior[0] = nct_read_reg(sc, REG_IOR, 0);
497 	sc->cache.ior[1] = nct_read_reg(sc, REG_IOR, 1);
498 
499 	/*
500 	 * Caching input values is meaningless as an input can be changed at any
501 	 * time by an external agent.  But outputs are controlled by this
502 	 * driver, so it can cache their state.  Also, the hardware remembers
503 	 * the output state of a pin when the pin is switched to input mode and
504 	 * then back to output mode.  So, the cache stays valid.
505 	 * The only problem is with pins that are in input mode at the attach
506 	 * time.  For them the output state is not known until it is set by the
507 	 * driver for the first time.
508 	 * 'out' and 'out_known' bits form a tri-state output cache:
509 	 * |-----+-----------+---------|
510 	 * | out | out_known | cache   |
511 	 * |-----+-----------+---------|
512 	 * |   X |         0 | invalid |
513 	 * |   0 |         1 |       0 |
514 	 * |   1 |         1 |       1 |
515 	 * |-----+-----------+---------|
516 	 */
517 	sc->cache.out[0] = nct_read_reg(sc, REG_DAT, 0);
518 	sc->cache.out[1] = nct_read_reg(sc, REG_DAT, 1);
519 	sc->cache.out_known[0] = ~sc->cache.ior[0];
520 	sc->cache.out_known[1] = ~sc->cache.ior[1];
521 
522 	for (i = 0; i <= NCT_MAX_PIN; i++) {
523 		struct gpio_pin *pin;
524 
525 		pin = &sc->pins[i];
526 		pin->gp_pin = i;
527 		pin->gp_caps = NCT_GPIO_CAPS;
528 		pin->gp_flags = 0;
529 
530 		snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02o", i);
531 		pin->gp_name[GPIOMAXNAME - 1] = '\0';
532 
533 		if (nct_pin_is_input(sc, i))
534 			pin->gp_flags |= GPIO_PIN_INPUT;
535 		else
536 			pin->gp_flags |= GPIO_PIN_OUTPUT;
537 
538 		if (nct_pin_is_opendrain(sc, i))
539 			pin->gp_flags |= GPIO_PIN_OPENDRAIN;
540 		else
541 			pin->gp_flags |= GPIO_PIN_PUSHPULL;
542 
543 		if (nct_pin_is_inverted(sc, i))
544 			pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
545 	}
546 	GPIO_UNLOCK(sc);
547 
548 	sc->busdev = gpiobus_attach_bus(dev);
549 	if (sc->busdev == NULL) {
550 		GPIO_LOCK_DESTROY(sc);
551 		return (ENXIO);
552 	}
553 
554 	return (0);
555 }
556 
557 static int
558 nct_detach(device_t dev)
559 {
560 	struct nct_softc *sc;
561 
562 	sc = device_get_softc(dev);
563 	gpiobus_detach_bus(dev);
564 
565 	if (sc->iores != NULL)
566 		bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->iores);
567 	GPIO_ASSERT_UNLOCKED(sc);
568 	GPIO_LOCK_DESTROY(sc);
569 
570 	return (0);
571 }
572 
573 static device_t
574 nct_gpio_get_bus(device_t dev)
575 {
576 	struct nct_softc *sc;
577 
578 	sc = device_get_softc(dev);
579 
580 	return (sc->busdev);
581 }
582 
583 static int
584 nct_gpio_pin_max(device_t dev, int *npins)
585 {
586 	*npins = NCT_MAX_PIN;
587 
588 	return (0);
589 }
590 
591 static int
592 nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
593 {
594 	struct nct_softc *sc;
595 
596 	if (!NCT_IS_VALID_PIN(pin_num))
597 		return (EINVAL);
598 
599 	sc = device_get_softc(dev);
600 	GPIO_LOCK(sc);
601 	if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) {
602 		GPIO_UNLOCK(sc);
603 		return (EINVAL);
604 	}
605 	nct_write_pin(sc, pin_num, pin_value);
606 	GPIO_UNLOCK(sc);
607 
608 	return (0);
609 }
610 
611 static int
612 nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
613 {
614 	struct nct_softc *sc;
615 
616 	if (!NCT_IS_VALID_PIN(pin_num))
617 		return (EINVAL);
618 
619 	sc = device_get_softc(dev);
620 	GPIO_ASSERT_UNLOCKED(sc);
621 	GPIO_LOCK(sc);
622 	*pin_value = nct_read_pin(sc, pin_num);
623 	GPIO_UNLOCK(sc);
624 
625 	return (0);
626 }
627 
628 static int
629 nct_gpio_pin_toggle(device_t dev, uint32_t pin_num)
630 {
631 	struct nct_softc *sc;
632 
633 	if (!NCT_IS_VALID_PIN(pin_num))
634 		return (EINVAL);
635 
636 	sc = device_get_softc(dev);
637 	GPIO_ASSERT_UNLOCKED(sc);
638 	GPIO_LOCK(sc);
639 	if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) {
640 		GPIO_UNLOCK(sc);
641 		return (EINVAL);
642 	}
643 	if (nct_read_pin(sc, pin_num))
644 		nct_write_pin(sc, pin_num, 0);
645 	else
646 		nct_write_pin(sc, pin_num, 1);
647 
648 	GPIO_UNLOCK(sc);
649 
650 	return (0);
651 }
652 
653 static int
654 nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps)
655 {
656 	struct nct_softc *sc;
657 
658 	if (!NCT_IS_VALID_PIN(pin_num))
659 		return (EINVAL);
660 
661 	sc = device_get_softc(dev);
662 	GPIO_ASSERT_UNLOCKED(sc);
663 	GPIO_LOCK(sc);
664 	*caps = sc->pins[pin_num].gp_caps;
665 	GPIO_UNLOCK(sc);
666 
667 	return (0);
668 }
669 
670 static int
671 nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags)
672 {
673 	struct nct_softc *sc;
674 
675 	if (!NCT_IS_VALID_PIN(pin_num))
676 		return (EINVAL);
677 
678 	sc = device_get_softc(dev);
679 	GPIO_ASSERT_UNLOCKED(sc);
680 	GPIO_LOCK(sc);
681 	*flags = sc->pins[pin_num].gp_flags;
682 	GPIO_UNLOCK(sc);
683 
684 	return (0);
685 }
686 
687 static int
688 nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name)
689 {
690 	struct nct_softc *sc;
691 
692 	if (!NCT_IS_VALID_PIN(pin_num))
693 		return (EINVAL);
694 
695 	sc = device_get_softc(dev);
696 	GPIO_ASSERT_UNLOCKED(sc);
697 	GPIO_LOCK(sc);
698 	memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
699 	GPIO_UNLOCK(sc);
700 
701 	return (0);
702 }
703 
704 static int
705 nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
706 {
707 	struct nct_softc *sc;
708 	struct gpio_pin *pin;
709 
710 	if (!NCT_IS_VALID_PIN(pin_num))
711 		return (EINVAL);
712 
713 	sc = device_get_softc(dev);
714 	pin = &sc->pins[pin_num];
715 	if ((flags & pin->gp_caps) != flags)
716 		return (EINVAL);
717 
718 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
719 		(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
720 			return (EINVAL);
721 	}
722 	if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) ==
723 		(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
724 			return (EINVAL);
725 	}
726 	if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) ==
727 		(GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
728 			return (EINVAL);
729 	}
730 
731 	GPIO_ASSERT_UNLOCKED(sc);
732 	GPIO_LOCK(sc);
733 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 0) {
734 		nct_set_pin_input(sc, pin_num, (flags & GPIO_PIN_INPUT) != 0);
735 		pin->gp_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
736 		pin->gp_flags |= flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
737 	}
738 	if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) != 0) {
739 		nct_set_pin_inverted(sc, pin_num,
740 		    (flags & GPIO_PIN_INVIN) != 0);
741 		pin->gp_flags &= ~(GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
742 		pin->gp_flags |= flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
743 	}
744 	if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) != 0) {
745 		if (flags & GPIO_PIN_OPENDRAIN)
746 			nct_set_pin_opendrain(sc, pin_num);
747 		else
748 			nct_set_pin_pushpull(sc, pin_num);
749 		pin->gp_flags &= ~(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL);
750 		pin->gp_flags |=
751 		    flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL);
752 	}
753 	GPIO_UNLOCK(sc);
754 
755 	return (0);
756 }
757 
758 static device_method_t nct_methods[] = {
759 	/* Device interface */
760 	DEVMETHOD(device_probe,		nct_probe),
761 	DEVMETHOD(device_attach,	nct_attach),
762 	DEVMETHOD(device_detach,	nct_detach),
763 
764 	/* GPIO */
765 	DEVMETHOD(gpio_get_bus,		nct_gpio_get_bus),
766 	DEVMETHOD(gpio_pin_max,		nct_gpio_pin_max),
767 	DEVMETHOD(gpio_pin_get,		nct_gpio_pin_get),
768 	DEVMETHOD(gpio_pin_set,		nct_gpio_pin_set),
769 	DEVMETHOD(gpio_pin_toggle,	nct_gpio_pin_toggle),
770 	DEVMETHOD(gpio_pin_getname,	nct_gpio_pin_getname),
771 	DEVMETHOD(gpio_pin_getcaps,	nct_gpio_pin_getcaps),
772 	DEVMETHOD(gpio_pin_getflags,	nct_gpio_pin_getflags),
773 	DEVMETHOD(gpio_pin_setflags,	nct_gpio_pin_setflags),
774 
775 	DEVMETHOD_END
776 };
777 
778 static driver_t nct_driver = {
779 	"gpio",
780 	nct_methods,
781 	sizeof(struct nct_softc)
782 };
783 
784 static devclass_t nct_devclass;
785 
786 DRIVER_MODULE(nctgpio, superio, nct_driver, nct_devclass, NULL, NULL);
787 MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1);
788 MODULE_DEPEND(nctgpio, superio, 1, 1, 1);
789 MODULE_VERSION(nctgpio, 1);
790 
791