Commit 0e2feb17dec9d97f6b44d5af872633f7ffba9ffb
Committed by
Thierry Reding
1 parent
0074b49b3f
Exists in
master
and in
20 other branches
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, |