diff options
author | Armin Wolf <W_Armin@gmx.de> | 2022-02-24 07:12:10 +0100 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2022-02-27 17:03:19 -0800 |
commit | aa9f833dfc128169a1162261c5641aa516b4a231 (patch) | |
tree | 532f604431483d8501ded64a41bac75a3f7080e3 /drivers/hwmon | |
parent | e75d16e58467c5703821e12536c7dc438f3c425d (diff) |
hwmon: (sch5627) Add pwmX_auto_channels_temp support
After doing some research, it seems that Fujitsu's
hardware monitoring solution exports data describing
which temperature sensors affect which fans, similar
to the data in fan_source of the ftsteutates driver.
Writing 0 into these registers forces the fans to
full speed.
Export this data with standard attributes.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20220224061210.16452-3-W_Armin@gmx.de
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/sch5627.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c index 72c3f6757e34..25fbbd4c9a2b 100644 --- a/drivers/hwmon/sch5627.c +++ b/drivers/hwmon/sch5627.c @@ -52,6 +52,9 @@ static const u16 SCH5627_REG_FAN[SCH5627_NO_FANS] = { static const u16 SCH5627_REG_FAN_MIN[SCH5627_NO_FANS] = { 0x62, 0x64, 0x66, 0x68 }; +static const u16 SCH5627_REG_PWM_MAP[SCH5627_NO_FANS] = { + 0xA0, 0xA1, 0xA2, 0xA3 }; + static const u16 SCH5627_REG_IN_MSB[SCH5627_NO_IN] = { 0x22, 0x23, 0x24, 0x25, 0x189 }; static const u16 SCH5627_REG_IN_LSN[SCH5627_NO_IN] = { @@ -223,6 +226,9 @@ static int reg_to_rpm(u16 reg) static umode_t sch5627_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr, int channel) { + if (type == hwmon_pwm && attr == hwmon_pwm_auto_channels_temp) + return 0644; + return 0444; } @@ -278,6 +284,23 @@ static int sch5627_read(struct device *dev, enum hwmon_sensor_types type, u32 at break; } break; + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_auto_channels_temp: + mutex_lock(&data->update_lock); + ret = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_PWM_MAP[channel]); + mutex_unlock(&data->update_lock); + + if (ret < 0) + return ret; + + *val = ret; + + return 0; + default: + break; + } + break; case hwmon_in: ret = sch5627_update_in(data); if (ret < 0) @@ -318,10 +341,42 @@ static int sch5627_read_string(struct device *dev, enum hwmon_sensor_types type, return -EOPNOTSUPP; } +static int sch5627_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, + long val) +{ + struct sch5627_data *data = dev_get_drvdata(dev); + int ret; + + switch (type) { + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_auto_channels_temp: + /* registers are 8 bit wide */ + if (val > U8_MAX || val < 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + ret = sch56xx_write_virtual_reg(data->addr, SCH5627_REG_PWM_MAP[channel], + val); + mutex_unlock(&data->update_lock); + + return ret; + default: + break; + } + break; + default: + break; + } + + return -EOPNOTSUPP; +} + static const struct hwmon_ops sch5627_ops = { .is_visible = sch5627_is_visible, .read = sch5627_read, .read_string = sch5627_read_string, + .write = sch5627_write, }; static const struct hwmon_channel_info *sch5627_info[] = { @@ -342,6 +397,12 @@ static const struct hwmon_channel_info *sch5627_info[] = { HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_FAULT ), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_AUTO_CHANNELS_TEMP, + HWMON_PWM_AUTO_CHANNELS_TEMP, + HWMON_PWM_AUTO_CHANNELS_TEMP, + HWMON_PWM_AUTO_CHANNELS_TEMP + ), HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL, |