diff options
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.c | 8 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 58 |
2 files changed, 64 insertions, 2 deletions
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index d0d386990af5..ce2f020f09d7 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -29,6 +29,7 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, struct pmbus_driver_info *info) { int page; + int fan_mode; /* Sensors detected on page 0 only */ if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) @@ -47,13 +48,20 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, info->func[0] |= PMBUS_HAVE_FAN12; if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + fan_mode = pmbus_read_byte_data(client, page, PMBUS_FAN_CONFIG_12); + if ((fan_mode & (PB_FAN_1_RPM | PB_FAN_2_RPM)) != (PB_FAN_1_RPM | PB_FAN_2_RPM)) + info->func[0] |= PMBUS_HAVE_PWM12; } if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { info->func[0] |= PMBUS_HAVE_FAN34; if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + fan_mode = pmbus_read_byte_data(client, page, PMBUS_FAN_CONFIG_34); + if ((fan_mode & (PB_FAN_1_RPM | PB_FAN_2_RPM)) != (PB_FAN_1_RPM | PB_FAN_2_RPM)) + info->func[0] |= PMBUS_HAVE_PWM34; } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) info->func[0] |= PMBUS_HAVE_TEMP; if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index ec44e4847c48..ceb1b4db985e 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -241,12 +241,32 @@ int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg, } EXPORT_SYMBOL_NS_GPL(pmbus_write_word_data, PMBUS); +static int pmbus_update_fan_config(struct i2c_client *client, int page, int id, + u8 config, u8 mask) +{ + int from; + int rv; + u8 to; + + from = pmbus_read_byte_data(client, page, pmbus_fan_config_registers[id]); + if (from < 0) + return from; + + to = (from & ~mask) | (config & mask); + if (to != from) { + rv = pmbus_write_byte_data(client, page, pmbus_fan_config_registers[id], to); + if (rv < 0) + return rv; + } + return 0; +} static int pmbus_write_virt_reg(struct i2c_client *client, int page, int reg, u16 word) { int bit; int id; + int config; int rv; switch (reg) { @@ -255,6 +275,18 @@ static int pmbus_write_virt_reg(struct i2c_client *client, int page, int reg, bit = pmbus_fan_rpm_mask[id]; rv = pmbus_update_fan(client, page, id, bit, bit, word); break; + case PMBUS_VIRT_PWM_1 ... PMBUS_VIRT_PWM_4: + id = reg - PMBUS_VIRT_PWM_1; + bit = pmbus_fan_rpm_mask[id]; + /* 0 is pwm mode */ + rv = pmbus_update_fan(client, page, id, 0, bit, word); + break; + case PMBUS_VIRT_PWM_ENABLE_1 ... PMBUS_VIRT_PWM_ENABLE_4: + id = reg - PMBUS_VIRT_PWM_ENABLE_1; + bit = pmbus_fan_rpm_mask[id]; + config = word ? bit : 0; + rv = pmbus_update_fan_config(client, page, id, config, bit); + break; default: rv = -ENXIO; break; @@ -293,8 +325,7 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id, int rv; u8 to; - from = pmbus_read_byte_data(client, page, - pmbus_fan_config_registers[id]); + from = pmbus_read_byte_data(client, page, pmbus_fan_config_registers[id]); if (from < 0) return from; @@ -323,16 +354,39 @@ int pmbus_read_word_data(struct i2c_client *client, int page, int phase, u8 reg) } EXPORT_SYMBOL_NS_GPL(pmbus_read_word_data, PMBUS); +static int pmbus_get_fan_config(struct i2c_client *client, int page, int id, u8 mask) +{ + int from; + + from = pmbus_read_byte_data(client, page, pmbus_fan_config_registers[id]); + if (from < 0) + return from; + + return from & mask; +} + static int pmbus_read_virt_reg(struct i2c_client *client, int page, int reg) { int rv; int id; + int bit; switch (reg) { case PMBUS_VIRT_FAN_TARGET_1 ... PMBUS_VIRT_FAN_TARGET_4: id = reg - PMBUS_VIRT_FAN_TARGET_1; rv = pmbus_get_fan_rate_device(client, page, id, rpm); break; + case PMBUS_VIRT_PWM_1 ... PMBUS_VIRT_PWM_4: + id = reg - PMBUS_VIRT_PWM_1; + rv = pmbus_get_fan_rate_device(client, page, id, percent); + break; + case PMBUS_VIRT_PWM_ENABLE_1 ... PMBUS_VIRT_PWM_ENABLE_4: + id = reg - PMBUS_VIRT_PWM_ENABLE_1; + bit = pmbus_fan_rpm_mask[id]; + rv = pmbus_get_fan_config(client, page, id, bit); + if (rv >= 0) + rv = !rv; /* PWM is enabled when rpm bit is not set (rv = 0) */ + break; default: rv = -ENXIO; break; |