diff options
-rw-r--r-- | Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt | 18 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/pwm/vt8500-pwm.txt | 9 | ||||
-rw-r--r-- | drivers/pwm/Kconfig | 18 | ||||
-rw-r--r-- | drivers/pwm/Makefile | 1 | ||||
-rw-r--r-- | drivers/pwm/core.c | 14 | ||||
-rw-r--r-- | drivers/pwm/pwm-atmel-tcb.c | 445 | ||||
-rw-r--r-- | drivers/pwm/pwm-tegra.c | 4 | ||||
-rw-r--r-- | drivers/pwm/pwm-tiecap.c | 53 | ||||
-rw-r--r-- | drivers/pwm/pwm-tiehrpwm.c | 93 | ||||
-rw-r--r-- | drivers/pwm/pwm-twl-led.c | 1 | ||||
-rw-r--r-- | drivers/pwm/pwm-twl.c | 10 | ||||
-rw-r--r-- | drivers/pwm/pwm-vt8500.c | 87 | ||||
-rw-r--r-- | drivers/video/backlight/pwm_bl.c | 20 | ||||
-rw-r--r-- | include/linux/pwm.h | 10 |
14 files changed, 741 insertions, 42 deletions
diff --git a/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt b/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt new file mode 100644 index 000000000000..de0eaed86651 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | Atmel TCB PWM controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "atmel,tcb-pwm" | ||
5 | - #pwm-cells: Should be 3. The first cell specifies the per-chip index | ||
6 | of the PWM to use, the second cell is the period in nanoseconds and | ||
7 | bit 0 in the third cell is used to encode the polarity of PWM output. | ||
8 | Set bit 0 of the third cell in PWM specifier to 1 for inverse polarity & | ||
9 | set to 0 for normal polarity. | ||
10 | - tc-block: The Timer Counter block to use as a PWM chip. | ||
11 | |||
12 | Example: | ||
13 | |||
14 | pwm { | ||
15 | compatible = "atmel,tcb-pwm"; | ||
16 | #pwm-cells = <3>; | ||
17 | tc-block = <1>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt index bcc63678a9a5..d21d82d29855 100644 --- a/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt | |||
@@ -3,14 +3,17 @@ VIA/Wondermedia VT8500/WM8xxx series SoC PWM controller | |||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: should be "via,vt8500-pwm" | 4 | - compatible: should be "via,vt8500-pwm" |
5 | - reg: physical base address and length of the controller's registers | 5 | - reg: physical base address and length of the controller's registers |
6 | - #pwm-cells: should be 2. The first cell specifies the per-chip index | 6 | - #pwm-cells: Should be 3. Number of cells being used to specify PWM property. |
7 | of the PWM to use and the second cell is the period in nanoseconds. | 7 | First cell specifies the per-chip index of the PWM to use, the second |
8 | cell is the period in nanoseconds and bit 0 in the third cell is used to | ||
9 | encode the polarity of PWM output. Set bit 0 of the third in PWM specifier | ||
10 | to 1 for inverse polarity & set to 0 for normal polarity. | ||
8 | - clocks: phandle to the PWM source clock | 11 | - clocks: phandle to the PWM source clock |
9 | 12 | ||
10 | Example: | 13 | Example: |
11 | 14 | ||
12 | pwm1: pwm@d8220000 { | 15 | pwm1: pwm@d8220000 { |
13 | #pwm-cells = <2>; | 16 | #pwm-cells = <3>; |
14 | compatible = "via,vt8500-pwm"; | 17 | compatible = "via,vt8500-pwm"; |
15 | reg = <0xd8220000 0x1000>; | 18 | reg = <0xd8220000 0x1000>; |
16 | clocks = <&clkpwm>; | 19 | clocks = <&clkpwm>; |
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index e513cd998170..0e0bfa035083 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
@@ -37,6 +37,18 @@ config PWM_AB8500 | |||
37 | To compile this driver as a module, choose M here: the module | 37 | To compile this driver as a module, choose M here: the module |
38 | will be called pwm-ab8500. | 38 | will be called pwm-ab8500. |
39 | 39 | ||
40 | config PWM_ATMEL_TCB | ||
41 | tristate "Atmel TC Block PWM support" | ||
42 | depends on ATMEL_TCLIB && OF | ||
43 | help | ||
44 | Generic PWM framework driver for Atmel Timer Counter Block. | ||
45 | |||
46 | A Timer Counter Block provides 6 PWM devices grouped by 2. | ||
47 | Devices in a given group must have the same period. | ||
48 | |||
49 | To compile this driver as a module, choose M here: the module | ||
50 | will be called pwm-atmel-tcb. | ||
51 | |||
40 | config PWM_BFIN | 52 | config PWM_BFIN |
41 | tristate "Blackfin PWM support" | 53 | tristate "Blackfin PWM support" |
42 | depends on BFIN_GPTIMERS | 54 | depends on BFIN_GPTIMERS |
@@ -47,7 +59,7 @@ config PWM_BFIN | |||
47 | will be called pwm-bfin. | 59 | will be called pwm-bfin. |
48 | 60 | ||
49 | config PWM_IMX | 61 | config PWM_IMX |
50 | tristate "i.MX pwm support" | 62 | tristate "i.MX PWM support" |
51 | depends on ARCH_MXC | 63 | depends on ARCH_MXC |
52 | help | 64 | help |
53 | Generic PWM framework driver for i.MX. | 65 | Generic PWM framework driver for i.MX. |
@@ -104,7 +116,7 @@ config PWM_PXA | |||
104 | will be called pwm-pxa. | 116 | will be called pwm-pxa. |
105 | 117 | ||
106 | config PWM_SAMSUNG | 118 | config PWM_SAMSUNG |
107 | tristate "Samsung pwm support" | 119 | tristate "Samsung PWM support" |
108 | depends on PLAT_SAMSUNG | 120 | depends on PLAT_SAMSUNG |
109 | help | 121 | help |
110 | Generic PWM framework driver for Samsung. | 122 | Generic PWM framework driver for Samsung. |
@@ -183,7 +195,7 @@ config PWM_TWL_LED | |||
183 | will be called pwm-twl-led. | 195 | will be called pwm-twl-led. |
184 | 196 | ||
185 | config PWM_VT8500 | 197 | config PWM_VT8500 |
186 | tristate "vt8500 pwm support" | 198 | tristate "vt8500 PWM support" |
187 | depends on ARCH_VT8500 | 199 | depends on ARCH_VT8500 |
188 | help | 200 | help |
189 | Generic PWM framework driver for vt8500. | 201 | Generic PWM framework driver for vt8500. |
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 62a2963cfe58..94ba21e24bd6 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_PWM) += core.o | 1 | obj-$(CONFIG_PWM) += core.o |
2 | obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o | 2 | obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o |
3 | obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o | ||
3 | obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o | 4 | obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o |
4 | obj-$(CONFIG_PWM_IMX) += pwm-imx.o | 5 | obj-$(CONFIG_PWM_IMX) += pwm-imx.o |
5 | obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o | 6 | obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o |
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 4a13da48fefe..32221cb0cbe7 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c | |||
@@ -211,6 +211,7 @@ int pwm_set_chip_data(struct pwm_device *pwm, void *data) | |||
211 | 211 | ||
212 | return 0; | 212 | return 0; |
213 | } | 213 | } |
214 | EXPORT_SYMBOL_GPL(pwm_set_chip_data); | ||
214 | 215 | ||
215 | /** | 216 | /** |
216 | * pwm_get_chip_data() - get private chip data for a PWM | 217 | * pwm_get_chip_data() - get private chip data for a PWM |
@@ -220,6 +221,7 @@ void *pwm_get_chip_data(struct pwm_device *pwm) | |||
220 | { | 221 | { |
221 | return pwm ? pwm->chip_data : NULL; | 222 | return pwm ? pwm->chip_data : NULL; |
222 | } | 223 | } |
224 | EXPORT_SYMBOL_GPL(pwm_get_chip_data); | ||
223 | 225 | ||
224 | /** | 226 | /** |
225 | * pwmchip_add() - register a new PWM chip | 227 | * pwmchip_add() - register a new PWM chip |
@@ -763,6 +765,18 @@ void devm_pwm_put(struct device *dev, struct pwm_device *pwm) | |||
763 | } | 765 | } |
764 | EXPORT_SYMBOL_GPL(devm_pwm_put); | 766 | EXPORT_SYMBOL_GPL(devm_pwm_put); |
765 | 767 | ||
768 | /** | ||
769 | * pwm_can_sleep() - report whether PWM access will sleep | ||
770 | * @pwm: PWM device | ||
771 | * | ||
772 | * It returns true if accessing the PWM can sleep, false otherwise. | ||
773 | */ | ||
774 | bool pwm_can_sleep(struct pwm_device *pwm) | ||
775 | { | ||
776 | return pwm->chip->can_sleep; | ||
777 | } | ||
778 | EXPORT_SYMBOL_GPL(pwm_can_sleep); | ||
779 | |||
766 | #ifdef CONFIG_DEBUG_FS | 780 | #ifdef CONFIG_DEBUG_FS |
767 | static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) | 781 | static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) |
768 | { | 782 | { |
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c new file mode 100644 index 000000000000..16cb53092857 --- /dev/null +++ b/drivers/pwm/pwm-atmel-tcb.c | |||
@@ -0,0 +1,445 @@ | |||
1 | /* | ||
2 | * Copyright (C) Overkiz SAS 2012 | ||
3 | * | ||
4 | * Author: Boris BREZILLON <b.brezillon@overkiz.com> | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/clocksource.h> | ||
11 | #include <linux/clockchips.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/irq.h> | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/ioport.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/atmel_tc.h> | ||
21 | #include <linux/pwm.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | #define NPWM 6 | ||
26 | |||
27 | #define ATMEL_TC_ACMR_MASK (ATMEL_TC_ACPA | ATMEL_TC_ACPC | \ | ||
28 | ATMEL_TC_AEEVT | ATMEL_TC_ASWTRG) | ||
29 | |||
30 | #define ATMEL_TC_BCMR_MASK (ATMEL_TC_BCPB | ATMEL_TC_BCPC | \ | ||
31 | ATMEL_TC_BEEVT | ATMEL_TC_BSWTRG) | ||
32 | |||
33 | struct atmel_tcb_pwm_device { | ||
34 | enum pwm_polarity polarity; /* PWM polarity */ | ||
35 | unsigned div; /* PWM clock divider */ | ||
36 | unsigned duty; /* PWM duty expressed in clk cycles */ | ||
37 | unsigned period; /* PWM period expressed in clk cycles */ | ||
38 | }; | ||
39 | |||
40 | struct atmel_tcb_pwm_chip { | ||
41 | struct pwm_chip chip; | ||
42 | spinlock_t lock; | ||
43 | struct atmel_tc *tc; | ||
44 | struct atmel_tcb_pwm_device *pwms[NPWM]; | ||
45 | }; | ||
46 | |||
47 | static inline struct atmel_tcb_pwm_chip *to_tcb_chip(struct pwm_chip *chip) | ||
48 | { | ||
49 | return container_of(chip, struct atmel_tcb_pwm_chip, chip); | ||
50 | } | ||
51 | |||
52 | static int atmel_tcb_pwm_set_polarity(struct pwm_chip *chip, | ||
53 | struct pwm_device *pwm, | ||
54 | enum pwm_polarity polarity) | ||
55 | { | ||
56 | struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm); | ||
57 | |||
58 | tcbpwm->polarity = polarity; | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int atmel_tcb_pwm_request(struct pwm_chip *chip, | ||
64 | struct pwm_device *pwm) | ||
65 | { | ||
66 | struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); | ||
67 | struct atmel_tcb_pwm_device *tcbpwm; | ||
68 | struct atmel_tc *tc = tcbpwmc->tc; | ||
69 | void __iomem *regs = tc->regs; | ||
70 | unsigned group = pwm->hwpwm / 2; | ||
71 | unsigned index = pwm->hwpwm % 2; | ||
72 | unsigned cmr; | ||
73 | int ret; | ||
74 | |||
75 | tcbpwm = devm_kzalloc(chip->dev, sizeof(*tcbpwm), GFP_KERNEL); | ||
76 | if (!tcbpwm) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | ret = clk_enable(tc->clk[group]); | ||
80 | if (ret) { | ||
81 | devm_kfree(chip->dev, tcbpwm); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | pwm_set_chip_data(pwm, tcbpwm); | ||
86 | tcbpwm->polarity = PWM_POLARITY_NORMAL; | ||
87 | tcbpwm->duty = 0; | ||
88 | tcbpwm->period = 0; | ||
89 | tcbpwm->div = 0; | ||
90 | |||
91 | spin_lock(&tcbpwmc->lock); | ||
92 | cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR)); | ||
93 | /* | ||
94 | * Get init config from Timer Counter registers if | ||
95 | * Timer Counter is already configured as a PWM generator. | ||
96 | */ | ||
97 | if (cmr & ATMEL_TC_WAVE) { | ||
98 | if (index == 0) | ||
99 | tcbpwm->duty = | ||
100 | __raw_readl(regs + ATMEL_TC_REG(group, RA)); | ||
101 | else | ||
102 | tcbpwm->duty = | ||
103 | __raw_readl(regs + ATMEL_TC_REG(group, RB)); | ||
104 | |||
105 | tcbpwm->div = cmr & ATMEL_TC_TCCLKS; | ||
106 | tcbpwm->period = __raw_readl(regs + ATMEL_TC_REG(group, RC)); | ||
107 | cmr &= (ATMEL_TC_TCCLKS | ATMEL_TC_ACMR_MASK | | ||
108 | ATMEL_TC_BCMR_MASK); | ||
109 | } else | ||
110 | cmr = 0; | ||
111 | |||
112 | cmr |= ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO | ATMEL_TC_EEVT_XC0; | ||
113 | __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR)); | ||
114 | spin_unlock(&tcbpwmc->lock); | ||
115 | |||
116 | tcbpwmc->pwms[pwm->hwpwm] = tcbpwm; | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static void atmel_tcb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | ||
122 | { | ||
123 | struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); | ||
124 | struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm); | ||
125 | struct atmel_tc *tc = tcbpwmc->tc; | ||
126 | |||
127 | clk_disable(tc->clk[pwm->hwpwm / 2]); | ||
128 | tcbpwmc->pwms[pwm->hwpwm] = NULL; | ||
129 | devm_kfree(chip->dev, tcbpwm); | ||
130 | } | ||
131 | |||
132 | static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
133 | { | ||
134 | struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); | ||
135 | struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm); | ||
136 | struct atmel_tc *tc = tcbpwmc->tc; | ||
137 | void __iomem *regs = tc->regs; | ||
138 | unsigned group = pwm->hwpwm / 2; | ||
139 | unsigned index = pwm->hwpwm % 2; | ||
140 | unsigned cmr; | ||
141 | enum pwm_polarity polarity = tcbpwm->polarity; | ||
142 | |||
143 | /* | ||
144 | * If duty is 0 the timer will be stopped and we have to | ||
145 | * configure the output correctly on software trigger: | ||
146 | * - set output to high if PWM_POLARITY_INVERSED | ||
147 | * - set output to low if PWM_POLARITY_NORMAL | ||
148 | * | ||
149 | * This is why we're reverting polarity in this case. | ||
150 | */ | ||
151 | if (tcbpwm->duty == 0) | ||
152 | polarity = !polarity; | ||
153 | |||
154 | spin_lock(&tcbpwmc->lock); | ||
155 | cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR)); | ||
156 | |||
157 | /* flush old setting and set the new one */ | ||
158 | if (index == 0) { | ||
159 | cmr &= ~ATMEL_TC_ACMR_MASK; | ||
160 | if (polarity == PWM_POLARITY_INVERSED) | ||
161 | cmr |= ATMEL_TC_ASWTRG_CLEAR; | ||
162 | else | ||
163 | cmr |= ATMEL_TC_ASWTRG_SET; | ||
164 | } else { | ||
165 | cmr &= ~ATMEL_TC_BCMR_MASK; | ||
166 | if (polarity == PWM_POLARITY_INVERSED) | ||
167 | cmr |= ATMEL_TC_BSWTRG_CLEAR; | ||
168 | else | ||
169 | cmr |= ATMEL_TC_BSWTRG_SET; | ||
170 | } | ||
171 | |||
172 | __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR)); | ||
173 | |||
174 | /* | ||
175 | * Use software trigger to apply the new setting. | ||
176 | * If both PWM devices in this group are disabled we stop the clock. | ||
177 | */ | ||
178 | if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC))) | ||
179 | __raw_writel(ATMEL_TC_SWTRG | ATMEL_TC_CLKDIS, | ||
180 | regs + ATMEL_TC_REG(group, CCR)); | ||
181 | else | ||
182 | __raw_writel(ATMEL_TC_SWTRG, regs + | ||
183 | ATMEL_TC_REG(group, CCR)); | ||
184 | |||
185 | spin_unlock(&tcbpwmc->lock); | ||
186 | } | ||
187 | |||
188 | static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
189 | { | ||
190 | struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); | ||
191 | struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm); | ||
192 | struct atmel_tc *tc = tcbpwmc->tc; | ||
193 | void __iomem *regs = tc->regs; | ||
194 | unsigned group = pwm->hwpwm / 2; | ||
195 | unsigned index = pwm->hwpwm % 2; | ||
196 | u32 cmr; | ||
197 | enum pwm_polarity polarity = tcbpwm->polarity; | ||
198 | |||
199 | /* | ||
200 | * If duty is 0 the timer will be stopped and we have to | ||
201 | * configure the output correctly on software trigger: | ||
202 | * - set output to high if PWM_POLARITY_INVERSED | ||
203 | * - set output to low if PWM_POLARITY_NORMAL | ||
204 | * | ||
205 | * This is why we're reverting polarity in this case. | ||
206 | */ | ||
207 | if (tcbpwm->duty == 0) | ||
208 | polarity = !polarity; | ||
209 | |||
210 | spin_lock(&tcbpwmc->lock); | ||
211 | cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR)); | ||
212 | |||
213 | /* flush old setting and set the new one */ | ||
214 | cmr &= ~ATMEL_TC_TCCLKS; | ||
215 | |||
216 | if (index == 0) { | ||
217 | cmr &= ~ATMEL_TC_ACMR_MASK; | ||
218 | |||
219 | /* Set CMR flags according to given polarity */ | ||
220 | if (polarity == PWM_POLARITY_INVERSED) | ||
221 | cmr |= ATMEL_TC_ASWTRG_CLEAR; | ||
222 | else | ||
223 | cmr |= ATMEL_TC_ASWTRG_SET; | ||
224 | } else { | ||
225 | cmr &= ~ATMEL_TC_BCMR_MASK; | ||
226 | if (polarity == PWM_POLARITY_INVERSED) | ||
227 | cmr |= ATMEL_TC_BSWTRG_CLEAR; | ||
228 | else | ||
229 | cmr |= ATMEL_TC_BSWTRG_SET; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * If duty is 0 or equal to period there's no need to register | ||
234 | * a specific action on RA/RB and RC compare. | ||
235 | * The output will be configured on software trigger and keep | ||
236 | * this config till next config call. | ||
237 | */ | ||
238 | if (tcbpwm->duty != tcbpwm->period && tcbpwm->duty > 0) { | ||
239 | if (index == 0) { | ||
240 | if (polarity == PWM_POLARITY_INVERSED) | ||
241 | cmr |= ATMEL_TC_ACPA_SET | ATMEL_TC_ACPC_CLEAR; | ||
242 | else | ||
243 | cmr |= ATMEL_TC_ACPA_CLEAR | ATMEL_TC_ACPC_SET; | ||
244 | } else { | ||
245 | if (polarity == PWM_POLARITY_INVERSED) | ||
246 | cmr |= ATMEL_TC_BCPB_SET | ATMEL_TC_BCPC_CLEAR; | ||
247 | else | ||
248 | cmr |= ATMEL_TC_BCPB_CLEAR | ATMEL_TC_BCPC_SET; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR)); | ||
253 | |||
254 | if (index == 0) | ||
255 | __raw_writel(tcbpwm->duty, regs + ATMEL_TC_REG(group, RA)); | ||
256 | else | ||
257 | __raw_writel(tcbpwm->duty, regs + ATMEL_TC_REG(group, RB)); | ||
258 | |||
259 | __raw_writel(tcbpwm->period, regs + ATMEL_TC_REG(group, RC)); | ||
260 | |||
261 | /* Use software trigger to apply the new setting */ | ||
262 | __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, | ||
263 | regs + ATMEL_TC_REG(group, CCR)); | ||
264 | spin_unlock(&tcbpwmc->lock); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
269 | int duty_ns, int period_ns) | ||
270 | { | ||
271 | struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); | ||
272 | struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm); | ||
273 | unsigned group = pwm->hwpwm / 2; | ||
274 | unsigned index = pwm->hwpwm % 2; | ||
275 | struct atmel_tcb_pwm_device *atcbpwm = NULL; | ||
276 | struct atmel_tc *tc = tcbpwmc->tc; | ||
277 | int i; | ||
278 | int slowclk = 0; | ||
279 | unsigned period; | ||
280 | unsigned duty; | ||
281 | unsigned rate = clk_get_rate(tc->clk[group]); | ||
282 | unsigned long long min; | ||
283 | unsigned long long max; | ||
284 | |||
285 | /* | ||
286 | * Find best clk divisor: | ||
287 | * the smallest divisor which can fulfill the period_ns requirements. | ||
288 | */ | ||
289 | for (i = 0; i < 5; ++i) { | ||
290 | if (atmel_tc_divisors[i] == 0) { | ||
291 | slowclk = i; | ||
292 | continue; | ||
293 | } | ||
294 | min = div_u64((u64)NSEC_PER_SEC * atmel_tc_divisors[i], rate); | ||
295 | max = min << tc->tcb_config->counter_width; | ||
296 | if (max >= period_ns) | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * If none of the divisor are small enough to represent period_ns | ||
302 | * take slow clock (32KHz). | ||
303 | */ | ||
304 | if (i == 5) { | ||
305 | i = slowclk; | ||
306 | rate = 32768; | ||
307 | min = div_u64(NSEC_PER_SEC, rate); | ||
308 | max = min << 16; | ||
309 | |||
310 | /* If period is too big return ERANGE error */ | ||
311 | if (max < period_ns) | ||
312 | return -ERANGE; | ||
313 | } | ||
314 | |||
315 | duty = div_u64(duty_ns, min); | ||
316 | period = div_u64(period_ns, min); | ||
317 | |||
318 | if (index == 0) | ||
319 | atcbpwm = tcbpwmc->pwms[pwm->hwpwm + 1]; | ||
320 | else | ||
321 | atcbpwm = tcbpwmc->pwms[pwm->hwpwm - 1]; | ||
322 | |||
323 | /* | ||
324 | * PWM devices provided by TCB driver are grouped by 2: | ||
325 | * - group 0: PWM 0 & 1 | ||
326 | * - group 1: PWM 2 & 3 | ||
327 | * - group 2: PWM 4 & 5 | ||
328 | * | ||
329 | * PWM devices in a given group must be configured with the | ||
330 | * same period_ns. | ||
331 | * | ||
332 | * We're checking the period value of the second PWM device | ||
333 | * in this group before applying the new config. | ||
334 | */ | ||
335 | if ((atcbpwm && atcbpwm->duty > 0 && | ||
336 | atcbpwm->duty != atcbpwm->period) && | ||
337 | (atcbpwm->div != i || atcbpwm->period != period)) { | ||
338 | dev_err(chip->dev, | ||
339 | "failed to configure period_ns: PWM group already configured with a different value\n"); | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | tcbpwm->period = period; | ||
344 | tcbpwm->div = i; | ||
345 | tcbpwm->duty = duty; | ||
346 | |||
347 | /* If the PWM is enabled, call enable to apply the new conf */ | ||
348 | if (test_bit(PWMF_ENABLED, &pwm->flags)) | ||
349 | atmel_tcb_pwm_enable(chip, pwm); | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static const struct pwm_ops atmel_tcb_pwm_ops = { | ||
355 | .request = atmel_tcb_pwm_request, | ||
356 | .free = atmel_tcb_pwm_free, | ||
357 | .config = atmel_tcb_pwm_config, | ||
358 | .set_polarity = atmel_tcb_pwm_set_polarity, | ||
359 | .enable = atmel_tcb_pwm_enable, | ||
360 | .disable = atmel_tcb_pwm_disable, | ||
361 | }; | ||
362 | |||
363 | static int atmel_tcb_pwm_probe(struct platform_device *pdev) | ||
364 | { | ||
365 | struct atmel_tcb_pwm_chip *tcbpwm; | ||
366 | struct device_node *np = pdev->dev.of_node; | ||
367 | struct atmel_tc *tc; | ||
368 | int err; | ||
369 | int tcblock; | ||
370 | |||
371 | err = of_property_read_u32(np, "tc-block", &tcblock); | ||
372 | if (err < 0) { | ||
373 | dev_err(&pdev->dev, | ||
374 | "failed to get Timer Counter Block number from device tree (error: %d)\n", | ||
375 | err); | ||
376 | return err; | ||
377 | } | ||
378 | |||
379 | tc = atmel_tc_alloc(tcblock, "tcb-pwm"); | ||
380 | if (tc == NULL) { | ||
381 | dev_err(&pdev->dev, "failed to allocate Timer Counter Block\n"); | ||
382 | return -ENOMEM; | ||
383 | } | ||
384 | |||
385 | tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL); | ||
386 | if (tcbpwm == NULL) { | ||
387 | atmel_tc_free(tc); | ||
388 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
389 | return -ENOMEM; | ||
390 | } | ||
391 | |||
392 | tcbpwm->chip.dev = &pdev->dev; | ||
393 | tcbpwm->chip.ops = &atmel_tcb_pwm_ops; | ||
394 | tcbpwm->chip.of_xlate = of_pwm_xlate_with_flags; | ||
395 | tcbpwm->chip.of_pwm_n_cells = 3; | ||
396 | tcbpwm->chip.base = -1; | ||
397 | tcbpwm->chip.npwm = NPWM; | ||
398 | tcbpwm->tc = tc; | ||
399 | |||
400 | spin_lock_init(&tcbpwm->lock); | ||
401 | |||
402 | err = pwmchip_add(&tcbpwm->chip); | ||
403 | if (err < 0) { | ||
404 | atmel_tc_free(tc); | ||
405 | return err; | ||
406 | } | ||
407 | |||
408 | platform_set_drvdata(pdev, tcbpwm); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int atmel_tcb_pwm_remove(struct platform_device *pdev) | ||
414 | { | ||
415 | struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev); | ||
416 | int err; | ||
417 | |||
418 | err = pwmchip_remove(&tcbpwm->chip); | ||
419 | if (err < 0) | ||
420 | return err; | ||
421 | |||
422 | atmel_tc_free(tcbpwm->tc); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static const struct of_device_id atmel_tcb_pwm_dt_ids[] = { | ||
428 | { .compatible = "atmel,tcb-pwm", }, | ||
429 | { /* sentinel */ } | ||
430 | }; | ||
431 | MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids); | ||
432 | |||
433 | static struct platform_driver atmel_tcb_pwm_driver = { | ||
434 | .driver = { | ||
435 | .name = "atmel-tcb-pwm", | ||
436 | .of_match_table = atmel_tcb_pwm_dt_ids, | ||
437 | }, | ||
438 | .probe = atmel_tcb_pwm_probe, | ||
439 | .remove = atmel_tcb_pwm_remove, | ||
440 | }; | ||
441 | module_platform_driver(atmel_tcb_pwm_driver); | ||
442 | |||
443 | MODULE_AUTHOR("Boris BREZILLON <b.brezillon@overkiz.com>"); | ||
444 | MODULE_DESCRIPTION("Atmel Timer Counter Pulse Width Modulation Driver"); | ||
445 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 71900e8cd3d1..af3ab48cb7ef 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c | |||
@@ -233,7 +233,6 @@ static int tegra_pwm_remove(struct platform_device *pdev) | |||
233 | return pwmchip_remove(&pc->chip); | 233 | return pwmchip_remove(&pc->chip); |
234 | } | 234 | } |
235 | 235 | ||
236 | #ifdef CONFIG_OF | ||
237 | static struct of_device_id tegra_pwm_of_match[] = { | 236 | static struct of_device_id tegra_pwm_of_match[] = { |
238 | { .compatible = "nvidia,tegra20-pwm" }, | 237 | { .compatible = "nvidia,tegra20-pwm" }, |
239 | { .compatible = "nvidia,tegra30-pwm" }, | 238 | { .compatible = "nvidia,tegra30-pwm" }, |
@@ -241,12 +240,11 @@ static struct of_device_id tegra_pwm_of_match[] = { | |||
241 | }; | 240 | }; |
242 | 241 | ||
243 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); | 242 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); |
244 | #endif | ||
245 | 243 | ||
246 | static struct platform_driver tegra_pwm_driver = { | 244 | static struct platform_driver tegra_pwm_driver = { |
247 | .driver = { | 245 | .driver = { |
248 | .name = "tegra-pwm", | 246 | .name = "tegra-pwm", |
249 | .of_match_table = of_match_ptr(tegra_pwm_of_match), | 247 | .of_match_table = tegra_pwm_of_match, |
250 | }, | 248 | }, |
251 | .probe = tegra_pwm_probe, | 249 | .probe = tegra_pwm_probe, |
252 | .remove = tegra_pwm_remove, | 250 | .remove = tegra_pwm_remove, |
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 | ||
44 | struct ecap_context { | ||
45 | u32 cap3; | ||
46 | u32 cap4; | ||
47 | u16 ecctl2; | ||
48 | }; | ||
49 | |||
44 | struct ecap_pwm_chip { | 50 | struct 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 | ||
50 | static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip) | 57 | static 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 | ||
298 | void 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 | |||
307 | void 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 | |||
314 | static 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 | |||
328 | static 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 | |||
341 | static SIMPLE_DEV_PM_OPS(ecap_pwm_pm_ops, ecap_pwm_suspend, ecap_pwm_resume); | ||
342 | |||
291 | static struct platform_driver ecap_pwm_driver = { | 343 | static 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, |
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 | ||
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 | struct ehrpwm_pwm_chip { | 127 | struct 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 | ||
125 | static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) | 137 | static 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 | ||
142 | static u16 ehrpwm_read(void *base, int offset) | ||
143 | { | ||
144 | return readw(base + offset); | ||
145 | } | ||
146 | |||
130 | static void ehrpwm_write(void *base, int offset, unsigned int val) | 147 | static 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 | ||
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 | |||
513 | static struct platform_driver ehrpwm_pwm_driver = { | 601 | static 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, |
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c index 9dfa0f3eca30..83e25d45d640 100644 --- a/drivers/pwm/pwm-twl-led.c +++ b/drivers/pwm/pwm-twl-led.c | |||
@@ -300,6 +300,7 @@ static int twl_pwmled_probe(struct platform_device *pdev) | |||
300 | 300 | ||
301 | twl->chip.dev = &pdev->dev; | 301 | twl->chip.dev = &pdev->dev; |
302 | twl->chip.base = -1; | 302 | twl->chip.base = -1; |
303 | twl->chip.can_sleep = true; | ||
303 | 304 | ||
304 | mutex_init(&twl->mutex); | 305 | mutex_init(&twl->mutex); |
305 | 306 | ||
diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c index e65db95d5e59..bf3fda294223 100644 --- a/drivers/pwm/pwm-twl.c +++ b/drivers/pwm/pwm-twl.c | |||
@@ -200,8 +200,7 @@ out: | |||
200 | 200 | ||
201 | static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | 201 | static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) |
202 | { | 202 | { |
203 | struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip, | 203 | struct twl_pwm_chip *twl = to_twl(chip); |
204 | chip); | ||
205 | int ret; | 204 | int ret; |
206 | u8 val, mask; | 205 | u8 val, mask; |
207 | 206 | ||
@@ -231,8 +230,7 @@ out: | |||
231 | 230 | ||
232 | static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 231 | static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
233 | { | 232 | { |
234 | struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip, | 233 | struct twl_pwm_chip *twl = to_twl(chip); |
235 | chip); | ||
236 | int ret; | 234 | int ret; |
237 | u8 val; | 235 | u8 val; |
238 | 236 | ||
@@ -255,8 +253,7 @@ out: | |||
255 | 253 | ||
256 | static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | 254 | static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
257 | { | 255 | { |
258 | struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip, | 256 | struct twl_pwm_chip *twl = to_twl(chip); |
259 | chip); | ||
260 | int ret; | 257 | int ret; |
261 | u8 val; | 258 | u8 val; |
262 | 259 | ||
@@ -315,6 +312,7 @@ static int twl_pwm_probe(struct platform_device *pdev) | |||
315 | twl->chip.dev = &pdev->dev; | 312 | twl->chip.dev = &pdev->dev; |
316 | twl->chip.base = -1; | 313 | twl->chip.base = -1; |
317 | twl->chip.npwm = 2; | 314 | twl->chip.npwm = 2; |
315 | twl->chip.can_sleep = true; | ||
318 | 316 | ||
319 | mutex_init(&twl->mutex); | 317 | mutex_init(&twl->mutex); |
320 | 318 | ||
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index f9de9b28e46e..69effd19afc7 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c | |||
@@ -36,6 +36,25 @@ | |||
36 | */ | 36 | */ |
37 | #define VT8500_NR_PWMS 2 | 37 | #define VT8500_NR_PWMS 2 |
38 | 38 | ||
39 | #define REG_CTRL(pwm) (((pwm) << 4) + 0x00) | ||
40 | #define REG_SCALAR(pwm) (((pwm) << 4) + 0x04) | ||
41 | #define REG_PERIOD(pwm) (((pwm) << 4) + 0x08) | ||
42 | #define REG_DUTY(pwm) (((pwm) << 4) + 0x0C) | ||
43 | #define REG_STATUS 0x40 | ||
44 | |||
45 | #define CTRL_ENABLE BIT(0) | ||
46 | #define CTRL_INVERT BIT(1) | ||
47 | #define CTRL_AUTOLOAD BIT(2) | ||
48 | #define CTRL_STOP_IMM BIT(3) | ||
49 | #define CTRL_LOAD_PRESCALE BIT(4) | ||
50 | #define CTRL_LOAD_PERIOD BIT(5) | ||
51 | |||
52 | #define STATUS_CTRL_UPDATE BIT(0) | ||
53 | #define STATUS_SCALAR_UPDATE BIT(1) | ||
54 | #define STATUS_PERIOD_UPDATE BIT(2) | ||
55 | #define STATUS_DUTY_UPDATE BIT(3) | ||
56 | #define STATUS_ALL_UPDATE 0x0F | ||
57 | |||
39 | struct vt8500_chip { | 58 | struct vt8500_chip { |
40 | struct pwm_chip chip; | 59 | struct pwm_chip chip; |
41 | void __iomem *base; | 60 | void __iomem *base; |
@@ -45,15 +64,17 @@ struct vt8500_chip { | |||
45 | #define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) | 64 | #define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) |
46 | 65 | ||
47 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) | 66 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) |
48 | static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) | 67 | static inline void pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 bitmask) |
49 | { | 68 | { |
50 | int loops = msecs_to_loops(10); | 69 | int loops = msecs_to_loops(10); |
51 | while ((readb(reg) & bitmask) && --loops) | 70 | u32 mask = bitmask << (nr << 8); |
71 | |||
72 | while ((readl(vt8500->base + REG_STATUS) & mask) && --loops) | ||
52 | cpu_relax(); | 73 | cpu_relax(); |
53 | 74 | ||
54 | if (unlikely(!loops)) | 75 | if (unlikely(!loops)) |
55 | pr_warn("Waiting for status bits 0x%x to clear timed out\n", | 76 | dev_warn(vt8500->chip.dev, "Waiting for status bits 0x%x to clear timed out\n", |
56 | bitmask); | 77 | mask); |
57 | } | 78 | } |
58 | 79 | ||
59 | static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 80 | static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
@@ -63,6 +84,7 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
63 | unsigned long long c; | 84 | unsigned long long c; |
64 | unsigned long period_cycles, prescale, pv, dc; | 85 | unsigned long period_cycles, prescale, pv, dc; |
65 | int err; | 86 | int err; |
87 | u32 val; | ||
66 | 88 | ||
67 | err = clk_enable(vt8500->clk); | 89 | err = clk_enable(vt8500->clk); |
68 | if (err < 0) { | 90 | if (err < 0) { |
@@ -91,14 +113,19 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
91 | do_div(c, period_ns); | 113 | do_div(c, period_ns); |
92 | dc = c; | 114 | dc = c; |
93 | 115 | ||
94 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 1)); | 116 | writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm)); |
95 | writel(prescale, vt8500->base + 0x4 + (pwm->hwpwm << 4)); | 117 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_SCALAR_UPDATE); |
96 | 118 | ||
97 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 2)); | 119 | writel(pv, vt8500->base + REG_PERIOD(pwm->hwpwm)); |
98 | writel(pv, vt8500->base + 0x8 + (pwm->hwpwm << 4)); | 120 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_PERIOD_UPDATE); |
99 | 121 | ||
100 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 3)); | 122 | writel(dc, vt8500->base + REG_DUTY(pwm->hwpwm)); |
101 | writel(dc, vt8500->base + 0xc + (pwm->hwpwm << 4)); | 123 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_DUTY_UPDATE); |
124 | |||
125 | val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); | ||
126 | val |= CTRL_AUTOLOAD; | ||
127 | writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); | ||
128 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); | ||
102 | 129 | ||
103 | clk_disable(vt8500->clk); | 130 | clk_disable(vt8500->clk); |
104 | return 0; | 131 | return 0; |
@@ -106,8 +133,9 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
106 | 133 | ||
107 | static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 134 | static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
108 | { | 135 | { |
109 | int err; | ||
110 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); | 136 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); |
137 | int err; | ||
138 | u32 val; | ||
111 | 139 | ||
112 | err = clk_enable(vt8500->clk); | 140 | err = clk_enable(vt8500->clk); |
113 | if (err < 0) { | 141 | if (err < 0) { |
@@ -115,25 +143,52 @@ static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
115 | return err; | 143 | return err; |
116 | } | 144 | } |
117 | 145 | ||
118 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); | 146 | val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); |
119 | writel(5, vt8500->base + (pwm->hwpwm << 4)); | 147 | val |= CTRL_ENABLE; |
148 | writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); | ||
149 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); | ||
150 | |||
120 | return 0; | 151 | return 0; |
121 | } | 152 | } |
122 | 153 | ||
123 | static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | 154 | static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
124 | { | 155 | { |
125 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); | 156 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); |
157 | u32 val; | ||
126 | 158 | ||
127 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); | 159 | val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); |
128 | writel(0, vt8500->base + (pwm->hwpwm << 4)); | 160 | val &= ~CTRL_ENABLE; |
161 | writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); | ||
162 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); | ||
129 | 163 | ||
130 | clk_disable(vt8500->clk); | 164 | clk_disable(vt8500->clk); |
131 | } | 165 | } |
132 | 166 | ||
167 | static int vt8500_pwm_set_polarity(struct pwm_chip *chip, | ||
168 | struct pwm_device *pwm, | ||
169 | enum pwm_polarity polarity) | ||
170 | { | ||
171 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); | ||
172 | u32 val; | ||
173 | |||
174 | val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); | ||
175 | |||
176 | if (polarity == PWM_POLARITY_INVERSED) | ||
177 | val |= CTRL_INVERT; | ||
178 | else | ||
179 | val &= ~CTRL_INVERT; | ||
180 | |||
181 | writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); | ||
182 | pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
133 | static struct pwm_ops vt8500_pwm_ops = { | 187 | static struct pwm_ops vt8500_pwm_ops = { |
134 | .enable = vt8500_pwm_enable, | 188 | .enable = vt8500_pwm_enable, |
135 | .disable = vt8500_pwm_disable, | 189 | .disable = vt8500_pwm_disable, |
136 | .config = vt8500_pwm_config, | 190 | .config = vt8500_pwm_config, |
191 | .set_polarity = vt8500_pwm_set_polarity, | ||
137 | .owner = THIS_MODULE, | 192 | .owner = THIS_MODULE, |
138 | }; | 193 | }; |
139 | 194 | ||
@@ -163,6 +218,8 @@ static int vt8500_pwm_probe(struct platform_device *pdev) | |||
163 | 218 | ||
164 | chip->chip.dev = &pdev->dev; | 219 | chip->chip.dev = &pdev->dev; |
165 | chip->chip.ops = &vt8500_pwm_ops; | 220 | chip->chip.ops = &vt8500_pwm_ops; |
221 | chip->chip.of_xlate = of_pwm_xlate_with_flags; | ||
222 | chip->chip.of_pwm_n_cells = 3; | ||
166 | chip->chip.base = -1; | 223 | chip->chip.base = -1; |
167 | chip->chip.npwm = VT8500_NR_PWMS; | 224 | chip->chip.npwm = VT8500_NR_PWMS; |
168 | 225 | ||
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index f2f4c43d6e22..fa00304a63d8 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -41,10 +41,9 @@ static int pwm_backlight_update_status(struct backlight_device *bl) | |||
41 | int brightness = bl->props.brightness; | 41 | int brightness = bl->props.brightness; |
42 | int max = bl->props.max_brightness; | 42 | int max = bl->props.max_brightness; |
43 | 43 | ||
44 | if (bl->props.power != FB_BLANK_UNBLANK) | 44 | if (bl->props.power != FB_BLANK_UNBLANK || |
45 | brightness = 0; | 45 | bl->props.fb_blank != FB_BLANK_UNBLANK || |
46 | 46 | bl->props.state & BL_CORE_FBBLANK) | |
47 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | ||
48 | brightness = 0; | 47 | brightness = 0; |
49 | 48 | ||
50 | if (pb->notify) | 49 | if (pb->notify) |
@@ -135,12 +134,6 @@ static int pwm_backlight_parse_dt(struct device *dev, | |||
135 | if (ret < 0) | 134 | if (ret < 0) |
136 | return ret; | 135 | return ret; |
137 | 136 | ||
138 | if (value >= data->max_brightness) { | ||
139 | dev_warn(dev, "invalid default brightness level: %u, using %u\n", | ||
140 | value, data->max_brightness - 1); | ||
141 | value = data->max_brightness - 1; | ||
142 | } | ||
143 | |||
144 | data->dft_brightness = value; | 137 | data->dft_brightness = value; |
145 | data->max_brightness--; | 138 | data->max_brightness--; |
146 | } | 139 | } |
@@ -249,6 +242,13 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
249 | goto err_alloc; | 242 | goto err_alloc; |
250 | } | 243 | } |
251 | 244 | ||
245 | if (data->dft_brightness > data->max_brightness) { | ||
246 | dev_warn(&pdev->dev, | ||
247 | "invalid default brightness level: %u, using %u\n", | ||
248 | data->dft_brightness, data->max_brightness); | ||
249 | data->dft_brightness = data->max_brightness; | ||
250 | } | ||
251 | |||
252 | bl->props.brightness = data->dft_brightness; | 252 | bl->props.brightness = data->dft_brightness; |
253 | backlight_update_status(bl); | 253 | backlight_update_status(bl); |
254 | 254 | ||
diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 70655a205b74..a4df2042b79c 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h | |||
@@ -146,6 +146,8 @@ struct pwm_ops { | |||
146 | * @base: number of first PWM controlled by this chip | 146 | * @base: number of first PWM controlled by this chip |
147 | * @npwm: number of PWMs controlled by this chip | 147 | * @npwm: number of PWMs controlled by this chip |
148 | * @pwms: array of PWM devices allocated by the framework | 148 | * @pwms: array of PWM devices allocated by the framework |
149 | * @can_sleep: must be true if the .config(), .enable() or .disable() | ||
150 | * operations may sleep | ||
149 | */ | 151 | */ |
150 | struct pwm_chip { | 152 | struct pwm_chip { |
151 | struct device *dev; | 153 | struct device *dev; |
@@ -159,6 +161,7 @@ struct pwm_chip { | |||
159 | struct pwm_device * (*of_xlate)(struct pwm_chip *pc, | 161 | struct pwm_device * (*of_xlate)(struct pwm_chip *pc, |
160 | const struct of_phandle_args *args); | 162 | const struct of_phandle_args *args); |
161 | unsigned int of_pwm_n_cells; | 163 | unsigned int of_pwm_n_cells; |
164 | bool can_sleep; | ||
162 | }; | 165 | }; |
163 | 166 | ||
164 | #if IS_ENABLED(CONFIG_PWM) | 167 | #if IS_ENABLED(CONFIG_PWM) |
@@ -182,6 +185,8 @@ struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id); | |||
182 | struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, | 185 | struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, |
183 | const char *con_id); | 186 | const char *con_id); |
184 | void devm_pwm_put(struct device *dev, struct pwm_device *pwm); | 187 | void devm_pwm_put(struct device *dev, struct pwm_device *pwm); |
188 | |||
189 | bool pwm_can_sleep(struct pwm_device *pwm); | ||
185 | #else | 190 | #else |
186 | static inline int pwm_set_chip_data(struct pwm_device *pwm, void *data) | 191 | static inline int pwm_set_chip_data(struct pwm_device *pwm, void *data) |
187 | { | 192 | { |
@@ -242,6 +247,11 @@ static inline struct pwm_device *devm_of_pwm_get(struct device *dev, | |||
242 | static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm) | 247 | static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm) |
243 | { | 248 | { |
244 | } | 249 | } |
250 | |||
251 | static inline bool pwm_can_sleep(struct pwm_device *pwm) | ||
252 | { | ||
253 | return false; | ||
254 | } | ||
245 | #endif | 255 | #endif |
246 | 256 | ||
247 | struct pwm_lookup { | 257 | struct pwm_lookup { |