Lines Matching +full:pwm +full:- +full:active +full:- +full:state

1 // SPDX-License-Identifier: GPL-2.0-only
9 * Also based on pwm-samsung.c
13 * PWM driver / controller, using the OMAP's dual-mode timers
15 * reloaded with the load value and the pwm output goes up.
20 * - When PWM is stopped, timer counter gets stopped immediately. This
21 * doesn't allow the current PWM period to complete and stops abruptly.
22 * - When PWM is running and changing both duty cycle and period,
25 * is updated while the pwm pin is high, current pwm period/duty_cycle
27 * - period for current cycle = current_period + new period
28 * - duty_cycle for current period = current period + new duty_cycle.
29 * - PWM OMAP DM timer cannot change the polarity when pwm is active. When
30 * user requests a change in polarity when in active state:
31 * - PWM is stopped abruptly(without completing the current cycle)
32 * - Polarity is changed
33 * - A fresh cycle is started.
43 #include <clocksource/timer-ti-dm.h>
44 #include <linux/platform_data/dmtimer-omap.h>
47 #include <linux/pwm.h>
55 * struct pwm_omap_dmtimer_chip - Structure representing a pwm chip
57 * @chip: PWM chip structure representing PWM controller
58 * @mutex: Mutex to protect pwm apply state
65 /* Mutex to protect pwm apply state */
79 * pwm_omap_dmtimer_get_clock_cycles() - Get clock cycles in a time frame
80 * @clk_rate: pwm timer clock rate
91 * pwm_omap_dmtimer_start() - Start the pwm omap dm timer in pwm mode
92 * @omap: Pointer to pwm omap dm timer chip
99 * that the PWM line is toggled on the first event. in pwm_omap_dmtimer_start()
104 omap->pdata->enable(omap->dm_timer); in pwm_omap_dmtimer_start()
105 omap->pdata->write_counter(omap->dm_timer, DM_TIMER_LOAD_MIN); in pwm_omap_dmtimer_start()
106 omap->pdata->disable(omap->dm_timer); in pwm_omap_dmtimer_start()
108 omap->pdata->start(omap->dm_timer); in pwm_omap_dmtimer_start()
112 * pwm_omap_dmtimer_is_enabled() - Detect if the pwm is enabled.
113 * @omap: Pointer to pwm omap dm timer chip
115 * Return true if pwm is enabled else false.
121 status = omap->pdata->get_pwm_status(omap->dm_timer); in pwm_omap_dmtimer_is_enabled()
127 * pwm_omap_dmtimer_polarity() - Detect the polarity of pwm.
128 * @omap: Pointer to pwm omap dm timer chip
130 * Return the polarity of pwm.
136 status = omap->pdata->get_pwm_status(omap->dm_timer); in pwm_omap_dmtimer_polarity()
142 * pwm_omap_dmtimer_config() - Update the configuration of pwm omap dm timer
143 * @chip: Pointer to PWM controller
144 * @pwm: Pointer to PWM channel
152 struct pwm_device *pwm, in pwm_omap_dmtimer_config() argument
161 dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n", in pwm_omap_dmtimer_config()
164 if (duty_ns == pwm_get_duty_cycle(pwm) && in pwm_omap_dmtimer_config()
165 period_ns == pwm_get_period(pwm)) in pwm_omap_dmtimer_config()
168 fclk = omap->pdata->get_fclk(omap->dm_timer); in pwm_omap_dmtimer_config()
170 dev_err(chip->dev, "invalid pmtimer fclk\n"); in pwm_omap_dmtimer_config()
171 return -EINVAL; in pwm_omap_dmtimer_config()
176 dev_err(chip->dev, "invalid pmtimer fclk rate\n"); in pwm_omap_dmtimer_config()
177 return -EINVAL; in pwm_omap_dmtimer_config()
180 dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); in pwm_omap_dmtimer_config()
187 * The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles. in pwm_omap_dmtimer_config()
188 * Similarly, the active time lasts (match_value-load_value+1) cycles. in pwm_omap_dmtimer_config()
189 * The non-active time is the remainder: (DM_TIMER_MAX-match_value) in pwm_omap_dmtimer_config()
202 dev_info(chip->dev, in pwm_omap_dmtimer_config()
205 return -EINVAL; in pwm_omap_dmtimer_config()
209 dev_dbg(chip->dev, in pwm_omap_dmtimer_config()
212 dev_dbg(chip->dev, "using minimum of 1 clock cycle\n"); in pwm_omap_dmtimer_config()
215 dev_dbg(chip->dev, in pwm_omap_dmtimer_config()
218 dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n"); in pwm_omap_dmtimer_config()
219 duty_cycles = period_cycles - 1; in pwm_omap_dmtimer_config()
222 dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n", in pwm_omap_dmtimer_config()
228 load_value = (DM_TIMER_MAX - period_cycles) + 1; in pwm_omap_dmtimer_config()
229 match_value = load_value + duty_cycles - 1; in pwm_omap_dmtimer_config()
231 omap->pdata->set_load(omap->dm_timer, load_value); in pwm_omap_dmtimer_config()
232 omap->pdata->set_match(omap->dm_timer, true, match_value); in pwm_omap_dmtimer_config()
234 dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n", in pwm_omap_dmtimer_config()
241 * pwm_omap_dmtimer_set_polarity() - Changes the polarity of the pwm dm timer.
242 * @chip: Pointer to PWM controller
243 * @pwm: Pointer to PWM channel
244 * @polarity: New pwm polarity to be set
247 struct pwm_device *pwm, in pwm_omap_dmtimer_set_polarity() argument
253 /* Disable the PWM before changing the polarity. */ in pwm_omap_dmtimer_set_polarity()
256 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_set_polarity()
258 omap->pdata->set_pwm(omap->dm_timer, in pwm_omap_dmtimer_set_polarity()
268 * pwm_omap_dmtimer_apply() - Changes the state of the pwm omap dm timer.
269 * @chip: Pointer to PWM controller
270 * @pwm: Pointer to PWM channel
271 * @state: New state to apply
273 * Return 0 if successfully changed the state else appropriate error.
276 struct pwm_device *pwm, in pwm_omap_dmtimer_apply() argument
277 const struct pwm_state *state) in pwm_omap_dmtimer_apply() argument
282 mutex_lock(&omap->mutex); in pwm_omap_dmtimer_apply()
284 if (pwm_omap_dmtimer_is_enabled(omap) && !state->enabled) { in pwm_omap_dmtimer_apply()
285 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_apply()
289 if (pwm_omap_dmtimer_polarity(omap) != state->polarity) in pwm_omap_dmtimer_apply()
290 pwm_omap_dmtimer_set_polarity(chip, pwm, state->polarity); in pwm_omap_dmtimer_apply()
292 ret = pwm_omap_dmtimer_config(chip, pwm, state->duty_cycle, in pwm_omap_dmtimer_apply()
293 state->period); in pwm_omap_dmtimer_apply()
297 if (!pwm_omap_dmtimer_is_enabled(omap) && state->enabled) { in pwm_omap_dmtimer_apply()
298 omap->pdata->set_pwm(omap->dm_timer, in pwm_omap_dmtimer_apply()
299 state->polarity == PWM_POLARITY_INVERSED, in pwm_omap_dmtimer_apply()
307 mutex_unlock(&omap->mutex); in pwm_omap_dmtimer_apply()
319 struct device_node *np = pdev->dev.of_node; in pwm_omap_dmtimer_probe()
331 return -ENODEV; in pwm_omap_dmtimer_probe()
335 dev_err(&pdev->dev, "Unable to find Timer pdev\n"); in pwm_omap_dmtimer_probe()
336 ret = -ENODEV; in pwm_omap_dmtimer_probe()
340 timer_pdata = dev_get_platdata(&timer_pdev->dev); in pwm_omap_dmtimer_probe()
342 dev_dbg(&pdev->dev, in pwm_omap_dmtimer_probe()
344 ret = -EPROBE_DEFER; in pwm_omap_dmtimer_probe()
348 pdata = timer_pdata->timer_ops; in pwm_omap_dmtimer_probe()
350 if (!pdata || !pdata->request_by_node || in pwm_omap_dmtimer_probe()
351 !pdata->free || in pwm_omap_dmtimer_probe()
352 !pdata->enable || in pwm_omap_dmtimer_probe()
353 !pdata->disable || in pwm_omap_dmtimer_probe()
354 !pdata->get_fclk || in pwm_omap_dmtimer_probe()
355 !pdata->start || in pwm_omap_dmtimer_probe()
356 !pdata->stop || in pwm_omap_dmtimer_probe()
357 !pdata->set_load || in pwm_omap_dmtimer_probe()
358 !pdata->set_match || in pwm_omap_dmtimer_probe()
359 !pdata->set_pwm || in pwm_omap_dmtimer_probe()
360 !pdata->get_pwm_status || in pwm_omap_dmtimer_probe()
361 !pdata->set_prescaler || in pwm_omap_dmtimer_probe()
362 !pdata->write_counter) { in pwm_omap_dmtimer_probe()
363 dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n"); in pwm_omap_dmtimer_probe()
364 ret = -EINVAL; in pwm_omap_dmtimer_probe()
368 if (!of_get_property(timer, "ti,timer-pwm", NULL)) { in pwm_omap_dmtimer_probe()
369 dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n"); in pwm_omap_dmtimer_probe()
370 ret = -ENODEV; in pwm_omap_dmtimer_probe()
374 dm_timer = pdata->request_by_node(timer); in pwm_omap_dmtimer_probe()
376 ret = -EPROBE_DEFER; in pwm_omap_dmtimer_probe()
380 omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL); in pwm_omap_dmtimer_probe()
382 ret = -ENOMEM; in pwm_omap_dmtimer_probe()
386 omap->pdata = pdata; in pwm_omap_dmtimer_probe()
387 omap->dm_timer = dm_timer; in pwm_omap_dmtimer_probe()
388 omap->dm_timer_pdev = timer_pdev; in pwm_omap_dmtimer_probe()
391 * Ensure that the timer is stopped before we allow PWM core to call in pwm_omap_dmtimer_probe()
394 if (pm_runtime_active(&omap->dm_timer_pdev->dev)) in pwm_omap_dmtimer_probe()
395 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_probe()
397 if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v)) in pwm_omap_dmtimer_probe()
398 omap->pdata->set_prescaler(omap->dm_timer, v); in pwm_omap_dmtimer_probe()
401 if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v)) in pwm_omap_dmtimer_probe()
402 omap->pdata->set_source(omap->dm_timer, v); in pwm_omap_dmtimer_probe()
404 omap->chip.dev = &pdev->dev; in pwm_omap_dmtimer_probe()
405 omap->chip.ops = &pwm_omap_dmtimer_ops; in pwm_omap_dmtimer_probe()
406 omap->chip.npwm = 1; in pwm_omap_dmtimer_probe()
408 mutex_init(&omap->mutex); in pwm_omap_dmtimer_probe()
410 ret = pwmchip_add(&omap->chip); in pwm_omap_dmtimer_probe()
412 dev_err(&pdev->dev, "failed to register PWM\n"); in pwm_omap_dmtimer_probe()
430 pdata->free(dm_timer); in pwm_omap_dmtimer_probe()
436 put_device(&timer_pdev->dev); in pwm_omap_dmtimer_probe()
448 pwmchip_remove(&omap->chip); in pwm_omap_dmtimer_remove()
450 if (pm_runtime_active(&omap->dm_timer_pdev->dev)) in pwm_omap_dmtimer_remove()
451 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_remove()
453 omap->pdata->free(omap->dm_timer); in pwm_omap_dmtimer_remove()
455 put_device(&omap->dm_timer_pdev->dev); in pwm_omap_dmtimer_remove()
457 mutex_destroy(&omap->mutex); in pwm_omap_dmtimer_remove()
463 {.compatible = "ti,omap-dmtimer-pwm"},
470 .name = "omap-dmtimer-pwm",
482 MODULE_DESCRIPTION("OMAP PWM Driver using Dual-mode Timers");