Right now, the divisor (which determines the speed range) can be only set by setting fanX_min or fanX_target. This is fine for RPM mode, but in other cases, it might not be enough. This patch makes it possible to set the divisor independently. Signed-off-by: Václav Kubernát <kubernat@xxxxxxxxx> --- Documentation/hwmon/max31790.rst | 4 ++ drivers/hwmon/max31790.c | 68 ++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index 9225c2a78b68..818e4fe8c797 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -50,6 +50,10 @@ fan[1-12]_min RW minimum fan speed in RPM. Equivalent to target fan speed and the chip will report a fault condition if the fan speed is below the target fan speed. fan[1-6]_target RW desired fan speed in RPM +fan[1-12]_div RW fan speed range + The value is RO for companion channels (7-12). For those + channels, the value matches the value of the primary channel. + Setting fanX_target or fanX_min also sets this value. pwm[1-6]_enable RW regulator mode, 0=disabled (duty cycle=0%), 1=manual mode, 2=rpm mode pwm[1-6] RW read: current pwm duty cycle, write: target pwm duty cycle (0-255) diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 39a4ece4276a..f6c38094c19c 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -160,6 +160,26 @@ static u8 bits_for_tach_period(int rpm) return bits; } +static int bits_for_speed_range(long speed_range) +{ + switch (speed_range) { + case 1: + return 0x0; + case 2: + return 0x1; + case 4: + return 0x2; + case 8: + return 0x3; + case 16: + return 0x4; + case 32: + return 0x5; + default: + return -1; + } +} + static int max31790_read_fan(struct device *dev, u32 attr, int channel, long *val) { @@ -173,6 +193,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, case hwmon_fan_enable: *val = !!(data->fan_config[channel % NR_CHANNEL] & MAX31790_FAN_CFG_TACH_INPUT_EN); return 0; + case hwmon_fan_div: + *val = get_tach_period(data->fan_dynamics[channel % NR_CHANNEL]); + return 0; case hwmon_fan_input: sr = get_tach_period(data->fan_dynamics[channel % NR_CHANNEL]); if (data->tach[channel] == FAN_COUNT_REG_MAX) @@ -293,6 +316,20 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, MAX31790_REG_TARGET_COUNT(channel), data->target_count[channel]); break; + case hwmon_fan_div: + sr = bits_for_speed_range(val); + if (sr < 0) { + err = -EINVAL; + break; + } + + data->fan_dynamics[channel] = ((data->fan_dynamics[channel] & + ~MAX31790_FAN_DYN_SR_MASK) | + (sr << MAX31790_FAN_DYN_SR_SHIFT)); + err = i2c_smbus_write_byte_data(client, + MAX31790_REG_FAN_DYNAMICS(channel), + data->fan_dynamics[channel]); + break; default: err = -EOPNOTSUPP; break; @@ -311,6 +348,7 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel) switch (attr) { case hwmon_fan_min: case hwmon_fan_enable: + case hwmon_fan_div: if (channel < NR_CHANNEL) return 0644; if (fan_config & MAX31790_FAN_CFG_TACH_INPUT) @@ -481,23 +519,29 @@ static umode_t max31790_is_visible(const void *data, static const struct hwmon_channel_info *max31790_info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_TARGET | - HWMON_F_FAULT, + HWMON_F_FAULT | HWMON_F_DIV, HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_TARGET | - HWMON_F_FAULT, + HWMON_F_FAULT | HWMON_F_DIV, HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_TARGET | - HWMON_F_FAULT, + HWMON_F_FAULT | HWMON_F_DIV, HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_TARGET | - HWMON_F_FAULT, + HWMON_F_FAULT | HWMON_F_DIV, HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_TARGET | - HWMON_F_FAULT, + HWMON_F_FAULT | HWMON_F_DIV, HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_TARGET | - HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT), + HWMON_F_FAULT | HWMON_F_DIV, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT | + HWMON_F_DIV, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT | + HWMON_F_DIV, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT | + HWMON_F_DIV, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT | + HWMON_F_DIV, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT | + HWMON_F_DIV, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT | + HWMON_F_DIV), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, -- 2.31.1