Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163288996
D56776.id177090.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D56776.id177090.diff
View Options
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1866,6 +1866,7 @@
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
--- /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 <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * 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
--- a/sys/modules/i2c/Makefile
+++ b/sys/modules/i2c/Makefile
@@ -32,7 +32,8 @@
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
--- /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 <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jul 22, 6:39 PM (4 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35373092
Default Alt Text
D56776.id177090.diff (10 KB)
Attached To
Mode
D56776: i2c/sensors: Add driver for W83793 hardware monitor
Attached
Detach File
Event Timeline
Log In to Comment