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