diff --git a/sys/dev/it8613hwm/it8613hwm.c b/sys/dev/it8613hwm/it8613hwm.c new file mode 100644 --- /dev/null +++ b/sys/dev/it8613hwm/it8613hwm.c @@ -0,0 +1,175 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Johannes Totz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +struct it8613hwm_softc { + struct resource* ioport_res; + int ioport_rid; + + struct mtx lock; +}; + +static int it8613hwm_get_temp_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t) arg1; + struct it8613hwm_softc* sc = device_get_softc(dev); + int tempindex = arg2; + int tempkelvin = 0; + uint8_t temp_celsius; + + if (tempindex >= 0 && tempindex < 3) + { + mtx_lock(&sc->lock); + + bus_write_1(sc->ioport_res, 0, 0x29 + tempindex); + temp_celsius = bus_read_1(sc->ioport_res, 1); + tempkelvin = temp_celsius + 273; + + mtx_unlock(&sc->lock); + } + + return sysctl_handle_int(oidp, &tempkelvin, 0, req); +} + +static int it8613hwm_probe(device_t dev) +{ + if (superio_vendor(dev) != SUPERIO_VENDOR_ITE) + return (ENXIO); + if (superio_get_type(dev) != SUPERIO_DEV_HWM) + return (ENXIO); + if (superio_devid(dev) != 0x8613) + return (ENXIO); + + device_set_desc(dev, "Hardware monitor on ITE SuperIO"); + return (BUS_PROBE_DEFAULT); +} + +static int it8613hwm_attach(device_t dev) +{ + struct it8613hwm_softc* sc = device_get_softc(dev); + struct sysctl_ctx_list* ctx; + int error; + uint16_t iobase; + uint8_t chipid; + + /* + * The hardware monitor sits at offset 5 in the chip's io address space. + * We'll claim two ports: first (iobase + 5 + 0) is the chip's register + * selector; the second (iobase + 5 + 1) is the data register. + */ + iobase = superio_get_iobase(dev); + error = bus_set_resource(dev, SYS_RES_IOPORT, sc->ioport_rid, + iobase + 5, 2); + if (error != 0) + { + device_printf(dev, "bus_set_resource failed\n"); + return (ENXIO); + } + sc->ioport_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, + &sc->ioport_rid, RF_ACTIVE); + if (sc->ioport_res == NULL) + { + device_printf(dev, "bus_alloc_resource_any failed\n"); + return (ENXIO); + } + + /* Check hardware monitor id... this should be 0x90 for the it8613. */ + bus_write_1(sc->ioport_res, 0, 0x58); // chip id register + chipid = bus_read_1(sc->ioport_res, 1); + if (chipid != 0x90) + { + device_printf(dev, "unexpected chip id: actual %i != expected %i\n", + chipid, 0x90); + bus_release_resource(dev, SYS_RES_IOPORT, sc->ioport_rid, + sc->ioport_res); + return (ENXIO); + } + + mtx_init(&sc->lock, device_get_nameunit(dev), "it8613hwm", MTX_DEF); + + ctx = device_get_sysctl_ctx(dev); + /* Gets us "dev.it8613hwm.0.temperature0" etc */ + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "temperature0", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, 0, it8613hwm_get_temp_sysctl, "IK0", "Temperature sensor 0"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "temperature1", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, 1, it8613hwm_get_temp_sysctl, "IK0", "Temperature sensor 1"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "temperature2", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, 2, it8613hwm_get_temp_sysctl, "IK0", "Temperature sensor 2"); + + return (0); +} + +static int it8613hwm_detach(device_t dev) +{ + struct it8613hwm_softc* sc = device_get_softc(dev); + + bus_release_resource(dev, SYS_RES_IOPORT, sc->ioport_rid, + sc->ioport_res); + mtx_destroy(&sc->lock); + + return (0); +} + +static device_method_t it8613hwm_methods[] = { + /* Methods from the device interface */ + DEVMETHOD(device_probe, it8613hwm_probe), + DEVMETHOD(device_attach, it8613hwm_attach), + DEVMETHOD(device_detach, it8613hwm_detach), + + /* Terminate method list */ + { 0, 0 } +}; + +static driver_t it8613hwm_driver = { + "it8613hwm", + it8613hwm_methods, + sizeof(struct it8613hwm_softc) +}; + +static devclass_t it8613hwm_devclass; + +DRIVER_MODULE(it8613hwm, superio, it8613hwm_driver, it8613hwm_devclass, NULL, + NULL); +MODULE_DEPEND(it8613hwm, superio, 1, 1, 1); +MODULE_VERSION(it8613hwm, 1); diff --git a/sys/dev/superio/superio.c b/sys/dev/superio/superio.c --- a/sys/dev/superio/superio.c +++ b/sys/dev/superio/superio.c @@ -293,6 +293,10 @@ const char *descr; const struct sio_device *devices; } superio_table[] = { + { + .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8613, + .devices = ite_devices, + }, { .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8712, .devices = ite_devices, @@ -549,8 +553,9 @@ sc->revid = revid; KASSERT(sc->vendor == SUPERIO_VENDOR_ITE || - sc->vendor == SUPERIO_VENDOR_NUVOTON, - ("Only ITE and Nuvoton SuperIO-s are supported")); + sc->vendor == SUPERIO_VENDOR_NUVOTON || + sc->vendor == SUPERIO_VENDOR_FINTEK, + ("Only ITE, Nuvoton or Fintek SuperIO-s are supported")); sc->ldn_reg = 0x07; sc->enable_reg = 0x30; sc->current_ldn = 0xff; /* no device should have this */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -192,6 +192,7 @@ ${_iser} \ isp \ ${_ispfw} \ + ${_it8613hwm} \ ${_itwd} \ ${_iwi} \ ${_iwifw} \ @@ -685,6 +686,7 @@ _if_ndis= if_ndis _igc= igc _io= io +_it8613hwm= it8613hwm _itwd= itwd _ix= ix _ixv= ixv diff --git a/sys/modules/it8613hwm/Makefile b/sys/modules/it8613hwm/Makefile new file mode 100644 --- /dev/null +++ b/sys/modules/it8613hwm/Makefile @@ -0,0 +1,7 @@ +.PATH: ${SRCTOP}/sys/dev/it8613hwm + +KMOD= it8613hwm +SRCS= it8613hwm.c +SRCS+= device_if.h bus_if.h isa_if.h + +.include