Index: src/sys/dev/i2c/adt7462.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/adt7462.c,v
retrieving revision 1.2
diff -u -r1.2 adt7462.c
--- src/sys/dev/i2c/adt7462.c	7 Jul 2026 12:28:44 -0000	1.2
+++ src/sys/dev/i2c/adt7462.c	7 Aug 2026 08:57:50 -0000
@@ -148,6 +148,7 @@
 	int sc_crit_therm[ADT7462_MAX_SENSORS];
 	uint8_t sc_highlim[ADT7462_MAX_SENSORS];
 	uint8_t sc_lowlim[ADT7462_MAX_SENSORS];
+	int sc_temp_off[ADT7462_MAX_TEMPS];
 	uint8_t sc_fan_conf;
 	char sc_sys_ctrl[ADT7462_NUM_PWM][ADT7462_DESC_LEN]; /* sysctl str */
 	struct sysctllog *sc_sysctl_log;
@@ -163,7 +164,7 @@
 static int adt7462_start_monitor(struct adt7462_softc *, int);
 static int adt7462_stop_monitor(struct adt7462_softc *);
 static int adt7462_setup_fans(struct adt7462_softc *, uint8_t *);
-static int adt7462_setup_temps(struct adt7462_softc *, uint8_t *);
+static int adt7462_setup_temps(struct adt7462_softc *, uint8_t *, uint32_t);
 static int adt7462_setup_volts(struct adt7462_softc *, uint8_t *);
 static int adt7462_setup_faults(struct adt7462_softc *);
 static int adt7462_setup_sysctl(struct adt7462_softc *, uint8_t *);
@@ -264,6 +265,7 @@
 	struct adt7462_softc *sc = device_private(self);
 	struct i2c_attach_args *ia = aux;
 	prop_dictionary_t props = device_properties(self);
+	uint32_t temp_off;
 	uint8_t reg, rev, val, pin_cfg[4];
 
 	sc->sc_tag = ia->ia_tag;
@@ -275,6 +277,11 @@
 	    &sc->sc_fan_conf) == 0)
 		sc->sc_fan_conf = 0xff;	/* 4 + 4 fans */
 
+	/* Property override for temperature offsets */
+	if (prop_dictionary_get_uint32(props, "temp_off",
+	    &temp_off) == 0)
+		temp_off = 0x0;	/* no offsets */
+
 	(void) adt7462_ident(sc->sc_tag, sc->sc_address, 0, &rev);
 	aprint_normal(": ADT7462 system monitor: rev. 0x%x\n", rev);
 
@@ -315,7 +322,7 @@
 	sc->sc_nfaults = 0;
 	if (adt7462_setup_fans(sc, pin_cfg))
 		goto bad;
-	if (adt7462_setup_temps(sc, pin_cfg))
+	if (adt7462_setup_temps(sc, pin_cfg, temp_off))
 		goto bad;
 	if (adt7462_setup_volts(sc, pin_cfg))
 		goto bad;
