Lines Matching +full:duty +full:- +full:cycle

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
20 * - When PWM is stopped, timer counter gets stopped immediately. This
22 * - When PWM is running and changing both duty cycle and period,
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
31 * - PWM is stopped abruptly(without completing the current cycle)
32 * - Polarity is changed
33 * - A fresh cycle is started.
42 #include <clocksource/timer-ti-dm.h>
43 #include <linux/platform_data/dmtimer-omap.h>
54 * struct pwm_omap_dmtimer_chip - Structure representing a pwm chip
76 * pwm_omap_dmtimer_get_clock_cycles() - Get clock cycles in a time frame
88 * pwm_omap_dmtimer_start() - Start the pwm omap dm timer in pwm mode
101 omap->pdata->enable(omap->dm_timer); in pwm_omap_dmtimer_start()
102 omap->pdata->write_counter(omap->dm_timer, DM_TIMER_LOAD_MIN); in pwm_omap_dmtimer_start()
103 omap->pdata->disable(omap->dm_timer); in pwm_omap_dmtimer_start()
105 omap->pdata->start(omap->dm_timer); in pwm_omap_dmtimer_start()
109 * pwm_omap_dmtimer_is_enabled() - Detect if the pwm is enabled.
118 status = omap->pdata->get_pwm_status(omap->dm_timer); in pwm_omap_dmtimer_is_enabled()
124 * pwm_omap_dmtimer_polarity() - Detect the polarity of pwm.
133 status = omap->pdata->get_pwm_status(omap->dm_timer); in pwm_omap_dmtimer_polarity()
139 * pwm_omap_dmtimer_config() - Update the configuration of pwm omap dm timer
142 * @duty_ns: New duty cycle in nano seconds
158 dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n", in pwm_omap_dmtimer_config()
165 fclk = omap->pdata->get_fclk(omap->dm_timer); in pwm_omap_dmtimer_config()
167 dev_err(chip->dev, "invalid pmtimer fclk\n"); in pwm_omap_dmtimer_config()
168 return -EINVAL; in pwm_omap_dmtimer_config()
173 dev_err(chip->dev, "invalid pmtimer fclk rate\n"); in pwm_omap_dmtimer_config()
174 return -EINVAL; in pwm_omap_dmtimer_config()
177 dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); in pwm_omap_dmtimer_config()
181 * specified period and duty cycle. The load value determines the in pwm_omap_dmtimer_config()
182 * period time and the match value determines the duty time. in pwm_omap_dmtimer_config()
184 * The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles. in pwm_omap_dmtimer_config()
185 * Similarly, the active time lasts (match_value-load_value+1) cycles. in pwm_omap_dmtimer_config()
186 * The non-active time is the remainder: (DM_TIMER_MAX-match_value) in pwm_omap_dmtimer_config()
199 dev_info(chip->dev, in pwm_omap_dmtimer_config()
202 return -EINVAL; in pwm_omap_dmtimer_config()
206 dev_dbg(chip->dev, in pwm_omap_dmtimer_config()
207 "duty cycle %d ns is too short for clock rate %lu Hz\n", in pwm_omap_dmtimer_config()
209 dev_dbg(chip->dev, "using minimum of 1 clock cycle\n"); in pwm_omap_dmtimer_config()
212 dev_dbg(chip->dev, in pwm_omap_dmtimer_config()
213 "duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n", in pwm_omap_dmtimer_config()
215 dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n"); in pwm_omap_dmtimer_config()
216 duty_cycles = period_cycles - 1; in pwm_omap_dmtimer_config()
219 dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n", in pwm_omap_dmtimer_config()
225 load_value = (DM_TIMER_MAX - period_cycles) + 1; in pwm_omap_dmtimer_config()
226 match_value = load_value + duty_cycles - 1; in pwm_omap_dmtimer_config()
228 omap->pdata->set_load(omap->dm_timer, load_value); in pwm_omap_dmtimer_config()
229 omap->pdata->set_match(omap->dm_timer, true, match_value); in pwm_omap_dmtimer_config()
231 dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n", in pwm_omap_dmtimer_config()
238 * pwm_omap_dmtimer_set_polarity() - Changes the polarity of the pwm dm timer.
253 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_set_polarity()
255 omap->pdata->set_pwm(omap->dm_timer, in pwm_omap_dmtimer_set_polarity()
265 * pwm_omap_dmtimer_apply() - Changes the state of the pwm omap dm timer.
279 if (pwm_omap_dmtimer_is_enabled(omap) && !state->enabled) { in pwm_omap_dmtimer_apply()
280 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_apply()
284 if (pwm_omap_dmtimer_polarity(omap) != state->polarity) in pwm_omap_dmtimer_apply()
285 pwm_omap_dmtimer_set_polarity(chip, pwm, state->polarity); in pwm_omap_dmtimer_apply()
287 ret = pwm_omap_dmtimer_config(chip, pwm, state->duty_cycle, in pwm_omap_dmtimer_apply()
288 state->period); in pwm_omap_dmtimer_apply()
292 if (!pwm_omap_dmtimer_is_enabled(omap) && state->enabled) { in pwm_omap_dmtimer_apply()
293 omap->pdata->set_pwm(omap->dm_timer, in pwm_omap_dmtimer_apply()
294 state->polarity == PWM_POLARITY_INVERSED, in pwm_omap_dmtimer_apply()
310 struct device_node *np = pdev->dev.of_node; in pwm_omap_dmtimer_probe()
322 return -ENODEV; in pwm_omap_dmtimer_probe()
326 dev_err(&pdev->dev, "Unable to find Timer pdev\n"); in pwm_omap_dmtimer_probe()
327 ret = -ENODEV; in pwm_omap_dmtimer_probe()
331 timer_pdata = dev_get_platdata(&timer_pdev->dev); in pwm_omap_dmtimer_probe()
333 dev_dbg(&pdev->dev, in pwm_omap_dmtimer_probe()
335 ret = -EPROBE_DEFER; in pwm_omap_dmtimer_probe()
339 pdata = timer_pdata->timer_ops; in pwm_omap_dmtimer_probe()
341 if (!pdata || !pdata->request_by_node || in pwm_omap_dmtimer_probe()
342 !pdata->free || in pwm_omap_dmtimer_probe()
343 !pdata->enable || in pwm_omap_dmtimer_probe()
344 !pdata->disable || in pwm_omap_dmtimer_probe()
345 !pdata->get_fclk || in pwm_omap_dmtimer_probe()
346 !pdata->start || in pwm_omap_dmtimer_probe()
347 !pdata->stop || in pwm_omap_dmtimer_probe()
348 !pdata->set_load || in pwm_omap_dmtimer_probe()
349 !pdata->set_match || in pwm_omap_dmtimer_probe()
350 !pdata->set_pwm || in pwm_omap_dmtimer_probe()
351 !pdata->get_pwm_status || in pwm_omap_dmtimer_probe()
352 !pdata->set_prescaler || in pwm_omap_dmtimer_probe()
353 !pdata->write_counter) { in pwm_omap_dmtimer_probe()
354 dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n"); in pwm_omap_dmtimer_probe()
355 ret = -EINVAL; in pwm_omap_dmtimer_probe()
359 if (!of_get_property(timer, "ti,timer-pwm", NULL)) { in pwm_omap_dmtimer_probe()
360 dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n"); in pwm_omap_dmtimer_probe()
361 ret = -ENODEV; in pwm_omap_dmtimer_probe()
365 dm_timer = pdata->request_by_node(timer); in pwm_omap_dmtimer_probe()
367 ret = -EPROBE_DEFER; in pwm_omap_dmtimer_probe()
371 omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL); in pwm_omap_dmtimer_probe()
373 ret = -ENOMEM; in pwm_omap_dmtimer_probe()
377 omap->pdata = pdata; in pwm_omap_dmtimer_probe()
378 omap->dm_timer = dm_timer; in pwm_omap_dmtimer_probe()
379 omap->dm_timer_pdev = timer_pdev; in pwm_omap_dmtimer_probe()
385 if (pm_runtime_active(&omap->dm_timer_pdev->dev)) in pwm_omap_dmtimer_probe()
386 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_probe()
388 if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v)) in pwm_omap_dmtimer_probe()
389 omap->pdata->set_prescaler(omap->dm_timer, v); in pwm_omap_dmtimer_probe()
392 if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v)) in pwm_omap_dmtimer_probe()
393 omap->pdata->set_source(omap->dm_timer, v); in pwm_omap_dmtimer_probe()
395 omap->chip.dev = &pdev->dev; in pwm_omap_dmtimer_probe()
396 omap->chip.ops = &pwm_omap_dmtimer_ops; in pwm_omap_dmtimer_probe()
397 omap->chip.npwm = 1; in pwm_omap_dmtimer_probe()
399 ret = pwmchip_add(&omap->chip); in pwm_omap_dmtimer_probe()
401 dev_err(&pdev->dev, "failed to register PWM\n"); in pwm_omap_dmtimer_probe()
419 pdata->free(dm_timer); in pwm_omap_dmtimer_probe()
425 put_device(&timer_pdev->dev); in pwm_omap_dmtimer_probe()
437 pwmchip_remove(&omap->chip); in pwm_omap_dmtimer_remove()
439 if (pm_runtime_active(&omap->dm_timer_pdev->dev)) in pwm_omap_dmtimer_remove()
440 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_remove()
442 omap->pdata->free(omap->dm_timer); in pwm_omap_dmtimer_remove()
444 put_device(&omap->dm_timer_pdev->dev); in pwm_omap_dmtimer_remove()
448 {.compatible = "ti,omap-dmtimer-pwm"},
455 .name = "omap-dmtimer-pwm",
467 MODULE_DESCRIPTION("OMAP PWM Driver using Dual-mode Timers");