aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-tiecap.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-tiecap.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-tiecap.c')
-rw-r--r--drivers/pwm/pwm-tiecap.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 27a67d6b27c1..22e96e2bffd3 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -41,10 +41,17 @@
41#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6)) 41#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6))
42#define ECCTL2_TSCTR_FREERUN BIT(4) 42#define ECCTL2_TSCTR_FREERUN BIT(4)
43 43
44struct ecap_context {
45 u32 cap3;
46 u32 cap4;
47 u16 ecctl2;
48};
49
44struct ecap_pwm_chip { 50struct ecap_pwm_chip {
45 struct pwm_chip chip; 51 struct pwm_chip chip;
46 unsigned int clk_rate; 52 unsigned int clk_rate;
47 void __iomem *mmio_base; 53 void __iomem *mmio_base;
54 struct ecap_context ctx;
48}; 55};
49 56
50static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip) 57static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip)
@@ -288,11 +295,57 @@ static int ecap_pwm_remove(struct platform_device *pdev)
288 return pwmchip_remove(&pc->chip); 295 return pwmchip_remove(&pc->chip);
289} 296}
290 297
298void ecap_pwm_save_context(struct ecap_pwm_chip *pc)
299{
300 pm_runtime_get_sync(pc->chip.dev);
301 pc->ctx.ecctl2 = readw(pc->mmio_base + ECCTL2);
302 pc->ctx.cap4 = readl(pc->mmio_base + CAP4);
303 pc->ctx.cap3 = readl(pc->mmio_base + CAP3);
304 pm_runtime_put_sync(pc->chip.dev);
305}
306
307void ecap_pwm_restore_context(struct ecap_pwm_chip *pc)
308{
309 writel(pc->ctx.cap3, pc->mmio_base + CAP3);
310 writel(pc->ctx.cap4, pc->mmio_base + CAP4);
311 writew(pc->ctx.ecctl2, pc->mmio_base + ECCTL2);
312}
313
314static int ecap_pwm_suspend(struct device *dev)
315{
316 struct ecap_pwm_chip *pc = dev_get_drvdata(dev);
317 struct pwm_device *pwm = pc->chip.pwms;
318
319 ecap_pwm_save_context(pc);
320
321 /* Disable explicitly if PWM is running */
322 if (test_bit(PWMF_ENABLED, &pwm->flags))
323 pm_runtime_put_sync(dev);
324
325 return 0;
326}
327
328static int ecap_pwm_resume(struct device *dev)
329{
330 struct ecap_pwm_chip *pc = dev_get_drvdata(dev);
331 struct pwm_device *pwm = pc->chip.pwms;
332
333 /* Enable explicitly if PWM was running */
334 if (test_bit(PWMF_ENABLED, &pwm->flags))
335 pm_runtime_get_sync(dev);
336
337 ecap_pwm_restore_context(pc);
338 return 0;
339}
340
341static SIMPLE_DEV_PM_OPS(ecap_pwm_pm_ops, ecap_pwm_suspend, ecap_pwm_resume);
342
291static struct platform_driver ecap_pwm_driver = { 343static struct platform_driver ecap_pwm_driver = {
292 .driver = { 344 .driver = {
293 .name = "ecap", 345 .name = "ecap",
294 .owner = THIS_MODULE, 346 .owner = THIS_MODULE,
295 .of_match_table = ecap_of_match, 347 .of_match_table = ecap_of_match,
348 .pm = &ecap_pwm_pm_ops,
296 }, 349 },
297 .probe = ecap_pwm_probe, 350 .probe = ecap_pwm_probe,
298 .remove = ecap_pwm_remove, 351 .remove = ecap_pwm_remove,