Skip to content

Commit 0d01110

Browse files
tq-steinagroeck
authored andcommitted
hwmon: (gpio-fan) Add regulator support
FANs might be supplied by a regulator which needs to be enabled as well. This is implemented using runtime PM. Every time speed_index changes from 0 to non-zero and vise versa RPM is resumed or suspended. Intitial RPM state is determined by initial value of speed_index. Signed-off-by: Alexander Stein <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 9b116ba commit 0d01110

File tree

1 file changed

+87
-16
lines changed

1 file changed

+87
-16
lines changed

drivers/hwmon/gpio-fan.c

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include <linux/gpio/consumer.h>
2121
#include <linux/of.h>
2222
#include <linux/of_platform.h>
23+
#include <linux/pm.h>
24+
#include <linux/pm_runtime.h>
25+
#include <linux/regulator/consumer.h>
2326
#include <linux/thermal.h>
2427

2528
struct gpio_fan_speed {
@@ -42,6 +45,7 @@ struct gpio_fan_data {
4245
bool pwm_enable;
4346
struct gpio_desc *alarm_gpio;
4447
struct work_struct alarm_work;
48+
struct regulator *supply;
4549
};
4650

4751
/*
@@ -125,13 +129,32 @@ static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
125129
}
126130

127131
/* Must be called with fan_data->lock held, except during initialization. */
128-
static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
132+
static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
129133
{
130134
if (fan_data->speed_index == speed_index)
131-
return;
135+
return 0;
136+
137+
if (fan_data->speed_index == 0 && speed_index > 0) {
138+
int ret;
139+
140+
ret = pm_runtime_resume_and_get(fan_data->dev);
141+
if (ret < 0)
142+
return ret;
143+
}
132144

133145
__set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
146+
147+
if (fan_data->speed_index > 0 && speed_index == 0) {
148+
int ret;
149+
150+
ret = pm_runtime_put_sync(fan_data->dev);
151+
if (ret < 0)
152+
return ret;
153+
}
154+
134155
fan_data->speed_index = speed_index;
156+
157+
return 0;
135158
}
136159

137160
static int get_fan_speed_index(struct gpio_fan_data *fan_data)
@@ -176,7 +199,7 @@ static ssize_t pwm1_store(struct device *dev, struct device_attribute *attr,
176199
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
177200
unsigned long pwm;
178201
int speed_index;
179-
int ret = count;
202+
int ret;
180203

181204
if (kstrtoul(buf, 10, &pwm) || pwm > 255)
182205
return -EINVAL;
@@ -189,12 +212,12 @@ static ssize_t pwm1_store(struct device *dev, struct device_attribute *attr,
189212
}
190213

191214
speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);
192-
set_fan_speed(fan_data, speed_index);
215+
ret = set_fan_speed(fan_data, speed_index);
193216

194217
exit_unlock:
195218
mutex_unlock(&fan_data->lock);
196219

197-
return ret;
220+
return ret ? ret : count;
198221
}
199222

