Lines Matching +full:pulses +full:- +full:per +full:- +full:revolution
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>
37 atomic_t pulses; member
58 atomic_inc(&ctx->pulses); in pulse_handler()
66 unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start); in sample_timer()
67 int pulses; in sample_timer() local
70 pulses = atomic_read(&ctx->pulses); in sample_timer()
71 atomic_sub(pulses, &ctx->pulses); in sample_timer()
72 ctx->rpm = (unsigned int)(pulses * 1000 * 60) / in sample_timer()
73 (ctx->pulses_per_revolution * delta); in sample_timer()
75 ctx->sample_start = ktime_get(); in sample_timer()
78 mod_timer(&ctx->rpm_timer, jiffies + HZ); in sample_timer()
87 mutex_lock(&ctx->lock); in __set_pwm()
88 if (ctx->pwm_value == pwm) in __set_pwm()
91 pwm_init_state(ctx->pwm, &state); in __set_pwm()
92 period = ctx->pwm->args.period; in __set_pwm()
93 state.duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM); in __set_pwm()
96 ret = pwm_apply_state(ctx->pwm, &state); in __set_pwm()
98 ctx->pwm_value = pwm; in __set_pwm()
100 mutex_unlock(&ctx->lock); in __set_pwm()
108 for (i = 0; i < ctx->pwm_fan_max_state; ++i) in pwm_fan_update_state()
109 if (pwm < ctx->pwm_fan_cooling_levels[i + 1]) in pwm_fan_update_state()
112 ctx->pwm_fan_state = i; in pwm_fan_update_state()
123 return -EINVAL; in pwm_store()
138 return sprintf(buf, "%u\n", ctx->pwm_value); in pwm_show()
146 return sprintf(buf, "%u\n", ctx->rpm); in rpm_show()
165 if (n == 1 && ctx->irq <= 0) in pwm_fan_attrs_visible()
168 return a->mode; in pwm_fan_attrs_visible()
185 struct pwm_fan_ctx *ctx = cdev->devdata; in pwm_fan_get_max_state()
188 return -EINVAL; in pwm_fan_get_max_state()
190 *state = ctx->pwm_fan_max_state; in pwm_fan_get_max_state()
198 struct pwm_fan_ctx *ctx = cdev->devdata; in pwm_fan_get_cur_state()
201 return -EINVAL; in pwm_fan_get_cur_state()
203 *state = ctx->pwm_fan_state; in pwm_fan_get_cur_state()
211 struct pwm_fan_ctx *ctx = cdev->devdata; in pwm_fan_set_cur_state()
214 if (!ctx || (state > ctx->pwm_fan_max_state)) in pwm_fan_set_cur_state()
215 return -EINVAL; in pwm_fan_set_cur_state()
217 if (state == ctx->pwm_fan_state) in pwm_fan_set_cur_state()
220 ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]); in pwm_fan_set_cur_state()
222 dev_err(&cdev->device, "Cannot set pwm!\n"); in pwm_fan_set_cur_state()
226 ctx->pwm_fan_state = state; in pwm_fan_set_cur_state()
240 struct device_node *np = dev->of_node; in pwm_fan_of_get_cooling_data()
243 if (!of_find_property(np, "cooling-levels", NULL)) in pwm_fan_of_get_cooling_data()
246 ret = of_property_count_u32_elems(np, "cooling-levels"); in pwm_fan_of_get_cooling_data()
249 return ret ? : -EINVAL; in pwm_fan_of_get_cooling_data()
253 ctx->pwm_fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32), in pwm_fan_of_get_cooling_data()
255 if (!ctx->pwm_fan_cooling_levels) in pwm_fan_of_get_cooling_data()
256 return -ENOMEM; in pwm_fan_of_get_cooling_data()
258 ret = of_property_read_u32_array(np, "cooling-levels", in pwm_fan_of_get_cooling_data()
259 ctx->pwm_fan_cooling_levels, num); in pwm_fan_of_get_cooling_data()
261 dev_err(dev, "Property 'cooling-levels' cannot be read!\n"); in pwm_fan_of_get_cooling_data()
266 if (ctx->pwm_fan_cooling_levels[i] > MAX_PWM) { in pwm_fan_of_get_cooling_data()
268 ctx->pwm_fan_cooling_levels[i], MAX_PWM); in pwm_fan_of_get_cooling_data()
269 return -EINVAL; in pwm_fan_of_get_cooling_data()
273 ctx->pwm_fan_max_state = num - 1; in pwm_fan_of_get_cooling_data()
286 pwm_disable(ctx->pwm); in pwm_fan_pwm_disable()
287 del_timer_sync(&ctx->rpm_timer); in pwm_fan_pwm_disable()
293 struct device_node *np = dev->of_node; in pwm_fan_get_thermal_trips()
300 return -EINVAL; in pwm_fan_get_thermal_trips()
301 if (!prop->value) in pwm_fan_get_thermal_trips()
302 return -ENODATA; in pwm_fan_get_thermal_trips()
305 return -EINVAL; in pwm_fan_get_thermal_trips()
307 return -EINVAL; in pwm_fan_get_thermal_trips()
312 return -ENOMEM; in pwm_fan_get_thermal_trips()
330 struct thermal_trips *trips = ctx->thermal_trips; in pwm_fan_temp_to_state()
351 state = pwm_fan_temp_to_state(ctx, event_data->temp); in pwm_fan_thermal_notifier_call()
352 if (state > ctx->pwm_fan_max_state) in pwm_fan_thermal_notifier_call()
354 if (state == ctx->pwm_fan_state) in pwm_fan_thermal_notifier_call()
357 ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]); in pwm_fan_thermal_notifier_call()
361 ctx->pwm_fan_state = state; in pwm_fan_thermal_notifier_call()
369 if (pwm_fan_get_thermal_trips(dev, "rockchip,temp-trips", in pwm_fan_register_thermal_notifier()
370 &ctx->thermal_trips)) in pwm_fan_register_thermal_notifier()
371 return -EINVAL; in pwm_fan_register_thermal_notifier()
373 ctx->thermal_nb.notifier_call = pwm_fan_thermal_notifier_call; in pwm_fan_register_thermal_notifier()
375 return rockchip_system_monitor_register_notifier(&ctx->thermal_nb); in pwm_fan_register_thermal_notifier()
381 struct device *dev = &pdev->dev; in pwm_fan_probe()
390 return -ENOMEM; in pwm_fan_probe()
392 mutex_init(&ctx->lock); in pwm_fan_probe()
394 ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL); in pwm_fan_probe()
395 if (IS_ERR(ctx->pwm)) in pwm_fan_probe()
396 return dev_err_probe(dev, PTR_ERR(ctx->pwm), "Could not get PWM\n"); in pwm_fan_probe()
400 ctx->irq = platform_get_irq_optional(pdev, 0); in pwm_fan_probe()
401 if (ctx->irq == -EPROBE_DEFER) in pwm_fan_probe()
402 return ctx->irq; in pwm_fan_probe()
404 ctx->reg_en = devm_regulator_get_optional(dev, "fan"); in pwm_fan_probe()
405 if (IS_ERR(ctx->reg_en)) { in pwm_fan_probe()
406 if (PTR_ERR(ctx->reg_en) != -ENODEV) in pwm_fan_probe()
407 return PTR_ERR(ctx->reg_en); in pwm_fan_probe()
409 ctx->reg_en = NULL; in pwm_fan_probe()
411 ret = regulator_enable(ctx->reg_en); in pwm_fan_probe()
417 ctx->reg_en); in pwm_fan_probe()
422 ctx->pwm_value = MAX_PWM; in pwm_fan_probe()
424 pwm_init_state(ctx->pwm, &state); in pwm_fan_probe()
426 * __set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned in pwm_fan_probe()
432 return -EINVAL; in pwm_fan_probe()
436 state.duty_cycle = ctx->pwm->args.period - 1; in pwm_fan_probe()
439 ret = pwm_apply_state(ctx->pwm, &state); in pwm_fan_probe()
444 timer_setup(&ctx->rpm_timer, sample_timer, 0); in pwm_fan_probe()
449 of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr); in pwm_fan_probe()
450 ctx->pulses_per_revolution = ppr; in pwm_fan_probe()
451 if (!ctx->pulses_per_revolution) { in pwm_fan_probe()
452 dev_err(dev, "pulses-per-revolution can't be zero.\n"); in pwm_fan_probe()
453 return -EINVAL; in pwm_fan_probe()
456 if (ctx->irq > 0) { in pwm_fan_probe()
457 ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0, in pwm_fan_probe()
458 pdev->name, ctx); in pwm_fan_probe()
463 ctx->sample_start = ktime_get(); in pwm_fan_probe()
464 mod_timer(&ctx->rpm_timer, jiffies + HZ); in pwm_fan_probe()
478 ctx->pwm_fan_state = ctx->pwm_fan_max_state; in pwm_fan_probe()
480 of_find_property(dev->of_node, "rockchip,temp-trips", NULL)) { in pwm_fan_probe()
485 ctx->thermal_notifier_is_ok = true; in pwm_fan_probe()
490 dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops); in pwm_fan_probe()
494 "Failed to register pwm-fan as cooling device: %d\n", in pwm_fan_probe()
498 ctx->cdev = cdev; in pwm_fan_probe()
511 pwm_get_args(ctx->pwm, &args); in pwm_fan_disable()
513 if (ctx->pwm_value || ctx->thermal_notifier_is_ok) { in pwm_fan_disable()
514 ret = pwm_config(ctx->pwm, 0, args.period); in pwm_fan_disable()
518 pwm_disable(ctx->pwm); in pwm_fan_disable()
521 if (ctx->reg_en) { in pwm_fan_disable()
522 ret = regulator_disable(ctx->reg_en); in pwm_fan_disable()
534 pwm_fan_disable(&pdev->dev); in pwm_fan_shutdown()
550 if (ctx->reg_en) { in pwm_fan_resume()
551 ret = regulator_enable(ctx->reg_en); in pwm_fan_resume()
558 if (ctx->pwm_value == 0 && !ctx->thermal_notifier_is_ok) in pwm_fan_resume()
561 pwm_get_args(ctx->pwm, &pargs); in pwm_fan_resume()
562 duty = DIV_ROUND_UP_ULL(ctx->pwm_value * (pargs.period - 1), MAX_PWM); in pwm_fan_resume()
563 ret = pwm_config(ctx->pwm, duty, pargs.period); in pwm_fan_resume()
566 return pwm_enable(ctx->pwm); in pwm_fan_resume()
573 { .compatible = "pwm-fan", },
582 .name = "pwm-fan",
591 MODULE_ALIAS("platform:pwm-fan");