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>