aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-tiehrpwm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:34:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:34:29 -0500
commit3eb05225ee8efb81fe50558f5f9d94e7477ade8f (patch)
tree40692236718c808455f1fcdfbc1c6de6a274eb36 /drivers/pwm/pwm-tiehrpwm.c
parented5dc2372dba46e0ecd08791b1a0399d313e5cff (diff)
parent30f786170352b8264bc7b61c2482713e54accec8 (diff)
Merge tag 'for-3.9-rc1' of git://gitorious.org/linux-pwm/linux-pwm
Pull PWM changes from Thierry Reding: "A new driver has been added to support the PWM mode of the timer counter blocks found on Atmel AT91 SoCs. The VT8500 driver now supports changing the PWM signal polarity and the TI drivers (EHRPWM and ECAP) gained suspend and resume functionality. User drivers can now query the core for whether access to a PWM device will sleep (if the PWM chip is on a slow bus such as I2C or SPI). The pwm-backlight driver now handles the backlight BL_CORE_FBBLANK state in addition to the FB layer's blanking states. To round things off, a few fixes and cleanups are also included" * tag 'for-3.9-rc1' of git://gitorious.org/linux-pwm/linux-pwm: pwm: twl: Use to_twl() instead of container_of() pwm: tegra: assume CONFIG_OF pwm_backlight: Validate dft_brightness in main probe function pwm: Export pwm_{set,get}_chip_data() pwm: Make Kconfig entries more consistent pwm: Add can_sleep property to drivers pwm: Add pwm_can_sleep() as exported API to users pwm-backlight: handle BL_CORE_FBBLANK state pwm: pwm-tiecap: Low power sleep support pwm: pwm-tiehrpwm: Low power sleep support pwm: pwm-tiehrpwm: Update the clock handling of pwm-tiehrpwm driver pwm: vt8500: Add polarity support pwm: vt8500: Register write busy test performed incorrectly pwm: atmel: add Timer Counter Block PWM driver
Diffstat (limited to 'drivers/pwm/pwm-tiehrpwm.c')
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c93
1 files changed, 91 insertions, 2 deletions
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 5a1399580533..8b4c86fa99c8 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -113,6 +113,17 @@
113 113
114#define NUM_PWM_CHANNEL 2 /* EHRPWM channels */ 114#define NUM_PWM_CHANNEL 2 /* EHRPWM channels */
115 115
116struct 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
116struct ehrpwm_pwm_chip { 127struct ehrpwm_pwm_chip {
117 struct pwm_chip chip; 128 struct pwm_chip chip;
118 unsigned int clk_rate; 129 unsigned int clk_rate;
@@ -120,6 +131,7 @@ struct ehrpwm_pwm_chip {
120 unsigned long period_cycles[NUM_PWM_CHANNEL]; 131 unsigned long period_cycles[NUM_PWM_CHANNEL];
121 enum pwm_polarity polarity[NUM_PWM_CHANNEL]; 132 enum pwm_polarity polarity[NUM_PWM_CHANNEL];
122 struct clk *tbclk; 133 struct clk *tbclk;
134 struct ehrpwm_context ctx;
123}; 135};
124 136
125static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) 137static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -127,6 +139,11 @@ static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
127 return container_of(chip, struct ehrpwm_pwm_chip, chip); 139 return container_of(chip, struct ehrpwm_pwm_chip, chip);
128} 140}
129 141
142static u16 ehrpwm_read(void *base, int offset)
143{
144 return readw(base + offset);
145}
146
130static void ehrpwm_write(void *base, int offset, unsigned int val) 147static void ehrpwm_write(void *base, int offset, unsigned int val)
131{ 148{
132 writew(val & 0xFFFF, base + offset); 149 writew(val & 0xFFFF, base + offset);
@@ -318,6 +335,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
318{ 335{
319 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); 336 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
320 unsigned short aqcsfrc_val, aqcsfrc_mask; 337 unsigned short aqcsfrc_val, aqcsfrc_mask;
338 int ret;
321 339
322 /* Leave clock enabled on enabling PWM */ 340 /* Leave clock enabled on enabling PWM */
323 pm_runtime_get_sync(chip->dev); 341 pm_runtime_get_sync(chip->dev);
@@ -341,7 +359,12 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
341 configure_polarity(pc, pwm->hwpwm); 359 configure_polarity(pc, pwm->hwpwm);
342 360
343 /* Enable TBCLK before enabling PWM device */ 361 /* Enable TBCLK before enabling PWM device */
344 clk_enable(pc->tbclk); 362 ret = clk_prepare_enable(pc->tbclk);
363 if (ret) {
364 pr_err("Failed to enable TBCLK for %s\n",
365 dev_name(pc->chip.dev));
366 return ret;
367 }
345 368
346 /* Enable time counter for free_run */ 369 /* Enable time counter for free_run */
347 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); 370 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
@@ -372,7 +395,7 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
372 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); 395 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
373 396
374 /* Disabling TBCLK on PWM disable */ 397 /* Disabling TBCLK on PWM disable */
375 clk_disable(pc->tbclk); 398 clk_disable_unprepare(pc->tbclk);
376 399
377 /* Stop Time base counter */ 400 /* Stop Time base counter */
378 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); 401 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
@@ -510,11 +533,77 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev)
510 return pwmchip_remove(&pc->chip); 533 return pwmchip_remove(&pc->chip);
511} 534}
512 535
536void 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
550void 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
562static 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
580static 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
598static SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
599 ehrpwm_pwm_resume);
600
513static struct platform_driver ehrpwm_pwm_driver = { 601static struct platform_driver ehrpwm_pwm_driver = {
514 .driver = { 602 .driver = {
515 .name = "ehrpwm", 603 .name = "ehrpwm",
516 .owner = THIS_MODULE, 604 .owner = THIS_MODULE,
517 .of_match_table = ehrpwm_of_match, 605 .of_match_table = ehrpwm_of_match,
606 .pm = &ehrpwm_pwm_pm_ops,
518 }, 607 },
519 .probe = ehrpwm_pwm_probe, 608 .probe = ehrpwm_pwm_probe,
520 .remove = ehrpwm_pwm_remove, 609 .remove = ehrpwm_pwm_remove,