summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/pmbus/pmbus.c8
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c58
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;