Skip to content

Commit 255ab27

Browse files
Marek Vasutgroeck
authored andcommitted
hwmon: (pwm-fan) Introduce start from stopped state handling
Delta AFC0612DB-F00 fan has to be set to at least 30% PWM duty cycle to spin up from a stopped state, and can be afterward throttled down to lower PWM duty cycle. Introduce support for operating such fans which need to start at higher PWM duty cycle first and can slow down next. Introduce two new DT properties, "fan-stop-to-start-percent" and "fan-stop-to-start-us". The former describes the minimum percent of fan RPM at which it will surely spin up from stopped state. This value can be found in the fan datasheet and can be converted to PWM duty cycle easily. The "fan-stop-to-start-us" describes the minimum time in microseconds for which the fan has to be set to stopped state start RPM for the fan to surely spin up. Adjust the PWM setting code such that if the PWM duty cycle is below the minimum duty cycle needed by the fan to spin up from stopped state, then first set the PWM duty cycle to the minimum duty cycle needed by the fan to spin up from stopped state, then wait the time necessary for the fan to spin up from stopped state, and finally set the PWM duty cycle to the one desired by user. Signed-off-by: Marek Vasut <[email protected]> Message-ID: <[email protected]> Signed-off-by: Guenter Roeck <[email protected]>
1 parent 80bc642 commit 255ab27

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

drivers/hwmon/pwm-fan.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Author: Kamil Debski <[email protected]>
88
*/
99

10+
#include <linux/delay.h>
1011
#include <linux/hwmon.h>
1112
#include <linux/interrupt.h>
1213
#include <linux/mod_devicetable.h>
@@ -60,6 +61,9 @@ struct pwm_fan_ctx {
6061

6162
struct hwmon_chip_info info;
6263
struct hwmon_channel_info fan_channel;
64+
65+
u64 pwm_duty_cycle_from_stopped;
66+
u32 pwm_usec_from_stopped;
6367
};
6468

6569
/* This handler assumes self resetting edge triggered interrupt. */
@@ -199,7 +203,9 @@ static int pwm_fan_power_off(struct pwm_fan_ctx *ctx, bool force_disable)
199203
static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
200204
{
201205
struct pwm_state *state = &ctx->pwm_state;
206+
unsigned long final_pwm = pwm;
202207
unsigned long period;
208+
bool update = false;
203209
int ret = 0;
204210

205211
if (pwm > 0) {
@@ -208,11 +214,22 @@ static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
208214
return 0;
209215

210216
period = state->period;
211-
state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
217+
update = state->duty_cycle < ctx->pwm_duty_cycle_from_stopped;
218+
if (update)
219+
state->duty_cycle = ctx->pwm_duty_cycle_from_stopped;
220+
else
221+
state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
212222
ret = pwm_apply_might_sleep(ctx->pwm, state);
213223
if (ret)
214224
return ret;
215225
ret = pwm_fan_power_on(ctx);
226+
if (!ret && update) {
227+
pwm = final_pwm;
228+
state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
229+
usleep_range(ctx->pwm_usec_from_stopped,
230+
ctx->pwm_usec_from_stopped * 2);
231+
ret = pwm_apply_might_sleep(ctx->pwm, state);
232+
}
216233
} else {
217234
ret = pwm_fan_power_off(ctx, false);
218235
}
@@ -480,6 +497,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
480497
struct device *hwmon;
481498
int ret;
482499
const struct hwmon_channel_info **channels;
500+
u32 pwm_min_from_stopped = 0;
483501
u32 *fan_channel_config;
484502
int channel_count = 1; /* We always have a PWM channel. */
485503
int i;
@@ -620,6 +638,19 @@ static int pwm_fan_probe(struct platform_device *pdev)
620638
channels[1] = &ctx->fan_channel;
621639
}
622640

641+
ret = of_property_read_u32(dev->of_node, "fan-stop-to-start-percent",
642+
&pwm_min_from_stopped);
643+
if (!ret && pwm_min_from_stopped) {
644+
ctx->pwm_duty_cycle_from_stopped =
645+
DIV_ROUND_UP_ULL(pwm_min_from_stopped *
646+
(ctx->pwm_state.period - 1),
647+
100);
648+
}
649+
ret = of_property_read_u32(dev->of_node, "fan-stop-to-start-us",
650+
&ctx->pwm_usec_from_stopped);
651+
if (ret)
652+
ctx->pwm_usec_from_stopped = 250000;
653+
623654
ctx->info.ops = &pwm_fan_hwmon_ops;
624655
ctx->info.info = channels;
625656

0 commit comments

Comments
 (0)