Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 Jul 2023 17:20:48 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 350b7c3570aa - main - superio+ncthwm: Add hardware monitoring support
Message-ID:  <202307011720.361HKmB3066388@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202307011720.361HKmB3066388>