xref: /freebsd/sys/dev/nctgpio/nctgpio.c (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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 #include <sys/cdefs.h>
35 
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 #include <sys/bus.h>
40 #include <sys/eventhandler.h>
41 #include <sys/lock.h>
42 
43 #include <sys/module.h>
44 #include <sys/gpio.h>
45 
46 #include <machine/bus.h>
47 
48 #include <dev/gpio/gpiobusvar.h>
49 #include <dev/superio/superio.h>
50 
51 #include "gpio_if.h"
52 
53 #define NCT_PPOD_LDN 0xf /* LDN used to select Push-Pull/Open-Drain */
54 
55 /* Direct access through GPIO register table */
56 #define	NCT_IO_GSR			0 /* Group Select */
57 #define	NCT_IO_IOR			1 /* I/O */
58 #define	NCT_IO_DAT			2 /* Data */
59 #define	NCT_IO_INV			3 /* Inversion */
60 #define	NCT_IO_DST          4 /* Status */
61 
62 #define NCT_MAX_GROUP   9
63 #define NCT_MAX_PIN     75
64 
65 #define NCT_PIN_IS_VALID(_sc, _p)   ((_p) < (_sc)->npins)
66 #define NCT_PIN_GROUP(_sc, _p)      ((_sc)->pinmap[(_p)].group)
67 #define NCT_PIN_GRPNUM(_sc, _p)     ((_sc)->pinmap[(_p)].grpnum)
68 #define NCT_PIN_BIT(_sc, _p)        ((_sc)->pinmap[(_p)].bit)
69 #define NCT_PIN_BITMASK(_p)         (1 << ((_p) & 7))
70 
71 #define NCT_GPIO_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
72 	GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \
73 	GPIO_PIN_INVIN | GPIO_PIN_INVOUT)
74 
75 #define NCT_PREFER_INDIRECT_CHANNEL 2
76 
77 #define NCT_VERBOSE_PRINTF(dev, ...)            \
78 	do {                                        \
79 		if (__predict_false(bootverbose))       \
80 			device_printf(dev, __VA_ARGS__);    \
81 	} while (0)
82 
83 /*
84  * Note that the values are important.
85  * They match actual register offsets.
86  */
87 typedef enum {
88 	REG_IOR = 0,
89 	REG_DAT = 1,
90 	REG_INV = 2,
91 } reg_t;
92 
93 struct nct_gpio_group {
94  	uint32_t    caps;
95 	uint8_t     enable_ldn;
96 	uint8_t     enable_reg;
97 	uint8_t     enable_mask;
98 	uint8_t     data_ldn;
99 	uint8_t     iobase;
100 	uint8_t     ppod_reg; /* Push-Pull/Open-Drain */
101 	uint8_t     grpnum;
102 	uint8_t     pinbits[8];
103 	uint8_t     npins;
104 };
105 
106 struct nct_softc {
107 	device_t			dev;
108 	device_t			busdev;
109 	struct mtx			mtx;
110 	struct resource			*iores;
111 	int				iorid;
112 	int				curgrp;
113 	struct {
114 		uint8_t ior[NCT_MAX_GROUP + 1];       /* direction, 1: input 0: output */
115 		uint8_t out[NCT_MAX_GROUP + 1];       /* output value */
116 		uint8_t out_known[NCT_MAX_GROUP + 1]; /* whether out is valid */
117 		uint8_t inv[NCT_MAX_GROUP + 1];       /* inversion, 1: inverted */
118 	} cache;
119 	struct gpio_pin				pins[NCT_MAX_PIN + 1];
120 	struct nct_device			*nctdevp;
121 	int							npins; /* Total number of pins */
122 
123 	/* Lookup tables */
124 	struct {
125 		struct nct_gpio_group *group;
126 		uint8_t                grpnum;
127 		uint8_t                bit;
128 	} pinmap[NCT_MAX_PIN+1];
129 	struct nct_gpio_group *grpmap[NCT_MAX_GROUP+1];
130 };
131 
132 #define GPIO_LOCK_INIT(_sc)	mtx_init(&(_sc)->mtx,		\
133 		device_get_nameunit(dev), NULL, MTX_DEF)
134 #define GPIO_LOCK_DESTROY(_sc)		mtx_destroy(&(_sc)->mtx)
135 #define GPIO_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
136 #define GPIO_UNLOCK(_sc)	mtx_unlock(&(_sc)->mtx)
137 #define GPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_OWNED)
138 #define GPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_NOTOWNED)
139 
140 #define GET_BIT(v, b)	(((v) >> (b)) & 1)
141 
142 /*
143  * For most devices there are several GPIO devices, we attach only to one of
144  * them and use the rest without attaching.
145  */
146 struct nct_device {
147 	uint16_t                  devid;
148 	int                       extid;
149 	const char               *descr;
150 	int                       ngroups;
151 	struct nct_gpio_group     groups[NCT_MAX_GROUP + 1];
152 } nct_devices[] = {
153 	{
154 		.devid   = 0xa025,
155 		.descr   = "GPIO on Winbond 83627DHG IC ver. 5",
156 		.ngroups = 5,
157 		.groups  = {
158 			{
159 				.grpnum      = 2,
160 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
161 				.enable_ldn  = 0x09,
162 				.enable_reg  = 0x30,
163 				.enable_mask = 0x01,
164 				.data_ldn    = 0x09,
165 				.ppod_reg    = 0xe0, /* FIXME Need to check for this group. */
166 				.caps        = NCT_GPIO_CAPS,
167 				.npins       = 8,
168 				.iobase      = 0xe3,
169 			},
170 			{
171 				.grpnum      = 3,
172 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
173 				.enable_ldn  = 0x09,
174 				.enable_reg  = 0x30,
175 				.enable_mask = 0x02,
176 				.data_ldn    = 0x09,
177 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
178 				.caps        = NCT_GPIO_CAPS,
179 				.npins       = 8,
180 				.iobase      = 0xf0,
181 			},
182 			{
183 				.grpnum      = 4,
184 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
185 				.enable_ldn  = 0x09,
186 				.enable_reg  = 0x30,
187 				.enable_mask = 0x04,
188 				.data_ldn    = 0x09,
189 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
190 				.caps        = NCT_GPIO_CAPS,
191 				.npins       = 8,
192 				.iobase      = 0xf4,
193 			},
194 			{
195 				.grpnum      = 5,
196 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
197 				.enable_ldn  = 0x09,
198 				.enable_reg  = 0x30,
199 				.enable_mask = 0x08,
200 				.data_ldn    = 0x09,
201 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
202 				.caps        = NCT_GPIO_CAPS,
203 				.npins       = 8,
204 				.iobase      = 0xe0,
205 			},
206 			{
207 				.grpnum      = 6,
208 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
209 				.enable_ldn  = 0x07,
210 				.enable_reg  = 0x30,
211 				.enable_mask = 0x01,
212 				.data_ldn    = 0x07,
213 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
214 				.caps        = NCT_GPIO_CAPS,
215 				.npins       = 8,
216 				.iobase      = 0xf4,
217 			},
218 		},
219 	},
220 	{
221 		.devid   = 0x1061,
222 		.descr   = "GPIO on Nuvoton NCT5104D",
223 		.ngroups = 2,
224 		.groups  = {
225 			{
226 				.grpnum      = 0,
227 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
228 				.enable_ldn  = 0x07,
229 				.enable_reg  = 0x30,
230 				.enable_mask = 0x01,
231 				.data_ldn    = 0x07,
232 				.ppod_reg    = 0xe0,
233 				.caps        = NCT_GPIO_CAPS,
234 				.npins       = 8,
235 				.iobase      = 0xe0,
236 			},
237 			{
238 				.grpnum      = 1,
239 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
240 				.enable_ldn  = 0x07,
241 				.enable_reg  = 0x30,
242 				.enable_mask = 0x02,
243 				.data_ldn    = 0x07,
244 				.ppod_reg    = 0xe1,
245 				.caps        = NCT_GPIO_CAPS,
246 				.npins       = 8,
247 				.iobase      = 0xe4,
248 			},
249 		},
250 	},
251 	{
252 		.devid   = 0xc452, /* FIXME Conflict with Nuvoton NCT6106D. See NetBSD's nct_match. */
253 		.descr   = "GPIO on Nuvoton NCT5104D (PC-Engines APU)",
254 		.ngroups = 2,
255 		.groups  = {
256 			{
257 				.grpnum      = 0,
258 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
259 				.enable_ldn  = 0x07,
260 				.enable_reg  = 0x30,
261 				.enable_mask = 0x01,
262 				.data_ldn    = 0x07,
263 				.ppod_reg    = 0xe0,
264 				.caps        = NCT_GPIO_CAPS,
265 				.npins       = 8,
266 				.iobase      = 0xe0,
267 			},
268 			{
269 				.grpnum      = 1,
270 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
271 				.enable_ldn  = 0x07,
272 				.enable_reg  = 0x30,
273 				.enable_mask = 0x02,
274 				.data_ldn    = 0x07,
275 				.ppod_reg    = 0xe1,
276 				.caps        = NCT_GPIO_CAPS,
277 				.npins       = 8,
278 				.iobase      = 0xe4,
279 			},
280 		},
281 	},
282 	{
283 		.devid   = 0xc453,
284 		.descr   = "GPIO on Nuvoton NCT5104D (PC-Engines APU3)",
285 		.ngroups = 2,
286 		.groups  = {
287 			{
288 				.grpnum      = 0,
289 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
290 				.enable_ldn  = 0x07,
291 				.enable_reg  = 0x30,
292 				.enable_mask = 0x01,
293 				.data_ldn    = 0x07,
294 				.ppod_reg    = 0xe0,
295 				.caps        = NCT_GPIO_CAPS,
296 				.npins       = 8,
297 				.iobase      = 0xe0,
298 			},
299 			{
300 				.grpnum      = 1,
301 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
302 				.enable_ldn  = 0x07,
303 				.enable_reg  = 0x30,
304 				.enable_mask = 0x02,
305 				.data_ldn    = 0x07,
306 				.ppod_reg    = 0xe1,
307 				.caps        = NCT_GPIO_CAPS,
308 				.npins       = 8,
309 				.iobase      = 0xe4,
310 			},
311 		},
312 	},
313 	{
314 		.devid  = 0xd42a,
315 		.extid  = 1,
316 		.descr  = "GPIO on Nuvoton NCT6796D-E",
317 		.ngroups = 10,
318 		.groups  = {
319 			{
320 				.grpnum      = 0,
321 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
322 				.enable_ldn  = 0x08,
323 				.enable_reg  = 0x30,
324 				.enable_mask = 0x02,
325 				.data_ldn    = 0x08,
326 				.ppod_reg    = 0xe0, /* FIXME Need to check for this group. */
327 				.caps        = NCT_GPIO_CAPS,
328 				.npins       = 8,
329 				.iobase      = 0xe0,
330 			},
331 			{
332 				.grpnum      = 1,
333 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
334 				.enable_ldn  = 0x08,
335 				.enable_reg  = 0x30,
336 				.enable_mask = 0x80,
337 				.data_ldn    = 0x08,
338 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
339 				.caps        = NCT_GPIO_CAPS,
340 				.npins       = 8,
341 				.iobase      = 0xf0,
342 			},
343 			{
344 				.grpnum      = 2,
345 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
346 				.enable_ldn  = 0x09,
347 				.enable_reg  = 0x30,
348 				.enable_mask = 0x01,
349 				.data_ldn    = 0x09,
350 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
351 				.caps        = NCT_GPIO_CAPS,
352 				.npins       = 8,
353 				.iobase      = 0xe0,
354 			},
355 			{
356 				.grpnum      = 3,
357 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6 },
358 				.enable_ldn  = 0x09,
359 				.enable_reg  = 0x30,
360 				.enable_mask = 0x02,
361 				.data_ldn    = 0x09,
362 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
363 				.caps        = NCT_GPIO_CAPS,
364 				.npins       = 7,
365 				.iobase      = 0xe4,
366 			},
367 			{
368 				.grpnum      = 4,
369 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
370 				.enable_ldn  = 0x09,
371 				.enable_reg  = 0x30,
372 				.enable_mask = 0x04,
373 				.data_ldn    = 0x09,
374 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
375 				.caps        = NCT_GPIO_CAPS,
376 				.npins       = 8,
377 				.iobase      = 0xf0, /* FIXME Page 344 say "F0~F2, E8",
378 										not "F0~F3". */
379 			},
380 			{
381 				.grpnum      = 5,
382 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
383 				.enable_ldn  = 0x09,
384 				.enable_reg  = 0x30,
385 				.enable_mask = 0x08,
386 				.data_ldn    = 0x09,
387 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
388 				.caps        = NCT_GPIO_CAPS,
389 				.npins       = 8,
390 				.iobase      = 0xf4,
391 			},
392 			{
393 				.grpnum      = 6,
394 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
395 				.enable_ldn  = 0x07,
396 				.enable_reg  = 0x30,
397 				.enable_mask = 0x01,
398 				.data_ldn    = 0x07,
399 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
400 				.caps        = NCT_GPIO_CAPS,
401 				.npins       = 8,
402 				.iobase      = 0xf4,
403 			},
404 			{
405 				.grpnum      = 7,
406 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
407 				.enable_ldn  = 0x07,
408 				.enable_reg  = 0x30,
409 				.enable_mask = 0x02,
410 				.data_ldn    = 0x07,
411 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
412 				.caps        = NCT_GPIO_CAPS,
413 				.npins       = 8,
414 				.iobase      = 0xe0,
415 			},
416 			{
417 				.grpnum      = 8,
418 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
419 				.enable_ldn  = 0x07,
420 				.enable_reg  = 0x30,
421 				.enable_mask = 0x04,
422 				.data_ldn    = 0x07,
423 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
424 				.caps        = NCT_GPIO_CAPS,
425 				.npins       = 8,
426 				.iobase      = 0xe4,
427 			},
428 			{
429 				.grpnum      = 9,
430 				.pinbits     = { 0, 1, 2, 3 },
431 				.enable_ldn  = 0x07,
432 				.enable_reg  = 0x30,
433 				.enable_mask = 0x08,
434 				.data_ldn    = 0x07,
435 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
436 				.caps        = NCT_GPIO_CAPS,
437 				.npins       = 4,
438 				.iobase      = 0xe8,
439 			},
440 		},
441 	},
442 	{
443 		.devid   = 0xd42a,
444 		.extid   = 2,
445 		.descr   = "GPIO on Nuvoton NCT5585D",
446 		.ngroups = 6,
447 		.groups  = {
448 			{
449 				.grpnum      = 2,
450 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6 },
451 				.enable_ldn  = 0x09,
452 				.enable_reg  = 0x30,
453 				.enable_mask = 0x01,
454 				.data_ldn    = 0x09,
455 				.ppod_reg    = 0xe1,
456 				.caps        = NCT_GPIO_CAPS,
457 				.npins       = 7,
458 				.iobase      = 0xe0,
459 			},
460 			{
461 				.grpnum      = 3,
462 				.pinbits     = { 1, 2, 3 },
463 				.enable_ldn  = 0x09,
464 				.enable_reg  = 0x30,
465 				.enable_mask = 0x02,
466 				.data_ldn    = 0x09,
467 				.ppod_reg    = 0xe2,
468 				.caps        = NCT_GPIO_CAPS,
469 				.npins       = 3,
470 				.iobase      = 0xe4,
471 			},
472 			{
473 				.grpnum      = 5,
474 				.pinbits     = { 0, 2, 6, 7 },
475 				.enable_ldn  = 0x09,
476 				.enable_reg  = 0x30,
477 				.enable_mask = 0x08,
478 				.data_ldn    = 0x09,
479 				.ppod_reg    = 0xe4,
480 				.caps        = NCT_GPIO_CAPS,
481 				.npins       = 4,
482 				.iobase      = 0xf4,
483 			},
484 			{
485 				.grpnum      = 7,
486 				.pinbits     = { 4 },
487 				.enable_ldn  = 0x07,
488 				.enable_reg  = 0x30,
489 				.enable_mask = 0x02,
490 				.data_ldn    = 0x07,
491 				.ppod_reg    = 0xe6,
492 				.caps        = NCT_GPIO_CAPS,
493 				.npins       = 1,
494 				.iobase      = 0xe0,
495 			},
496 			{
497 				.grpnum      = 8,
498 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
499 				.enable_ldn  = 0x07,
500 				.enable_reg  = 0x30,
501 				.enable_mask = 0x04,
502 				.data_ldn    = 0x07,
503 				.ppod_reg    = 0xe7,
504 				.caps        = NCT_GPIO_CAPS,
505 				.npins       = 8,
506 				.iobase      = 0xe4,
507 			},
508 			{
509 				.grpnum      = 9,
510 				.pinbits     = { 0, 2 },
511 				.enable_ldn  = 0x07,
512 				.enable_reg  = 0x30,
513 				.enable_mask = 0x08,
514 				.data_ldn    = 0x07,
515 				.ppod_reg    = 0xea,
516 				.caps        = NCT_GPIO_CAPS,
517 				.npins       = 2,
518 				.iobase      = 0xe8,
519 			},
520 		},
521 	},
522 	{
523 		.devid   = 0xc562,
524 		.descr   = "GPIO on Nuvoton NCT6779D",
525 		.ngroups = 9,
526 		.groups  = {
527 			{
528 				.grpnum      = 0,
529 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
530 				.enable_ldn  = 0x08,
531 				.enable_reg  = 0x30,
532 				.enable_mask = 0x01,
533 				.data_ldn    = 0x08,
534 				.ppod_reg    = 0xe0, /* FIXME Need to check for this group. */
535 				.caps        = NCT_GPIO_CAPS,
536 				.npins       = 8,
537 				.iobase      = 0xe0,
538 			},
539 			{
540 				.grpnum      = 1,
541 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
542 				.enable_ldn  = 0x09,
543 				.enable_reg  = 0x30,
544 				.enable_mask = 0x01,
545 				.data_ldn    = 0x08,
546 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
547 				.caps        = NCT_GPIO_CAPS,
548 				.npins       = 8,
549 				.iobase      = 0xf0,
550 			},
551 			{
552 				.grpnum      = 2,
553 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
554 				.enable_ldn  = 0x09,
555 				.enable_reg  = 0x30,
556 				.enable_mask = 0x01,
557 				.data_ldn    = 0x09,
558 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
559 				.caps        = NCT_GPIO_CAPS,
560 				.npins       = 8,
561 				.iobase      = 0xe0,
562 			},
563 			{
564 				.grpnum      = 3,
565 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6 },
566 				.enable_ldn  = 0x09,
567 				.enable_reg  = 0x30,
568 				.enable_mask = 0x02,
569 				.data_ldn    = 0x09,
570 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
571 				.caps        = NCT_GPIO_CAPS,
572 				.npins       = 7,
573 				.iobase      = 0xe4,
574 			},
575 			{
576 				.grpnum      = 4,
577 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
578 				.enable_ldn  = 0x09,
579 				.enable_reg  = 0x30,
580 				.enable_mask = 0x04,
581 				.data_ldn    = 0x09,
582 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
583 				.caps        = NCT_GPIO_CAPS,
584 				.npins       = 8,
585 				.iobase      = 0xf0,
586 			},
587 			{
588 				.grpnum      = 5,
589 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
590 				.enable_ldn  = 0x09,
591 				.enable_reg  = 0x30,
592 				.enable_mask = 0x08,
593 				.data_ldn    = 0x09,
594 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
595 				.caps        = NCT_GPIO_CAPS,
596 				.npins       = 8,
597 				.iobase      = 0xf4,
598 			},
599 			{
600 				.grpnum      = 6,
601 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
602 				.enable_ldn  = 0x09,
603 				.enable_reg  = 0x30,
604 				.enable_mask = 0x01,
605 				.data_ldn    = 0x07,
606 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
607 				.caps        = NCT_GPIO_CAPS,
608 				.npins       = 8,
609 				.iobase      = 0xf4,
610 			},
611 			{
612 				.grpnum      = 7,
613 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6 },
614 				.enable_ldn  = 0x09,
615 				.enable_reg  = 0x30,
616 				.enable_mask = 0x02,
617 				.data_ldn    = 0x07,
618 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
619 				.caps        = NCT_GPIO_CAPS,
620 				.npins       = 7,
621 				.iobase      = 0xe0,
622 			},
623 			{
624 				.grpnum      = 8,
625 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
626 				.enable_ldn  = 0x09,
627 				.enable_reg  = 0x30,
628 				.enable_mask = 0x04,
629 				.data_ldn    = 0x07,
630 				.ppod_reg    = 0xe1, /* FIXME Need to check for this group. */
631 				.caps        = NCT_GPIO_CAPS,
632 				.npins       = 8,
633 				.iobase      = 0xe4,
634 			},
635 		},
636 	},
637 	{
638 		.devid   = 0xd282,
639 		.descr   = "GPIO on Nuvoton NCT6112D/NCT6114D/NCT6116D",
640 		.ngroups = 9,
641 		.groups  = {
642 			{
643 				.grpnum      = 0,
644 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
645 				.enable_ldn  = 0x07,
646 				.enable_reg  = 0x30,
647 				.enable_mask = 0x01,
648 				.data_ldn    = 0x07,
649 				.ppod_reg    = 0xe0,
650 				.caps        = NCT_GPIO_CAPS,
651 				.npins       = 8,
652 				.iobase      = 0xe0,
653 			},
654 			{
655 				.grpnum      = 1,
656 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
657 				.enable_ldn  = 0x07,
658 				.enable_reg  = 0x30,
659 				.enable_mask = 0x02,
660 				.data_ldn    = 0x07,
661 				.ppod_reg    = 0xe1,
662 				.caps        = NCT_GPIO_CAPS,
663 				.npins       = 8,
664 				.iobase      = 0xe4,
665 			},
666 			{
667 				.grpnum      = 2,
668 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
669 				.enable_ldn  = 0x07,
670 				.enable_reg  = 0x30,
671 				.enable_mask = 0x04,
672 				.data_ldn    = 0x07,
673 				.ppod_reg    = 0xe1,
674 				.caps        = NCT_GPIO_CAPS,
675 				.npins       = 8,
676 				.iobase      = 0xe8,
677 			},
678 			{
679 				.grpnum      = 3,
680 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
681 				.enable_ldn  = 0x07,
682 				.enable_reg  = 0x30,
683 				.enable_mask = 0x08,
684 				.data_ldn    = 0x07,
685 				.ppod_reg    = 0xe1,
686 				.caps        = NCT_GPIO_CAPS,
687 				.npins       = 8,
688 				.iobase      = 0xec,
689 			},
690 			{
691 				.grpnum      = 4,
692 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
693 				.enable_ldn  = 0x07,
694 				.enable_reg  = 0x30,
695 				.enable_mask = 0x10,
696 				.data_ldn    = 0x07,
697 				.ppod_reg    = 0xe1,
698 				.caps        = NCT_GPIO_CAPS,
699 				.npins       = 8,
700 				.iobase      = 0xf0,
701 			},
702 			{
703 				.grpnum      = 5,
704 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
705 				.enable_ldn  = 0x07,
706 				.enable_reg  = 0x30,
707 				.enable_mask = 0x20,
708 				.data_ldn    = 0x07,
709 				.ppod_reg    = 0xe1,
710 				.caps        = NCT_GPIO_CAPS,
711 				.npins       = 8,
712 				.iobase      = 0xf4,
713 			},
714 			{
715 				.grpnum      = 6,
716 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
717 				.enable_ldn  = 0x07,
718 				.enable_reg  = 0x30,
719 				.enable_mask = 0x40,
720 				.data_ldn    = 0x07,
721 				.ppod_reg    = 0xe1,
722 				.caps        = NCT_GPIO_CAPS,
723 				.npins       = 8,
724 				.iobase      = 0xf8,
725 			},
726 			{
727 				.grpnum      = 7,
728 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
729 				.enable_ldn  = 0x07,
730 				.enable_reg  = 0x30,
731 				.enable_mask = 0x80,
732 				.data_ldn    = 0x07,
733 				.ppod_reg    = 0xe1,
734 				.caps        = NCT_GPIO_CAPS,
735 				.npins       = 8,
736 				.iobase      = 0xfc,
737 			},
738 			{
739 				.grpnum      = 8,
740 				.pinbits     = { 0, 1, 2, 3, 4, 5, 6, 7 },
741 				.enable_ldn  = 0x09,
742 				.enable_reg  = 0x30,
743 				.enable_mask = 0x01,
744 				.data_ldn    = 0x09,
745 				.ppod_reg    = 0xe1,
746 				.caps        = NCT_GPIO_CAPS,
747 				.npins       = 8,
748 				.iobase      = 0xf0,
749 			},
750 		},
751 	},
752 };
753 
754 static const char *
755 io2str(uint8_t ioport)
756 {
757 	switch (ioport) {
758 	case NCT_IO_GSR: return ("grpsel");
759 	case NCT_IO_IOR: return ("io");
760 	case NCT_IO_DAT: return ("data");
761 	case NCT_IO_INV: return ("inv");
762 	case NCT_IO_DST: return ("status");
763 	default:         return ("?");
764 	}
765 }
766 
767 static void
768 nct_io_set_group(struct nct_softc *sc, uint8_t grpnum)
769 {
770 	GPIO_ASSERT_LOCKED(sc);
771 
772 	if (grpnum == sc->curgrp)
773 		return;
774 
775 	NCT_VERBOSE_PRINTF(sc->dev, "write %s 0x%x ioport %d\n",
776 		io2str(NCT_IO_GSR), grpnum, NCT_IO_GSR);
777 	bus_write_1(sc->iores, NCT_IO_GSR, grpnum);
778 	sc->curgrp = grpnum;
779 }
780 
781 static uint8_t
782 nct_io_read(struct nct_softc *sc, uint8_t grpnum, uint8_t reg)
783 {
784 	uint8_t val;
785 
786 	nct_io_set_group(sc, grpnum);
787 
788 	val = bus_read_1(sc->iores, reg);
789 	NCT_VERBOSE_PRINTF(sc->dev, "read %s 0x%x ioport %d\n",
790 		io2str(reg), val, reg);
791 	return (val);
792 }
793 
794 static void
795 nct_io_write(struct nct_softc *sc, uint8_t grpnum, uint8_t reg, uint8_t val)
796 {
797 	nct_io_set_group(sc, grpnum);
798 
799 	NCT_VERBOSE_PRINTF(sc->dev, "write %s 0x%x ioport %d\n",
800 		io2str(reg), val, reg);
801 	bus_write_1(sc->iores, reg, val);
802 }
803 
804 static uint8_t
805 nct_get_ioreg(struct nct_softc *sc, reg_t reg, uint8_t grpnum)
806 {
807 	uint8_t iobase;
808 
809 	if (sc->iores != NULL)
810 		iobase = NCT_IO_IOR;
811 	else
812 		iobase = sc->grpmap[grpnum]->iobase;
813 	return (iobase + reg);
814 }
815 
816 static const char *
817 reg2str(reg_t reg)
818 {
819 	switch (reg) {
820 	case REG_IOR: return ("io");
821 	case REG_DAT: return ("data");
822 	case REG_INV: return ("inv");
823 	default:      return ("?");
824 	}
825 }
826 
827 static uint8_t
828 nct_read_reg(struct nct_softc *sc, reg_t reg, uint8_t grpnum)
829 {
830 	struct nct_gpio_group *gp;
831 	uint8_t                ioreg;
832 	uint8_t                val;
833 
834 	ioreg = nct_get_ioreg(sc, reg, grpnum);
835 
836 	if (sc->iores != NULL)
837 		return (nct_io_read(sc, grpnum, ioreg));
838 
839 	gp  = sc->grpmap[grpnum];
840 	val = superio_ldn_read(sc->dev, gp->data_ldn, ioreg);
841 	NCT_VERBOSE_PRINTF(sc->dev, "read %s 0x%x from group GPIO%u ioreg 0x%x\n",
842 		reg2str(reg), val, grpnum, ioreg);
843 	return (val);
844 }
845 
846 static int
847 nct_get_pin_cache(struct nct_softc *sc, uint32_t pin_num, uint8_t *cache)
848 {
849 	uint8_t bit;
850 	uint8_t group;
851 	uint8_t val;
852 
853 	KASSERT(NCT_PIN_IS_VALID(sc, pin_num), ("%s: invalid pin number %d",
854 	    __func__, pin_num));
855 
856 	group = NCT_PIN_GRPNUM(sc, pin_num);
857 	bit   = NCT_PIN_BIT(sc, pin_num);
858 	val   = cache[group];
859 	return (GET_BIT(val, bit));
860 }
861 
862 static void
863 nct_write_reg(struct nct_softc *sc, reg_t reg, uint8_t grpnum, uint8_t val)
864 {
865 	struct nct_gpio_group *gp;
866 	uint8_t                ioreg;
867 
868 	ioreg = nct_get_ioreg(sc, reg, grpnum);
869 
870 	if (sc->iores != NULL) {
871 		nct_io_write(sc, grpnum, ioreg, val);
872 		return;
873 	}
874 
875 	gp = sc->grpmap[grpnum];
876 	superio_ldn_write(sc->dev, gp->data_ldn, ioreg, val);
877 
878 	NCT_VERBOSE_PRINTF(sc->dev, "write %s 0x%x to group GPIO%u ioreg 0x%x\n",
879 		reg2str(reg), val, grpnum, ioreg);
880 }
881 
882 static void
883 nct_set_pin_reg(struct nct_softc *sc, reg_t reg, uint32_t pin_num, bool val)
884 {
885 	uint8_t *cache;
886 	uint8_t bit;
887 	uint8_t bitval;
888 	uint8_t group;
889 	uint8_t mask;
890 
891 	KASSERT(NCT_PIN_IS_VALID(sc, pin_num),
892 	    ("%s: invalid pin number %d", __func__, pin_num));
893 	KASSERT(reg == REG_IOR || reg == REG_INV,
894 	    ("%s: unsupported register %d", __func__, reg));
895 
896 	group  = NCT_PIN_GRPNUM(sc, pin_num);
897 	bit    = NCT_PIN_BIT(sc, pin_num);
898 	mask   = (uint8_t)1 << bit;
899 	bitval = (uint8_t)val << bit;
900 
901 	if (reg == REG_IOR)
902 		cache = &sc->cache.ior[group];
903 	else
904 		cache = &sc->cache.inv[group];
905 	if ((*cache & mask) == bitval)
906 		return;
907 	*cache &= ~mask;
908 	*cache |= bitval;
909 	nct_write_reg(sc, reg, group, *cache);
910 }
911 
912 /*
913  * Set a pin to input (val is true) or output (val is false) mode.
914  */
915 static void
916 nct_set_pin_input(struct nct_softc *sc, uint32_t pin_num, bool val)
917 {
918 	nct_set_pin_reg(sc, REG_IOR, pin_num, val);
919 }
920 
921 /*
922  * Check whether a pin is configured as an input.
923  */
924 static bool
925 nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
926 {
927 	return (nct_get_pin_cache(sc, pin_num, sc->cache.ior));
928 }
929 
930 /*
931  * Set a pin to inverted (val is true) or normal (val is false) mode.
932  */
933 static void
934 nct_set_pin_inverted(struct nct_softc *sc, uint32_t pin_num, bool val)
935 {
936 	nct_set_pin_reg(sc, REG_INV, pin_num, val);
937 }
938 
939 static bool
940 nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
941 {
942 	return (nct_get_pin_cache(sc, pin_num, sc->cache.inv));
943 }
944 
945 /*
946  * Write a value to an output pin.
947  * NB: the hardware remembers last output value across switching from
948  * output mode to input mode and back.
949  * Writes to a pin in input mode are not allowed here as they cannot
950  * have any effect and would corrupt the output value cache.
951  */
952 static void
953 nct_write_pin(struct nct_softc *sc, uint32_t pin_num, bool val)
954 {
955 	uint8_t bit;
956 	uint8_t group;
957 
958 	KASSERT(!nct_pin_is_input(sc, pin_num), ("attempt to write input pin"));
959 	group = NCT_PIN_GRPNUM(sc, pin_num);
960 	bit   = NCT_PIN_BIT(sc, pin_num);
961 
962 	if (GET_BIT(sc->cache.out_known[group], bit) &&
963 	    GET_BIT(sc->cache.out[group], bit) == val) {
964 		/* The pin is already in requested state. */
965 		return;
966 	}
967 	sc->cache.out_known[group] |= 1 << bit;
968 	if (val)
969 		sc->cache.out[group] |= 1 << bit;
970 	else
971 		sc->cache.out[group] &= ~(1 << bit);
972 	nct_write_reg(sc, REG_DAT, group, sc->cache.out[group]);
973 }
974 
975 static bool
976 nct_get_pin_reg(struct nct_softc *sc, reg_t reg, uint32_t pin_num)
977 {
978 	uint8_t            bit;
979 	uint8_t            group;
980 	uint8_t            val;
981 	bool               b;
982 
983 	KASSERT(NCT_PIN_IS_VALID(sc, pin_num), ("%s: invalid pin number %d",
984 			__func__, pin_num));
985 
986 	group = NCT_PIN_GRPNUM(sc, pin_num);
987 	bit   = NCT_PIN_BIT(sc, pin_num);
988 	val   = nct_read_reg(sc, reg, group);
989 	b     = GET_BIT(val, bit);
990 
991 	if (__predict_false(bootverbose)) {
992 		if (nct_pin_is_input(sc, pin_num))
993 			NCT_VERBOSE_PRINTF(sc->dev, "read %d from input pin %u<GPIO%u%u>\n",
994 				b, pin_num, group, bit);
995 		else
996 			NCT_VERBOSE_PRINTF(sc->dev,
997 				"read %d from output pin %u<GPIO%u%u>, cache miss\n",
998 				b, pin_num, group, bit);
999 	}
1000 
1001 	return (b);
1002 }
1003 
1004 /*
1005  * NB: state of an input pin cannot be cached, of course.
1006  * For an output we can either take the value from the cache if it's valid
1007  * or read the state from the hadrware and cache it.
1008  */
1009 static bool
1010 nct_read_pin(struct nct_softc *sc, uint32_t pin_num)
1011 {
1012 	uint8_t bit;
1013 	uint8_t group;
1014 	bool    val;
1015 
1016 	if (nct_pin_is_input(sc, pin_num)) {
1017 		return (nct_get_pin_reg(sc, REG_DAT, pin_num));
1018 	}
1019 
1020 	group = NCT_PIN_GRPNUM(sc, pin_num);
1021 	bit   = NCT_PIN_BIT(sc, pin_num);
1022 
1023 	if (GET_BIT(sc->cache.out_known[group], bit)) {
1024 		val = GET_BIT(sc->cache.out[group], bit);
1025 
1026 		NCT_VERBOSE_PRINTF(sc->dev,
1027 			"read %d from output pin %u<GPIO%u%u>, cache hit\n",
1028 			val, pin_num, group, bit);
1029 
1030 		return (val);
1031 	}
1032 
1033 	val = nct_get_pin_reg(sc, REG_DAT, pin_num);
1034 	sc->cache.out_known[group] |= 1 << bit;
1035 	if (val)
1036 		sc->cache.out[group] |= 1 << bit;
1037 	else
1038 		sc->cache.out[group] &= ~(1 << bit);
1039 	return (val);
1040 }
1041 
1042 /* FIXME Incorret for NCT5585D and probably other chips. */
1043 static uint8_t
1044 nct_ppod_reg(struct nct_softc *sc, uint32_t pin_num)
1045 {
1046 	uint8_t group = NCT_PIN_GRPNUM(sc, pin_num);
1047 
1048 	return (sc->grpmap[group]->ppod_reg);
1049 }
1050 
1051 /*
1052  * NB: PP/OD can be configured only via configuration registers.
1053  * Also, the registers are in a different logical device.
1054  * So, this is a special case.  No caching too.
1055  */
1056 static void
1057 nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num)
1058 {
1059 	uint8_t reg;
1060 	uint8_t outcfg;
1061 
1062 	reg = nct_ppod_reg(sc, pin_num);
1063 	outcfg = superio_ldn_read(sc->dev, NCT_PPOD_LDN, reg);
1064 	outcfg |= NCT_PIN_BITMASK(pin_num);
1065 	superio_ldn_write(sc->dev, 0xf, reg, outcfg);
1066 }
1067 
1068 static void
1069 nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num)
1070 {
1071 	uint8_t reg;
1072 	uint8_t outcfg;
1073 
1074 	reg = nct_ppod_reg(sc, pin_num);
1075 	outcfg = superio_ldn_read(sc->dev, NCT_PPOD_LDN, reg);
1076 	outcfg &= ~NCT_PIN_BITMASK(pin_num);
1077 	superio_ldn_write(sc->dev, 0xf, reg, outcfg);
1078 }
1079 
1080 static bool
1081 nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num)
1082 {
1083 	uint8_t reg;
1084 	uint8_t outcfg;
1085 
1086 	reg = nct_ppod_reg(sc, pin_num);
1087 	outcfg = superio_ldn_read(sc->dev, NCT_PPOD_LDN, reg);
1088 	return (outcfg & NCT_PIN_BITMASK(pin_num));
1089 }
1090 
1091 static struct nct_device *
1092 nct_lookup_device(device_t dev)
1093 {
1094 	struct nct_device *nctdevp;
1095 	uint16_t           devid;
1096 	int                i, extid;
1097 
1098 	devid = superio_devid(dev);
1099 	extid = superio_extid(dev);
1100 	for (i = 0, nctdevp = nct_devices; i < nitems(nct_devices); i++, nctdevp++) {
1101 		if (devid == nctdevp->devid && nctdevp->extid == extid)
1102 			return (nctdevp);
1103 	}
1104 	return (NULL);
1105 }
1106 
1107 static int
1108 nct_probe(device_t dev)
1109 {
1110 	struct nct_device *nctdevp;
1111 	uint8_t            ldn;
1112 
1113 	ldn = superio_get_ldn(dev);
1114 
1115 	if (superio_vendor(dev) != SUPERIO_VENDOR_NUVOTON) {
1116 		NCT_VERBOSE_PRINTF(dev, "ldn 0x%x not a Nuvoton device\n", ldn);
1117 		return (ENXIO);
1118 	}
1119 	if (superio_get_type(dev) != SUPERIO_DEV_GPIO) {
1120 		NCT_VERBOSE_PRINTF(dev, "ldn 0x%x not a GPIO device\n", ldn);
1121 		return (ENXIO);
1122 	}
1123 
1124 	nctdevp = nct_lookup_device(dev);
1125 	if (nctdevp == NULL) {
1126 		NCT_VERBOSE_PRINTF(dev, "ldn 0x%x not supported\n", ldn);
1127 		return (ENXIO);
1128 	}
1129 	device_set_desc(dev, nctdevp->descr);
1130 	return (BUS_PROBE_DEFAULT);
1131 }
1132 
1133 static int
1134 nct_attach(device_t dev)
1135 {
1136 	struct nct_softc *sc;
1137 	struct nct_gpio_group *gp;
1138 	uint32_t pin_num;
1139 	uint8_t v;
1140 	int flags, i, g;
1141 
1142 	sc          = device_get_softc(dev);
1143 	sc->dev     = dev;
1144 	sc->nctdevp = nct_lookup_device(dev);
1145 
1146 	flags = 0;
1147 	(void)resource_int_value(device_get_name(dev), device_get_unit(dev), "flags", &flags);
1148 
1149 	if ((flags & NCT_PREFER_INDIRECT_CHANNEL) == 0) {
1150 		uint16_t iobase;
1151 		device_t dev_8;
1152 
1153 		/*
1154 		 * As strange as it may seem, I/O port base is configured in the
1155 		 * Logical Device 8 which is primarily used for WDT, but also plays
1156 		 * a role in GPIO configuration.
1157 		 */
1158 		iobase = 0;
1159 		dev_8 = superio_find_dev(device_get_parent(dev), SUPERIO_DEV_WDT, 8);
1160 		if (dev_8 != NULL)
1161 			iobase = superio_get_iobase(dev_8);
1162 		if (iobase != 0 && iobase != 0xffff) {
1163 			int err;
1164 
1165 			NCT_VERBOSE_PRINTF(dev, "iobase %#x\n", iobase);
1166 			sc->curgrp = -1;
1167 			sc->iorid = 0;
1168 			err = bus_set_resource(dev, SYS_RES_IOPORT, sc->iorid,
1169 				iobase, 7); /* FIXME NCT6796D-E have 8 registers according to table 18.3. */
1170 			if (err == 0) {
1171 				sc->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
1172 					&sc->iorid, RF_ACTIVE);
1173 				if (sc->iores == NULL) {
1174 					device_printf(dev, "can't map i/o space, "
1175 						"iobase=%#x\n", iobase);
1176 				}
1177 			} else {
1178 				device_printf(dev,
1179 					"failed to set io port resource at %#x\n", iobase);
1180 			}
1181 		}
1182 	}
1183 	NCT_VERBOSE_PRINTF(dev, "iores %p %s channel\n",
1184 		sc->iores, (sc->iores ? "direct" : "indirect"));
1185 
1186 	/* Enable GPIO groups */
1187 	for (g = 0, gp = sc->nctdevp->groups; g < sc->nctdevp->ngroups; g++, gp++) {
1188 		NCT_VERBOSE_PRINTF(dev,
1189 			"GPIO%d: %d pins, enable with mask 0x%x via ldn 0x%x reg 0x%x\n",
1190 			gp->grpnum, gp->npins, gp->enable_mask, gp->enable_ldn,
1191 			gp->enable_reg);
1192 		v = superio_ldn_read(dev, gp->enable_ldn, gp->enable_reg);
1193 		v |= gp->enable_mask;
1194 		superio_ldn_write(dev, gp->enable_ldn, gp->enable_reg, v);
1195 	}
1196 
1197 	GPIO_LOCK_INIT(sc);
1198 	GPIO_LOCK(sc);
1199 
1200 	pin_num   = 0;
1201 	sc->npins = 0;
1202 	for (g = 0, gp = sc->nctdevp->groups; g < sc->nctdevp->ngroups; g++, gp++) {
1203 
1204 		sc->grpmap[gp->grpnum] = gp;
1205 
1206 		/*
1207 		 * Caching input values is meaningless as an input can be changed at any
1208 		 * time by an external agent.  But outputs are controlled by this
1209 		 * driver, so it can cache their state.  Also, the hardware remembers
1210 		 * the output state of a pin when the pin is switched to input mode and
1211 		 * then back to output mode.  So, the cache stays valid.
1212 		 * The only problem is with pins that are in input mode at the attach
1213 		 * time.  For them the output state is not known until it is set by the
1214 		 * driver for the first time.
1215 		 * 'out' and 'out_known' bits form a tri-state output cache:
1216 		 * |-----+-----------+---------|
1217 		 * | out | out_known | cache   |
1218 		 * |-----+-----------+---------|
1219 		 * |   X |         0 | invalid |
1220 		 * |   0 |         1 |       0 |
1221 		 * |   1 |         1 |       1 |
1222 		 * |-----+-----------+---------|
1223 		 */
1224 		sc->cache.inv[gp->grpnum]       = nct_read_reg(sc, REG_INV, gp->grpnum);
1225 		sc->cache.ior[gp->grpnum]       = nct_read_reg(sc, REG_IOR, gp->grpnum);
1226 		sc->cache.out[gp->grpnum]       = nct_read_reg(sc, REG_DAT, gp->grpnum);
1227 		sc->cache.out_known[gp->grpnum] = ~sc->cache.ior[gp->grpnum];
1228 
1229 		sc->npins += gp->npins;
1230 		for (i = 0; i < gp->npins; i++, pin_num++) {
1231 			struct gpio_pin *pin;
1232 
1233 			sc->pinmap[pin_num].group  = gp;
1234 			sc->pinmap[pin_num].grpnum = gp->grpnum;
1235 			sc->pinmap[pin_num].bit    = gp->pinbits[i];
1236 
1237 			pin           = &sc->pins[pin_num];
1238 			pin->gp_pin   = pin_num;
1239 			pin->gp_caps  = gp->caps;
1240 			pin->gp_flags = 0;
1241 
1242 			snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%u%u",
1243 				gp->grpnum, gp->pinbits[i]);
1244 
1245 			if (nct_pin_is_input(sc, pin_num))
1246 				pin->gp_flags |= GPIO_PIN_INPUT;
1247 			else
1248 				pin->gp_flags |= GPIO_PIN_OUTPUT;
1249 
1250 			if (nct_pin_is_opendrain(sc, pin_num))
1251 				pin->gp_flags |= GPIO_PIN_OPENDRAIN;
1252 			else
1253 				pin->gp_flags |= GPIO_PIN_PUSHPULL;
1254 
1255 			if (nct_pin_is_inverted(sc, pin_num))
1256 				pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
1257 		}
1258 	}
1259 	NCT_VERBOSE_PRINTF(dev, "%d pins available\n", sc->npins);
1260 
1261 	GPIO_UNLOCK(sc);
1262 
1263 	sc->busdev = gpiobus_attach_bus(dev);
1264 	if (sc->busdev == NULL) {
1265 		device_printf(dev, "failed to attach to gpiobus\n");
1266 		GPIO_LOCK_DESTROY(sc);
1267 		return (ENXIO);
1268 	}
1269 
1270 	return (0);
1271 }
1272 
1273 static int
1274 nct_detach(device_t dev)
1275 {
1276 	struct nct_softc *sc;
1277 
1278 	sc = device_get_softc(dev);
1279 	gpiobus_detach_bus(dev);
1280 
1281 	if (sc->iores != NULL)
1282 		bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->iores);
1283 	GPIO_ASSERT_UNLOCKED(sc);
1284 	GPIO_LOCK_DESTROY(sc);
1285 
1286 	return (0);
1287 }
1288 
1289 static device_t
1290 nct_gpio_get_bus(device_t dev)
1291 {
1292 	struct nct_softc *sc;
1293 
1294 	sc = device_get_softc(dev);
1295 
1296 	return (sc->busdev);
1297 }
1298 
1299 static int
1300 nct_gpio_pin_max(device_t dev, int *maxpin)
1301 {
1302 	struct nct_softc *sc;
1303 
1304 	sc      = device_get_softc(dev);
1305 	*maxpin = sc->npins - 1;
1306 	return (0);
1307 }
1308 
1309 static int
1310 nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
1311 {
1312 	struct nct_softc *sc;
1313 
1314 	sc = device_get_softc(dev);
1315 
1316 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1317 		return (EINVAL);
1318 
1319 	GPIO_LOCK(sc);
1320 	if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) {
1321 		GPIO_UNLOCK(sc);
1322 		return (EINVAL);
1323 	}
1324 	nct_write_pin(sc, pin_num, pin_value);
1325 	GPIO_UNLOCK(sc);
1326 
1327 	return (0);
1328 }
1329 
1330 static int
1331 nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
1332 {
1333 	struct nct_softc *sc;
1334 
1335 	sc = device_get_softc(dev);
1336 
1337 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1338 		return (EINVAL);
1339 
1340 	GPIO_ASSERT_UNLOCKED(sc);
1341 	GPIO_LOCK(sc);
1342 	*pin_value = nct_read_pin(sc, pin_num);
1343 	GPIO_UNLOCK(sc);
1344 
1345 	return (0);
1346 }
1347 
1348 static int
1349 nct_gpio_pin_toggle(device_t dev, uint32_t pin_num)
1350 {
1351 	struct nct_softc *sc;
1352 
1353 	sc = device_get_softc(dev);
1354 
1355 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1356 		return (EINVAL);
1357 
1358 	GPIO_ASSERT_UNLOCKED(sc);
1359 	GPIO_LOCK(sc);
1360 	if ((sc->pins[pin_num].gp_flags & GPIO_PIN_OUTPUT) == 0) {
1361 		GPIO_UNLOCK(sc);
1362 		return (EINVAL);
1363 	}
1364 	if (nct_read_pin(sc, pin_num))
1365 		nct_write_pin(sc, pin_num, 0);
1366 	else
1367 		nct_write_pin(sc, pin_num, 1);
1368 
1369 	GPIO_UNLOCK(sc);
1370 
1371 	return (0);
1372 }
1373 
1374 static int
1375 nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps)
1376 {
1377 	struct nct_softc *sc;
1378 
1379 	sc = device_get_softc(dev);
1380 
1381 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1382 		return (EINVAL);
1383 
1384 	GPIO_ASSERT_UNLOCKED(sc);
1385 	GPIO_LOCK(sc);
1386 	*caps = sc->pins[pin_num].gp_caps;
1387 	GPIO_UNLOCK(sc);
1388 
1389 	return (0);
1390 }
1391 
1392 static int
1393 nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags)
1394 {
1395 	struct nct_softc *sc;
1396 
1397 	sc = device_get_softc(dev);
1398 
1399 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1400 		return (EINVAL);
1401 
1402 	GPIO_ASSERT_UNLOCKED(sc);
1403 	GPIO_LOCK(sc);
1404 	*flags = sc->pins[pin_num].gp_flags;
1405 	GPIO_UNLOCK(sc);
1406 
1407 	return (0);
1408 }
1409 
1410 static int
1411 nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name)
1412 {
1413 	struct nct_softc *sc;
1414 
1415 	sc = device_get_softc(dev);
1416 
1417 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1418 		return (EINVAL);
1419 
1420 	GPIO_ASSERT_UNLOCKED(sc);
1421 	GPIO_LOCK(sc);
1422 	memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
1423 	GPIO_UNLOCK(sc);
1424 
1425 	return (0);
1426 }
1427 
1428 static int
1429 nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
1430 {
1431 	struct nct_softc *sc;
1432 	struct gpio_pin *pin;
1433 
1434 	sc = device_get_softc(dev);
1435 
1436 	if (!NCT_PIN_IS_VALID(sc, pin_num))
1437 		return (EINVAL);
1438 
1439 	pin = &sc->pins[pin_num];
1440 	if ((flags & pin->gp_caps) != flags)
1441 		return (EINVAL);
1442 
1443 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
1444 		(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
1445 			return (EINVAL);
1446 	}
1447 	if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) ==
1448 		(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
1449 			return (EINVAL);
1450 	}
1451 	if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) ==
1452 		(GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
1453 			return (EINVAL);
1454 	}
1455 
1456 	GPIO_ASSERT_UNLOCKED(sc);
1457 	GPIO_LOCK(sc);
1458 
1459 	/* input or output */
1460 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 0) {
1461 		nct_set_pin_input(sc, pin_num, (flags & GPIO_PIN_INPUT) != 0);
1462 		pin->gp_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
1463 		pin->gp_flags |= flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
1464 	}
1465 
1466 	/* invert */
1467 	if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) != 0) {
1468 		nct_set_pin_inverted(sc, pin_num, 1);
1469 		pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
1470 	} else {
1471 		nct_set_pin_inverted(sc, pin_num, 0);
1472 		pin->gp_flags &= ~(GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
1473 	}
1474 
1475 	/* Open drain or push pull */
1476 	if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) != 0) {
1477 		if (flags & GPIO_PIN_OPENDRAIN)
1478 			nct_set_pin_opendrain(sc, pin_num);
1479 		else
1480 			nct_set_pin_pushpull(sc, pin_num);
1481 		pin->gp_flags &= ~(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL);
1482 		pin->gp_flags |=
1483 		    flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL);
1484 	}
1485 	GPIO_UNLOCK(sc);
1486 
1487 	return (0);
1488 }
1489 
1490 static device_method_t nct_methods[] = {
1491 	/* Device interface */
1492 	DEVMETHOD(device_probe,		nct_probe),
1493 	DEVMETHOD(device_attach,	nct_attach),
1494 	DEVMETHOD(device_detach,	nct_detach),
1495 
1496 	/* GPIO */
1497 	DEVMETHOD(gpio_get_bus,		nct_gpio_get_bus),
1498 	DEVMETHOD(gpio_pin_max,		nct_gpio_pin_max),
1499 	DEVMETHOD(gpio_pin_get,		nct_gpio_pin_get),
1500 	DEVMETHOD(gpio_pin_set,		nct_gpio_pin_set),
1501 	DEVMETHOD(gpio_pin_toggle,	nct_gpio_pin_toggle),
1502 	DEVMETHOD(gpio_pin_getname,	nct_gpio_pin_getname),
1503 	DEVMETHOD(gpio_pin_getcaps,	nct_gpio_pin_getcaps),
1504 	DEVMETHOD(gpio_pin_getflags,	nct_gpio_pin_getflags),
1505 	DEVMETHOD(gpio_pin_setflags,	nct_gpio_pin_setflags),
1506 
1507 	DEVMETHOD_END
1508 };
1509 
1510 static driver_t nct_driver = {
1511 	"gpio",
1512 	nct_methods,
1513 	sizeof(struct nct_softc)
1514 };
1515 
1516 DRIVER_MODULE(nctgpio, superio, nct_driver, NULL, NULL);
1517 MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1);
1518 MODULE_DEPEND(nctgpio, superio, 1, 1, 1);
1519 MODULE_VERSION(nctgpio, 1);
1520