200223
static ssize_t pwm1_enable_show(struct device *dev,
@@ -211,6 +234,7 @@ static ssize_t pwm1_enable_store(struct device *dev,
211234
{
212235
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
213236
unsigned long val;
237+
int ret = 0;
214238

215239
if (kstrtoul(buf, 10, &val) || val > 1)
216240
return -EINVAL;
@@ -224,11 +248,11 @@ static ssize_t pwm1_enable_store(struct device *dev,
224248

225249
/* Disable manual control mode: set fan at full speed. */
226250
if (val == 0)
227-
set_fan_speed(fan_data, fan_data->num_speed - 1);
251+
ret = set_fan_speed(fan_data, fan_data->num_speed - 1);
228252

229253
mutex_unlock(&fan_data->lock);
230254

231-
return count;
255+
return ret ? ret : count;
232256
}
233257

234258
static ssize_t pwm1_mode_show(struct device *dev,
@@ -279,7 +303,7 @@ static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
279303
goto exit_unlock;
280304
}
281305

282-
set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
306+
ret = set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
283307

284308
exit_unlock:
285309
mutex_unlock(&fan_data->lock);
@@ -386,6 +410,7 @@ static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
386410
unsigned long state)
387411
{
388412
struct gpio_fan_data *fan_data = cdev->devdata;
413+
int ret;
389414

390415
if (!fan_data)
391416
return -EINVAL;
@@ -395,11 +420,11 @@ static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
395420

396421
mutex_lock(&fan_data->lock);
397422

398-
set_fan_speed(fan_data, state);
423+
ret = set_fan_speed(fan_data, state);
399424

400425
mutex_unlock(&fan_data->lock);
401426

402-
return 0;
427+
return ret;
403428
}
404429

405430
static const struct thermal_cooling_device_ops gpio_fan_cool_ops = {
@@ -499,6 +524,8 @@ static void gpio_fan_stop(void *data)
499524
mutex_lock(&fan_data->lock);
500525
set_fan_speed(data, 0);
501526
mutex_unlock(&fan_data->lock);
527+
528+
pm_runtime_disable(fan_data->dev);
502529
}
503530

504531
static int gpio_fan_probe(struct platform_device *pdev)
@@ -521,6 +548,11 @@ static int gpio_fan_probe(struct platform_device *pdev)
521548
platform_set_drvdata(pdev, fan_data);
522549
mutex_init(&fan_data->lock);
523550

551+
fan_data->supply = devm_regulator_get(dev, "fan");
552+
if (IS_ERR(fan_data->supply))
553+
return dev_err_probe(dev, PTR_ERR(fan_data->supply),
554+
"Failed to get fan-supply");
555+
524556
/* Configure control GPIOs if available. */
525557
if (fan_data->gpios && fan_data->num_gpios > 0) {
526558
if (!fan_data->speed || fan_data->num_speed <= 1)
@@ -548,6 +580,17 @@ static int gpio_fan_probe(struct platform_device *pdev)
548580
return err;
549581
}
550582

583+
pm_runtime_set_suspended(&pdev->dev);
584+
pm_runtime_enable(&pdev->dev);
585+
/* If current GPIO state is active, mark RPM as active as well */
586+
if (fan_data->speed_index > 0) {
587+
int ret;
588+
589+
ret = pm_runtime_resume_and_get(&pdev->dev);
590+
if (ret)
591+
return ret;
592+
}
593+
551594
/* Optional cooling device register for Device tree platforms */
552595
fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np,
553596
"gpio-fan", fan_data, &gpio_fan_cool_ops);
@@ -565,41 +608,69 @@ static void gpio_fan_shutdown(struct platform_device *pdev)
565608
set_fan_speed(fan_data, 0);
566609
}
567610

611+
static int gpio_fan_runtime_suspend(struct device *dev)
612+
{
613+
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
614+
int ret = 0;
615+
616+
if (fan_data->supply)
617+
ret = regulator_disable(fan_data->supply);
618+
619+
return ret;
620+
}
621+
622+
static int gpio_fan_runtime_resume(struct device *dev)
623+
{
624+
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
625+
int ret = 0;
626+
627+
if (fan_data->supply)
628+
ret = regulator_enable(fan_data->supply);
629+
630+
return ret;
631+
}
632+
568633
static int gpio_fan_suspend(struct device *dev)
569634
{
570635
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
636+
int ret = 0;
571637

572638
if (fan_data->gpios) {
573639
fan_data->resume_speed = fan_data->speed_index;
574640
mutex_lock(&fan_data->lock);
575-
set_fan_speed(fan_data, 0);
641+
ret = set_fan_speed(fan_data, 0);
576642
mutex_unlock(&fan_data->lock);
577643
}
578644

579-
return 0;
645+
return ret;
580646
}
581647

582648
static int gpio_fan_resume(struct device *dev)
583649
{
584650
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
651+
int ret = 0;
585652

586653
if (fan_data->gpios) {
587654
mutex_lock(&fan_data->lock);
588-
set_fan_speed(fan_data, fan_data->resume_speed);
655+
ret = set_fan_speed(fan_data, fan_data->resume_speed);
589656
mutex_unlock(&fan_data->lock);
590657
}
591658

592-
return 0;
659+
return ret;
593660
}
594661

595-
static DEFINE_SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
662+
static const struct dev_pm_ops gpio_fan_pm = {
663+
RUNTIME_PM_OPS(gpio_fan_runtime_suspend,
664+
gpio_fan_runtime_resume, NULL)
665+
SYSTEM_SLEEP_PM_OPS(gpio_fan_suspend, gpio_fan_resume)
666+
};
596667

597668
static struct platform_driver gpio_fan_driver = {
598669
.probe = gpio_fan_probe,
599670
.shutdown = gpio_fan_shutdown,
600671
.driver = {
601672
.name = "gpio-fan",
602-
.pm = pm_sleep_ptr(&gpio_fan_pm),
673+
.pm = pm_ptr(&gpio_fan_pm),
603674
.of_match_table = of_gpio_fan_match,
604675
},
605676
};

0 commit comments

Comments
 (0)