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	20 Jul 2026 07:43:17 -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);
 
@@ -538,6 +538,12 @@
 	{ DBC_EOF,  {0, 0, 0 }, 0, 0, 0 }
 };
 
+struct dbcool_fan_div ADM1030_fan_div_table[] = {
+	{ 0x08, 0x20 },
+	{ 0x09, 0x21 },
+	{ 0, 0 }
+};
+
 struct dbcool_power_control ADM1030_power_table[] = {
 	{ { DBCOOL_ADM1030_CFG1,  DBCOOL_NO_REG, DBCOOL_NO_REG,
 	    DBCOOL_ADM1030_FAN_SPEED_CFG },
@@ -664,60 +670,62 @@
 
 struct chip_id chip_table[] = {
 	{ DBCOOL_COMPANYID, ADT7490_DEVICEID, ADT7490_REV_ID,
-		ADT7490_sensor_table, ADT7475_power_table,
+		ADT7490_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_PECI,
 		90000 * 60, "ADT7490" },
 	{ DBCOOL_COMPANYID, ADT7476_DEVICEID, 0xff,
-		ADT7476_sensor_table, ADT7475_power_table,
+		ADT7476_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY,
 		90000 * 60, "ADT7476" },
 	{ DBCOOL_COMPANYID, ADT7475_DEVICEID, 0xff,
-		ADT7475_sensor_table, ADT7475_power_table,
+		ADT7475_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
 		90000 * 60, "ADT7475" },
 	{ DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID1,
-		ADT7475_sensor_table, ADT7475_power_table,
+		ADT7475_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
 		90000 * 60, "ADT7460/ADT7463" },
 	{ DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID2,
-		ADT7475_sensor_table, ADT7475_power_table,
+		ADT7475_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
 		90000 * 60, "ADT7463-1" },
 	{ DBCOOL_COMPANYID, ADT7468_DEVICEID, 0xff,
-		ADT7476_sensor_table, ADT7475_power_table,
+		ADT7476_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_TEMPOFFSET  | DBCFLAG_MULTI_VCC | DBCFLAG_HAS_MAXDUTY |
 		    DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN,
 		90000 * 60, "ADT7467/ADT7468" },
 	{ DBCOOL_COMPANYID, ADT7466_DEVICEID, 0xff,
-		ADT7466_sensor_table, NULL,
+		ADT7466_sensor_table, NULL, NULL,
 		DBCFLAG_ADT7466 | DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_SHDN,
 		82000 * 60, "ADT7466" },
 	{ DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID1,
-		ADM1027_sensor_table, ADT7475_power_table,
+		ADM1027_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN,
 		90000 * 60, "ADT7463" },
 	{ DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID2,
-		ADM1027_sensor_table, ADT7475_power_table,
+		ADM1027_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN |
 		    DBCFLAG_HAS_VID_SEL,
 		90000 * 60, "ADT7463" },
 	{ DBCOOL_COMPANYID, ADM1027_DEVICEID, ADM1027_REV_ID,
-		ADM1027_sensor_table, ADT7475_power_table,
+		ADM1027_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER,
 		90000 * 60, "ADM1027" },
 	{ DBCOOL_COMPANYID, ADM1030_DEVICEID, 0xff,
 		ADM1030_sensor_table, ADM1030_power_table,
-		DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE,
+		ADM1030_fan_div_table,
+		DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE | DBCFLAG_HAS_FANDIV,
 		11250 * 60, "ADM1030" },
 	{ DBCOOL_COMPANYID, ADM1031_DEVICEID, 0xff,
 		ADM1031_sensor_table, ADM1030_power_table,
-		DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE,
+		ADM1030_fan_div_table,
+		DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE | DBCFLAG_HAS_FANDIV,
 		11250 * 60, "ADM1031" },
 	{ SMSC_COMPANYID, EMC6D103S_DEVICEID, EMC6D103S_REV_ID,
-		EMC6D103S_sensor_table, ADT7475_power_table,
+		EMC6D103S_sensor_table, ADT7475_power_table, NULL,
 		DBCFLAG_4BIT_VER,
 		90000 * 60, "EMC6D103S" },
-	{ 0, 0, 0, NULL, NULL, 0, 0, NULL }
+	{ 0, 0, 0, NULL, NULL, NULL, 0, 0, NULL }
 };
 
 static const char *behavior[] = {
@@ -1004,7 +1012,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 +1028,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 */
@@ -1604,10 +1613,11 @@
 static int
 dbcool_setup_sensors(struct dbcool_softc *sc)
 {
-	int i;
+	int i, j;
 	int error = 0;
-	uint8_t	vid_reg, vid_val;
+	uint8_t	vid_reg, vid_val, fanchar_reg, fanchar_val;
 	struct chip_id *chip = sc->sc_dc.dc_chip;
+	struct dbcool_fan_div *fan_div_table = chip->fan_div;
 
 	for (i=0; chip->table[i].type != DBC_EOF; i++) {
 		if (i < DBCOOL_MAXSENSORS)
@@ -1642,6 +1652,38 @@
 			error = dbcool_attach_sensor(sc, i);
 			break;
 		case DBC_FAN:
+			fanchar_reg = 0;
+			if (chip->flags & DBCFLAG_HAS_FANDIV &&
+			    fan_div_table != NULL) {
+				for (j=0; fan_div_table[j].fan_reg != 0; j++)
+					if (chip->table[i].reg.val_reg ==
+					    fan_div_table[j].fan_reg)
+						fanchar_reg =
+						    fan_div_table[j].char_reg;
+			}
+			if (fanchar_reg) {
+				fanchar_val = sc->sc_dc.dc_readreg(&sc->sc_dc,
+				    fanchar_reg);
+				/* We only handle ADM1030 fan div here. */
+				fanchar_val &= DBCOOL_ADM1030_FANDIV_MASK;
+				switch (fanchar_val)
+				{
+					case DBCOOL_ADM1030_FANDIV_8:
+						sc->sc_fan_div[i] = 8;
+						break;
+					case DBCOOL_ADM1030_FANDIV_4:
+						sc->sc_fan_div[i] = 4;
+						break;
+					case DBCOOL_ADM1030_FANDIV_2:
+						sc->sc_fan_div[i] = 2;
+						break;
+					case DBCOOL_ADM1030_FANDIV_1:
+					default:
+						sc->sc_fan_div[i] = 1;
+						break;
+				}
+			} else
+				sc->sc_fan_div[i] = 1;
 			sc->sc_sensor[i].units = ENVSYS_SFANRPM;
 			sc->sc_sensor[i].state = ENVSYS_SINVALID;
 			sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
@@ -1811,7 +1853,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 +1871,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 +2058,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_reg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/dbcool_reg.h,v
retrieving revision 1.9
diff -u -r1.9 dbcool_reg.h
--- src/sys/dev/i2c/dbcool_reg.h	16 Apr 2020 23:29:53 -0000	1.9
+++ src/sys/dev/i2c/dbcool_reg.h	20 Jul 2026 07:43:17 -0000
@@ -362,6 +362,13 @@
 #define	DBCOOL_ADM1030_COMPANYID	DBCOOL_COMPANYID_REG
 #define	DBCOOL_ADM1030_REVISION		DBCOOL_REVISION_REG
 
+/* ADM1030 fan characteristics registers: fan speed range (divider) */
+#define DBCOOL_ADM1030_FANDIV_MASK	0xc0
+#define DBCOOL_ADM1030_FANDIV_1		0x00
+#define DBCOOL_ADM1030_FANDIV_2		0x40
+#define DBCOOL_ADM1030_FANDIV_4		0x80
+#define DBCOOL_ADM1030_FANDIV_8		0xc0
+
 /*      
  * Macros to locate limit registers for the various sensor types
  */     
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	20 Jul 2026 07:43:18 -0000
@@ -74,6 +74,7 @@
 #define	DBCFLAG_OBSOLETE	0x0020	/* was DBCFLAG_HAS_VID */
 #define	DBCFLAG_HAS_VID_SEL	0x0040
 #define	DBCFLAG_HAS_PECI	0x0080
+#define	DBCFLAG_HAS_FANDIV	0x0100
 #define	DBCFLAG_NO_READBYTE	0x1000
 #define	DBCFLAG_ADM1030		0x2000
 #define	DBCFLAG_ADT7466		0x4000
@@ -95,6 +96,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 +131,7 @@
 	int sc_sysctl_num[DBCOOL_MAXSENSORS];
 	struct reg_list *sc_regs[DBCOOL_MAXSENSORS];
 	int sc_nom_volt[DBCOOL_MAXSENSORS];
+	int sc_fan_div[DBCOOL_MAXSENSORS];
 	int sc_temp_offset;
 	int64_t sc_supply_voltage;
 	bool sc_suspend;
@@ -140,6 +147,7 @@
 	uint8_t rev;
 	struct dbcool_sensor *table;
 	struct dbcool_power_control *power;
+	struct dbcool_fan_div *fan_div;
 	int flags;
 	int rpm_dividend;
 	const char *name;
