Index: src/sys/dev/i2c/dbcool.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/dbcool.c,v retrieving revision 1.69 diff -u -r1.69 dbcool.c --- src/sys/dev/i2c/dbcool.c 7 Jul 2026 12:42:58 -0000 1.69 +++ src/sys/dev/i2c/dbcool.c 5 Aug 2026 18:42:55 -0000 @@ -73,7 +73,7 @@ /* Sensor read functions */ static void dbcool_refresh(struct sysmon_envsys *, envsys_data_t *); -static int dbcool_read_rpm(struct dbcool_softc *, uint8_t); +static int dbcool_read_rpm(struct dbcool_softc *, uint8_t, int); static int dbcool_read_temp(struct dbcool_softc *, uint8_t, bool); static int dbcool_read_volt(struct dbcool_softc *, uint8_t, int, bool); @@ -107,8 +107,10 @@ static int sysctl_dbcool_thyst(SYSCTLFN_PROTO); /* Set-up subroutines */ +static int dbcool_set_fan_divider(struct dbcool_softc *, prop_dictionary_t, + int); static void dbcool_setup_controllers(struct dbcool_softc *); -static int dbcool_setup_sensors(struct dbcool_softc *); +static int dbcool_setup_sensors(struct dbcool_softc *, prop_dictionary_t); static int dbcool_attach_sensor(struct dbcool_softc *, int); static int dbcool_attach_temp_control(struct dbcool_softc *, int, struct chip_id *); @@ -1004,7 +1006,7 @@ } static int -dbcool_read_rpm(struct dbcool_softc *sc, uint8_t reg) +dbcool_read_rpm(struct dbcool_softc *sc, uint8_t reg, int fan_div) { int rpm; uint8_t rpm_lo, rpm_hi; @@ -1020,7 +1022,8 @@ return 0; /* 0xffff indicates stalled/failed fan */ /* don't divide by zero */ - return (rpm == 0)? 0 : (sc->sc_dc.dc_chip->rpm_dividend / rpm); + return (rpm == 0)? 0 : + (sc->sc_dc.dc_chip->rpm_dividend / rpm / fan_div); } /* Provide chip's supply voltage, in microvolts */ @@ -1536,7 +1539,7 @@ /* Create the sensors for this device */ sc->sc_sme = sysmon_envsys_create(); - if (dbcool_setup_sensors(sc)) + if (dbcool_setup_sensors(sc, device_properties(self))) goto out; if (sc->sc_root_sysctl_num != 0) { @@ -1602,13 +1605,37 @@ } static int -dbcool_setup_sensors(struct dbcool_softc *sc) +dbcool_set_fan_divider(struct dbcool_softc *sc, prop_dictionary_t props, + int sensor) +{ + uint16_t props_fan_div, div_val; + int div; + + div = 1; + + /* + * Do we have a fan divider property? + * Each 4 bits contains a divider for that fan. + * We only accept dividers up to 8x + */ + if (prop_dictionary_get_uint16(props, + "fan_div", &props_fan_div) != 0) { + div_val = (props_fan_div >> (sc->sc_fan_num * 4)) & 0x0f; + if (div_val > 1 && div_val < 9) + div *= div_val; + } + return div; +} + +static int +dbcool_setup_sensors(struct dbcool_softc *sc, prop_dictionary_t props) { int i; int error = 0; uint8_t vid_reg, vid_val; struct chip_id *chip = sc->sc_dc.dc_chip; + sc->sc_fan_num = 0; for (i=0; chip->table[i].type != DBC_EOF; i++) { if (i < DBCOOL_MAXSENSORS) sc->sc_sysctl_num[i] = -1; @@ -1642,11 +1669,15 @@ error = dbcool_attach_sensor(sc, i); break; case DBC_FAN: + sc->sc_fan_div[i] = dbcool_set_fan_divider(sc, + props, i); + sc->sc_sensor[i].units = ENVSYS_SFANRPM; sc->sc_sensor[i].state = ENVSYS_SINVALID; sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS; sc->sc_sensor[i].flags |= ENVSYS_FHAS_ENTROPY; error = dbcool_attach_sensor(sc, i); + sc->sc_fan_num++; break; case DBC_VID: sc->sc_sensor[i].units = ENVSYS_INTEGER; @@ -1811,7 +1842,7 @@ dbcool_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) { struct dbcool_softc *sc=sme->sme_cookie; - int i, nom_volt_idx, cur; + int i, nom_volt_idx, fan_div, cur; struct reg_list *reg; i = edata->sensor; @@ -1829,7 +1860,8 @@ true); break; case ENVSYS_SFANRPM: - cur = dbcool_read_rpm(sc, reg->val_reg); + fan_div = sc->sc_fan_div[i]; + cur = dbcool_read_rpm(sc, reg->val_reg, fan_div); break; case ENVSYS_INTEGER: return; @@ -2015,9 +2047,10 @@ sysmon_envsys_lim_t *lims, uint32_t *props) { struct reg_list *reg = sc->sc_regs[idx]; + int fan_div = sc->sc_fan_div[idx]; int32_t limit; - limit = dbcool_read_rpm(sc, reg->lo_lim_reg); + limit = dbcool_read_rpm(sc, reg->lo_lim_reg, fan_div); if (limit) { lims->sel_critmin = limit; *props |= PROP_CRITMIN; Index: src/sys/dev/i2c/dbcool_var.h =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/dbcool_var.h,v retrieving revision 1.18 diff -u -r1.18 dbcool_var.h --- src/sys/dev/i2c/dbcool_var.h 21 Sep 2025 13:54:56 -0000 1.18 +++ src/sys/dev/i2c/dbcool_var.h 5 Aug 2026 18:42:55 -0000 @@ -95,6 +95,11 @@ int nom_volt_index; }; +struct dbcool_fan_div { + uint8_t fan_reg; + uint8_t char_reg; +}; + /* * The members of dbcool_power_control need to stay in the same order * as the enum dbc_pwm_params above @@ -125,6 +130,8 @@ int sc_sysctl_num[DBCOOL_MAXSENSORS]; struct reg_list *sc_regs[DBCOOL_MAXSENSORS]; int sc_nom_volt[DBCOOL_MAXSENSORS]; + int sc_fan_num; + int sc_fan_div[DBCOOL_MAXSENSORS]; int sc_temp_offset; int64_t sc_supply_voltage; bool sc_suspend; Index: src/sys/dev/i2c/files.i2c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/files.i2c,v retrieving revision 1.138 diff -u -r1.138 files.i2c --- src/sys/dev/i2c/files.i2c 3 Jun 2026 11:12:09 -0000 1.138 +++ src/sys/dev/i2c/files.i2c 5 Aug 2026 18:42:55 -0000 @@ -476,6 +476,6 @@ file dev/i2c/nxp75a.c nxp75a # ADM7462 system monitor -device adt7462sm: sysmon_envsys +device adt7462sm: gpiobus, sysmon_envsys attach adt7462sm at iic file dev/i2c/adt7462.c adt7462sm