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.
42 #include <clocksource/timer-ti-dm.h>
43 #include <linux/platform_data/dmtimer-omap.h>
46 #include <linux/pwm.h>
54 * struct pwm_omap_dmtimer_chip - Structure representing a pwm chip
61 /* Mutex to protect pwm apply state */
74 * pwm_omap_dmtimer_get_clock_cycles() - Get clock cycles in a time frame
75 * @clk_rate: pwm timer clock rate
86 * pwm_omap_dmtimer_start() - Start the pwm omap dm timer in pwm mode
87 * @omap: Pointer to pwm omap dm timer chip
94 * that the PWM line is toggled on the first event. in pwm_omap_dmtimer_start()
99 omap->pdata->enable(omap->dm_timer); in pwm_omap_dmtimer_start()
100 omap->pdata->write_counter(omap->dm_timer, DM_TIMER_LOAD_MIN); in pwm_omap_dmtimer_start()
101 omap->pdata->disable(omap->dm_timer); in pwm_omap_dmtimer_start()
103 omap->pdata->start(omap->dm_timer); in pwm_omap_dmtimer_start()
107 * pwm_omap_dmtimer_is_enabled() - Detect if the pwm is enabled.
108 * @omap: Pointer to pwm omap dm timer chip
110 * Return true if pwm is enabled else false.
116 status = omap->pdata->get_pwm_status(omap->dm_timer); in pwm_omap_dmtimer_is_enabled()
122 * pwm_omap_dmtimer_polarity() - Detect the polarity of pwm.
123 * @omap: Pointer to pwm omap dm timer chip
125 * Return the polarity of pwm.
131 status = omap->pdata->get_pwm_status(omap->dm_timer); in pwm_omap_dmtimer_polarity()
137 * pwm_omap_dmtimer_config() - Update the configuration of pwm omap dm timer
138 * @chip: Pointer to PWM controller
139 * @pwm: Pointer to PWM channel
147 struct pwm_device *pwm, in pwm_omap_dmtimer_config() argument
159 if (duty_ns == pwm_get_duty_cycle(pwm) && in pwm_omap_dmtimer_config()
160 period_ns == pwm_get_period(pwm)) in pwm_omap_dmtimer_config()
163 fclk = omap->pdata->get_fclk(omap->dm_timer); in pwm_omap_dmtimer_config()
166 return -EINVAL; in pwm_omap_dmtimer_config()
172 return -EINVAL; in pwm_omap_dmtimer_config()
182 * The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles. in pwm_omap_dmtimer_config()
183 * Similarly, the active time lasts (match_value-load_value+1) cycles. in pwm_omap_dmtimer_config()
184 * The non-active time is the remainder: (DM_TIMER_MAX-match_value) in pwm_omap_dmtimer_config()
200 return -EINVAL; in pwm_omap_dmtimer_config()
214 duty_cycles = period_cycles - 1; in pwm_omap_dmtimer_config()
223 load_value = (DM_TIMER_MAX - period_cycles) + 1; in pwm_omap_dmtimer_config()
224 match_value = load_value + duty_cycles - 1; in pwm_omap_dmtimer_config()
226 omap->pdata->set_load(omap->dm_timer, load_value); in pwm_omap_dmtimer_config()
227 omap->pdata->set_match(omap->dm_timer, true, match_value); in pwm_omap_dmtimer_config()
236 * pwm_omap_dmtimer_set_polarity() - Changes the polarity of the pwm dm timer.
237 * @chip: Pointer to PWM controller
238 * @pwm: Pointer to PWM channel
239 * @polarity: New pwm polarity to be set
242 struct pwm_device *pwm, in pwm_omap_dmtimer_set_polarity() argument
248 /* Disable the PWM before changing the polarity. */ in pwm_omap_dmtimer_set_polarity()
251 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_set_polarity()
253 omap->pdata->set_pwm(omap->dm_timer, in pwm_omap_dmtimer_set_polarity()
263 * pwm_omap_dmtimer_apply() - Changes the state of the pwm omap dm timer.
264 * @chip: Pointer to PWM controller
265 * @pwm: Pointer to PWM channel
266 * @state: New state to apply
268 * Return 0 if successfully changed the state else appropriate error.
271 struct pwm_device *pwm, in pwm_omap_dmtimer_apply() argument
272 const struct pwm_state *state) in pwm_omap_dmtimer_apply() argument
277 if (pwm_omap_dmtimer_is_enabled(omap) && !state->enabled) { in pwm_omap_dmtimer_apply()
278 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_apply()
282 if (pwm_omap_dmtimer_polarity(omap) != state->polarity) in pwm_omap_dmtimer_apply()
283 pwm_omap_dmtimer_set_polarity(chip, pwm, state->polarity); in pwm_omap_dmtimer_apply()
285 ret = pwm_omap_dmtimer_config(chip, pwm, state->duty_cycle, in pwm_omap_dmtimer_apply()
286 state->period); in pwm_omap_dmtimer_apply()
290 if (!pwm_omap_dmtimer_is_enabled(omap) && state->enabled) { in pwm_omap_dmtimer_apply()
291 omap->pdata->set_pwm(omap->dm_timer, in pwm_omap_dmtimer_apply()
292 state->polarity == PWM_POLARITY_INVERSED, in pwm_omap_dmtimer_apply()
308 struct device_node *np = pdev->dev.of_node; in pwm_omap_dmtimer_probe()
321 return -ENODEV; in pwm_omap_dmtimer_probe()
325 dev_err(&pdev->dev, "Unable to find Timer pdev\n"); in pwm_omap_dmtimer_probe()
326 ret = -ENODEV; in pwm_omap_dmtimer_probe()
330 timer_pdata = dev_get_platdata(&timer_pdev->dev); in pwm_omap_dmtimer_probe()
332 dev_dbg(&pdev->dev, in pwm_omap_dmtimer_probe()
334 ret = -EPROBE_DEFER; in pwm_omap_dmtimer_probe()
338 pdata = timer_pdata->timer_ops; in pwm_omap_dmtimer_probe()
340 if (!pdata || !pdata->request_by_node || in pwm_omap_dmtimer_probe()
341 !pdata->free || in pwm_omap_dmtimer_probe()
342 !pdata->enable || in pwm_omap_dmtimer_probe()
343 !pdata->disable || in pwm_omap_dmtimer_probe()
344 !pdata->get_fclk || in pwm_omap_dmtimer_probe()
345 !pdata->start || in pwm_omap_dmtimer_probe()
346 !pdata->stop || in pwm_omap_dmtimer_probe()
347 !pdata->set_load || in pwm_omap_dmtimer_probe()
348 !pdata->set_match || in pwm_omap_dmtimer_probe()
349 !pdata->set_pwm || in pwm_omap_dmtimer_probe()
350 !pdata->get_pwm_status || in pwm_omap_dmtimer_probe()
351 !pdata->set_prescaler || in pwm_omap_dmtimer_probe()
352 !pdata->write_counter) { in pwm_omap_dmtimer_probe()
353 dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n"); in pwm_omap_dmtimer_probe()
354 ret = -EINVAL; in pwm_omap_dmtimer_probe()
358 if (!of_property_read_bool(timer, "ti,timer-pwm")) { in pwm_omap_dmtimer_probe()
359 dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n"); in pwm_omap_dmtimer_probe()
360 ret = -ENODEV; in pwm_omap_dmtimer_probe()
364 dm_timer = pdata->request_by_node(timer); in pwm_omap_dmtimer_probe()
366 ret = -EPROBE_DEFER; in pwm_omap_dmtimer_probe()
370 chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*omap)); 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()
382 * Ensure that the timer is stopped before we allow PWM core to call 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 chip->ops = &pwm_omap_dmtimer_ops; in pwm_omap_dmtimer_probe()
399 dev_err(&pdev->dev, "failed to register PWM\n"); in pwm_omap_dmtimer_probe()
417 pdata->free(dm_timer); in pwm_omap_dmtimer_probe()
423 put_device(&timer_pdev->dev); in pwm_omap_dmtimer_probe()
438 if (pm_runtime_active(&omap->dm_timer_pdev->dev)) in pwm_omap_dmtimer_remove()
439 omap->pdata->stop(omap->dm_timer); in pwm_omap_dmtimer_remove()
441 omap->pdata->free(omap->dm_timer); in pwm_omap_dmtimer_remove()
443 put_device(&omap->dm_timer_pdev->dev); in pwm_omap_dmtimer_remove()
447 {.compatible = "ti,omap-dmtimer-pwm"},
454 .name = "omap-dmtimer-pwm",
466 MODULE_DESCRIPTION("OMAP PWM Driver using Dual-mode Timers");