Lines Matching +full:cooling +full:- +full:levels
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * pwm-fan.c - Hwmon driver for fans connected to PWM lines.
11 #include <linux/hwmon-sysfs.h>
49 atomic_inc(&ctx->pulses); in pulse_handler()
57 unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start); in sample_timer()
61 pulses = atomic_read(&ctx->pulses); in sample_timer()
62 atomic_sub(pulses, &ctx->pulses); in sample_timer()
63 ctx->rpm = (unsigned int)(pulses * 1000 * 60) / in sample_timer()
64 (ctx->pulses_per_revolution * delta); in sample_timer()
66 ctx->sample_start = ktime_get(); in sample_timer()
69 mod_timer(&ctx->rpm_timer, jiffies + HZ); in sample_timer()
78 mutex_lock(&ctx->lock); in __set_pwm()
79 if (ctx->pwm_value == pwm) in __set_pwm()
82 pwm_init_state(ctx->pwm, &state); in __set_pwm()
83 period = ctx->pwm->args.period; in __set_pwm()
84 state.duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM); in __set_pwm()
87 ret = pwm_apply_state(ctx->pwm, &state); in __set_pwm()
89 ctx->pwm_value = pwm; in __set_pwm()
91 mutex_unlock(&ctx->lock); in __set_pwm()
99 for (i = 0; i < ctx->pwm_fan_max_state; ++i) in pwm_fan_update_state()
100 if (pwm < ctx->pwm_fan_cooling_levels[i + 1]) in pwm_fan_update_state()
103 ctx->pwm_fan_state = i; in pwm_fan_update_state()
114 return -EINVAL; in pwm_store()
129 return sprintf(buf, "%u\n", ctx->pwm_value); in pwm_show()
137 return sprintf(buf, "%u\n", ctx->rpm); in rpm_show()
156 if (n == 1 && ctx->irq <= 0) in pwm_fan_attrs_visible()
159 return a->mode; in pwm_fan_attrs_visible()
172 /* thermal cooling device callbacks */
176 struct pwm_fan_ctx *ctx = cdev->devdata; in pwm_fan_get_max_state()
179 return -EINVAL; in pwm_fan_get_max_state()
181 *state = ctx->pwm_fan_max_state; in pwm_fan_get_max_state()
189 struct pwm_fan_ctx *ctx = cdev->devdata; in pwm_fan_get_cur_state()
192 return -EINVAL; in pwm_fan_get_cur_state()
194 *state = ctx->pwm_fan_state; in pwm_fan_get_cur_state()
202 struct pwm_fan_ctx *ctx = cdev->devdata; in pwm_fan_set_cur_state()
205 if (!ctx || (state > ctx->pwm_fan_max_state)) in pwm_fan_set_cur_state()
206 return -EINVAL; in pwm_fan_set_cur_state()
208 if (state == ctx->pwm_fan_state) in pwm_fan_set_cur_state()
211 ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]); in pwm_fan_set_cur_state()
213 dev_err(&cdev->device, "Cannot set pwm!\n"); in pwm_fan_set_cur_state()
217 ctx->pwm_fan_state = state; in pwm_fan_set_cur_state()
231 struct device_node *np = dev->of_node; in pwm_fan_of_get_cooling_data()
234 if (!of_find_property(np, "cooling-levels", NULL)) in pwm_fan_of_get_cooling_data()
237 ret = of_property_count_u32_elems(np, "cooling-levels"); in pwm_fan_of_get_cooling_data()
240 return ret ? : -EINVAL; in pwm_fan_of_get_cooling_data()
244 ctx->pwm_fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32), in pwm_fan_of_get_cooling_data()
246 if (!ctx->pwm_fan_cooling_levels) in pwm_fan_of_get_cooling_data()
247 return -ENOMEM; in pwm_fan_of_get_cooling_data()
249 ret = of_property_read_u32_array(np, "cooling-levels", in pwm_fan_of_get_cooling_data()
250 ctx->pwm_fan_cooling_levels, num); in pwm_fan_of_get_cooling_data()
252 dev_err(dev, "Property 'cooling-levels' cannot be read!\n"); in pwm_fan_of_get_cooling_data()
257 if (ctx->pwm_fan_cooling_levels[i] > MAX_PWM) { in pwm_fan_of_get_cooling_data()
259 ctx->pwm_fan_cooling_levels[i], MAX_PWM); in pwm_fan_of_get_cooling_data()
260 return -EINVAL; in pwm_fan_of_get_cooling_data()
264 ctx->pwm_fan_max_state = num - 1; in pwm_fan_of_get_cooling_data()
277 pwm_disable(ctx->pwm); in pwm_fan_pwm_disable()
278 del_timer_sync(&ctx->rpm_timer); in pwm_fan_pwm_disable()
284 struct device *dev = &pdev->dev; in pwm_fan_probe()
293 return -ENOMEM; in pwm_fan_probe()
295 mutex_init(&ctx->lock); in pwm_fan_probe()
297 ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL); in pwm_fan_probe()
298 if (IS_ERR(ctx->pwm)) in pwm_fan_probe()
299 return dev_err_probe(dev, PTR_ERR(ctx->pwm), "Could not get PWM\n"); in pwm_fan_probe()
303 ctx->irq = platform_get_irq_optional(pdev, 0); in pwm_fan_probe()
304 if (ctx->irq == -EPROBE_DEFER) in pwm_fan_probe()
305 return ctx->irq; in pwm_fan_probe()
307 ctx->reg_en = devm_regulator_get_optional(dev, "fan"); in pwm_fan_probe()
308 if (IS_ERR(ctx->reg_en)) { in pwm_fan_probe()
309 if (PTR_ERR(ctx->reg_en) != -ENODEV) in pwm_fan_probe()
310 return PTR_ERR(ctx->reg_en); in pwm_fan_probe()
312 ctx->reg_en = NULL; in pwm_fan_probe()
314 ret = regulator_enable(ctx->reg_en); in pwm_fan_probe()
320 ctx->reg_en); in pwm_fan_probe()
325 ctx->pwm_value = MAX_PWM; in pwm_fan_probe()
327 pwm_init_state(ctx->pwm, &state); in pwm_fan_probe()
329 * __set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned in pwm_fan_probe()
335 return -EINVAL; in pwm_fan_probe()
339 state.duty_cycle = ctx->pwm->args.period - 1; in pwm_fan_probe()
342 ret = pwm_apply_state(ctx->pwm, &state); in pwm_fan_probe()
347 timer_setup(&ctx->rpm_timer, sample_timer, 0); in pwm_fan_probe()
352 of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr); in pwm_fan_probe()
353 ctx->pulses_per_revolution = ppr; in pwm_fan_probe()
354 if (!ctx->pulses_per_revolution) { in pwm_fan_probe()
355 dev_err(dev, "pulses-per-revolution can't be zero.\n"); in pwm_fan_probe()
356 return -EINVAL; in pwm_fan_probe()
359 if (ctx->irq > 0) { in pwm_fan_probe()
360 ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0, in pwm_fan_probe()
361 pdev->name, ctx); in pwm_fan_probe()
366 ctx->sample_start = ktime_get(); in pwm_fan_probe()
367 mod_timer(&ctx->rpm_timer, jiffies + HZ); in pwm_fan_probe()
381 ctx->pwm_fan_state = ctx->pwm_fan_max_state; in pwm_fan_probe()
384 dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops); in pwm_fan_probe()
388 "Failed to register pwm-fan as cooling device: %d\n", in pwm_fan_probe()
392 ctx->cdev = cdev; in pwm_fan_probe()
405 pwm_get_args(ctx->pwm, &args); in pwm_fan_disable()
407 if (ctx->pwm_value) { in pwm_fan_disable()
408 ret = pwm_config(ctx->pwm, 0, args.period); in pwm_fan_disable()
412 pwm_disable(ctx->pwm); in pwm_fan_disable()
415 if (ctx->reg_en) { in pwm_fan_disable()
416 ret = regulator_disable(ctx->reg_en); in pwm_fan_disable()
428 pwm_fan_disable(&pdev->dev); in pwm_fan_shutdown()
444 if (ctx->reg_en) { in pwm_fan_resume()
445 ret = regulator_enable(ctx->reg_en); in pwm_fan_resume()
452 if (ctx->pwm_value == 0) in pwm_fan_resume()
455 pwm_get_args(ctx->pwm, &pargs); in pwm_fan_resume()
456 duty = DIV_ROUND_UP_ULL(ctx->pwm_value * (pargs.period - 1), MAX_PWM); in pwm_fan_resume()
457 ret = pwm_config(ctx->pwm, duty, pargs.period); in pwm_fan_resume()
460 return pwm_enable(ctx->pwm); in pwm_fan_resume()
467 { .compatible = "pwm-fan", },
476 .name = "pwm-fan",
485 MODULE_ALIAS("platform:pwm-fan");