From nobody Wed May 20 02:23:38 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gKwMG4NLxz6dxZW for ; Wed, 20 May 2026 02:23:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gKwMG3hQqz3HMk for ; Wed, 20 May 2026 02:23:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779243818; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=MqVIj96JoV/gbAGCOP7lB5aRGDOJh0+7FMF9oGeqTm0=; b=imfo5r3Nc5LJgTn8MFJOnVHA2+64HS+EteYif+OWC0Mmwn1h4o9n/sq+T3kp3dDMGEQ7fb bK5SyJkAp3FDElqzC3ujz4MM6CvZRhi6iG7RsoUjJ5qFoPlI61kPEVbKqxSLkewuXoVGKh 6i3LTx5B6DgfT3nEdOuaidXDensH/Cloyi6fh8ERYLxUrS/kHBU8OB29vS8Y942G1+QZKE 5h/noWdLr9Zny3NYC8YeNZ8uh0aMTnqW267MFRGueEUES3LxyoLBcqeGnVaeb6Py4vLdKR E00K1XtH1xM/IcBxFQf8w4VbfEiNtxoivV78cFXQSDb5Jui37RXDkHxJk7jC4g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779243818; a=rsa-sha256; cv=none; b=Urv6grYQp3QMl3kS/S9H/lNUd7QGX/cNcdfsjTFs+lyExGz4xqNzpH/zDkiDe6YklU8WqW mpFZfX1QzK8YihM3+SX9LeJZ7Y81+SkTb9gGpdk1Siq+x2mHguxQFLszrO1WSB6WnYdEEG roMZKf5YHW45hUGmsjR7IatL5dythZUnys5uaPoA3yhPGoEJC5ASwDqxy5yb5sYyfXQPyI LibVG7IaCnCA4SsM2X3SKn10fQE/Tk4W/o865ox4La58cOhlzFD3KmhSJdlpm59rrnjOPk UMogkU8h83VIOs/wwBmaMKZk5AdjOmWR5NJ4fh6oIruRcldT9tzImvmguiiDvw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779243818; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=MqVIj96JoV/gbAGCOP7lB5aRGDOJh0+7FMF9oGeqTm0=; b=lECJorVvu42UgtnM6Zw/2syLAqbVi2w2AwtHP4Fa6KGR4xPIwWqZZFUaiORPT/YaNGH3RP qOJ72GGCnMD4FWn94r2Ppx3Lm0CEoSeYLqSLHGRQXl5qm8yB50B6anXewLqn1QJogn5AzG y0FXI8zBpZg2L/jduum+65BK77mlfiZ4mZMNwhvcmoL6btUp6MEHsLsIuZr5az4MKS4dAH WKQ+55xNac2Hx/k2YsYVciVJSJZufFqrQ1uA7jri2mKpSUwip4NExSIkiArrm4rivn2KHr jJcjJ0btUa7yluVC64NGIW9QT4BI5GOmnxPVSd5ZR7iJFMtcbRuUFh+GBdvyfQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gKwMG373bzj2d for ; Wed, 20 May 2026 02:23:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3a60d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 20 May 2026 02:23:38 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Justin Hibbits Subject: git: cd3cc6e910c0 - main - i2c/sensors: Add driver for W83793 hardware monitor List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhibbits X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: cd3cc6e910c0f739925c57e42fae6781d693db02 Auto-Submitted: auto-generated Date: Wed, 20 May 2026 02:23:38 +0000 Message-Id: <6a0d1b2a.3a60d.287b9f55@gitrepo.freebsd.org> The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=cd3cc6e910c0f739925c57e42fae6781d693db02 commit cd3cc6e910c0f739925c57e42fae6781d693db02 Author: Justin Hibbits AuthorDate: 2026-05-20 02:04:30 +0000 Commit: Justin Hibbits CommitDate: 2026-05-20 02:05:00 +0000 i2c/sensors: Add driver for W83793 hardware monitor The Winbond/Nuvoton W83793G system monitor chip includes many features not currently supported by this driver. The following are currently supported: * Up to 6 temperature sensors, 4 of which have 10-bit resolution (8.2),two with 8-bit resolution (no decimal component) * Up to 12 fans - Fans 0-4 (1-5 on the datasheet) are always enabled. The remaining 7 fans are individually enabled. * Multiple voltage sensors, reading up to 10 voltage sources. Sysctls are labeled to match the datasheet. * Chassis open detection. The W83793AG is a feature-reduced version, which lacks 3 thermal diodes and 2 voltage monitors. Since there is no way to tell the difference between the W83793AG and W83793G programmatically, sensors reported on the W83793AG will report strange values. Temperature sensors and 7 of the fans can be individually enabled on the chip, but currently not configured by this driver. The driver only reports what was configured by the firmware. Additionally, this driver numbers the sensors and fans according to the datasheet, so even if, for instance, fan 8 is disabled, it would skip from fan 7 to fan 9, it does not renumber. This makes it easier to follow for hardware debugging purposes. Missing features: * Smart Fan support * Fan PWM control * ASF (Alert Standard Format) Only Bank 0 registers are used at this time. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D56776 --- sys/conf/files | 1 + sys/dev/iicbus/sensor/w83793g.c | 366 +++++++++++++++++++++++++++++++++++++++ sys/modules/i2c/Makefile | 3 +- sys/modules/i2c/w83793g/Makefile | 14 ++ 4 files changed, 383 insertions(+), 1 deletion(-) diff --git a/sys/conf/files b/sys/conf/files index 6804c9c81c69..fac94252a362 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1866,6 +1866,7 @@ dev/iicbus/rtc/s35390a.c optional s35390a dev/iicbus/sensor/htu21.c optional htu21 dev/iicbus/sensor/lm75.c optional lm75 dev/iicbus/sensor/max44009.c optional max44009 +dev/iicbus/sensor/w83793g.c optional w83793g dev/iicbus/gpio/pcf8574.c optional pcf8574 dev/iicbus/gpio/tca64xx.c optional tca64xx fdt gpio dev/iicbus/pmic/fan53555.c optional fan53555 fdt | tcs4525 fdt diff --git a/sys/dev/iicbus/sensor/w83793g.c b/sys/dev/iicbus/sensor/w83793g.c new file mode 100644 index 000000000000..772384aa57a0 --- /dev/null +++ b/sys/dev/iicbus/sensor/w83793g.c @@ -0,0 +1,366 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Justin Hibbits + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +/* + * Driver for the Winbond W83793G hardware monitor. + * + * The hardware monitor supports the following sensors: + * - 6 temperature sensors + * - 4 with 1/4 integer precision + * - 2 with integer precision + * - 11 voltage sensors + * - 12 fan sensors + * - FanIn 6-12 are on multifunction pins, so may not be enabled. + * 8 DC/PWM fan outputs for fan speed control + * - Case open detection + */ + +#define WB_TD_BASE 0x1c +#define WB_TLOW 0x22 + +#define WB_VCORE_A 0x10 +#define WB_VCORE_B 0x11 +#define WB_VTT 0x12 +#define WB_VSEN1 0x14 +#define WB_VSEN2 0x15 +#define WB_VSEN3 0x16 +#define WB_VSEN4 0x17 +#define WB_5VDD 0x18 +#define WB_5VSB 0x19 +#define WB_VBAT 0x1a +#define WB_VLOW 0x1b +#define WB_FAN_BASE 0x23 + +#define INT_STS1 0x41 +#define INT_STS2 0x42 +#define INT_STS3 0x43 +#define INT_STS4 0x44 +#define CHASSIS 0x40 +#define INT_STS5 0x45 +#define INT_MASK1 0x46 +#define INT_MASK2 0x47 +#define INT_MASK3 0x48 +#define INT_MASK4 0x49 +#define CLR_CHS 0x80 +#define INT_MASK5 0x4a + +#define WB_MFC 0x58 /* Multi-function pin control */ +#define MFC_VIDBSEL 0x80 +#define MFC_SIB_SEL 0x40 +#define MFC_SID_SEL_M 0x30 +#define MFC_SID_VID 0x00 +#define MFC_SID_FANIN 0x20 +#define MFC_SIC_SEL_M 0x0c +#define MFC_SIC_VID 0x00 +#define MFC_SIC_FANIN 0x08 +#define MFC_SIA_SEL 0x02 +#define MFC_FAN8SEL 0x01 +#define WB_FANIN_CTRL 0x5c +#define FANIN_EN_12 0x40 +#define FANIN_EN_11 0x20 +#define FANIN_EN_10 0x10 +#define FANIN_EN_9 0x08 +#define FANIN_EN_8 0x04 +#define FANIN_EN_7 0x02 +#define FANIN_EN_6 0x01 +#define WB_FANIN_SEL 0x5d +#define WB_TD_MD 0x5e /* TD mode select register */ +#define TD_MD_M(n) (0x3 << ((n) * 2)) +#define TD_MD_S(n) ((n) * 2) +#define TD_STOP_M 0x0 +#define TD_INT_MD 0x1 +#define TD_EXT_MD 0x2 +#define WB_TR_MD 0x5f +#define TR2_MD 0x2 +#define TR1_MD 0x1 + +#define WB_TEMP_COUNT 6 /* Total temperature sensors */ +#define WB_TD_COUNT 4 /* Temp sensors with "low" part */ +#define WB_TR_COUNT 2 +#define WB_FAN_COUNT 12 +#define WB_FAN_ALWAYS_ON 5 /* First 5 are not controlled */ +#define WB_V_COUNT 11 + +static const struct wb_vsens { + const char *name; + int reg; + int scale; /* Scale in millivolts */ + int add; /* Scale in millivolts */ + int left_low; /* left bit in VLOW, if applicable */ +} voltages[] = { + { "v_core_a", WB_VCORE_A, 2, 0, 1 }, + { "v_core_b", WB_VCORE_B, 2, 0, 3 }, + { "v_tt", WB_VTT, 2, 0, 5 }, + { "v_sen_1", WB_VSEN1, 16 }, + { "v_sen_2", WB_VSEN2, 16 }, + { "v_sen_3", WB_VSEN3, 16 }, + { "v_sen_4", WB_VSEN4, 8 }, + { "5v", WB_5VDD, 24, 150 }, + { "5v_sb", WB_5VSB, 24, 150 }, + { "v_bat", WB_VBAT, 16 } +}; + +struct w83793g_softc { + device_t sc_dev; + +}; + +static device_probe_t w83793g_probe; +static device_attach_t w83793g_attach; +static device_detach_t w83793g_detach; +static int w83793g_temp_sysctl(SYSCTL_HANDLER_ARGS); +static int w83793g_fan_sysctl(SYSCTL_HANDLER_ARGS); +static int w83793g_voltage_sysctl(SYSCTL_HANDLER_ARGS); +static int w83793g_case_sysctl(SYSCTL_HANDLER_ARGS); + +static device_method_t w83793g_methods[] = { + DEVMETHOD(device_probe, w83793g_probe), + DEVMETHOD(device_attach, w83793g_attach), + DEVMETHOD(device_detach, w83793g_detach), + + DEVMETHOD_END +}; + +static struct ofw_compat_data compat[] = { + { "winbond,w83793", 1 }, + { NULL, 0 } +}; + +DEFINE_CLASS_0(w83793g, w83793g_driver, w83793g_methods, + sizeof(struct w83793g_softc)); +DRIVER_MODULE(w83793g, iicbus, w83793g_driver, NULL, NULL); +MODULE_VERSION(w83793g, 1); +MODULE_DEPEND(w83793g, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); +IICBUS_FDT_PNP_INFO(compat); + +static int +w83793g_readreg(device_t dev, int reg, uint8_t *output) +{ + return (iicdev_readfrom(dev, reg, output, sizeof(*output), IIC_WAIT)); +} + +static int +w83793g_writereg(device_t dev, int reg, uint8_t *output) +{ + return (iicdev_writeto(dev, reg, output, sizeof(*output), IIC_WAIT)); +} + +static bool +temp_enabled(struct w83793g_softc *sc, int sensor) +{ + uint8_t reg; + int error; + + if (sensor < WB_TD_COUNT) { + error = w83793g_readreg(sc->sc_dev, WB_TD_MD, ®); + if (error != 0) + return (false); + return ((reg & TD_MD_M(sensor)) != 0); + } else { + error = w83793g_readreg(sc->sc_dev, WB_TR_MD, ®); + sensor -= WB_TD_COUNT; + if (error != 0) + return (false); + return ((reg & (1 << sensor)) != 0); + } +} + +static bool +fan_enabled(struct w83793g_softc *sc, int fan) +{ + int error; + uint8_t fanin_ctl; + + if (fan < WB_FAN_ALWAYS_ON) + return (true); + + error = w83793g_readreg(sc->sc_dev, WB_FANIN_CTRL, &fanin_ctl); + if (error != 0) + return (false); + + fan -= WB_FAN_ALWAYS_ON; + + return ((fanin_ctl & (1 << fan)) != 0); +} + +static int +w83793g_probe(device_t dev) +{ + if (ofw_bus_search_compatible(dev, compat)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Winbond W83793 Hardware Monitor"); + + return (BUS_PROBE_DEFAULT); +} + +static int +w83793g_attach(device_t dev) +{ + struct w83793g_softc *sc = device_get_softc(dev); + struct sysctl_oid *root = device_get_sysctl_tree(dev); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); + struct sysctl_oid *node; + int i; + + sc->sc_dev = dev; + node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(root), OID_AUTO, "voltages", + CTLFLAG_RD, NULL, NULL); + for (i = 0; i < nitems(voltages); i++) { + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO, + voltages[i].name, CTLTYPE_INT | CTLFLAG_RD, sc, + i, w83793g_voltage_sysctl, "I", + "voltage (millivolts)"); + } + node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(root), OID_AUTO, "temp", + CTLFLAG_RD, NULL, NULL); + for (i = 0; i < WB_TEMP_COUNT; i++) { + /* Only supports single-digit sensors. */ + char name[sizeof("sensor_") + 1]; + + if (!temp_enabled(sc, i)) + continue; + snprintf(name, sizeof(name), "sensor_%d", i); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO, name, + CTLTYPE_INT | CTLFLAG_RD, sc, WB_TD_BASE + i, + w83793g_temp_sysctl, "IK2", NULL); + } + node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(root), OID_AUTO, "fans", + CTLFLAG_RD, NULL, NULL); + for (i = 0; i < WB_FAN_COUNT; i++) { + /* Supports up to 12 fans */ + char name[sizeof("fan_") + 2]; + + if (!fan_enabled(sc, i)) + continue; + snprintf(name, sizeof(name), "fan_%d", i); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO, name, + CTLTYPE_INT | CTLFLAG_RD, sc, WB_FAN_BASE + i, + w83793g_fan_sysctl, "I", NULL); + } + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(root), OID_AUTO, "chassis_open", + CTLTYPE_U8 | CTLFLAG_RD, sc, 0, w83793g_case_sysctl, "CU", + "report if the chassis_open was latched"); + return (0); +} + +static int +w83793g_detach(device_t dev) +{ + return (ENXIO); +} + +static int +w83793g_temp_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct w83793g_softc *sc = arg1; + int reg = arg2; + int temp; + int error; + int8_t t_reg; + uint8_t t_low; + + error = w83793g_readreg(sc->sc_dev, reg, &t_reg); + if (error != 0) + return (error); + + if (reg < WB_TD_BASE + WB_TD_COUNT) { + error = w83793g_readreg(sc->sc_dev, WB_TLOW, &t_low); + if (error != 0) + return (error); + } else + t_low = 0; + + temp = (int)t_reg * 100; + temp += (t_low >> (2 * (reg - WB_TD_BASE)) & 0x3) * 25; + temp += 27315; /* Convert celsius to kelvin */ + + error = sysctl_handle_int(oidp, &temp, 0, req); + + return (error); +} + +static int +w83793g_fan_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct w83793g_softc *sc = arg1; + int reg = arg2; + int count; + int error; + uint8_t reg_vals[2]; /* Fan count is 2 bytes */ + + error = iicdev_readfrom(sc->sc_dev, reg, reg_vals, sizeof(reg_vals), + IIC_WAIT); + if (error != 0) + return (error); + + count = ((int)reg_vals[0] << 8) | reg_vals[1]; + error = sysctl_handle_int(oidp, &count, 0, req); + + return (error); +} + +static int +w83793g_voltage_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct w83793g_softc *sc = arg1; + const struct wb_vsens *sensor; + int index = arg2; + int volts; + int error; + uint8_t v_reg; + uint8_t v_low; + + sensor = &voltages[index]; + error = w83793g_readreg(sc->sc_dev, sensor->reg, &v_reg); + if (error != 0) + return (error); + + volts = v_reg; + if (sensor->left_low != 0) { + volts <<= 2; + error = w83793g_readreg(sc->sc_dev, WB_VLOW, &v_low); + if (error != 0) + return (error); + volts |= (v_low >> (sensor->left_low - 1) & 0x3); + } + + volts *= sensor->scale; + volts += sensor->add; + + error = sysctl_handle_int(oidp, &volts, 0, req); + + return (error); +} + +static int +w83793g_case_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct w83793g_softc *sc = arg1; + int error; + uint8_t reg; + bool chassis; + + error = w83793g_readreg(sc->sc_dev, INT_STS4, ®); + if (error != 0) + return (error); + + chassis = ((reg & CHASSIS) != 0); + + return (sysctl_handle_bool(oidp, &chassis, 0, req)); +} diff --git a/sys/modules/i2c/Makefile b/sys/modules/i2c/Makefile index ff4536694dfc..64b22db3319d 100644 --- a/sys/modules/i2c/Makefile +++ b/sys/modules/i2c/Makefile @@ -32,7 +32,8 @@ SUBDIR += hym8563 \ rv3032 \ rx8803 \ tca64xx \ - tmp461 + tmp461 \ + w83793g .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ diff --git a/sys/modules/i2c/w83793g/Makefile b/sys/modules/i2c/w83793g/Makefile new file mode 100644 index 000000000000..d4329b00d30a --- /dev/null +++ b/sys/modules/i2c/w83793g/Makefile @@ -0,0 +1,14 @@ +.PATH: ${SRCTOP}/sys/dev/iicbus/sensor/ +KMOD = w83793g +SRCS = w83793g.c + +# Generated files... +SRCS+= \ + bus_if.h \ + clock_if.h \ + device_if.h \ + iicbus_if.h \ + opt_platform.h \ + ofw_bus_if.h \ + +.include