git: 350b7c3570aa - main - superio+ncthwm: Add hardware monitoring support
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 01 Jul 2023 17:20:48 UTC
The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=350b7c3570aa6c87c537e54f706f1866f93a4142 commit 350b7c3570aa6c87c537e54f706f1866f93a4142 Author: Stéphane Rochoy <stephane.rochoy@stormshield.eu> AuthorDate: 2023-07-01 17:19:44 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2023-07-01 17:19:53 +0000 superio+ncthwm: Add hardware monitoring support Add support for the following chips: - Nuvoton NCT6779D - Nuvoton NCT6796D-E Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/719 --- share/man/man4/ncthwm.4 | 53 +++++++++ sys/conf/files.amd64 | 1 + sys/dev/ncthwm/ncthwm.c | 261 ++++++++++++++++++++++++++++++++++++++++++++ sys/dev/superio/superio.c | 1 + sys/modules/Makefile | 2 + sys/modules/ncthwm/Makefile | 8 ++ 6 files changed, 326 insertions(+) diff --git a/share/man/man4/ncthwm.4 b/share/man/man4/ncthwm.4 new file mode 100644 index 000000000000..5a9265f5a6da --- /dev/null +++ b/share/man/man4/ncthwm.4 @@ -0,0 +1,53 @@ +.\" $FreeBSD$ +.\" +.Dd Apr 18, 2023 +.Dt NCTHWM 4 +.Os +.Sh NAME +.Nm ncthwm +.Nd Hardware monitoring controller on Nuvoton Super I/Os +.Sh SYNOPSIS +.Cd "device ncthwm" +.Cd "device superio" +.Sh DESCRIPTION +The +.Nm +is a driver for hardware monitoring controller that can be found in Nuvoton +Super I/O chips. It expose fan speed via +.Xr sysctl 8 . + +.Pp +The +.Nm +driver supports the following chips: +.Pp +.Bl -bullet -compact +.It +Nuvoton NCT6779 +.It +Nuvoton NCT6796D-E +.El + +.Sh SYSCTL VARIABLES +These variables are available as read-only +.Xr sysctl 8 +variables: +.Bl -tag -width indent +.It Va dev.ncthwm.0.CPUFAN +CPU fan speed in RPM. +.It Va dev.ncthwm.0.SYSFAN +System fan speed in RPM. +.It Va dev.ncthwm.0.AUXFAN0 +AUX0 fan speed in RPM. +.It Va dev.ncthwm.0.AUXFAN1 +AUX1 fan speed in RPM. +.It Va dev.ncthwm.0.AUXFAN2 +AUX2 fan speed in RPM. +.El + +.Sh HISTORY +The driver first appeared in +.Fx 14.0 . +.Sh AUTHORS +The driver was initially written by +.An Stéphane Rochoy Aq Mt stephane.rochoy@stormshield.eu . diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 37e069da5918..77fdf2ca411f 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -239,6 +239,7 @@ dev/ixl/i40e_adminq.c optional ixl pci \ dev/ixl/i40e_dcb.c optional ixl pci \ compile-with "${NORMAL_C} -I$S/dev/ixl" dev/nctgpio/nctgpio.c optional nctgpio +dev/ncthwm/ncthwm.c optional ncthwm superio dev/nfe/if_nfe.c optional nfe pci dev/ntb/if_ntb/if_ntb.c optional if_ntb dev/ntb/ntb_transport.c optional ntb_transport | if_ntb diff --git a/sys/dev/ncthwm/ncthwm.c b/sys/dev/ncthwm/ncthwm.c new file mode 100644 index 000000000000..b62dff68f171 --- /dev/null +++ b/sys/dev/ncthwm/ncthwm.c @@ -0,0 +1,261 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2016-2022 Stormshield + * + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/sysctl.h> +#include <sys/watchdog.h> + +#include <dev/superio/superio.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#define NCTHWM_FAN_MAX 5 + +#define NCTHWM_BANK_SELECT 0x4e +#define NCTHWM_VENDOR_ID 0x4f + +#define NCTHWM_VERBOSE_PRINTF(dev, ...) \ + do { \ + if (__predict_false(bootverbose)) \ + device_printf(dev, __VA_ARGS__); \ + } while (0) + +struct ncthwm_softc { + device_t dev; + struct ncthwm_device *nctdevp; + struct resource *iores; + int iorid; +}; + +struct ncthwm_fan_info +{ + const char *name; + uint8_t low_byte_offset; + uint8_t high_byte_offset; +}; + +struct ncthwm_device { + uint16_t devid; + const char *descr; + uint8_t base_offset; + uint8_t fan_bank; + uint8_t fan_count; + struct ncthwm_fan_info fan_info[NCTHWM_FAN_MAX]; +} ncthwm_devices[] = { + { + .devid = 0xc562, + .descr = "HWM on Nuvoton NCT6779D", + .base_offset = 5, + .fan_bank = 4, + .fan_count = 5, + .fan_info = { + { .name = "SYSFAN", .low_byte_offset = 0xc1, .high_byte_offset = 0xc0 }, + { .name = "CPUFAN", .low_byte_offset = 0xc3, .high_byte_offset = 0xc2 }, + { .name = "AUXFAN0", .low_byte_offset = 0xc5, .high_byte_offset = 0xc4 }, + { .name = "AUXFAN1", .low_byte_offset = 0xc7, .high_byte_offset = 0xc6 }, + { .name = "AUXFAN2", .low_byte_offset = 0xc9, .high_byte_offset = 0xc8 }, + }, + }, { + .devid = 0xd42a, + .descr = "HWM on Nuvoton NCT6796D-E", + .base_offset = 5, + .fan_bank = 4, + .fan_count = 5, + .fan_info = { + { .name = "SYSFAN", .low_byte_offset = 0xc1, .high_byte_offset = 0xc0 }, + { .name = "CPUFAN", .low_byte_offset = 0xc3, .high_byte_offset = 0xc2 }, + { .name = "AUXFAN0", .low_byte_offset = 0xc5, .high_byte_offset = 0xc4 }, + { .name = "AUXFAN1", .low_byte_offset = 0xc7, .high_byte_offset = 0xc6 }, + { .name = "AUXFAN2", .low_byte_offset = 0xc9, .high_byte_offset = 0xc8 }, + }, + } +}; + +static struct ncthwm_device * +ncthwm_lookup_device(device_t dev) +{ + int i; + uint16_t devid; + + devid = superio_devid(dev); + for (i = 0; i < nitems(ncthwm_devices); i++) { + if (devid == ncthwm_devices[i].devid) + return (ncthwm_devices + i); + } + return (NULL); +} + +static void +ncthwm_write(struct ncthwm_softc *sc, uint8_t reg, uint8_t val) +{ + bus_write_1(sc->iores, 0, reg); + bus_write_1(sc->iores, 1, val); +} + +static uint8_t +ncthwm_read(struct ncthwm_softc *sc, uint8_t reg) +{ + bus_write_1(sc->iores, 0, reg); + return (bus_read_1(sc->iores, 1)); +} + +static int +ncthwm_query_fan_speed(SYSCTL_HANDLER_ARGS) +{ + struct ncthwm_softc *sc; + struct ncthwm_fan_info *fan; + uint16_t val; + + sc = arg1; + if (sc == NULL) + return (EINVAL); + + KASSERT(sc->nctdevp != NULL, ("Unreachable")); + + if (sc->nctdevp->fan_count <= arg2) + return (EINVAL); + fan = &sc->nctdevp->fan_info[arg2]; + + KASSERT(sc->iores != NULL, ("Unreachable")); + + ncthwm_write(sc, NCTHWM_BANK_SELECT, sc->nctdevp->fan_bank); + val = ncthwm_read(sc, fan->high_byte_offset) << 8; + val |= ncthwm_read(sc, fan->low_byte_offset); + + NCTHWM_VERBOSE_PRINTF(sc->dev, "%s: read %u from bank %u offset 0x%x-0x%x\n", + fan->name, val, sc->nctdevp->fan_bank, fan->high_byte_offset, fan->low_byte_offset); + + return (sysctl_handle_int(oidp, &val, 0, req)); +} + +static int +ncthwm_probe(device_t dev) +{ + struct ncthwm_device *nctdevp; + uint8_t ldn; + + ldn = superio_get_ldn(dev); + + if (superio_vendor(dev) != SUPERIO_VENDOR_NUVOTON) { + NCTHWM_VERBOSE_PRINTF(dev, "ldn 0x%x not a Nuvoton device\n", ldn); + return (ENXIO); + } + if (superio_get_type(dev) != SUPERIO_DEV_HWM) { + NCTHWM_VERBOSE_PRINTF(dev, "ldn 0x%x not a HWM device\n", ldn); + return (ENXIO); + } + + nctdevp = ncthwm_lookup_device(dev); + if (nctdevp == NULL) { + NCTHWM_VERBOSE_PRINTF(dev, "ldn 0x%x not supported\n", ldn); + return (ENXIO); + } + device_set_desc(dev, nctdevp->descr); + return (BUS_PROBE_DEFAULT); +} + +static int +ncthwm_attach(device_t dev) +{ + struct ncthwm_softc *sc; + int i; + uint16_t iobase; + + sc = device_get_softc(dev); + sc->dev = dev; + + sc->nctdevp = ncthwm_lookup_device(dev); + if (sc->nctdevp == NULL) { + device_printf(dev, "device not supported\n"); + return (ENXIO); + } + + iobase = superio_get_iobase(dev) + sc->nctdevp->base_offset; + sc->iorid = 0; + if (bus_set_resource(dev, SYS_RES_IOPORT, sc->iorid, iobase, 2) != 0) { + device_printf(dev, "failed to set I/O port resource at 0x%x\n", iobase); + return (ENXIO); + } + sc->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, + &sc->iorid, RF_ACTIVE); + if (sc->iores == NULL) { + device_printf(dev, "can't map I/O space at 0x%x\n", iobase); + return (ENXIO); + } + NCTHWM_VERBOSE_PRINTF(dev, "iobase 0x%x iores %p\n", iobase, sc->iores); + + /* Register FAN sysctl */ + for (i = 0; i < sc->nctdevp->fan_count; i++) { + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + sc->nctdevp->fan_info[i].name, + CTLTYPE_U16 | CTLFLAG_RD, sc, i, + ncthwm_query_fan_speed, "SU", "Fan speed in RPM"); + } + + return (0); +} + +static int +ncthwm_detach(device_t dev) +{ + struct ncthwm_softc *sc = device_get_softc(dev); + + if (sc->iores) + bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->iores); + + return (0); +} + +static device_method_t ncthwm_methods[] = { + /* Methods from the device interface */ + DEVMETHOD(device_probe, ncthwm_probe), + DEVMETHOD(device_attach, ncthwm_attach), + DEVMETHOD(device_detach, ncthwm_detach), + + /* Terminate method list */ + { 0, 0 } +}; + +static driver_t ncthwm_driver = { + "ncthwm", + ncthwm_methods, + sizeof (struct ncthwm_softc) +}; + +DRIVER_MODULE(ncthwm, superio, ncthwm_driver, NULL, NULL); +MODULE_DEPEND(ncthwm, superio, 1, 1, 1); +MODULE_VERSION(ncthwm, 1); diff --git a/sys/dev/superio/superio.c b/sys/dev/superio/superio.c index 2d40d9ef43b7..4d1e9ef60974 100644 --- a/sys/dev/superio/superio.c +++ b/sys/dev/superio/superio.c @@ -303,6 +303,7 @@ const struct sio_device nct611x_devices[] = { const struct sio_device nct67xx_devices[] = { { .ldn = 0x8, .type = SUPERIO_DEV_WDT }, { .ldn = 0x9, .type = SUPERIO_DEV_GPIO }, + { .ldn = 0xb, .type = SUPERIO_DEV_HWM }, { .type = SUPERIO_DEV_NONE }, }; diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 54c98491228f..20945548604f 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -275,6 +275,7 @@ SUBDIR= \ mxge \ my \ ${_nctgpio} \ + ${_ncthwm} \ ${_neta} \ netlink \ ${_netgraph} \ @@ -726,6 +727,7 @@ _lio= lio _mana= mana _mgb= mgb _nctgpio= nctgpio +_ncthwm= ncthwm _ntb= ntb _ocs_fc= ocs_fc _p2sb= p2sb diff --git a/sys/modules/ncthwm/Makefile b/sys/modules/ncthwm/Makefile new file mode 100644 index 000000000000..e04beccf1861 --- /dev/null +++ b/sys/modules/ncthwm/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/ncthwm +KMOD= ncthwm +SRCS= ncthwm.c +SRCS+= device_if.h bus_if.h isa_if.h opt_platform.h + +.include <bsd.kmod.mk>