@@ -456,11 +463,18 @@
 adt7462_setup_fans(struct adt7462_softc *sc, uint8_t *pin_cfg)
 {
 	int i, map, snum;
-	uint8_t reg, val;
+	uint8_t reg, tach_en, val;
+
+	reg = ADT7462_TACH_EN;
+	if (adt7462_read_reg(sc->sc_tag, sc->sc_address, reg, &tach_en) != 0) {
+		aprint_error_dev(sc->sc_dev, "unable to read tach enable\n");
+		return 1;
+	}
 
 	for (i = 0; i < ADT7462_MAX_FANS; i++) {
-		/* Check fan conf and pin1/pin2 configurations. */
-		if (!(sc->sc_fan_conf & (1 << i)) ||
+		/* Check fan conf, tach en. and pin1/pin2 configurations. */
+		if (!ADT7462_FAN_TACH_EN(sc->sc_fan_conf, i) ||
+		    !ADT7462_FAN_TACH_EN(tach_en, i) ||
 		    !ADT7462_PCR1_TACH(pin_cfg[0], i) ||
 		    !ADT7462_PCR2_TACH(pin_cfg[1], i))
 			continue;
@@ -497,10 +511,12 @@
 }
 
 static int
-adt7462_setup_temps(struct adt7462_softc *sc, uint8_t *pin_cfg)
+adt7462_setup_temps(struct adt7462_softc *sc, uint8_t *pin_cfg,
+    uint32_t temp_off)
 {
 	int i, map, snum;
 	uint8_t reg, val, val2;
+	int8_t temp_off1;
 
 	for (i = 0; i < ADT7462_MAX_TEMPS; i++) {
 		/* Check pin1 configurations. */
@@ -509,6 +525,10 @@
 
 		snum = ADT7462_TEMP_NUM(i);
 
+		/* Store the offset in uK */
+		temp_off1 = temp_off >> (i * 8) & 0xff;
+		sc->sc_temp_off[i] = temp_off1 * 1000000;
+
 		/* Store initial limits */
 		reg = ADT7462_TEMP_THERM1(i);
 		if (adt7462_read_reg(sc->sc_tag, sc->sc_address,
@@ -1053,7 +1073,7 @@
 		return;
 	}
 
-	edata->value_cur = VAL_TO_TEMP(msb, lsb);
+	edata->value_cur = VAL_TO_TEMP(msb, lsb) + sc->sc_temp_off[temp];
 	edata->state = ENVSYS_SVALID;
 }
 
@@ -1159,19 +1179,19 @@
 		reg = ADT7462_TEMP_THERM2(temp);
 	if (adt7462_read_reg(sc->sc_tag, sc->sc_address, reg, &val) != 0)
 		return;
-	limits->sel_critmax = VAL_TO_TEMP(val, 0);
+	limits->sel_critmax = VAL_TO_TEMP(val, 0) + sc->sc_temp_off[temp];
 	*props |= PROP_CRITMAX;
 
 	reg = ADT7462_TEMP_HIGH(temp);
 	if (adt7462_read_reg(sc->sc_tag, sc->sc_address, reg, &val) != 0)
 		return;
-	limits->sel_warnmax = VAL_TO_TEMP(val, 0);
+	limits->sel_warnmax = VAL_TO_TEMP(val, 0) + sc->sc_temp_off[temp];
 	*props |= PROP_WARNMAX;
 
 	reg = ADT7462_TEMP_LOW(temp);
 	if (adt7462_read_reg(sc->sc_tag, sc->sc_address, reg, &val) != 0)
 		return;
-	limits->sel_warnmin = VAL_TO_TEMP(val, 0);
+	limits->sel_warnmin = VAL_TO_TEMP(val, 0) + sc->sc_temp_off[temp];
 	*props |= PROP_WARNMIN;
 }
 
@@ -1239,7 +1259,7 @@
 adt7462_set_temp_limits(struct adt7462_softc *sc, envsys_data_t *edata,
 	sysmon_envsys_lim_t *limits, uint32_t *props)
 {
-	int temp, snum;
+	int temp, snum, off;
 	uint8_t	reg, val;
 
 	temp = sc->sc_env_map[edata->sensor];
@@ -1252,7 +1272,8 @@
 			else
 				val = sc->sc_therm2[snum];
 		} else {
-			val = TEMP_TO_MSB(limits->sel_critmax);
+			off = limits->sel_critmax - sc->sc_temp_off[temp];
+			val = TEMP_TO_MSB(off);
 		}
 		/* Don't change order of therm limits */
 		if (sc->sc_crit_therm[snum] == 1) {
@@ -1273,7 +1294,8 @@
 		if (limits == NULL)	/* Restore defaults */
 			val = sc->sc_highlim[snum];
 		else {
-			val = TEMP_TO_MSB(limits->sel_warnmax);
+			off = limits->sel_warnmax - sc->sc_temp_off[temp];
+			val = TEMP_TO_MSB(off);
 		}
 		reg = ADT7462_TEMP_HIGH(temp);
 		adt7462_write_reg(sc->sc_tag, sc->sc_address, reg, val);
@@ -1283,7 +1305,8 @@
 		if (limits == NULL)	/* Restore defaults */
 			val = sc->sc_lowlim[snum];
 		else {
-			val = TEMP_TO_MSB(limits->sel_warnmin);
+			off = limits->sel_warnmin - sc->sc_temp_off[temp];
+			val = TEMP_TO_MSB(off);
 		}
 		reg = ADT7462_TEMP_LOW(temp);
 		adt7462_write_reg(sc->sc_tag, sc->sc_address, reg, val);
Index: src/sys/dev/i2c/adt7462reg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/adt7462reg.h,v
retrieving revision 1.2
diff -u -r1.2 adt7462reg.h
--- src/sys/dev/i2c/adt7462reg.h	7 Jul 2026 12:27:03 -0000	1.2
+++ src/sys/dev/i2c/adt7462reg.h	7 Aug 2026 08:57:50 -0000
@@ -294,6 +294,9 @@
 #define ADT7462_GPIO8_POL	0x40	/* GPIO8 polarity (0 low, 1 high) */
 #define ADT7462_GPIO8_DIR	0x80	/* GPIO8 direction (0 in, 1 out) */
 
+#define ADT7462_GPIO_POL(val, x)	(val & (1 << (i * 2)) ? 1 : 0)
+#define ADT7462_GPIO_DIR(val, x)	(val & (1 << (i * 2 + 1)) ? 1 : 0)
+
 /* 0x0b: Dynamix Tmin control register 1 */
 #define ADT7462_REM1_EN		0x01	/* Enable dynamic rem 1 Tmin control */
 #define ADT7462_REM2_EN		0x02	/* Enable dynamic rem 2 Tmin control */
@@ -347,6 +350,8 @@
 #define ADT7462_PCR1_PIN19_V(val)	(!(val & ADT7462_DIODE3_CONF))
 #define ADT7462_PCR1_PIN15_V(val)	(!(val & ADT7462_DIODE1_CONF))
 #define ADT7462_PCR1_VIDS(val)		((val & ADT7462_VID_EN) != 0)
+#define ADT7462_PCR1_GPIO(val, x)	(x > 3 || \
+    (!(val & ADT7462_VID_EN) && !(val & (1 << (4 - x)))))
 
 /* 0x11: Pin configuration register 2 */
 #define ADT7462_PIN23_CONF	0x03	/* 00 = Vcc, 2.5v, 1.8v, 11 = 1.5v */
@@ -393,6 +398,11 @@
 
 #define ADT7462_PCR4_P29_15V(val)	((val & ADT7462_PIN29_CONF) == 0x10)
 #define ADT7462_PCR4_P28_15V(val)	((val & ADT7462_PIN28_CONF) == 0x10)
+#define ADT7462_PCR4_GPIO(val, x)	(x < 4 || \
+    (x == 4 && !(val & ADT7462_PIN31_CONF)) || \
+    (x == 5 && !(val & ADT7462_PIN32_CONF)) || \
+    (x == 6 && !(val & ADT7462_PIN28_CONF)) || \
+    (x == 7 && !(val & ADT7462_PIN28_CONF)))
 
 /* 0x14: Easy configuration options */
 #define ADT7462_EASY1		0x01	/* Enable easy option 1 */
@@ -685,14 +695,7 @@
 #define ADT7462_15V1_TRIP	0x80
 
 /* 0xbd, 0xc5: Host/BMC fan status register */
-#define ADT7462_FAN1_FAULT	0x01
-#define ADT7462_FAN2_FAULT	0x02
-#define ADT7462_FAN3_FAULT	0x04
-#define ADT7462_FAN4_FAULT	0x08
-#define ADT7462_FAN5_FAULT	0x10
-#define ADT7462_FAN6_FAULT	0x20
-#define ADT7462_FAN7_FAULT	0x40
-#define ADT7462_FAN8_FAULT	0x80
+#define ADT7462_FAN_FAULT(val, x)	(val & (1 << x))
 
 /* 0xbe, 0xc6: Host/BMC digital status register */
 #define ADT7462_FAN2MAX_ASSERT	0x08
@@ -701,14 +704,7 @@
 #define ADT7462_VID_COMP_FLT	0x40
 #define ADT7462_CHASSIS_ASSERT	0x80
 
-/* 0xbe, 0xc6: Host/BMC GPIO status register */
-#define ADT7462_GPIO1_ASSERT	0x01
-#define ADT7462_GPIO2_ASSERT	0x02
-#define ADT7462_GPIO3_ASSERT	0x04
-#define ADT7462_GPIO4_ASSERT	0x08
-#define ADT7462_GPIO5_ASSERT	0x10
-#define ADT7462_GPIO6_ASSERT	0x20
-#define ADT7462_GPIO7_ASSERT	0x40
-#define ADT7462_GPIO8_ASSERT	0x80
+/* 0xbf: Host/BMC GPIO status register */
+#define ADT7462_GPIO_ASSERT(val, x)	(val & (1 << x))
 
 #endif /* _DEV_I2C_ADT7462REG_H_ */
