aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/Kconfig29
-rw-r--r--drivers/pwm/Makefile3
-rw-r--r--drivers/pwm/core.c82
-rw-r--r--drivers/pwm/pwm-ab8500.c153
-rw-r--r--drivers/pwm/pwm-bfin.c3
-rw-r--r--drivers/pwm/pwm-imx.c278
-rw-r--r--drivers/pwm/pwm-jz4740.c221
-rw-r--r--drivers/pwm/pwm-puv3.c161
-rw-r--r--drivers/pwm/pwm-pxa.c3
-rw-r--r--drivers/pwm/pwm-samsung.c3
-rw-r--r--drivers/pwm/pwm-tiecap.c24
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c75
12 files changed, 904 insertions, 131 deletions
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index d7c6b83097c1..ed81720e7b2b 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -1,6 +1,5 @@
1menuconfig PWM 1menuconfig PWM
2 bool "Pulse-Width Modulation (PWM) Support" 2 bool "Pulse-Width Modulation (PWM) Support"
3 depends on !MACH_JZ4740 && !PUV3_PWM
4 help 3 help
5 Generic Pulse-Width Modulation (PWM) support. 4 Generic Pulse-Width Modulation (PWM) support.
6 5
@@ -29,6 +28,15 @@ menuconfig PWM
29 28
30if PWM 29if PWM
31 30
31config PWM_AB8500
32 tristate "AB8500 PWM support"
33 depends on AB8500_CORE && ARCH_U8500
34 help
35 Generic PWM framework driver for Analog Baseband AB8500.
36
37 To compile this driver as a module, choose M here: the module
38 will be called pwm-ab8500.
39
32config PWM_BFIN 40config PWM_BFIN
33 tristate "Blackfin PWM support" 41 tristate "Blackfin PWM support"
34 depends on BFIN_GPTIMERS 42 depends on BFIN_GPTIMERS
@@ -47,6 +55,16 @@ config PWM_IMX
47 To compile this driver as a module, choose M here: the module 55 To compile this driver as a module, choose M here: the module
48 will be called pwm-imx. 56 will be called pwm-imx.
49 57
58config PWM_JZ4740
59 tristate "Ingenic JZ4740 PWM support"
60 depends on MACH_JZ4740
61 help
62 Generic PWM framework driver for Ingenic JZ4740 based
63 machines.
64
65 To compile this driver as a module, choose M here: the module
66 will be called pwm-jz4740.
67
50config PWM_LPC32XX 68config PWM_LPC32XX
51 tristate "LPC32XX PWM support" 69 tristate "LPC32XX PWM support"
52 depends on ARCH_LPC32XX 70 depends on ARCH_LPC32XX
@@ -67,6 +85,15 @@ config PWM_MXS
67 To compile this driver as a module, choose M here: the module 85 To compile this driver as a module, choose M here: the module
68 will be called pwm-mxs. 86 will be called pwm-mxs.
69 87
88config PWM_PUV3
89 tristate "PKUnity NetBook-0916 PWM support"
90 depends on ARCH_PUV3
91 help
92 Generic PWM framework driver for PKUnity NetBook-0916.
93
94 To compile this driver as a module, choose M here: the module
95 will be called pwm-puv3.
96
70config PWM_PXA 97config PWM_PXA
71 tristate "PXA PWM support" 98 tristate "PXA PWM support"
72 depends on ARCH_PXA 99 depends on ARCH_PXA
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 78f123dca30d..acfe4821c58b 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1,8 +1,11 @@
1obj-$(CONFIG_PWM) += core.o 1obj-$(CONFIG_PWM) += core.o
2obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
2obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o 3obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
3obj-$(CONFIG_PWM_IMX) += pwm-imx.o 4obj-$(CONFIG_PWM_IMX) += pwm-imx.o
5obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
4obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o 6obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
5obj-$(CONFIG_PWM_MXS) += pwm-mxs.o 7obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
8obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
6obj-$(CONFIG_PWM_PXA) += pwm-pxa.o 9obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
7obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o 10obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
8obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o 11obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index c6e05078d3ad..f5acdaa52707 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -371,7 +371,7 @@ EXPORT_SYMBOL_GPL(pwm_free);
371 */ 371 */
372int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) 372int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
373{ 373{
374 if (!pwm || period_ns == 0 || duty_ns > period_ns) 374 if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
375 return -EINVAL; 375 return -EINVAL;
376 376
377 return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); 377 return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
@@ -379,6 +379,28 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
379EXPORT_SYMBOL_GPL(pwm_config); 379EXPORT_SYMBOL_GPL(pwm_config);
380 380
381/** 381/**
382 * pwm_set_polarity() - configure the polarity of a PWM signal
383 * @pwm: PWM device
384 * @polarity: new polarity of the PWM signal
385 *
386 * Note that the polarity cannot be configured while the PWM device is enabled
387 */
388int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
389{
390 if (!pwm || !pwm->chip->ops)
391 return -EINVAL;
392
393 if (!pwm->chip->ops->set_polarity)
394 return -ENOSYS;
395
396 if (test_bit(PWMF_ENABLED, &pwm->flags))
397 return -EBUSY;
398
399 return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
400}
401EXPORT_SYMBOL_GPL(pwm_set_polarity);
402
403/**
382 * pwm_enable() - start a PWM output toggling 404 * pwm_enable() - start a PWM output toggling
383 * @pwm: PWM device 405 * @pwm: PWM device
384 */ 406 */
@@ -624,6 +646,64 @@ out:
624} 646}
625EXPORT_SYMBOL_GPL(pwm_put); 647EXPORT_SYMBOL_GPL(pwm_put);
626 648
649static void devm_pwm_release(struct device *dev, void *res)
650{
651 pwm_put(*(struct pwm_device **)res);
652}
653
654/**
655 * devm_pwm_get() - resource managed pwm_get()
656 * @dev: device for PWM consumer
657 * @con_id: consumer name
658 *
659 * This function performs like pwm_get() but the acquired PWM device will
660 * automatically be released on driver detach.
661 */
662struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id)
663{
664 struct pwm_device **ptr, *pwm;
665
666 ptr = devres_alloc(devm_pwm_release, sizeof(**ptr), GFP_KERNEL);
667 if (!ptr)
668 return ERR_PTR(-ENOMEM);
669
670 pwm = pwm_get(dev, con_id);
671 if (!IS_ERR(pwm)) {
672 *ptr = pwm;
673 devres_add(dev, ptr);
674 } else {
675 devres_free(ptr);
676 }
677
678 return pwm;
679}
680EXPORT_SYMBOL_GPL(devm_pwm_get);
681
682static int devm_pwm_match(struct device *dev, void *res, void *data)
683{
684 struct pwm_device **p = res;
685
686 if (WARN_ON(!p || !*p))
687 return 0;
688
689 return *p == data;
690}
691
692/**
693 * devm_pwm_put() - resource managed pwm_put()
694 * @dev: device for PWM consumer
695 * @pwm: PWM device
696 *
697 * Release a PWM previously allocated using devm_pwm_get(). Calling this
698 * function is usually not needed because devm-allocated resources are
699 * automatically released on driver detach.
700 */
701void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
702{
703 WARN_ON(devres_release(dev, devm_pwm_release, devm_pwm_match, pwm));
704}
705EXPORT_SYMBOL_GPL(devm_pwm_put);
706
627#ifdef CONFIG_DEBUG_FS 707#ifdef CONFIG_DEBUG_FS
628static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) 708static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
629{ 709{
diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
new file mode 100644
index 000000000000..cfb72ca873d1
--- /dev/null
+++ b/drivers/pwm/pwm-ab8500.c
@@ -0,0 +1,153 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * Author: Arun R Murthy <arun.murthy@stericsson.com>
5 * License terms: GNU General Public License (GPL) version 2
6 */
7#include <linux/err.h>
8#include <linux/platform_device.h>
9#include <linux/slab.h>
10#include <linux/pwm.h>
11#include <linux/mfd/abx500.h>
12#include <linux/mfd/abx500/ab8500.h>
13#include <linux/module.h>
14
15/*
16 * PWM Out generators
17 * Bank: 0x10
18 */
19#define AB8500_PWM_OUT_CTRL1_REG 0x60
20#define AB8500_PWM_OUT_CTRL2_REG 0x61
21#define AB8500_PWM_OUT_CTRL7_REG 0x66
22
23/* backlight driver constants */
24#define ENABLE_PWM 1
25#define DISABLE_PWM 0
26
27struct ab8500_pwm_chip {
28 struct pwm_chip chip;
29};
30
31static int ab8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
32 int duty_ns, int period_ns)
33{
34 int ret = 0;
35 unsigned int higher_val, lower_val;
36 u8 reg;
37
38 /*
39 * get the first 8 bits that are be written to
40 * AB8500_PWM_OUT_CTRL1_REG[0:7]
41 */
42 lower_val = duty_ns & 0x00FF;
43 /*
44 * get bits [9:10] that are to be written to
45 * AB8500_PWM_OUT_CTRL2_REG[0:1]
46 */
47 higher_val = ((duty_ns & 0x0300) >> 8);
48
49 reg = AB8500_PWM_OUT_CTRL1_REG + ((chip->base - 1) * 2);
50
51 ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
52 reg, (u8)lower_val);
53 if (ret < 0)
54 return ret;
55 ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
56 (reg + 1), (u8)higher_val);
57
58 return ret;
59}
60
61static int ab8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
62{
63 int ret;
64
65 ret = abx500_mask_and_set_register_interruptible(chip->dev,
66 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
67 1 << (chip->base - 1), ENABLE_PWM);
68 if (ret < 0)
69 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
70 pwm->label, ret);
71 return ret;
72}
73
74static void ab8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
75{
76 int ret;
77
78 ret = abx500_mask_and_set_register_interruptible(chip->dev,
79 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
80 1 << (chip->base - 1), DISABLE_PWM);
81 if (ret < 0)
82 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
83 pwm->label, ret);
84 return;
85}
86
87static const struct pwm_ops ab8500_pwm_ops = {
88 .config = ab8500_pwm_config,
89 .enable = ab8500_pwm_enable,
90 .disable = ab8500_pwm_disable,
91};
92
93static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
94{
95 struct ab8500_pwm_chip *ab8500;
96 int err;
97
98 /*
99 * Nothing to be done in probe, this is required to get the
100 * device which is required for ab8500 read and write
101 */
102 ab8500 = kzalloc(sizeof(*ab8500), GFP_KERNEL);
103 if (ab8500 == NULL) {
104 dev_err(&pdev->dev, "failed to allocate memory\n");
105 return -ENOMEM;
106 }
107
108 ab8500->chip.dev = &pdev->dev;
109 ab8500->chip.ops = &ab8500_pwm_ops;
110 ab8500->chip.base = pdev->id;
111 ab8500->chip.npwm = 1;
112
113 err = pwmchip_add(&ab8500->chip);
114 if (err < 0) {
115 kfree(ab8500);
116 return err;
117 }
118
119 dev_dbg(&pdev->dev, "pwm probe successful\n");
120 platform_set_drvdata(pdev, ab8500);
121
122 return 0;
123}
124
125static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
126{
127 struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
128 int err;
129
130 err = pwmchip_remove(&ab8500->chip);
131 if (err < 0)
132 return err;
133
134 dev_dbg(&pdev->dev, "pwm driver removed\n");
135 kfree(ab8500);
136
137 return 0;
138}
139
140static struct platform_driver ab8500_pwm_driver = {
141 .driver = {
142 .name = "ab8500-pwm",
143 .owner = THIS_MODULE,
144 },
145 .probe = ab8500_pwm_probe,
146 .remove = __devexit_p(ab8500_pwm_remove),
147};
148module_platform_driver(ab8500_pwm_driver);
149
150MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>");
151MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
152MODULE_ALIAS("platform:ab8500-pwm");
153MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c
index d53c4e7941ef..5da8e185e838 100644
--- a/drivers/pwm/pwm-bfin.c
+++ b/drivers/pwm/pwm-bfin.c
@@ -69,9 +69,6 @@ static int bfin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
69 unsigned long period, duty; 69 unsigned long period, duty;
70 unsigned long long val; 70 unsigned long long val;
71 71
72 if (duty_ns < 0 || duty_ns > period_ns)
73 return -EINVAL;
74
75 val = (unsigned long long)get_sclk() * period_ns; 72 val = (unsigned long long)get_sclk() * period_ns;
76 do_div(val, NSEC_PER_SEC); 73 do_div(val, NSEC_PER_SEC);
77 period = val; 74 period = val;
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 2a0b35333972..8a5d3ae2946a 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -16,8 +16,7 @@
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/pwm.h> 18#include <linux/pwm.h>
19#include <mach/hardware.h> 19#include <linux/of_device.h>
20
21 20
22/* i.MX1 and i.MX21 share the same PWM function block: */ 21/* i.MX1 and i.MX21 share the same PWM function block: */
23 22
@@ -25,6 +24,7 @@
25#define MX1_PWMS 0x04 /* PWM Sample Register */ 24#define MX1_PWMS 0x04 /* PWM Sample Register */
26#define MX1_PWMP 0x08 /* PWM Period Register */ 25#define MX1_PWMP 0x08 /* PWM Period Register */
27 26
27#define MX1_PWMC_EN (1 << 4)
28 28
29/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */ 29/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
30 30
@@ -40,110 +40,165 @@
40#define MX3_PWMCR_EN (1 << 0) 40#define MX3_PWMCR_EN (1 << 0)
41 41
42struct imx_chip { 42struct imx_chip {
43 struct clk *clk; 43 struct clk *clk_per;
44 struct clk *clk_ipg;
44 45
45 int clk_enabled; 46 int enabled;
46 void __iomem *mmio_base; 47 void __iomem *mmio_base;
47 48
48 struct pwm_chip chip; 49 struct pwm_chip chip;
50
51 int (*config)(struct pwm_chip *chip,
52 struct pwm_device *pwm, int duty_ns, int period_ns);
53 void (*set_enable)(struct pwm_chip *chip, bool enable);
49}; 54};
50 55
51#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip) 56#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip)
52 57
53static int imx_pwm_config(struct pwm_chip *chip, 58static int imx_pwm_config_v1(struct pwm_chip *chip,
54 struct pwm_device *pwm, int duty_ns, int period_ns) 59 struct pwm_device *pwm, int duty_ns, int period_ns)
55{ 60{
56 struct imx_chip *imx = to_imx_chip(chip); 61 struct imx_chip *imx = to_imx_chip(chip);
57 62
58 if (!(cpu_is_mx1() || cpu_is_mx21())) { 63 /*
59 unsigned long long c; 64 * The PWM subsystem allows for exact frequencies. However,
60 unsigned long period_cycles, duty_cycles, prescale; 65 * I cannot connect a scope on my device to the PWM line and
61 u32 cr; 66 * thus cannot provide the program the PWM controller
62 67 * exactly. Instead, I'm relying on the fact that the
63 c = clk_get_rate(imx->clk); 68 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
64 c = c * period_ns; 69 * function group already. So I'll just modify the PWM sample
65 do_div(c, 1000000000); 70 * register to follow the ratio of duty_ns vs. period_ns
66 period_cycles = c; 71 * accordingly.
67 72 *
68 prescale = period_cycles / 0x10000 + 1; 73 * This is good enough for programming the brightness of
69 74 * the LCD backlight.
70 period_cycles /= prescale; 75 *
71 c = (unsigned long long)period_cycles * duty_ns; 76 * The real implementation would divide PERCLK[0] first by
72 do_div(c, period_ns); 77 * both the prescaler (/1 .. /128) and then by CLKSEL
73 duty_cycles = c; 78 * (/2 .. /16).
74 79 */
75 /* 80 u32 max = readl(imx->mmio_base + MX1_PWMP);
76 * according to imx pwm RM, the real period value should be 81 u32 p = max * duty_ns / period_ns;
77 * PERIOD value in PWMPR plus 2. 82 writel(max - p, imx->mmio_base + MX1_PWMS);
78 */
79 if (period_cycles > 2)
80 period_cycles -= 2;
81 else
82 period_cycles = 0;
83
84 writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
85 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
86
87 cr = MX3_PWMCR_PRESCALER(prescale) |
88 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
89 MX3_PWMCR_DBGEN | MX3_PWMCR_EN;
90
91 if (cpu_is_mx25())
92 cr |= MX3_PWMCR_CLKSRC_IPG;
93 else
94 cr |= MX3_PWMCR_CLKSRC_IPG_HIGH;
95
96 writel(cr, imx->mmio_base + MX3_PWMCR);
97 } else if (cpu_is_mx1() || cpu_is_mx21()) {
98 /* The PWM subsystem allows for exact frequencies. However,
99 * I cannot connect a scope on my device to the PWM line and
100 * thus cannot provide the program the PWM controller
101 * exactly. Instead, I'm relying on the fact that the
102 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
103 * function group already. So I'll just modify the PWM sample
104 * register to follow the ratio of duty_ns vs. period_ns
105 * accordingly.
106 *
107 * This is good enough for programming the brightness of
108 * the LCD backlight.
109 *
110 * The real implementation would divide PERCLK[0] first by
111 * both the prescaler (/1 .. /128) and then by CLKSEL
112 * (/2 .. /16).
113 */
114 u32 max = readl(imx->mmio_base + MX1_PWMP);
115 u32 p = max * duty_ns / period_ns;
116 writel(max - p, imx->mmio_base + MX1_PWMS);
117 } else {
118 BUG();
119 }
120 83
121 return 0; 84 return 0;
122} 85}
123 86
87static void imx_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
88{
89 struct imx_chip *imx = to_imx_chip(chip);
90 u32 val;
91
92 val = readl(imx->mmio_base + MX1_PWMC);
93
94 if (enable)
95 val |= MX1_PWMC_EN;
96 else
97 val &= ~MX1_PWMC_EN;
98
99 writel(val, imx->mmio_base + MX1_PWMC);
100}
101
102static int imx_pwm_config_v2(struct pwm_chip *chip,
103 struct pwm_device *pwm, int duty_ns, int period_ns)
104{
105 struct imx_chip *imx = to_imx_chip(chip);
106 unsigned long long c;
107 unsigned long period_cycles, duty_cycles, prescale;
108 u32 cr;
109
110 c = clk_get_rate(imx->clk_per);
111 c = c * period_ns;
112 do_div(c, 1000000000);
113 period_cycles = c;
114
115 prescale = period_cycles / 0x10000 + 1;
116
117 period_cycles /= prescale;
118 c = (unsigned long long)period_cycles * duty_ns;
119 do_div(c, period_ns);
120 duty_cycles = c;
121
122 /*
123 * according to imx pwm RM, the real period value should be
124 * PERIOD value in PWMPR plus 2.
125 */
126 if (period_cycles > 2)
127 period_cycles -= 2;
128 else
129 period_cycles = 0;
130
131 writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
132 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
133
134 cr = MX3_PWMCR_PRESCALER(prescale) |
135 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
136 MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
137
138 if (imx->enabled)
139 cr |= MX3_PWMCR_EN;
140
141 writel(cr, imx->mmio_base + MX3_PWMCR);
142
143 return 0;
144}
145
146static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
147{
148 struct imx_chip *imx = to_imx_chip(chip);
149 u32 val;
150
151 val = readl(imx->mmio_base + MX3_PWMCR);
152
153 if (enable)
154 val |= MX3_PWMCR_EN;
155 else
156 val &= ~MX3_PWMCR_EN;
157
158 writel(val, imx->mmio_base + MX3_PWMCR);
159}
160
161static int imx_pwm_config(struct pwm_chip *chip,
162 struct pwm_device *pwm, int duty_ns, int period_ns)
163{
164 struct imx_chip *imx = to_imx_chip(chip);
165 int ret;
166
167 ret = clk_prepare_enable(imx->clk_ipg);
168 if (ret)
169 return ret;
170
171 ret = imx->config(chip, pwm, duty_ns, period_ns);
172
173 clk_disable_unprepare(imx->clk_ipg);
174
175 return ret;
176}
177
124static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 178static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
125{ 179{
126 struct imx_chip *imx = to_imx_chip(chip); 180 struct imx_chip *imx = to_imx_chip(chip);
127 int rc = 0; 181 int ret;
128 182
129 if (!imx->clk_enabled) { 183 ret = clk_prepare_enable(imx->clk_per);
130 rc = clk_prepare_enable(imx->clk); 184 if (ret)
131 if (!rc) 185 return ret;
132 imx->clk_enabled = 1; 186
133 } 187 imx->set_enable(chip, true);
134 return rc; 188
189 imx->enabled = 1;
190
191 return 0;
135} 192}
136 193
137static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 194static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
138{ 195{
139 struct imx_chip *imx = to_imx_chip(chip); 196 struct imx_chip *imx = to_imx_chip(chip);
140 197
141 writel(0, imx->mmio_base + MX3_PWMCR); 198 imx->set_enable(chip, false);
142 199
143 if (imx->clk_enabled) { 200 clk_disable_unprepare(imx->clk_per);
144 clk_disable_unprepare(imx->clk); 201 imx->enabled = 0;
145 imx->clk_enabled = 0;
146 }
147} 202}
148 203
149static struct pwm_ops imx_pwm_ops = { 204static struct pwm_ops imx_pwm_ops = {
@@ -153,30 +208,66 @@ static struct pwm_ops imx_pwm_ops = {
153 .owner = THIS_MODULE, 208 .owner = THIS_MODULE,
154}; 209};
155 210
211struct imx_pwm_data {
212 int (*config)(struct pwm_chip *chip,
213 struct pwm_device *pwm, int duty_ns, int period_ns);
214 void (*set_enable)(struct pwm_chip *chip, bool enable);
215};
216
217static struct imx_pwm_data imx_pwm_data_v1 = {
218 .config = imx_pwm_config_v1,
219 .set_enable = imx_pwm_set_enable_v1,
220};
221
222static struct imx_pwm_data imx_pwm_data_v2 = {
223 .config = imx_pwm_config_v2,
224 .set_enable = imx_pwm_set_enable_v2,
225};
226
227static const struct of_device_id imx_pwm_dt_ids[] = {
228 { .compatible = "fsl,imx1-pwm", .data = &imx_pwm_data_v1, },
229 { .compatible = "fsl,imx27-pwm", .data = &imx_pwm_data_v2, },
230 { /* sentinel */ }
231};
232MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
233
156static int __devinit imx_pwm_probe(struct platform_device *pdev) 234static int __devinit imx_pwm_probe(struct platform_device *pdev)
157{ 235{
236 const struct of_device_id *of_id =
237 of_match_device(imx_pwm_dt_ids, &pdev->dev);
238 struct imx_pwm_data *data;
158 struct imx_chip *imx; 239 struct imx_chip *imx;
159 struct resource *r; 240 struct resource *r;
160 int ret = 0; 241 int ret = 0;
161 242
243 if (!of_id)
244 return -ENODEV;
245
162 imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL); 246 imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
163 if (imx == NULL) { 247 if (imx == NULL) {
164 dev_err(&pdev->dev, "failed to allocate memory\n"); 248 dev_err(&pdev->dev, "failed to allocate memory\n");
165 return -ENOMEM; 249 return -ENOMEM;
166 } 250 }
167 251
168 imx->clk = devm_clk_get(&pdev->dev, "pwm"); 252 imx->clk_per = devm_clk_get(&pdev->dev, "per");
253 if (IS_ERR(imx->clk_per)) {
254 dev_err(&pdev->dev, "getting per clock failed with %ld\n",
255 PTR_ERR(imx->clk_per));
256 return PTR_ERR(imx->clk_per);
257 }
169 258
170 if (IS_ERR(imx->clk)) 259 imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
171 return PTR_ERR(imx->clk); 260 if (IS_ERR(imx->clk_ipg)) {
261 dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
262 PTR_ERR(imx->clk_ipg));
263 return PTR_ERR(imx->clk_ipg);
264 }
172 265
173 imx->chip.ops = &imx_pwm_ops; 266 imx->chip.ops = &imx_pwm_ops;
174 imx->chip.dev = &pdev->dev; 267 imx->chip.dev = &pdev->dev;
175 imx->chip.base = -1; 268 imx->chip.base = -1;
176 imx->chip.npwm = 1; 269 imx->chip.npwm = 1;
177 270
178 imx->clk_enabled = 0;
179
180 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 271 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
181 if (r == NULL) { 272 if (r == NULL) {
182 dev_err(&pdev->dev, "no memory resource defined\n"); 273 dev_err(&pdev->dev, "no memory resource defined\n");
@@ -187,6 +278,10 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
187 if (imx->mmio_base == NULL) 278 if (imx->mmio_base == NULL)
188 return -EADDRNOTAVAIL; 279 return -EADDRNOTAVAIL;
189 280
281 data = of_id->data;
282 imx->config = data->config;
283 imx->set_enable = data->set_enable;
284
190 ret = pwmchip_add(&imx->chip); 285 ret = pwmchip_add(&imx->chip);
191 if (ret < 0) 286 if (ret < 0)
192 return ret; 287 return ret;
@@ -208,23 +303,14 @@ static int __devexit imx_pwm_remove(struct platform_device *pdev)
208 303
209static struct platform_driver imx_pwm_driver = { 304static struct platform_driver imx_pwm_driver = {
210 .driver = { 305 .driver = {
211 .name = "mxc_pwm", 306 .name = "imx-pwm",
307 .of_match_table = of_match_ptr(imx_pwm_dt_ids),
212 }, 308 },
213 .probe = imx_pwm_probe, 309 .probe = imx_pwm_probe,
214 .remove = __devexit_p(imx_pwm_remove), 310 .remove = __devexit_p(imx_pwm_remove),
215}; 311};
216 312
217static int __init imx_pwm_init(void) 313module_platform_driver(imx_pwm_driver);
218{
219 return platform_driver_register(&imx_pwm_driver);
220}
221arch_initcall(imx_pwm_init);
222
223static void __exit imx_pwm_exit(void)
224{
225 platform_driver_unregister(&imx_pwm_driver);
226}
227module_exit(imx_pwm_exit);
228 314
229MODULE_LICENSE("GPL v2"); 315MODULE_LICENSE("GPL v2");
230MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 316MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
new file mode 100644
index 000000000000..10250fcefb98
--- /dev/null
+++ b/drivers/pwm/pwm-jz4740.c
@@ -0,0 +1,221 @@
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 platform PWM support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/clk.h>
17#include <linux/err.h>
18#include <linux/gpio.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/pwm.h>
23
24#include <asm/mach-jz4740/gpio.h>
25#include <asm/mach-jz4740/timer.h>
26
27#define NUM_PWM 8
28
29static const unsigned int jz4740_pwm_gpio_list[NUM_PWM] = {
30 JZ_GPIO_PWM0,
31 JZ_GPIO_PWM1,
32 JZ_GPIO_PWM2,
33 JZ_GPIO_PWM3,
34 JZ_GPIO_PWM4,
35 JZ_GPIO_PWM5,
36 JZ_GPIO_PWM6,
37 JZ_GPIO_PWM7,
38};
39
40struct jz4740_pwm_chip {
41 struct pwm_chip chip;
42 struct clk *clk;
43};
44
45static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
46{
47 return container_of(chip, struct jz4740_pwm_chip, chip);
48}
49
50static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
51{
52 unsigned int gpio = jz4740_pwm_gpio_list[pwm->hwpwm];
53 int ret;
54
55 /*
56 * Timers 0 and 1 are used for system tasks, so they are unavailable
57 * for use as PWMs.
58 */
59 if (pwm->hwpwm < 2)
60 return -EBUSY;
61
62 ret = gpio_request(gpio, pwm->label);
63 if (ret) {
64 dev_err(chip->dev, "Failed to request GPIO#%u for PWM: %d\n",
65 gpio, ret);
66 return ret;
67 }
68
69 jz_gpio_set_function(gpio, JZ_GPIO_FUNC_PWM);
70
71 jz4740_timer_start(pwm->hwpwm);
72
73 return 0;
74}
75
76static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
77{
78 unsigned int gpio = jz4740_pwm_gpio_list[pwm->hwpwm];
79
80 jz4740_timer_set_ctrl(pwm->hwpwm, 0);
81
82 jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
83 gpio_free(gpio);
84
85 jz4740_timer_stop(pwm->hwpwm);
86}
87
88static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
89{
90 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
91
92 ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
93 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
94 jz4740_timer_enable(pwm->hwpwm);
95
96 return 0;
97}
98
99static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
100{
101 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm);
102
103 ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
104 jz4740_timer_disable(pwm->hwpwm);
105 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
106}
107
108static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
109 int duty_ns, int period_ns)
110{
111 struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
112 unsigned long long tmp;
113 unsigned long period, duty;
114 unsigned int prescaler = 0;
115 uint16_t ctrl;
116 bool is_enabled;
117
118 tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns;
119 do_div(tmp, 1000000000);
120 period = tmp;
121
122 while (period > 0xffff && prescaler < 6) {
123 period >>= 2;
124 ++prescaler;
125 }
126
127 if (prescaler == 6)
128 return -EINVAL;
129
130 tmp = (unsigned long long)period * duty_ns;
131 do_div(tmp, period_ns);
132 duty = period - tmp;
133
134 if (duty >= period)
135 duty = period - 1;
136
137 is_enabled = jz4740_timer_is_enabled(pwm->hwpwm);
138 if (is_enabled)
139 jz4740_pwm_disable(chip, pwm);
140
141 jz4740_timer_set_count(pwm->hwpwm, 0);
142 jz4740_timer_set_duty(pwm->hwpwm, duty);
143 jz4740_timer_set_period(pwm->hwpwm, period);
144
145 ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
146 JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
147
148 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
149
150 if (is_enabled)
151 jz4740_pwm_enable(chip, pwm);
152
153 return 0;
154}
155
156static const struct pwm_ops jz4740_pwm_ops = {
157 .request = jz4740_pwm_request,
158 .free = jz4740_pwm_free,
159 .config = jz4740_pwm_config,
160 .enable = jz4740_pwm_enable,
161 .disable = jz4740_pwm_disable,
162 .owner = THIS_MODULE,
163};
164
165static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
166{
167 struct jz4740_pwm_chip *jz4740;
168 int ret;
169
170 jz4740 = devm_kzalloc(&pdev->dev, sizeof(*jz4740), GFP_KERNEL);
171 if (!jz4740)
172 return -ENOMEM;
173
174 jz4740->clk = clk_get(NULL, "ext");
175 if (IS_ERR(jz4740->clk))
176 return PTR_ERR(jz4740->clk);
177
178 jz4740->chip.dev = &pdev->dev;
179 jz4740->chip.ops = &jz4740_pwm_ops;
180 jz4740->chip.npwm = NUM_PWM;
181 jz4740->chip.base = -1;
182
183 ret = pwmchip_add(&jz4740->chip);
184 if (ret < 0) {
185 clk_put(jz4740->clk);
186 return ret;
187 }
188
189 platform_set_drvdata(pdev, jz4740);
190
191 return 0;
192}
193
194static int __devexit jz4740_pwm_remove(struct platform_device *pdev)
195{
196 struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
197 int ret;
198
199 ret = pwmchip_remove(&jz4740->chip);
200 if (ret < 0)
201 return ret;
202
203 clk_put(jz4740->clk);
204
205 return 0;
206}
207
208static struct platform_driver jz4740_pwm_driver = {
209 .driver = {
210 .name = "jz4740-pwm",
211 .owner = THIS_MODULE,
212 },
213 .probe = jz4740_pwm_probe,
214 .remove = __devexit_p(jz4740_pwm_remove),
215};
216module_platform_driver(jz4740_pwm_driver);
217
218MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
219MODULE_DESCRIPTION("Ingenic JZ4740 PWM driver");
220MODULE_ALIAS("platform:jz4740-pwm");
221MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
new file mode 100644
index 000000000000..2a93f37c46ad
--- /dev/null
+++ b/drivers/pwm/pwm-puv3.c
@@ -0,0 +1,161 @@
1/*
2 * linux/arch/unicore32/kernel/pwm.c
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
7 * Copyright (C) 2001-2010 Guan Xuetao
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18#include <linux/err.h>
19#include <linux/clk.h>
20#include <linux/io.h>
21#include <linux/pwm.h>
22
23#include <asm/div64.h>
24#include <mach/hardware.h>
25
26struct puv3_pwm_chip {
27 struct pwm_chip chip;
28 void __iomem *base;
29 struct clk *clk;
30 bool enabled;
31};
32
33static inline struct puv3_pwm_chip *to_puv3(struct pwm_chip *chip)
34{
35 return container_of(chip, struct puv3_pwm_chip, chip);
36}
37
38/*
39 * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
40 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
41 */
42static int puv3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
43 int duty_ns, int period_ns)
44{
45 unsigned long period_cycles, prescale, pv, dc;
46 struct puv3_pwm_chip *puv3 = to_puv3(chip);
47 unsigned long long c;
48
49 c = clk_get_rate(puv3->clk);
50 c = c * period_ns;
51 do_div(c, 1000000000);
52 period_cycles = c;
53
54 if (period_cycles < 1)
55 period_cycles = 1;
56
57 prescale = (period_cycles - 1) / 1024;
58 pv = period_cycles / (prescale + 1) - 1;
59
60 if (prescale > 63)
61 return -EINVAL;
62
63 if (duty_ns == period_ns)
64 dc = OST_PWMDCCR_FDCYCLE;
65 else
66 dc = (pv + 1) * duty_ns / period_ns;
67
68 /*
69 * NOTE: the clock to PWM has to be enabled first
70 * before writing to the registers
71 */
72 clk_prepare_enable(puv3->clk);
73
74 writel(prescale, puv3->base + OST_PWM_PWCR);
75 writel(pv - dc, puv3->base + OST_PWM_DCCR);
76 writel(pv, puv3->base + OST_PWM_PCR);
77
78 clk_disable_unprepare(puv3->clk);
79
80 return 0;
81}
82
83static int puv3_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
84{
85 struct puv3_pwm_chip *puv3 = to_puv3(chip);
86
87 return clk_prepare_enable(puv3->clk);
88}
89
90static void puv3_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
91{
92 struct puv3_pwm_chip *puv3 = to_puv3(chip);
93
94 clk_disable_unprepare(puv3->clk);
95}
96
97static const struct pwm_ops puv3_pwm_ops = {
98 .config = puv3_pwm_config,
99 .enable = puv3_pwm_enable,
100 .disable = puv3_pwm_disable,
101 .owner = THIS_MODULE,
102};
103
104static int __devinit pwm_probe(struct platform_device *pdev)
105{
106 struct puv3_pwm_chip *puv3;
107 struct resource *r;
108 int ret;
109
110 puv3 = devm_kzalloc(&pdev->dev, sizeof(*puv3), GFP_KERNEL);
111 if (puv3 == NULL) {
112 dev_err(&pdev->dev, "failed to allocate memory\n");
113 return -ENOMEM;
114 }
115
116 puv3->clk = devm_clk_get(&pdev->dev, "OST_CLK");
117 if (IS_ERR(puv3->clk))
118 return PTR_ERR(puv3->clk);
119
120 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
121 if (r == NULL) {
122 dev_err(&pdev->dev, "no memory resource defined\n");
123 return -ENODEV;
124 }
125
126 puv3->base = devm_request_and_ioremap(&pdev->dev, r);
127 if (puv3->base == NULL)
128 return -EADDRNOTAVAIL;
129
130 puv3->chip.dev = &pdev->dev;
131 puv3->chip.ops = &puv3_pwm_ops;
132 puv3->chip.base = -1;
133 puv3->chip.npwm = 1;
134
135 ret = pwmchip_add(&puv3->chip);
136 if (ret < 0) {
137 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
138 return ret;
139 }
140
141 platform_set_drvdata(pdev, puv3);
142 return 0;
143}
144
145static int __devexit pwm_remove(struct platform_device *pdev)
146{
147 struct puv3_pwm_chip *puv3 = platform_get_drvdata(pdev);
148
149 return pwmchip_remove(&puv3->chip);
150}
151
152static struct platform_driver puv3_pwm_driver = {
153 .driver = {
154 .name = "PKUnity-v3-PWM",
155 },
156 .probe = pwm_probe,
157 .remove = __devexit_p(pwm_remove),
158};
159module_platform_driver(puv3_pwm_driver);
160
161MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index bd5867a1c700..260c3a88564d 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -70,9 +70,6 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
70 unsigned long offset; 70 unsigned long offset;
71 int rc; 71 int rc;
72 72
73 if (period_ns == 0 || duty_ns > period_ns)
74 return -EINVAL;
75
76 offset = pwm->hwpwm ? 0x10 : 0; 73 offset = pwm->hwpwm ? 0x10 : 0;
77 74
78 c = clk_get_rate(pc->clk); 75 c = clk_get_rate(pc->clk);
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index e5187c0ade9f..023a3bee76e7 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -126,9 +126,6 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
126 if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ) 126 if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ)
127 return -ERANGE; 127 return -ERANGE;
128 128
129 if (duty_ns > period_ns)
130 return -EINVAL;
131
132 if (period_ns == s3c->period_ns && 129 if (period_ns == s3c->period_ns &&
133 duty_ns == s3c->duty_ns) 130 duty_ns == s3c->duty_ns)
134 return 0; 131 return 0;
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 4b6688909fee..d6d4cf05565e 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -32,6 +32,7 @@
32#define CAP3 0x10 32#define CAP3 0x10
33#define CAP4 0x14 33#define CAP4 0x14
34#define ECCTL2 0x2A 34#define ECCTL2 0x2A
35#define ECCTL2_APWM_POL_LOW BIT(10)
35#define ECCTL2_APWM_MODE BIT(9) 36#define ECCTL2_APWM_MODE BIT(9)
36#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6)) 37#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6))
37#define ECCTL2_TSCTR_FREERUN BIT(4) 38#define ECCTL2_TSCTR_FREERUN BIT(4)
@@ -59,7 +60,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
59 unsigned long period_cycles, duty_cycles; 60 unsigned long period_cycles, duty_cycles;
60 unsigned int reg_val; 61 unsigned int reg_val;
61 62
62 if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) 63 if (period_ns > NSEC_PER_SEC)
63 return -ERANGE; 64 return -ERANGE;
64 65
65 c = pc->clk_rate; 66 c = pc->clk_rate;
@@ -111,6 +112,26 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
111 return 0; 112 return 0;
112} 113}
113 114
115static int ecap_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
116 enum pwm_polarity polarity)
117{
118 struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
119 unsigned short reg_val;
120
121 pm_runtime_get_sync(pc->chip.dev);
122 reg_val = readw(pc->mmio_base + ECCTL2);
123 if (polarity == PWM_POLARITY_INVERSED)
124 /* Duty cycle defines LOW period of PWM */
125 reg_val |= ECCTL2_APWM_POL_LOW;
126 else
127 /* Duty cycle defines HIGH period of PWM */
128 reg_val &= ~ECCTL2_APWM_POL_LOW;
129
130 writew(reg_val, pc->mmio_base + ECCTL2);
131 pm_runtime_put_sync(pc->chip.dev);
132 return 0;
133}
134
114static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 135static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
115{ 136{
116 struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); 137 struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
@@ -157,6 +178,7 @@ static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
157static const struct pwm_ops ecap_pwm_ops = { 178static const struct pwm_ops ecap_pwm_ops = {
158 .free = ecap_pwm_free, 179 .free = ecap_pwm_free,
159 .config = ecap_pwm_config, 180 .config = ecap_pwm_config,
181 .set_polarity = ecap_pwm_set_polarity,
160 .enable = ecap_pwm_enable, 182 .enable = ecap_pwm_enable,
161 .disable = ecap_pwm_disable, 183 .disable = ecap_pwm_disable,
162 .owner = THIS_MODULE, 184 .owner = THIS_MODULE,
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index b1996bcd5b78..d3c1dff0a0dc 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -81,6 +81,15 @@
81#define AQCTL_ZRO_FRCHIGH BIT(1) 81#define AQCTL_ZRO_FRCHIGH BIT(1)
82#define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0)) 82#define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0))
83 83
84#define AQCTL_CHANA_POLNORMAL (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \
85 AQCTL_ZRO_FRCHIGH)
86#define AQCTL_CHANA_POLINVERSED (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \
87 AQCTL_ZRO_FRCLOW)
88#define AQCTL_CHANB_POLNORMAL (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \
89 AQCTL_ZRO_FRCHIGH)
90#define AQCTL_CHANB_POLINVERSED (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \
91 AQCTL_ZRO_FRCLOW)
92
84#define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6)) 93#define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6))
85#define AQSFRC_RLDCSF_ZRO 0 94#define AQSFRC_RLDCSF_ZRO 0
86#define AQSFRC_RLDCSF_PRD BIT(6) 95#define AQSFRC_RLDCSF_PRD BIT(6)
@@ -105,6 +114,7 @@ struct ehrpwm_pwm_chip {
105 unsigned int clk_rate; 114 unsigned int clk_rate;
106 void __iomem *mmio_base; 115 void __iomem *mmio_base;
107 unsigned long period_cycles[NUM_PWM_CHANNEL]; 116 unsigned long period_cycles[NUM_PWM_CHANNEL];
117 enum pwm_polarity polarity[NUM_PWM_CHANNEL];
108}; 118};
109 119
110static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) 120static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -165,39 +175,37 @@ static int set_prescale_div(unsigned long rqst_prescaler,
165 return 1; 175 return 1;
166} 176}
167 177
168static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan, 178static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
169 unsigned long duty_cycles)
170{ 179{
171 int cmp_reg, aqctl_reg; 180 int aqctl_reg;
172 unsigned short aqctl_val, aqctl_mask; 181 unsigned short aqctl_val, aqctl_mask;
173 182
174 /* 183 /*
175 * Channels can be configured from action qualifier module. 184 * Configure PWM output to HIGH/LOW level on counter
176 * Channel 0 configured with compare A register and for 185 * reaches compare register value and LOW/HIGH level
177 * up-counter mode. 186 * on counter value reaches period register value and
178 * Channel 1 configured with compare B register and for 187 * zero value on counter
179 * up-counter mode.
180 */ 188 */
181 if (chan == 1) { 189 if (chan == 1) {
182 aqctl_reg = AQCTLB; 190 aqctl_reg = AQCTLB;
183 cmp_reg = CMPB;
184 /* Configure PWM Low from compare B value */
185 aqctl_val = AQCTL_CBU_FRCLOW;
186 aqctl_mask = AQCTL_CBU_MASK; 191 aqctl_mask = AQCTL_CBU_MASK;
192
193 if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
194 aqctl_val = AQCTL_CHANB_POLINVERSED;
195 else
196 aqctl_val = AQCTL_CHANB_POLNORMAL;
187 } else { 197 } else {
188 cmp_reg = CMPA;
189 aqctl_reg = AQCTLA; 198 aqctl_reg = AQCTLA;
190 /* Configure PWM Low from compare A value*/
191 aqctl_val = AQCTL_CAU_FRCLOW;
192 aqctl_mask = AQCTL_CAU_MASK; 199 aqctl_mask = AQCTL_CAU_MASK;
200
201 if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
202 aqctl_val = AQCTL_CHANA_POLINVERSED;
203 else
204 aqctl_val = AQCTL_CHANA_POLNORMAL;
193 } 205 }
194 206
195 /* Configure PWM High from period value and zero value */
196 aqctl_val |= AQCTL_PRD_FRCHIGH | AQCTL_ZRO_FRCHIGH;
197 aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK; 207 aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
198 ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); 208 ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
199
200 ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
201} 209}
202 210
203/* 211/*
@@ -211,9 +219,9 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
211 unsigned long long c; 219 unsigned long long c;
212 unsigned long period_cycles, duty_cycles; 220 unsigned long period_cycles, duty_cycles;
213 unsigned short ps_divval, tb_divval; 221 unsigned short ps_divval, tb_divval;
214 int i; 222 int i, cmp_reg;
215 223
216 if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) 224 if (period_ns > NSEC_PER_SEC)
217 return -ERANGE; 225 return -ERANGE;
218 226
219 c = pc->clk_rate; 227 c = pc->clk_rate;
@@ -278,12 +286,29 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
278 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, 286 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
279 TBCTL_CTRMODE_UP); 287 TBCTL_CTRMODE_UP);
280 288
281 /* Configure the channel for duty cycle */ 289 if (pwm->hwpwm == 1)
282 configure_chans(pc, pwm->hwpwm, duty_cycles); 290 /* Channel 1 configured with compare B register */
291 cmp_reg = CMPB;
292 else
293 /* Channel 0 configured with compare A register */
294 cmp_reg = CMPA;
295
296 ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
297
283 pm_runtime_put_sync(chip->dev); 298 pm_runtime_put_sync(chip->dev);
284 return 0; 299 return 0;
285} 300}
286 301
302static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
303 struct pwm_device *pwm, enum pwm_polarity polarity)
304{
305 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
306
307 /* Configuration of polarity in hardware delayed, do at enable */
308 pc->polarity[pwm->hwpwm] = polarity;
309 return 0;
310}
311
287static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 312static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
288{ 313{
289 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); 314 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
@@ -307,6 +332,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
307 332
308 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); 333 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
309 334
335 /* Channels polarity can be configured from action qualifier module */
336 configure_polarity(pc, pwm->hwpwm);
337
310 /* Enable time counter for free_run */ 338 /* Enable time counter for free_run */
311 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); 339 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
312 return 0; 340 return 0;
@@ -358,6 +386,7 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
358static const struct pwm_ops ehrpwm_pwm_ops = { 386static const struct pwm_ops ehrpwm_pwm_ops = {
359 .free = ehrpwm_pwm_free, 387 .free = ehrpwm_pwm_free,
360 .config = ehrpwm_pwm_config, 388 .config = ehrpwm_pwm_config,
389 .set_polarity = ehrpwm_pwm_set_polarity,
361 .enable = ehrpwm_pwm_enable, 390 .enable = ehrpwm_pwm_enable,
362 .disable = ehrpwm_pwm_disable, 391 .disable = ehrpwm_pwm_disable,
363 .owner = THIS_MODULE, 392 .owner = THIS_MODULE,