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_ */