diff options
Diffstat (limited to 'drivers/hwmon/pwm-fan.c')
-rw-r--r-- | drivers/hwmon/pwm-fan.c | 68 |
1 files changed, 26 insertions, 42 deletions
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index f9af3935b427..70cc0d134f3c 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c | |||
@@ -40,31 +40,22 @@ struct pwm_fan_ctx { | |||
40 | 40 | ||
41 | static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm) | 41 | static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm) |
42 | { | 42 | { |
43 | struct pwm_args pargs; | 43 | unsigned long period; |
44 | unsigned long duty; | ||
45 | int ret = 0; | 44 | int ret = 0; |
46 | 45 | struct pwm_state state = { }; | |
47 | pwm_get_args(ctx->pwm, &pargs); | ||
48 | 46 | ||
49 | mutex_lock(&ctx->lock); | 47 | mutex_lock(&ctx->lock); |
50 | if (ctx->pwm_value == pwm) | 48 | if (ctx->pwm_value == pwm) |
51 | goto exit_set_pwm_err; | 49 | goto exit_set_pwm_err; |
52 | 50 | ||
53 | duty = DIV_ROUND_UP(pwm * (pargs.period - 1), MAX_PWM); | 51 | pwm_init_state(ctx->pwm, &state); |
54 | ret = pwm_config(ctx->pwm, duty, pargs.period); | 52 | period = ctx->pwm->args.period; |
55 | if (ret) | 53 | state.duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM); |
56 | goto exit_set_pwm_err; | 54 | state.enabled = pwm ? true : false; |
57 | |||
58 | if (pwm == 0) | ||
59 | pwm_disable(ctx->pwm); | ||
60 | |||
61 | if (ctx->pwm_value == 0) { | ||
62 | ret = pwm_enable(ctx->pwm); | ||
63 | if (ret) | ||
64 | goto exit_set_pwm_err; | ||
65 | } | ||
66 | 55 | ||
67 | ctx->pwm_value = pwm; | 56 | ret = pwm_apply_state(ctx->pwm, &state); |
57 | if (!ret) | ||
58 | ctx->pwm_value = pwm; | ||
68 | exit_set_pwm_err: | 59 | exit_set_pwm_err: |
69 | mutex_unlock(&ctx->lock); | 60 | mutex_unlock(&ctx->lock); |
70 | return ret; | 61 | return ret; |
@@ -218,10 +209,9 @@ static int pwm_fan_probe(struct platform_device *pdev) | |||
218 | { | 209 | { |
219 | struct thermal_cooling_device *cdev; | 210 | struct thermal_cooling_device *cdev; |
220 | struct pwm_fan_ctx *ctx; | 211 | struct pwm_fan_ctx *ctx; |
221 | struct pwm_args pargs; | ||
222 | struct device *hwmon; | 212 | struct device *hwmon; |
223 | int duty_cycle; | ||
224 | int ret; | 213 | int ret; |
214 | struct pwm_state state = { }; | ||
225 | 215 | ||
226 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); | 216 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); |
227 | if (!ctx) | 217 | if (!ctx) |
@@ -237,28 +227,16 @@ static int pwm_fan_probe(struct platform_device *pdev) | |||
237 | 227 | ||
238 | platform_set_drvdata(pdev, ctx); | 228 | platform_set_drvdata(pdev, ctx); |
239 | 229 | ||
240 | /* | ||
241 | * FIXME: pwm_apply_args() should be removed when switching to the | ||
242 | * atomic PWM API. | ||
243 | */ | ||
244 | pwm_apply_args(ctx->pwm); | ||
245 | |||
246 | /* Set duty cycle to maximum allowed */ | ||
247 | pwm_get_args(ctx->pwm, &pargs); | ||
248 | |||
249 | duty_cycle = pargs.period - 1; | ||
250 | ctx->pwm_value = MAX_PWM; | 230 | ctx->pwm_value = MAX_PWM; |
251 | 231 | ||
252 | ret = pwm_config(ctx->pwm, duty_cycle, pargs.period); | 232 | /* Set duty cycle to maximum allowed and enable PWM output */ |
253 | if (ret) { | 233 | pwm_init_state(ctx->pwm, &state); |
254 | dev_err(&pdev->dev, "Failed to configure PWM\n"); | 234 | state.duty_cycle = ctx->pwm->args.period - 1; |
255 | return ret; | 235 | state.enabled = true; |
256 | } | ||
257 | 236 | ||
258 | /* Enbale PWM output */ | 237 | ret = pwm_apply_state(ctx->pwm, &state); |
259 | ret = pwm_enable(ctx->pwm); | ||
260 | if (ret) { | 238 | if (ret) { |
261 | dev_err(&pdev->dev, "Failed to enable PWM\n"); | 239 | dev_err(&pdev->dev, "Failed to configure PWM\n"); |
262 | return ret; | 240 | return ret; |
263 | } | 241 | } |
264 | 242 | ||
@@ -266,8 +244,8 @@ static int pwm_fan_probe(struct platform_device *pdev) | |||
266 | ctx, pwm_fan_groups); | 244 | ctx, pwm_fan_groups); |
267 | if (IS_ERR(hwmon)) { | 245 | if (IS_ERR(hwmon)) { |
268 | dev_err(&pdev->dev, "Failed to register hwmon device\n"); | 246 | dev_err(&pdev->dev, "Failed to register hwmon device\n"); |
269 | pwm_disable(ctx->pwm); | 247 | ret = PTR_ERR(hwmon); |
270 | return PTR_ERR(hwmon); | 248 | goto err_pwm_disable; |
271 | } | 249 | } |
272 | 250 | ||
273 | ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx); | 251 | ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx); |
@@ -282,14 +260,20 @@ static int pwm_fan_probe(struct platform_device *pdev) | |||
282 | if (IS_ERR(cdev)) { | 260 | if (IS_ERR(cdev)) { |
283 | dev_err(&pdev->dev, | 261 | dev_err(&pdev->dev, |
284 | "Failed to register pwm-fan as cooling device"); | 262 | "Failed to register pwm-fan as cooling device"); |
285 | pwm_disable(ctx->pwm); | 263 | ret = PTR_ERR(cdev); |
286 | return PTR_ERR(cdev); | 264 | goto err_pwm_disable; |
287 | } | 265 | } |
288 | ctx->cdev = cdev; | 266 | ctx->cdev = cdev; |
289 | thermal_cdev_update(cdev); | 267 | thermal_cdev_update(cdev); |
290 | } | 268 | } |
291 | 269 | ||
292 | return 0; | 270 | return 0; |
271 | |||
272 | err_pwm_disable: | ||
273 | state.enabled = false; | ||
274 | pwm_apply_state(ctx->pwm, &state); | ||
275 | |||
276 | return ret; | ||
293 | } | 277 | } |
294 | 278 | ||
295 | static int pwm_fan_remove(struct platform_device *pdev) | 279 | static int pwm_fan_remove(struct platform_device *pdev) |