Commit 0e2feb17dec9d97f6b44d5af872633f7ffba9ffb

Authored by Philip Avinash
Committed by Thierry Reding
1 parent 0074b49b3f

pwm: pwm-tiehrpwm: Low power sleep support

In low power modes of AM33XX platforms, peripherals power is cut off.
This patch supports low power sleep transition support for EHRPWM
driver.

Signed-off-by: Philip Avinash <avinashphilip@ti.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>

Showing 1 changed file with 83 additions and 0 deletions Side-by-side Diff

drivers/pwm/pwm-tiehrpwm.c
... ... @@ -113,6 +113,17 @@
113 113  
114 114 #define NUM_PWM_CHANNEL 2 /* EHRPWM channels */
115 115  
  116 +struct ehrpwm_context {
  117 + u16 tbctl;
  118 + u16 tbprd;
  119 + u16 cmpa;
  120 + u16 cmpb;
  121 + u16 aqctla;
  122 + u16 aqctlb;
  123 + u16 aqsfrc;
  124 + u16 aqcsfrc;
  125 +};
  126 +
116 127 struct ehrpwm_pwm_chip {
117 128 struct pwm_chip chip;
118 129 unsigned int clk_rate;
... ... @@ -120,6 +131,7 @@
120 131 unsigned long period_cycles[NUM_PWM_CHANNEL];
121 132 enum pwm_polarity polarity[NUM_PWM_CHANNEL];
122 133 struct clk *tbclk;
  134 + struct ehrpwm_context ctx;
123 135 };
124 136  
125 137 static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
... ... @@ -127,6 +139,11 @@
127 139 return container_of(chip, struct ehrpwm_pwm_chip, chip);
128 140 }
129 141  
  142 +static u16 ehrpwm_read(void *base, int offset)
  143 +{
  144 + return readw(base + offset);
  145 +}
  146 +
130 147 static void ehrpwm_write(void *base, int offset, unsigned int val)
131 148 {
132 149 writew(val & 0xFFFF, base + offset);
133 150  
... ... @@ -516,11 +533,77 @@
516 533 return pwmchip_remove(&pc->chip);
517 534 }
518 535  
  536 +void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
  537 +{
  538 + pm_runtime_get_sync(pc->chip.dev);
  539 + pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL);
  540 + pc->ctx.tbprd = ehrpwm_read(pc->mmio_base, TBPRD);
  541 + pc->ctx.cmpa = ehrpwm_read(pc->mmio_base, CMPA);
  542 + pc->ctx.cmpb = ehrpwm_read(pc->mmio_base, CMPB);
  543 + pc->ctx.aqctla = ehrpwm_read(pc->mmio_base, AQCTLA);
  544 + pc->ctx.aqctlb = ehrpwm_read(pc->mmio_base, AQCTLB);
  545 + pc->ctx.aqsfrc = ehrpwm_read(pc->mmio_base, AQSFRC);
  546 + pc->ctx.aqcsfrc = ehrpwm_read(pc->mmio_base, AQCSFRC);
  547 + pm_runtime_put_sync(pc->chip.dev);
  548 +}
  549 +
  550 +void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
  551 +{
  552 + ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd);
  553 + ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa);
  554 + ehrpwm_write(pc->mmio_base, CMPB, pc->ctx.cmpb);
  555 + ehrpwm_write(pc->mmio_base, AQCTLA, pc->ctx.aqctla);
  556 + ehrpwm_write(pc->mmio_base, AQCTLB, pc->ctx.aqctlb);
  557 + ehrpwm_write(pc->mmio_base, AQSFRC, pc->ctx.aqsfrc);
  558 + ehrpwm_write(pc->mmio_base, AQCSFRC, pc->ctx.aqcsfrc);
  559 + ehrpwm_write(pc->mmio_base, TBCTL, pc->ctx.tbctl);
  560 +}
  561 +
  562 +static int ehrpwm_pwm_suspend(struct device *dev)
  563 +{
  564 + struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
  565 + int i;
  566 +
  567 + ehrpwm_pwm_save_context(pc);
  568 + for (i = 0; i < pc->chip.npwm; i++) {
  569 + struct pwm_device *pwm = &pc->chip.pwms[i];
  570 +
  571 + if (!test_bit(PWMF_ENABLED, &pwm->flags))
  572 + continue;
  573 +
  574 + /* Disable explicitly if PWM is running */
  575 + pm_runtime_put_sync(dev);
  576 + }
  577 + return 0;
  578 +}
  579 +
  580 +static int ehrpwm_pwm_resume(struct device *dev)
  581 +{
  582 + struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
  583 + int i;
  584 +
  585 + for (i = 0; i < pc->chip.npwm; i++) {
  586 + struct pwm_device *pwm = &pc->chip.pwms[i];
  587 +
  588 + if (!test_bit(PWMF_ENABLED, &pwm->flags))
  589 + continue;
  590 +
  591 + /* Enable explicitly if PWM was running */
  592 + pm_runtime_get_sync(dev);
  593 + }
  594 + ehrpwm_pwm_restore_context(pc);
  595 + return 0;
  596 +}
  597 +
  598 +static SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
  599 + ehrpwm_pwm_resume);
  600 +
519 601 static struct platform_driver ehrpwm_pwm_driver = {
520 602 .driver = {
521 603 .name = "ehrpwm",
522 604 .owner = THIS_MODULE,
523 605 .of_match_table = ehrpwm_of_match,
  606 + .pm = &ehrpwm_pwm_pm_ops,
524 607 },
525 608 .probe = ehrpwm_pwm_probe,
526 609 .remove = ehrpwm_pwm_remove,