Lines Matching +full:timer +full:- +full:pwm

1 // SPDX-License-Identifier: GPL-2.0-only
21 #include <linux/pwm.h>
36 unsigned div; /* PWM clock divider */
37 unsigned duty; /* PWM duty expressed in clk cycles */
38 unsigned period; /* PWM period expressed in clk cycles */
70 struct pwm_device *pwm) in atmel_tcb_pwm_request() argument
73 struct atmel_tcb_pwm_device *tcbpwm = &tcbpwmc->pwms[pwm->hwpwm]; in atmel_tcb_pwm_request()
77 ret = clk_prepare_enable(tcbpwmc->clk); in atmel_tcb_pwm_request()
81 tcbpwm->duty = 0; in atmel_tcb_pwm_request()
82 tcbpwm->period = 0; in atmel_tcb_pwm_request()
83 tcbpwm->div = 0; in atmel_tcb_pwm_request()
85 spin_lock(&tcbpwmc->lock); in atmel_tcb_pwm_request()
86 regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); in atmel_tcb_pwm_request()
88 * Get init config from Timer Counter registers if in atmel_tcb_pwm_request()
89 * Timer Counter is already configured as a PWM generator. in atmel_tcb_pwm_request()
92 if (pwm->hwpwm == 0) in atmel_tcb_pwm_request()
93 regmap_read(tcbpwmc->regmap, in atmel_tcb_pwm_request()
94 ATMEL_TC_REG(tcbpwmc->channel, RA), in atmel_tcb_pwm_request()
95 &tcbpwm->duty); in atmel_tcb_pwm_request()
97 regmap_read(tcbpwmc->regmap, in atmel_tcb_pwm_request()
98 ATMEL_TC_REG(tcbpwmc->channel, RB), in atmel_tcb_pwm_request()
99 &tcbpwm->duty); in atmel_tcb_pwm_request()
101 tcbpwm->div = cmr & ATMEL_TC_TCCLKS; in atmel_tcb_pwm_request()
102 regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, RC), in atmel_tcb_pwm_request()
103 &tcbpwm->period); in atmel_tcb_pwm_request()
110 regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), cmr); in atmel_tcb_pwm_request()
111 spin_unlock(&tcbpwmc->lock); in atmel_tcb_pwm_request()
116 static void atmel_tcb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) in atmel_tcb_pwm_free() argument
120 clk_disable_unprepare(tcbpwmc->clk); in atmel_tcb_pwm_free()
123 static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, in atmel_tcb_pwm_disable() argument
127 struct atmel_tcb_pwm_device *tcbpwm = &tcbpwmc->pwms[pwm->hwpwm]; in atmel_tcb_pwm_disable()
131 * If duty is 0 the timer will be stopped and we have to in atmel_tcb_pwm_disable()
133 * - set output to high if PWM_POLARITY_INVERSED in atmel_tcb_pwm_disable()
134 * - set output to low if PWM_POLARITY_NORMAL in atmel_tcb_pwm_disable()
138 if (tcbpwm->duty == 0) in atmel_tcb_pwm_disable()
141 spin_lock(&tcbpwmc->lock); in atmel_tcb_pwm_disable()
142 regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); in atmel_tcb_pwm_disable()
145 if (pwm->hwpwm == 0) { in atmel_tcb_pwm_disable()
159 regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), cmr); in atmel_tcb_pwm_disable()
163 * If both PWM devices in this group are disabled we stop the clock. in atmel_tcb_pwm_disable()
166 regmap_write(tcbpwmc->regmap, in atmel_tcb_pwm_disable()
167 ATMEL_TC_REG(tcbpwmc->channel, CCR), in atmel_tcb_pwm_disable()
169 tcbpwmc->bkup.enabled = 1; in atmel_tcb_pwm_disable()
171 regmap_write(tcbpwmc->regmap, in atmel_tcb_pwm_disable()
172 ATMEL_TC_REG(tcbpwmc->channel, CCR), in atmel_tcb_pwm_disable()
174 tcbpwmc->bkup.enabled = 0; in atmel_tcb_pwm_disable()
177 spin_unlock(&tcbpwmc->lock); in atmel_tcb_pwm_disable()
180 static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, in atmel_tcb_pwm_enable() argument
184 struct atmel_tcb_pwm_device *tcbpwm = &tcbpwmc->pwms[pwm->hwpwm]; in atmel_tcb_pwm_enable()
188 * If duty is 0 the timer will be stopped and we have to in atmel_tcb_pwm_enable()
190 * - set output to high if PWM_POLARITY_INVERSED in atmel_tcb_pwm_enable()
191 * - set output to low if PWM_POLARITY_NORMAL in atmel_tcb_pwm_enable()
195 if (tcbpwm->duty == 0) in atmel_tcb_pwm_enable()
198 spin_lock(&tcbpwmc->lock); in atmel_tcb_pwm_enable()
199 regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); in atmel_tcb_pwm_enable()
204 if (pwm->hwpwm == 0) { in atmel_tcb_pwm_enable()
226 if (tcbpwm->duty != tcbpwm->period && tcbpwm->duty > 0) { in atmel_tcb_pwm_enable()
227 if (pwm->hwpwm == 0) { in atmel_tcb_pwm_enable()
240 cmr |= (tcbpwm->div & ATMEL_TC_TCCLKS); in atmel_tcb_pwm_enable()
242 regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), cmr); in atmel_tcb_pwm_enable()
244 if (pwm->hwpwm == 0) in atmel_tcb_pwm_enable()
245 regmap_write(tcbpwmc->regmap, in atmel_tcb_pwm_enable()
246 ATMEL_TC_REG(tcbpwmc->channel, RA), in atmel_tcb_pwm_enable()
247 tcbpwm->duty); in atmel_tcb_pwm_enable()
249 regmap_write(tcbpwmc->regmap, in atmel_tcb_pwm_enable()
250 ATMEL_TC_REG(tcbpwmc->channel, RB), in atmel_tcb_pwm_enable()
251 tcbpwm->duty); in atmel_tcb_pwm_enable()
253 regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, RC), in atmel_tcb_pwm_enable()
254 tcbpwm->period); in atmel_tcb_pwm_enable()
257 regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CCR), in atmel_tcb_pwm_enable()
259 tcbpwmc->bkup.enabled = 1; in atmel_tcb_pwm_enable()
260 spin_unlock(&tcbpwmc->lock); in atmel_tcb_pwm_enable()
264 static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, in atmel_tcb_pwm_config() argument
268 struct atmel_tcb_pwm_device *tcbpwm = &tcbpwmc->pwms[pwm->hwpwm]; in atmel_tcb_pwm_config()
274 unsigned rate = clk_get_rate(tcbpwmc->clk); in atmel_tcb_pwm_config()
283 if (tcbpwmc->gclk) in atmel_tcb_pwm_config()
291 max = min << tcbpwmc->width; in atmel_tcb_pwm_config()
302 rate = clk_get_rate(tcbpwmc->slow_clk); in atmel_tcb_pwm_config()
304 max = min << tcbpwmc->width; in atmel_tcb_pwm_config()
308 return -ERANGE; in atmel_tcb_pwm_config()
314 if (pwm->hwpwm == 0) in atmel_tcb_pwm_config()
315 atcbpwm = &tcbpwmc->pwms[1]; in atmel_tcb_pwm_config()
317 atcbpwm = &tcbpwmc->pwms[0]; in atmel_tcb_pwm_config()
320 * PWM devices provided by the TCB driver are grouped by 2. in atmel_tcb_pwm_config()
321 * PWM devices in a given group must be configured with the in atmel_tcb_pwm_config()
324 * We're checking the period value of the second PWM device in atmel_tcb_pwm_config()
327 if ((atcbpwm && atcbpwm->duty > 0 && in atmel_tcb_pwm_config()
328 atcbpwm->duty != atcbpwm->period) && in atmel_tcb_pwm_config()
329 (atcbpwm->div != i || atcbpwm->period != period)) { in atmel_tcb_pwm_config()
330 dev_err(chip->dev, in atmel_tcb_pwm_config()
331 "failed to configure period_ns: PWM group already configured with a different value\n"); in atmel_tcb_pwm_config()
332 return -EINVAL; in atmel_tcb_pwm_config()
335 tcbpwm->period = period; in atmel_tcb_pwm_config()
336 tcbpwm->div = i; in atmel_tcb_pwm_config()
337 tcbpwm->duty = duty; in atmel_tcb_pwm_config()
342 static int atmel_tcb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in atmel_tcb_pwm_apply() argument
348 if (!state->enabled) { in atmel_tcb_pwm_apply()
349 atmel_tcb_pwm_disable(chip, pwm, state->polarity); in atmel_tcb_pwm_apply()
353 period = state->period < INT_MAX ? state->period : INT_MAX; in atmel_tcb_pwm_apply()
354 duty_cycle = state->duty_cycle < INT_MAX ? state->duty_cycle : INT_MAX; in atmel_tcb_pwm_apply()
356 ret = atmel_tcb_pwm_config(chip, pwm, duty_cycle, period); in atmel_tcb_pwm_apply()
360 return atmel_tcb_pwm_enable(chip, pwm, state->polarity); in atmel_tcb_pwm_apply()
383 { .compatible = "atmel,at91rm9200-tcb", .data = &tcb_rm9200_config, },
384 { .compatible = "atmel,at91sam9x5-tcb", .data = &tcb_sam9x5_config, },
385 { .compatible = "atmel,sama5d2-tcb", .data = &tcb_sama5d2_config, },
394 struct device_node *np = pdev->dev.of_node; in atmel_tcb_pwm_probe()
399 tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL); in atmel_tcb_pwm_probe()
401 return -ENOMEM; in atmel_tcb_pwm_probe()
405 dev_err(&pdev->dev, in atmel_tcb_pwm_probe()
406 "failed to get Timer Counter Block channel from device tree (error: %d)\n", in atmel_tcb_pwm_probe()
411 tcbpwm->regmap = syscon_node_to_regmap(np->parent); in atmel_tcb_pwm_probe()
412 if (IS_ERR(tcbpwm->regmap)) in atmel_tcb_pwm_probe()
413 return PTR_ERR(tcbpwm->regmap); in atmel_tcb_pwm_probe()
415 tcbpwm->slow_clk = of_clk_get_by_name(np->parent, "slow_clk"); in atmel_tcb_pwm_probe()
416 if (IS_ERR(tcbpwm->slow_clk)) in atmel_tcb_pwm_probe()
417 return PTR_ERR(tcbpwm->slow_clk); in atmel_tcb_pwm_probe()
420 tcbpwm->clk = of_clk_get_by_name(np->parent, clk_name); in atmel_tcb_pwm_probe()
421 if (IS_ERR(tcbpwm->clk)) in atmel_tcb_pwm_probe()
422 tcbpwm->clk = of_clk_get_by_name(np->parent, "t0_clk"); in atmel_tcb_pwm_probe()
423 if (IS_ERR(tcbpwm->clk)) { in atmel_tcb_pwm_probe()
424 err = PTR_ERR(tcbpwm->clk); in atmel_tcb_pwm_probe()
428 match = of_match_node(atmel_tcb_of_match, np->parent); in atmel_tcb_pwm_probe()
429 config = match->data; in atmel_tcb_pwm_probe()
431 if (config->has_gclk) { in atmel_tcb_pwm_probe()
432 tcbpwm->gclk = of_clk_get_by_name(np->parent, "gclk"); in atmel_tcb_pwm_probe()
433 if (IS_ERR(tcbpwm->gclk)) { in atmel_tcb_pwm_probe()
434 err = PTR_ERR(tcbpwm->gclk); in atmel_tcb_pwm_probe()
439 tcbpwm->chip.dev = &pdev->dev; in atmel_tcb_pwm_probe()
440 tcbpwm->chip.ops = &atmel_tcb_pwm_ops; in atmel_tcb_pwm_probe()
441 tcbpwm->chip.npwm = NPWM; in atmel_tcb_pwm_probe()
442 tcbpwm->channel = channel; in atmel_tcb_pwm_probe()
443 tcbpwm->width = config->counter_width; in atmel_tcb_pwm_probe()
445 err = clk_prepare_enable(tcbpwm->slow_clk); in atmel_tcb_pwm_probe()
449 spin_lock_init(&tcbpwm->lock); in atmel_tcb_pwm_probe()
451 err = pwmchip_add(&tcbpwm->chip); in atmel_tcb_pwm_probe()
460 clk_disable_unprepare(tcbpwm->slow_clk); in atmel_tcb_pwm_probe()
463 clk_put(tcbpwm->gclk); in atmel_tcb_pwm_probe()
466 clk_put(tcbpwm->clk); in atmel_tcb_pwm_probe()
469 clk_put(tcbpwm->slow_clk); in atmel_tcb_pwm_probe()
478 pwmchip_remove(&tcbpwm->chip); in atmel_tcb_pwm_remove()
480 clk_disable_unprepare(tcbpwm->slow_clk); in atmel_tcb_pwm_remove()
481 clk_put(tcbpwm->gclk); in atmel_tcb_pwm_remove()
482 clk_put(tcbpwm->clk); in atmel_tcb_pwm_remove()
483 clk_put(tcbpwm->slow_clk); in atmel_tcb_pwm_remove()
487 { .compatible = "atmel,tcb-pwm", },
495 struct atmel_tcb_channel *chan = &tcbpwm->bkup; in atmel_tcb_pwm_suspend()
496 unsigned int channel = tcbpwm->channel; in atmel_tcb_pwm_suspend()
498 regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, CMR), &chan->cmr); in atmel_tcb_pwm_suspend()
499 regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RA), &chan->ra); in atmel_tcb_pwm_suspend()
500 regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RB), &chan->rb); in atmel_tcb_pwm_suspend()
501 regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RC), &chan->rc); in atmel_tcb_pwm_suspend()
509 struct atmel_tcb_channel *chan = &tcbpwm->bkup; in atmel_tcb_pwm_resume()
510 unsigned int channel = tcbpwm->channel; in atmel_tcb_pwm_resume()
512 regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, CMR), chan->cmr); in atmel_tcb_pwm_resume()
513 regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RA), chan->ra); in atmel_tcb_pwm_resume()
514 regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RB), chan->rb); in atmel_tcb_pwm_resume()
515 regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RC), chan->rc); in atmel_tcb_pwm_resume()
517 if (chan->enabled) in atmel_tcb_pwm_resume()
518 regmap_write(tcbpwm->regmap, in atmel_tcb_pwm_resume()
530 .name = "atmel-tcb-pwm",
540 MODULE_DESCRIPTION("Atmel Timer Counter Pulse Width Modulation Driver");