Lines Matching +full:pwm +full:- +full:offset

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * EHRPWM PWM driver
5 * Copyright (C) 2012 Texas Instruments, Inc. - https://www.ti.com/
10 #include <linux/pwm.h>
121 static inline u16 ehrpwm_read(void __iomem *base, unsigned int offset) in ehrpwm_read() argument
123 return readw(base + offset); in ehrpwm_read()
126 static inline void ehrpwm_write(void __iomem *base, unsigned int offset, in ehrpwm_write() argument
129 writew(value, base + offset); in ehrpwm_write()
132 static void ehrpwm_modify(void __iomem *base, unsigned int offset, u16 mask, in ehrpwm_modify() argument
137 val = readw(base + offset); in ehrpwm_modify()
140 writew(val, base + offset); in ehrpwm_modify()
144 * set_prescale_div - Set up the prescaler divider function
186 * Configure PWM output to HIGH/LOW level on counter in configure_polarity()
195 if (pc->polarity[chan] == PWM_POLARITY_INVERSED) in configure_polarity()
203 if (pc->polarity[chan] == PWM_POLARITY_INVERSED) in configure_polarity()
210 ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); in configure_polarity()
217 static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, in ehrpwm_pwm_config() argument
227 return -ERANGE; in ehrpwm_pwm_config()
229 c = pc->clk_rate; in ehrpwm_pwm_config()
238 c = pc->clk_rate; in ehrpwm_pwm_config()
245 * Period values should be same for multiple PWM channels as IP uses in ehrpwm_pwm_config()
249 if (pc->period_cycles[i] && in ehrpwm_pwm_config()
250 (pc->period_cycles[i] != period_cycles)) { in ehrpwm_pwm_config()
255 if (i == pwm->hwpwm) in ehrpwm_pwm_config()
261 return -EINVAL; in ehrpwm_pwm_config()
265 pc->period_cycles[pwm->hwpwm] = period_cycles; in ehrpwm_pwm_config()
267 /* Configure clock prescaler to support Low frequency PWM wave */ in ehrpwm_pwm_config()
271 return -EINVAL; in ehrpwm_pwm_config()
277 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval); in ehrpwm_pwm_config()
284 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW); in ehrpwm_pwm_config()
286 ehrpwm_write(pc->mmio_base, TBPRD, period_cycles); in ehrpwm_pwm_config()
288 /* Configure ehrpwm counter for up-count mode */ in ehrpwm_pwm_config()
289 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, in ehrpwm_pwm_config()
292 if (pwm->hwpwm == 1) in ehrpwm_pwm_config()
299 ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles); in ehrpwm_pwm_config()
307 struct pwm_device *pwm, in ehrpwm_pwm_set_polarity() argument
313 pc->polarity[pwm->hwpwm] = polarity; in ehrpwm_pwm_set_polarity()
318 static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) in ehrpwm_pwm_enable() argument
324 /* Leave clock enabled on enabling PWM */ in ehrpwm_pwm_enable()
327 /* Disabling Action Qualifier on PWM output */ in ehrpwm_pwm_enable()
328 if (pwm->hwpwm) { in ehrpwm_pwm_enable()
337 ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK, in ehrpwm_pwm_enable()
340 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); in ehrpwm_pwm_enable()
343 configure_polarity(pc, pwm->hwpwm); in ehrpwm_pwm_enable()
346 ret = clk_enable(pc->tbclk); in ehrpwm_pwm_enable()
356 static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) in ehrpwm_pwm_disable() argument
361 /* Action Qualifier puts PWM output low forcefully */ in ehrpwm_pwm_disable()
362 if (pwm->hwpwm) { in ehrpwm_pwm_disable()
371 ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK, in ehrpwm_pwm_disable()
373 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); in ehrpwm_pwm_disable()
376 * Action Qualifier control on PWM output from next TBCLK in ehrpwm_pwm_disable()
378 ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK, in ehrpwm_pwm_disable()
381 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); in ehrpwm_pwm_disable()
383 /* Disabling TBCLK on PWM disable */ in ehrpwm_pwm_disable()
384 clk_disable(pc->tbclk); in ehrpwm_pwm_disable()
386 /* Disable clock on PWM disable */ in ehrpwm_pwm_disable()
390 static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) in ehrpwm_pwm_free() argument
394 if (pwm_is_enabled(pwm)) { in ehrpwm_pwm_free()
395 dev_warn(pwmchip_parent(chip), "Removing PWM device without disabling\n"); in ehrpwm_pwm_free()
400 pc->period_cycles[pwm->hwpwm] = 0; in ehrpwm_pwm_free()
403 static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in ehrpwm_pwm_apply() argument
407 bool enabled = pwm->state.enabled; in ehrpwm_pwm_apply()
409 if (state->polarity != pwm->state.polarity) { in ehrpwm_pwm_apply()
411 ehrpwm_pwm_disable(chip, pwm); in ehrpwm_pwm_apply()
415 err = ehrpwm_pwm_set_polarity(chip, pwm, state->polarity); in ehrpwm_pwm_apply()
420 if (!state->enabled) { in ehrpwm_pwm_apply()
422 ehrpwm_pwm_disable(chip, pwm); in ehrpwm_pwm_apply()
426 err = ehrpwm_pwm_config(chip, pwm, state->duty_cycle, state->period); in ehrpwm_pwm_apply()
431 err = ehrpwm_pwm_enable(chip, pwm); in ehrpwm_pwm_apply()
442 { .compatible = "ti,am3352-ehrpwm" },
443 { .compatible = "ti,am33xx-ehrpwm" },
450 struct device_node *np = pdev->dev.of_node; in ehrpwm_pwm_probe()
456 chip = devm_pwmchip_alloc(&pdev->dev, NUM_PWM_CHANNEL, sizeof(*pc)); in ehrpwm_pwm_probe()
461 clk = devm_clk_get(&pdev->dev, "fck"); in ehrpwm_pwm_probe()
463 if (of_device_is_compatible(np, "ti,am33xx-ecap")) { in ehrpwm_pwm_probe()
464 dev_warn(&pdev->dev, "Binding is obsolete.\n"); in ehrpwm_pwm_probe()
465 clk = devm_clk_get(pdev->dev.parent, "fck"); in ehrpwm_pwm_probe()
470 return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Failed to get fck\n"); in ehrpwm_pwm_probe()
472 pc->clk_rate = clk_get_rate(clk); in ehrpwm_pwm_probe()
473 if (!pc->clk_rate) { in ehrpwm_pwm_probe()
474 dev_err(&pdev->dev, "failed to get clock rate\n"); in ehrpwm_pwm_probe()
475 return -EINVAL; in ehrpwm_pwm_probe()
478 chip->ops = &ehrpwm_pwm_ops; in ehrpwm_pwm_probe()
480 pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); in ehrpwm_pwm_probe()
481 if (IS_ERR(pc->mmio_base)) in ehrpwm_pwm_probe()
482 return PTR_ERR(pc->mmio_base); in ehrpwm_pwm_probe()
485 pc->tbclk = devm_clk_get(&pdev->dev, "tbclk"); in ehrpwm_pwm_probe()
486 if (IS_ERR(pc->tbclk)) in ehrpwm_pwm_probe()
487 return dev_err_probe(&pdev->dev, PTR_ERR(pc->tbclk), "Failed to get tbclk\n"); in ehrpwm_pwm_probe()
489 ret = clk_prepare(pc->tbclk); in ehrpwm_pwm_probe()
491 dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret); in ehrpwm_pwm_probe()
497 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); in ehrpwm_pwm_probe()
502 pm_runtime_enable(&pdev->dev); in ehrpwm_pwm_probe()
507 clk_unprepare(pc->tbclk); in ehrpwm_pwm_probe()
519 clk_unprepare(pc->tbclk); in ehrpwm_pwm_remove()
521 pm_runtime_disable(&pdev->dev); in ehrpwm_pwm_remove()
530 pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL); in ehrpwm_pwm_save_context()
531 pc->ctx.tbprd = ehrpwm_read(pc->mmio_base, TBPRD); in ehrpwm_pwm_save_context()
532 pc->ctx.cmpa = ehrpwm_read(pc->mmio_base, CMPA); in ehrpwm_pwm_save_context()
533 pc->ctx.cmpb = ehrpwm_read(pc->mmio_base, CMPB); in ehrpwm_pwm_save_context()
534 pc->ctx.aqctla = ehrpwm_read(pc->mmio_base, AQCTLA); in ehrpwm_pwm_save_context()
535 pc->ctx.aqctlb = ehrpwm_read(pc->mmio_base, AQCTLB); in ehrpwm_pwm_save_context()
536 pc->ctx.aqsfrc = ehrpwm_read(pc->mmio_base, AQSFRC); in ehrpwm_pwm_save_context()
537 pc->ctx.aqcsfrc = ehrpwm_read(pc->mmio_base, AQCSFRC); in ehrpwm_pwm_save_context()
546 ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd); in ehrpwm_pwm_restore_context()
547 ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa); in ehrpwm_pwm_restore_context()
548 ehrpwm_write(pc->mmio_base, CMPB, pc->ctx.cmpb); in ehrpwm_pwm_restore_context()
549 ehrpwm_write(pc->mmio_base, AQCTLA, pc->ctx.aqctla); in ehrpwm_pwm_restore_context()
550 ehrpwm_write(pc->mmio_base, AQCTLB, pc->ctx.aqctlb); in ehrpwm_pwm_restore_context()
551 ehrpwm_write(pc->mmio_base, AQSFRC, pc->ctx.aqsfrc); in ehrpwm_pwm_restore_context()
552 ehrpwm_write(pc->mmio_base, AQCSFRC, pc->ctx.aqcsfrc); in ehrpwm_pwm_restore_context()
553 ehrpwm_write(pc->mmio_base, TBCTL, pc->ctx.tbctl); in ehrpwm_pwm_restore_context()
563 for (i = 0; i < chip->npwm; i++) { in ehrpwm_pwm_suspend()
564 struct pwm_device *pwm = &chip->pwms[i]; in ehrpwm_pwm_suspend() local
566 if (!pwm_is_enabled(pwm)) in ehrpwm_pwm_suspend()
569 /* Disable explicitly if PWM is running */ in ehrpwm_pwm_suspend()
581 for (i = 0; i < chip->npwm; i++) { in ehrpwm_pwm_resume()
582 struct pwm_device *pwm = &chip->pwms[i]; in ehrpwm_pwm_resume() local
584 if (!pwm_is_enabled(pwm)) in ehrpwm_pwm_resume()
587 /* Enable explicitly if PWM was running */ in ehrpwm_pwm_resume()
610 MODULE_DESCRIPTION("EHRPWM PWM driver");