Add regulator support for boards where the fan-supply have to be
powered up before it can be used.
Signed-off-by: Patrick Rudolph <[email protected]>
Signed-off-by: Marcello Sylvester Bauer <[email protected]>
---
drivers/hwmon/max6639.c | 75 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 67 insertions(+), 8 deletions(-)
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index ccc0f047bd44..d733c35b5bcf 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -87,6 +87,9 @@ struct max6639_data {
/* Register values initialized only once */
u8 ppr; /* Pulses per rotation 0..3 for 1..4 ppr */
u8 rpm_range; /* Index in above rpm_ranges table */
+
+ /* Optional regulator for FAN supply */
+ struct regulator *reg;
};
static struct max6639_data *max6639_update_device(struct device *dev)
@@ -296,6 +299,17 @@ static ssize_t pwm_store(struct device *dev,
return res;
val = clamp_val(val, 0, 255);
+ if (data->reg) {
+ res = 0;
+ if (val == 0)
+ res = regulator_disable(data->reg);
+ else
+ res = regulator_enable(data->reg);
+ if (res) {
+ dev_err(dev, "Failed to operate fan supply: %d\n", res);
+ return res;
+ }
+ }
mutex_lock(&data->update_lock);
data->pwm[attr->index] = (u8)(val * 120 / 255);
@@ -516,6 +530,11 @@ static int max6639_detect(struct i2c_client *client,
return 0;
}
+static void max6639_regulator_disable(void *data)
+{
+ regulator_disable(data);
+}
+
static int max6639_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -528,6 +547,30 @@ static int max6639_probe(struct i2c_client *client)
return -ENOMEM;
data->client = client;
+
+ data->reg = devm_regulator_get_optional(dev, "fan");
+ if (IS_ERR(data->reg)) {
+ if (PTR_ERR(data->reg) != -ENODEV) {
+ err = (int)PTR_ERR(data->reg);
+ dev_warn(dev, "Failed looking up fan supply: %d\n", err);
+ return err;
+ }
+ data->reg = NULL;
+ } else {
+ /* Spin up fans */
+ err = regulator_enable(data->reg);
+ if (err) {
+ dev_err(dev, "Failed to enable fan supply: %d\n", err);
+ return err;
+ }
+ err = devm_add_action_or_reset(dev, max6639_regulator_disable,
+ data->reg);
+ if (err) {
+ dev_err(dev, "Failed to register action: %d\n", err);
+ return err;
+ }
+ }
+
mutex_init(&data->update_lock);
/* Initialize the max6639 chip */
@@ -545,23 +588,39 @@ static int max6639_probe(struct i2c_client *client)
static int max6639_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
- if (data < 0)
- return data;
+ struct max6639_data *data = dev_get_drvdata(dev);
+ int ret = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
+
+ if (ret < 0)
+ return ret;
+
+ if (data->reg)
+ regulator_disable(data->reg);
return i2c_smbus_write_byte_data(client,
- MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY);
+ MAX6639_REG_GCONFIG, ret | MAX6639_GCONFIG_STANDBY);
}
static int max6639_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
- if (data < 0)
- return data;
+ struct max6639_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ if (data->reg) {
+ ret = regulator_enable(data->reg);
+ if (ret) {
+ dev_err(dev, "Failed to enable fan supply: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
+ if (ret < 0)
+ return ret;
return i2c_smbus_write_byte_data(client,
- MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY);
+ MAX6639_REG_GCONFIG, ret & ~MAX6639_GCONFIG_STANDBY);
}
#endif /* CONFIG_PM_SLEEP */
--
2.33.1