2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2019 Andriy Gapon
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
37 #include <sys/kernel.h>
39 #include <sys/mutex.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
46 #include <machine/bus.h>
47 #include <machine/resource.h>
48 #include <machine/stdarg.h>
50 #include <isa/isavar.h>
52 #include <dev/superio/superio.h>
53 #include <dev/superio/superio_io.h>
58 typedef void (*sio_conf_enter_f)(struct resource*, uint16_t);
59 typedef void (*sio_conf_exit_f)(struct resource*, uint16_t);
61 struct sio_conf_methods {
62 sio_conf_enter_f enter;
64 superio_vendor_t vendor;
69 superio_dev_type_t type;
72 struct superio_devinfo {
73 STAILQ_ENTRY(superio_devinfo) link;
74 struct resource_list resources;
77 superio_dev_type_t type;
86 STAILQ_HEAD(, superio_devinfo) devlist;
87 struct resource* io_res;
91 const struct sio_conf_methods *methods;
92 const struct sio_device *known_devices;
93 superio_vendor_t vendor;
101 static d_ioctl_t superio_ioctl;
103 static struct cdevsw superio_cdevsw = {
104 .d_version = D_VERSION,
105 .d_ioctl = superio_ioctl,
112 sio_read(struct resource* res, uint8_t reg)
114 bus_write_1(res, 0, reg);
115 return (bus_read_1(res, 1));
118 /* Read a word from two one-byte registers, big endian. */
120 sio_readw(struct resource* res, uint8_t reg)
124 v = sio_read(res, reg);
126 v |= sio_read(res, reg + 1);
131 sio_write(struct resource* res, uint8_t reg, uint8_t val)
133 bus_write_1(res, 0, reg);
134 bus_write_1(res, 1, val);
138 sio_ldn_select(struct siosc *sc, uint8_t ldn)
140 mtx_assert(&sc->conf_lock, MA_OWNED);
141 if (ldn == sc->current_ldn)
143 sio_write(sc->io_res, sc->ldn_reg, ldn);
144 sc->current_ldn = ldn;
148 sio_ldn_read(struct siosc *sc, uint8_t ldn, uint8_t reg)
150 mtx_assert(&sc->conf_lock, MA_OWNED);
151 if (reg >= sc->enable_reg) {
152 sio_ldn_select(sc, ldn);
153 KASSERT(sc->current_ldn == ldn, ("sio_ldn_select failed"));
155 return (sio_read(sc->io_res, reg));
159 sio_ldn_readw(struct siosc *sc, uint8_t ldn, uint8_t reg)
161 mtx_assert(&sc->conf_lock, MA_OWNED);
162 if (reg >= sc->enable_reg) {
163 sio_ldn_select(sc, ldn);
164 KASSERT(sc->current_ldn == ldn, ("sio_ldn_select failed"));
166 return (sio_readw(sc->io_res, reg));
170 sio_ldn_write(struct siosc *sc, uint8_t ldn, uint8_t reg, uint8_t val)
172 mtx_assert(&sc->conf_lock, MA_OWNED);
173 if (reg <= sc->ldn_reg) {
174 printf("ignored attempt to write special register 0x%x\n", reg);
177 sio_ldn_select(sc, ldn);
178 KASSERT(sc->current_ldn == ldn, ("sio_ldn_select failed"));
179 sio_write(sc->io_res, reg, val);
183 sio_conf_enter(struct siosc *sc)
185 mtx_lock(&sc->conf_lock);
186 sc->methods->enter(sc->io_res, sc->io_port);
190 sio_conf_exit(struct siosc *sc)
192 sc->methods->exit(sc->io_res, sc->io_port);
193 sc->current_ldn = 0xff;
194 mtx_unlock(&sc->conf_lock);
198 ite_conf_enter(struct resource* res, uint16_t port)
200 bus_write_1(res, 0, 0x87);
201 bus_write_1(res, 0, 0x01);
202 bus_write_1(res, 0, 0x55);
203 bus_write_1(res, 0, port == 0x2e ? 0x55 : 0xaa);
207 ite_conf_exit(struct resource* res, uint16_t port)
209 sio_write(res, 0x02, 0x02);
212 static const struct sio_conf_methods ite_conf_methods = {
213 .enter = ite_conf_enter,
214 .exit = ite_conf_exit,
215 .vendor = SUPERIO_VENDOR_ITE
219 nvt_conf_enter(struct resource* res, uint16_t port)
221 bus_write_1(res, 0, 0x87);
222 bus_write_1(res, 0, 0x87);
226 nvt_conf_exit(struct resource* res, uint16_t port)
228 bus_write_1(res, 0, 0xaa);
231 static const struct sio_conf_methods nvt_conf_methods = {
232 .enter = nvt_conf_enter,
233 .exit = nvt_conf_exit,
234 .vendor = SUPERIO_VENDOR_NUVOTON
237 static const struct sio_conf_methods * const methods_table[] = {
243 static const uint16_t ports_table[] = {
247 const struct sio_device ite_devices[] = {
248 { .ldn = 4, .type = SUPERIO_DEV_HWM },
249 { .ldn = 7, .type = SUPERIO_DEV_WDT },
250 { .type = SUPERIO_DEV_NONE },
253 const struct sio_device nvt_devices[] = {
254 { .ldn = 8, .type = SUPERIO_DEV_WDT },
255 { .type = SUPERIO_DEV_NONE },
258 const struct sio_device nct5104_devices[] = {
259 { .ldn = 7, .type = SUPERIO_DEV_GPIO },
260 { .ldn = 8, .type = SUPERIO_DEV_WDT },
261 { .ldn = 15, .type = SUPERIO_DEV_GPIO },
262 { .type = SUPERIO_DEV_NONE },
265 static const struct {
266 superio_vendor_t vendor;
270 const struct sio_device *devices;
271 } superio_table[] = {
273 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8712,
274 .devices = ite_devices,
277 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8716,
278 .devices = ite_devices,
281 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8718,
282 .devices = ite_devices,
285 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8720,
286 .devices = ite_devices,
289 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8721,
290 .devices = ite_devices,
293 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8726,
294 .devices = ite_devices,
297 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8728,
298 .devices = ite_devices,
301 .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8771,
302 .devices = ite_devices,
305 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x1061, .mask = 0x00,
306 .descr = "Nuvoton NCT5104D/NCT6102D/NCT6106D (rev. A)",
307 .devices = nct5104_devices,
310 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x5200, .mask = 0xff,
311 .descr = "Winbond 83627HF/F/HG/G",
312 .devices = nvt_devices,
315 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x5900, .mask = 0xff,
316 .descr = "Winbond 83627S",
317 .devices = nvt_devices,
320 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x6000, .mask = 0xff,
321 .descr = "Winbond 83697HF",
322 .devices = nvt_devices,
325 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x6800, .mask = 0xff,
326 .descr = "Winbond 83697UG",
327 .devices = nvt_devices,
330 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x7000, .mask = 0xff,
331 .descr = "Winbond 83637HF",
332 .devices = nvt_devices,
335 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x8200, .mask = 0xff,
336 .descr = "Winbond 83627THF",
337 .devices = nvt_devices,
340 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x8500, .mask = 0xff,
341 .descr = "Winbond 83687THF",
342 .devices = nvt_devices,
345 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0x8800, .mask = 0xff,
346 .descr = "Winbond 83627EHF",
347 .devices = nvt_devices,
350 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xa000, .mask = 0xff,
351 .descr = "Winbond 83627DHG",
352 .devices = nvt_devices,
355 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xa200, .mask = 0xff,
356 .descr = "Winbond 83627UHG",
357 .devices = nvt_devices,
360 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xa500, .mask = 0xff,
361 .descr = "Winbond 83667HG",
362 .devices = nvt_devices,
365 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xb000, .mask = 0xff,
366 .descr = "Winbond 83627DHG-P",
367 .devices = nvt_devices,
370 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xb300, .mask = 0xff,
371 .descr = "Winbond 83667HG-B",
372 .devices = nvt_devices,
375 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xb400, .mask = 0xff,
376 .descr = "Nuvoton NCT6775",
377 .devices = nvt_devices,
380 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xc300, .mask = 0xff,
381 .descr = "Nuvoton NCT6776",
382 .devices = nvt_devices,
385 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xc400, .mask = 0xff,
386 .descr = "Nuvoton NCT5104D/NCT6102D/NCT6106D (rev. B+)",
387 .devices = nct5104_devices,
390 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xc500, .mask = 0xff,
391 .descr = "Nuvoton NCT6779",
392 .devices = nvt_devices,
395 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xc800, .mask = 0xff,
396 .descr = "Nuvoton NCT6791",
397 .devices = nvt_devices,
400 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xc900, .mask = 0xff,
401 .descr = "Nuvoton NCT6792",
402 .devices = nvt_devices,
405 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xd100, .mask = 0xff,
406 .descr = "Nuvoton NCT6793",
407 .devices = nvt_devices,
410 .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xd300, .mask = 0xff,
411 .descr = "Nuvoton NCT6795",
412 .devices = nvt_devices,
418 devtype_to_str(superio_dev_type_t type)
421 case SUPERIO_DEV_NONE:
423 case SUPERIO_DEV_HWM:
425 case SUPERIO_DEV_WDT:
427 case SUPERIO_DEV_GPIO:
429 case SUPERIO_DEV_MAX:
436 superio_detect(device_t dev, bool claim, struct siosc *sc)
438 struct resource *res;
447 error = bus_get_resource(dev, SYS_RES_IOPORT, 0, &port, &count);
450 if (port > UINT16_MAX || count < NUMPORTS) {
451 device_printf(dev, "unexpected I/O range size\n");
456 * Make a temporary resource reservation for hardware probing.
457 * If we can't get the resources we need then
458 * we need to abort. Possibly this indicates
459 * the resources were used by another device
460 * in which case the probe would have failed anyhow.
463 res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
466 device_printf(dev, "failed to allocate I/O resource\n");
470 for (m = 0; methods_table[m] != NULL; m++) {
471 methods_table[m]->enter(res, port);
472 if (methods_table[m]->vendor == SUPERIO_VENDOR_ITE) {
473 devid = sio_readw(res, 0x20);
474 revid = sio_read(res, 0x22);
475 } else if (methods_table[m]->vendor == SUPERIO_VENDOR_NUVOTON) {
476 devid = sio_read(res, 0x20);
477 revid = sio_read(res, 0x21);
478 devid = (devid << 8) | revid;
482 methods_table[m]->exit(res, port);
483 for (i = 0; superio_table[i].vendor != 0; i++) {
486 mask = superio_table[i].mask;
487 if (superio_table[i].vendor !=
488 methods_table[m]->vendor)
490 if ((superio_table[i].devid & ~mask) != (devid & ~mask))
495 /* Found a matching SuperIO entry. */
496 if (superio_table[i].vendor != 0)
500 if (methods_table[m] == NULL)
504 if (!claim || error != 0) {
505 bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
509 sc->methods = methods_table[m];
510 sc->vendor = sc->methods->vendor;
511 sc->known_devices = superio_table[i].devices;
518 KASSERT(sc->vendor == SUPERIO_VENDOR_ITE ||
519 sc->vendor == SUPERIO_VENDOR_NUVOTON,
520 ("Only ITE and Nuvoton SuperIO-s are supported"));
522 sc->enable_reg = 0x30;
523 sc->current_ldn = 0xff; /* no device should have this */
525 if (superio_table[i].descr != NULL) {
526 device_set_desc(dev, superio_table[i].descr);
527 } else if (sc->vendor == SUPERIO_VENDOR_ITE) {
530 snprintf(descr, sizeof(descr),
531 "ITE IT%4x SuperIO (revision 0x%02x)",
532 sc->devid, sc->revid);
533 device_set_desc_copy(dev, descr);
539 superio_identify(driver_t *driver, device_t parent)
545 * Don't create child devices if any already exist.
546 * Those could be created via isa hints or if this
547 * driver is loaded, unloaded and then loaded again.
549 if (device_find_child(parent, "superio", -1)) {
551 printf("superio: device(s) already created\n");
556 * Create a child for each candidate port.
557 * It would be nice if we could somehow clean up those
558 * that this driver fails to probe.
560 for (i = 0; ports_table[i] != 0; i++) {
561 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE,
564 device_printf(parent, "failed to add superio child\n");
567 bus_set_resource(child, SYS_RES_IOPORT, 0, ports_table[i], 2);
568 if (superio_detect(child, false, NULL) != 0)
569 device_delete_child(parent, child);
574 superio_probe(device_t dev)
579 /* Make sure we do not claim some ISA PNP device. */
580 if (isa_get_logicalid(dev) != 0)
584 * XXX We can populate the softc now only because we return
587 sc = device_get_softc(dev);
588 error = superio_detect(dev, true, sc);
591 return (BUS_PROBE_SPECIFIC);
595 superio_add_known_child(device_t dev, superio_dev_type_t type, uint8_t ldn)
597 struct siosc *sc = device_get_softc(dev);
598 struct superio_devinfo *dinfo;
601 child = BUS_ADD_CHILD(dev, 0, NULL, -1);
603 device_printf(dev, "failed to add child for ldn %d, type %s\n",
604 ldn, devtype_to_str(type));
607 dinfo = device_get_ivars(child);
611 dinfo->iobase = sio_ldn_readw(sc, ldn, 0x60);
612 dinfo->iobase2 = sio_ldn_readw(sc, ldn, 0x62);
613 dinfo->irq = sio_ldn_readw(sc, ldn, 0x70);
614 dinfo->dma = sio_ldn_readw(sc, ldn, 0x74);
616 STAILQ_INSERT_TAIL(&sc->devlist, dinfo, link);
620 superio_attach(device_t dev)
622 struct siosc *sc = device_get_softc(dev);
625 mtx_init(&sc->conf_lock, device_get_nameunit(dev), "superio", MTX_DEF);
626 STAILQ_INIT(&sc->devlist);
628 for (i = 0; sc->known_devices[i].type != SUPERIO_DEV_NONE; i++) {
629 superio_add_known_child(dev, sc->known_devices[i].type,
630 sc->known_devices[i].ldn);
633 bus_generic_probe(dev);
634 bus_generic_attach(dev);
636 sc->chardev = make_dev(&superio_cdevsw, device_get_unit(dev),
637 UID_ROOT, GID_WHEEL, 0600, "superio%d", device_get_unit(dev));
638 if (sc->chardev == NULL)
639 device_printf(dev, "failed to create character device\n");
641 sc->chardev->si_drv1 = sc;
646 superio_detach(device_t dev)
648 struct siosc *sc = device_get_softc(dev);
651 error = bus_generic_detach(dev);
654 if (sc->chardev != NULL)
655 destroy_dev(sc->chardev);
656 device_delete_children(dev);
657 bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid, sc->io_res);
658 mtx_destroy(&sc->conf_lock);
663 superio_add_child(device_t dev, u_int order, const char *name, int unit)
665 struct superio_devinfo *dinfo;
668 child = device_add_child_ordered(dev, order, name, unit);
671 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
673 device_delete_child(dev, child);
677 dinfo->type = SUPERIO_DEV_NONE;
679 resource_list_init(&dinfo->resources);
680 device_set_ivars(child, dinfo);
685 superio_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
687 struct superio_devinfo *dinfo;
689 dinfo = device_get_ivars(child);
691 case SUPERIO_IVAR_LDN:
692 *result = dinfo->ldn;
694 case SUPERIO_IVAR_TYPE:
695 *result = dinfo->type;
697 case SUPERIO_IVAR_IOBASE:
698 *result = dinfo->iobase;
700 case SUPERIO_IVAR_IOBASE2:
701 *result = dinfo->iobase2;
703 case SUPERIO_IVAR_IRQ:
704 *result = dinfo->irq;
706 case SUPERIO_IVAR_DMA:
707 *result = dinfo->dma;
716 superio_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
720 case SUPERIO_IVAR_LDN:
721 case SUPERIO_IVAR_TYPE:
722 case SUPERIO_IVAR_IOBASE:
723 case SUPERIO_IVAR_IOBASE2:
724 case SUPERIO_IVAR_IRQ:
725 case SUPERIO_IVAR_DMA:
732 static struct resource_list *
733 superio_get_resource_list(device_t dev, device_t child)
735 struct superio_devinfo *dinfo = device_get_ivars(child);
737 return (&dinfo->resources);
741 superio_printf(struct superio_devinfo *dinfo, const char *fmt, ...)
746 retval = printf("superio:%s@ldn%0x2x: ",
747 devtype_to_str(dinfo->type), dinfo->ldn);
749 retval += vprintf(fmt, ap);
755 superio_child_detached(device_t dev, device_t child)
757 struct superio_devinfo *dinfo;
758 struct resource_list *rl;
760 dinfo = device_get_ivars(child);
761 rl = &dinfo->resources;
763 if (resource_list_release_active(rl, dev, child, SYS_RES_IRQ) != 0)
764 superio_printf(dinfo, "Device leaked IRQ resources\n");
765 if (resource_list_release_active(rl, dev, child, SYS_RES_MEMORY) != 0)
766 superio_printf(dinfo, "Device leaked memory resources\n");
767 if (resource_list_release_active(rl, dev, child, SYS_RES_IOPORT) != 0)
768 superio_printf(dinfo, "Device leaked I/O resources\n");
772 superio_child_location_str(device_t parent, device_t child, char *buf,
777 ldn = superio_get_ldn(child);
778 snprintf(buf, buflen, "ldn=0x%02x", ldn);
783 superio_child_pnp_str(device_t parent, device_t child, char *buf,
786 superio_dev_type_t type;
788 type = superio_get_type(child);
789 snprintf(buf, buflen, "type=%s", devtype_to_str(type));
794 superio_print_child(device_t parent, device_t child)
796 superio_dev_type_t type;
800 ldn = superio_get_ldn(child);
801 type = superio_get_type(child);
803 retval = bus_print_child_header(parent, child);
804 retval += printf(" at %s ldn 0x%02x", devtype_to_str(type), ldn);
805 retval += bus_print_child_footer(parent, child);
811 superio_vendor(device_t dev)
813 device_t sio_dev = device_get_parent(dev);
814 struct siosc *sc = device_get_softc(sio_dev);
820 superio_devid(device_t dev)
822 device_t sio_dev = device_get_parent(dev);
823 struct siosc *sc = device_get_softc(sio_dev);
829 superio_revid(device_t dev)
831 device_t sio_dev = device_get_parent(dev);
832 struct siosc *sc = device_get_softc(sio_dev);
838 superio_read(device_t dev, uint8_t reg)
840 device_t sio_dev = device_get_parent(dev);
841 struct siosc *sc = device_get_softc(sio_dev);
842 struct superio_devinfo *dinfo = device_get_ivars(dev);
846 v = sio_ldn_read(sc, dinfo->ldn, reg);
852 superio_write(device_t dev, uint8_t reg, uint8_t val)
854 device_t sio_dev = device_get_parent(dev);
855 struct siosc *sc = device_get_softc(sio_dev);
856 struct superio_devinfo *dinfo = device_get_ivars(dev);
859 sio_ldn_write(sc, dinfo->ldn, reg, val);
864 superio_dev_enabled(device_t dev, uint8_t mask)
866 device_t sio_dev = device_get_parent(dev);
867 struct siosc *sc = device_get_softc(sio_dev);
868 struct superio_devinfo *dinfo = device_get_ivars(dev);
871 /* GPIO device is always active in ITE chips. */
872 if (sc->vendor == SUPERIO_VENDOR_ITE && dinfo->ldn == 7)
875 v = superio_read(dev, sc->enable_reg);
876 return ((v & mask) != 0);
880 superio_dev_enable(device_t dev, uint8_t mask)
882 device_t sio_dev = device_get_parent(dev);
883 struct siosc *sc = device_get_softc(sio_dev);
884 struct superio_devinfo *dinfo = device_get_ivars(dev);
887 /* GPIO device is always active in ITE chips. */
888 if (sc->vendor == SUPERIO_VENDOR_ITE && dinfo->ldn == 7)
892 v = sio_ldn_read(sc, dinfo->ldn, sc->enable_reg);
894 sio_ldn_write(sc, dinfo->ldn, sc->enable_reg, v);
899 superio_dev_disable(device_t dev, uint8_t mask)
901 device_t sio_dev = device_get_parent(dev);
902 struct siosc *sc = device_get_softc(sio_dev);
903 struct superio_devinfo *dinfo = device_get_ivars(dev);
906 /* GPIO device is always active in ITE chips. */
907 if (sc->vendor == SUPERIO_VENDOR_ITE && dinfo->ldn == 7)
911 v = sio_ldn_read(sc, dinfo->ldn, sc->enable_reg);
913 sio_ldn_write(sc, dinfo->ldn, sc->enable_reg, v);
918 superio_find_dev(device_t superio, superio_dev_type_t type, int ldn)
920 struct siosc *sc = device_get_softc(superio);
921 struct superio_devinfo *dinfo;
923 if (ldn < -1 || ldn > UINT8_MAX)
924 return (NULL); /* ERANGE */
925 if (type == SUPERIO_DEV_NONE && ldn == -1)
926 return (NULL); /* EINVAL */
928 STAILQ_FOREACH(dinfo, &sc->devlist, link) {
929 if (ldn != -1 && dinfo->ldn != ldn)
931 if (type != SUPERIO_DEV_NONE && dinfo->type != type)
939 superio_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
943 struct superiocmd *s;
946 s = (struct superiocmd *)data;
948 case SUPERIO_CR_READ:
950 s->val = sio_ldn_read(sc, s->ldn, s->cr);
953 case SUPERIO_CR_WRITE:
955 sio_ldn_write(sc, s->ldn, s->cr, s->val);
963 static devclass_t superio_devclass;
965 static device_method_t superio_methods[] = {
966 DEVMETHOD(device_identify, superio_identify),
967 DEVMETHOD(device_probe, superio_probe),
968 DEVMETHOD(device_attach, superio_attach),
969 DEVMETHOD(device_detach, superio_detach),
970 DEVMETHOD(device_shutdown, bus_generic_shutdown),
971 DEVMETHOD(device_suspend, bus_generic_suspend),
972 DEVMETHOD(device_resume, bus_generic_resume),
974 DEVMETHOD(bus_add_child, superio_add_child),
975 DEVMETHOD(bus_child_detached, superio_child_detached),
976 DEVMETHOD(bus_child_location_str, superio_child_location_str),
977 DEVMETHOD(bus_child_pnpinfo_str, superio_child_pnp_str),
978 DEVMETHOD(bus_print_child, superio_print_child),
979 DEVMETHOD(bus_read_ivar, superio_read_ivar),
980 DEVMETHOD(bus_write_ivar, superio_write_ivar),
981 DEVMETHOD(bus_get_resource_list, superio_get_resource_list),
982 DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
983 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
984 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
985 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
986 DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
987 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
988 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
989 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
990 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
995 static driver_t superio_driver = {
1001 DRIVER_MODULE(superio, isa, superio_driver, superio_devclass, 0, 0);
1002 MODULE_VERSION(superio, 1);