Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (mlxreg-fan) Add support for new flavour of capability register

FAN platform data is common across the various systems, while fan
driver should be able to apply only the fan instances relevant
to specific system.

For example, platform data might contain descriptions for fan1,
fan2, ..., fan{n}, while some systems equipped with all 'n' fans,
others with less.
Also, on some systems fan drawer can be equipped with several
tachometers and on others only with one.

For detection of the real number of equipped drawers and tachometers
special capability registers are used.
These registers used to indicate presence of drawers and tachometers
through the bitmap.

For some new big modular systems this register will provide presence
data by counter.

Use slot parameter to distinct whether capability register contains
bitmask or counter.

Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Link: https://lore.kernel.org/r/20250113084859.27064-3-vadimp@nvidia.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Vadim Pasternak and committed by
Guenter Roeck
1e11552e c02e4644

+15 -3
+15 -3
drivers/hwmon/mlxreg-fan.c
··· 63 63 * @reg: register offset; 64 64 * @mask: fault mask; 65 65 * @prsnt: present register offset; 66 + * @shift: tacho presence bit shift; 66 67 */ 67 68 struct mlxreg_fan_tacho { 68 69 bool connected; 69 70 u32 reg; 70 71 u32 mask; 71 72 u32 prsnt; 73 + u32 shift; 72 74 }; 73 75 74 76 /* ··· 145 143 /* 146 144 * Map channel to presence bit - drawer can be equipped with 147 145 * one or few FANs, while presence is indicated per drawer. 146 + * Shift channel value if necessary to align with register value. 148 147 */ 149 - if (BIT(channel / fan->tachos_per_drwr) & regval) { 148 + if (BIT(rol32(channel, tacho->shift) / fan->tachos_per_drwr) & 149 + regval) { 150 150 /* FAN is not connected - return zero for FAN speed. */ 151 151 *val = 0; 152 152 return 0; ··· 412 408 return err; 413 409 } 414 410 415 - return !!(regval & data->bit); 411 + return data->slot ? (data->slot <= regval ? 1 : 0) : !!(regval & data->bit); 416 412 } 417 413 418 414 static int mlxreg_pwm_connect_verify(struct mlxreg_fan *fan, ··· 549 545 return err; 550 546 } 551 547 552 - drwr_avail = hweight32(regval); 548 + /* 549 + * The number of drawers could be specified in registers by counters for newer 550 + * systems, or by bitmasks for older systems. In case the data is provided by 551 + * counter, it is indicated through 'version' field. 552 + */ 553 + if (pdata->version) 554 + drwr_avail = regval; 555 + else 556 + drwr_avail = hweight32(regval); 553 557 if (!tacho_avail || !drwr_avail || tacho_avail < drwr_avail) { 554 558 dev_err(fan->dev, "Configuration is invalid: drawers num %d tachos num %d\n", 555 559 drwr_avail, tacho_avail);