aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-21 11:17:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-21 11:17:43 -0400
commit5b9c8972527fdb52d5cd7dadc9853c57430e0ff5 (patch)
treea829bb857ae7f19369fd7479597c640d30e0f47e
parent3d430bdb74140224d90dd6253d67ff71d181cf64 (diff)
parentdec02f98ae2e341a2e0bb25f27e84867e5f9f64a (diff)
Merge tag 'pwm/for-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm changes from Thierry Reding: "There are no new drivers here, only a couple of fixes all over the place" * tag 'pwm/for-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: pwm: Let PWM_CLPS711X depend on HAS_IOMEM pwm: atmel: Fix calculation of prescale value pwm: Fix uninitialized warnings in pwm_get() pwm: rockchip: Allow polarity invert on rk3288 pwm: imx: Avoid sample FIFO overflow for i.MX PWM version2 pwm: imx: Cleanup indentation for register definitions pwm: imx: Fix the macro MX3_PWMCR_PRESCALER(x) definition pwm: Fix possible ZERO_SIZE_PTR pointer dereferencing error. pwm: lpss: make it buildable only on X86 pwm: lpss: use c99 initializers in structures pwm: lpss: Fix build failure on PowerPC pwm: lpss: pci: Move to use pcim_enable_device() pwm: lpss: Properly split driver to parts pwm: lpss: Add ACPI and PCI IDs for Intel Braswell pwm: fsl-ftm: Select REGMAP_MMIO pwm: fsl-ftm: Document 'big-endian' property pwm: fsl-ftm: Convert to direct regmap API usage pwm: fsl-ftm: Clean up the code
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt19
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-rockchip.txt4
-rw-r--r--drivers/pwm/Kconfig22
-rw-r--r--drivers/pwm/Makefile2
-rw-r--r--drivers/pwm/core.c31
-rw-r--r--drivers/pwm/pwm-atmel.c24
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c90
-rw-r--r--drivers/pwm/pwm-imx.c71
-rw-r--r--drivers/pwm/pwm-lpss-pci.c64
-rw-r--r--drivers/pwm/pwm-lpss-platform.c68
-rw-r--r--drivers/pwm/pwm-lpss.c137
-rw-r--r--drivers/pwm/pwm-lpss.h32
-rw-r--r--drivers/pwm/pwm-rockchip.c57
13 files changed, 399 insertions, 222 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
index 0bda229a6171..3899d6a557c1 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
@@ -1,5 +1,20 @@
1Freescale FlexTimer Module (FTM) PWM controller 1Freescale FlexTimer Module (FTM) PWM controller
2 2
3The same FTM PWM device can have a different endianness on different SoCs. The
4device tree provides a property to describing this so that an operating system
5device driver can handle all variants of the device. Refer to the table below
6for the endianness of the FTM PWM block as integrated into the existing SoCs:
7
8 SoC | FTM-PWM endianness
9 --------+-------------------
10 Vybrid | LE
11 LS1 | BE
12 LS2 | LE
13
14Please see ../regmap/regmap.txt for more detail about how to specify endian
15modes in device tree.
16
17
3Required properties: 18Required properties:
4- compatible: Should be "fsl,vf610-ftm-pwm". 19- compatible: Should be "fsl,vf610-ftm-pwm".
5- reg: Physical base address and length of the controller's registers 20- reg: Physical base address and length of the controller's registers
@@ -16,7 +31,8 @@ Required properties:
16- pinctrl-names: Must contain a "default" entry. 31- pinctrl-names: Must contain a "default" entry.
17- pinctrl-NNN: One property must exist for each entry in pinctrl-names. 32- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
18 See pinctrl/pinctrl-bindings.txt for details of the property values. 33 See pinctrl/pinctrl-bindings.txt for details of the property values.
19 34- big-endian: Boolean property, required if the FTM PWM registers use a big-
35 endian rather than little-endian layout.
20 36
21Example: 37Example:
22 38
@@ -32,4 +48,5 @@ pwm0: pwm@40038000 {
32 <&clks VF610_CLK_FTM0_EXT_FIX_EN>; 48 <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
33 pinctrl-names = "default"; 49 pinctrl-names = "default";
34 pinctrl-0 = <&pinctrl_pwm0_1>; 50 pinctrl-0 = <&pinctrl_pwm0_1>;
51 big-endian;
35}; 52};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
index d47d15a6a298..b8be3d09ee26 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
@@ -7,8 +7,8 @@ Required properties:
7 "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC 7 "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
8 - reg: physical base address and length of the controller's registers 8 - reg: physical base address and length of the controller's registers
9 - clocks: phandle and clock specifier of the PWM reference clock 9 - clocks: phandle and clock specifier of the PWM reference clock
10 - #pwm-cells: should be 2. See pwm.txt in this directory for a 10 - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
11 description of the cell format. 11 for a description of the cell format.
12 12
13Example: 13Example:
14 14
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index b800783800a3..ef2dd2e4754b 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -83,6 +83,7 @@ config PWM_BFIN
83config PWM_CLPS711X 83config PWM_CLPS711X
84 tristate "CLPS711X PWM support" 84 tristate "CLPS711X PWM support"
85 depends on ARCH_CLPS711X || COMPILE_TEST 85 depends on ARCH_CLPS711X || COMPILE_TEST
86 depends on HAS_IOMEM
86 help 87 help
87 Generic PWM framework driver for Cirrus Logic CLPS711X. 88 Generic PWM framework driver for Cirrus Logic CLPS711X.
88 89
@@ -101,6 +102,7 @@ config PWM_EP93XX
101config PWM_FSL_FTM 102config PWM_FSL_FTM
102 tristate "Freescale FlexTimer Module (FTM) PWM support" 103 tristate "Freescale FlexTimer Module (FTM) PWM support"
103 depends on OF 104 depends on OF
105 select REGMAP_MMIO
104 help 106 help
105 Generic FTM PWM framework driver for Freescale VF610 and 107 Generic FTM PWM framework driver for Freescale VF610 and
106 Layerscape LS-1 SoCs. 108 Layerscape LS-1 SoCs.
@@ -149,7 +151,7 @@ config PWM_LPC32XX
149 151
150config PWM_LPSS 152config PWM_LPSS
151 tristate "Intel LPSS PWM support" 153 tristate "Intel LPSS PWM support"
152 depends on ACPI 154 depends on X86
153 help 155 help
154 Generic PWM framework driver for Intel Low Power Subsystem PWM 156 Generic PWM framework driver for Intel Low Power Subsystem PWM
155 controller. 157 controller.
@@ -157,6 +159,24 @@ config PWM_LPSS
157 To compile this driver as a module, choose M here: the module 159 To compile this driver as a module, choose M here: the module
158 will be called pwm-lpss. 160 will be called pwm-lpss.
159 161
162config PWM_LPSS_PCI
163 tristate "Intel LPSS PWM PCI driver"
164 depends on PWM_LPSS && PCI
165 help
166 The PCI driver for Intel Low Power Subsystem PWM controller.
167
168 To compile this driver as a module, choose M here: the module
169 will be called pwm-lpss-pci.
170
171config PWM_LPSS_PLATFORM
172 tristate "Intel LPSS PWM platform driver"
173 depends on PWM_LPSS && ACPI
174 help
175 The platform driver for Intel Low Power Subsystem PWM controller.
176
177 To compile this driver as a module, choose M here: the module
178 will be called pwm-lpss-platform.
179
160config PWM_MXS 180config PWM_MXS
161 tristate "Freescale MXS PWM support" 181 tristate "Freescale MXS PWM support"
162 depends on ARCH_MXS && OF 182 depends on ARCH_MXS && OF
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index f8c577d41091..c458606c3755 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
13obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o 13obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o
14obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o 14obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
15obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o 15obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o
16obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o
17obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
16obj-$(CONFIG_PWM_MXS) += pwm-mxs.o 18obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
17obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o 19obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
18obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o 20obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index d2c35920ff08..966497d10c6e 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -236,7 +236,7 @@ int pwmchip_add(struct pwm_chip *chip)
236 int ret; 236 int ret;
237 237
238 if (!chip || !chip->dev || !chip->ops || !chip->ops->config || 238 if (!chip || !chip->dev || !chip->ops || !chip->ops->config ||
239 !chip->ops->enable || !chip->ops->disable) 239 !chip->ops->enable || !chip->ops->disable || !chip->npwm)
240 return -EINVAL; 240 return -EINVAL;
241 241
242 mutex_lock(&pwm_lock); 242 mutex_lock(&pwm_lock);
@@ -602,12 +602,9 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
602 struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); 602 struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER);
603 const char *dev_id = dev ? dev_name(dev) : NULL; 603 const char *dev_id = dev ? dev_name(dev) : NULL;
604 struct pwm_chip *chip = NULL; 604 struct pwm_chip *chip = NULL;
605 unsigned int index = 0;
606 unsigned int best = 0; 605 unsigned int best = 0;
607 struct pwm_lookup *p; 606 struct pwm_lookup *p, *chosen = NULL;
608 unsigned int match; 607 unsigned int match;
609 unsigned int period;
610 enum pwm_polarity polarity;
611 608
612 /* look up via DT first */ 609 /* look up via DT first */
613 if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) 610 if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
@@ -653,10 +650,7 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
653 } 650 }
654 651
655 if (match > best) { 652 if (match > best) {
656 chip = pwmchip_find_by_name(p->provider); 653 chosen = p;
657 index = p->index;
658 period = p->period;
659 polarity = p->polarity;
660 654
661 if (match != 3) 655 if (match != 3)
662 best = match; 656 best = match;
@@ -665,17 +659,22 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
665 } 659 }
666 } 660 }
667 661
668 mutex_unlock(&pwm_lookup_lock); 662 if (!chosen)
663 goto out;
669 664
670 if (chip) 665 chip = pwmchip_find_by_name(chosen->provider);
671 pwm = pwm_request_from_chip(chip, index, con_id ?: dev_id); 666 if (!chip)
672 if (IS_ERR(pwm)) 667 goto out;
673 return pwm;
674 668
675 pwm_set_period(pwm, period); 669 pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id);
676 pwm_set_polarity(pwm, polarity); 670 if (IS_ERR(pwm))
671 goto out;
677 672
673 pwm_set_period(pwm, chosen->period);
674 pwm_set_polarity(pwm, chosen->polarity);
678 675
676out:
677 mutex_unlock(&pwm_lookup_lock);
679 return pwm; 678 return pwm;
680} 679}
681EXPORT_SYMBOL_GPL(pwm_get); 680EXPORT_SYMBOL_GPL(pwm_get);
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 6e700a541ca3..d3c22de9ee47 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -102,7 +102,7 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
102 int duty_ns, int period_ns) 102 int duty_ns, int period_ns)
103{ 103{
104 struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); 104 struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
105 unsigned long clk_rate, prd, dty; 105 unsigned long prd, dty;
106 unsigned long long div; 106 unsigned long long div;
107 unsigned int pres = 0; 107 unsigned int pres = 0;
108 u32 val; 108 u32 val;
@@ -113,20 +113,18 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
113 return -EBUSY; 113 return -EBUSY;
114 } 114 }
115 115
116 clk_rate = clk_get_rate(atmel_pwm->clk); 116 /* Calculate the period cycles and prescale value */
117 div = clk_rate; 117 div = (unsigned long long)clk_get_rate(atmel_pwm->clk) * period_ns;
118 do_div(div, NSEC_PER_SEC);
118 119
119 /* Calculate the period cycles */
120 while (div > PWM_MAX_PRD) { 120 while (div > PWM_MAX_PRD) {
121 div = clk_rate / (1 << pres); 121 div >>= 1;
122 div = div * period_ns; 122 pres++;
123 /* 1/Hz = 100000000 ns */ 123 }
124 do_div(div, 1000000000); 124
125 125 if (pres > PRD_MAX_PRES) {
126 if (pres++ > PRD_MAX_PRES) { 126 dev_err(chip->dev, "pres exceeds the maximum value\n");
127 dev_err(chip->dev, "pres exceeds the maximum value\n"); 127 return -EINVAL;
128 return -EINVAL;
129 }
130 } 128 }
131 129
132 /* Calculate the duty cycles */ 130 /* Calculate the duty cycles */
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index a18bc8fea385..0f2cc7ef7784 100644
--- a/drivers/pwm/pwm-fsl-ftm.c
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -18,14 +18,14 @@
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/pwm.h> 20#include <linux/pwm.h>
21#include <linux/regmap.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22 23
23#define FTM_SC 0x00 24#define FTM_SC 0x00
24#define FTM_SC_CLK_MASK 0x3 25#define FTM_SC_CLK_MASK_SHIFT 3
25#define FTM_SC_CLK_SHIFT 3 26#define FTM_SC_CLK_MASK (3 << FTM_SC_CLK_MASK_SHIFT)
26#define FTM_SC_CLK(c) (((c) + 1) << FTM_SC_CLK_SHIFT) 27#define FTM_SC_CLK(c) (((c) + 1) << FTM_SC_CLK_MASK_SHIFT)
27#define FTM_SC_PS_MASK 0x7 28#define FTM_SC_PS_MASK 0x7
28#define FTM_SC_PS_SHIFT 0
29 29
30#define FTM_CNT 0x04 30#define FTM_CNT 0x04
31#define FTM_MOD 0x08 31#define FTM_MOD 0x08
@@ -83,7 +83,7 @@ struct fsl_pwm_chip {
83 unsigned int cnt_select; 83 unsigned int cnt_select;
84 unsigned int clk_ps; 84 unsigned int clk_ps;
85 85
86 void __iomem *base; 86 struct regmap *regmap;
87 87
88 int period_ns; 88 int period_ns;
89 89
@@ -219,10 +219,11 @@ static unsigned long fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc,
219 unsigned long period_ns, 219 unsigned long period_ns,
220 unsigned long duty_ns) 220 unsigned long duty_ns)
221{ 221{
222 unsigned long long val, duty; 222 unsigned long long duty;
223 u32 val;
223 224
224 val = readl(fpc->base + FTM_MOD); 225 regmap_read(fpc->regmap, FTM_MOD, &val);
225 duty = duty_ns * (val + 1); 226 duty = (unsigned long long)duty_ns * (val + 1);
226 do_div(duty, period_ns); 227 do_div(duty, period_ns);
227 228
228 return (unsigned long)duty; 229 return (unsigned long)duty;
@@ -232,7 +233,7 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
232 int duty_ns, int period_ns) 233 int duty_ns, int period_ns)
233{ 234{
234 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 235 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
235 u32 val, period, duty; 236 u32 period, duty;
236 237
237 mutex_lock(&fpc->lock); 238 mutex_lock(&fpc->lock);
238 239
@@ -257,11 +258,9 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
257 return -EINVAL; 258 return -EINVAL;
258 } 259 }
259 260
260 val = readl(fpc->base + FTM_SC); 261 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
261 val &= ~(FTM_SC_PS_MASK << FTM_SC_PS_SHIFT); 262 fpc->clk_ps);
262 val |= fpc->clk_ps; 263 regmap_write(fpc->regmap, FTM_MOD, period - 1);
263 writel(val, fpc->base + FTM_SC);
264 writel(period - 1, fpc->base + FTM_MOD);
265 264
266 fpc->period_ns = period_ns; 265 fpc->period_ns = period_ns;
267 } 266 }
@@ -270,8 +269,9 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
270 269
271 duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns); 270 duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns);
272 271
273 writel(FTM_CSC_MSB | FTM_CSC_ELSB, fpc->base + FTM_CSC(pwm->hwpwm)); 272 regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm),
274 writel(duty, fpc->base + FTM_CV(pwm->hwpwm)); 273 FTM_CSC_MSB | FTM_CSC_ELSB);
274 regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty);
275 275
276 return 0; 276 return 0;
277} 277}
@@ -283,31 +283,28 @@ static int fsl_pwm_set_polarity(struct pwm_chip *chip,
283 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 283 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
284 u32 val; 284 u32 val;
285 285
286 val = readl(fpc->base + FTM_POL); 286 regmap_read(fpc->regmap, FTM_POL, &val);
287 287
288 if (polarity == PWM_POLARITY_INVERSED) 288 if (polarity == PWM_POLARITY_INVERSED)
289 val |= BIT(pwm->hwpwm); 289 val |= BIT(pwm->hwpwm);
290 else 290 else
291 val &= ~BIT(pwm->hwpwm); 291 val &= ~BIT(pwm->hwpwm);
292 292
293 writel(val, fpc->base + FTM_POL); 293 regmap_write(fpc->regmap, FTM_POL, val);
294 294
295 return 0; 295 return 0;
296} 296}
297 297
298static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc) 298static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
299{ 299{
300 u32 val;
301 int ret; 300 int ret;
302 301
303 if (fpc->use_count != 0) 302 if (fpc->use_count != 0)
304 return 0; 303 return 0;
305 304
306 /* select counter clock source */ 305 /* select counter clock source */
307 val = readl(fpc->base + FTM_SC); 306 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
308 val &= ~(FTM_SC_CLK_MASK << FTM_SC_CLK_SHIFT); 307 FTM_SC_CLK(fpc->cnt_select));
309 val |= FTM_SC_CLK(fpc->cnt_select);
310 writel(val, fpc->base + FTM_SC);
311 308
312 ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]); 309 ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]);
313 if (ret) 310 if (ret)
@@ -327,13 +324,10 @@ static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
327static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 324static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
328{ 325{
329 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 326 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
330 u32 val;
331 int ret; 327 int ret;
332 328
333 mutex_lock(&fpc->lock); 329 mutex_lock(&fpc->lock);
334 val = readl(fpc->base + FTM_OUTMASK); 330 regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), 0);
335 val &= ~BIT(pwm->hwpwm);
336 writel(val, fpc->base + FTM_OUTMASK);
337 331
338 ret = fsl_counter_clock_enable(fpc); 332 ret = fsl_counter_clock_enable(fpc);
339 mutex_unlock(&fpc->lock); 333 mutex_unlock(&fpc->lock);
@@ -343,8 +337,6 @@ static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
343 337
344static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc) 338static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
345{ 339{
346 u32 val;
347
348 /* 340 /*
349 * already disabled, do nothing 341 * already disabled, do nothing
350 */ 342 */
@@ -356,9 +348,7 @@ static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
356 return; 348 return;
357 349
358 /* no users left, disable PWM counter clock */ 350 /* no users left, disable PWM counter clock */
359 val = readl(fpc->base + FTM_SC); 351 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK, 0);
360 val &= ~(FTM_SC_CLK_MASK << FTM_SC_CLK_SHIFT);
361 writel(val, fpc->base + FTM_SC);
362 352
363 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]); 353 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
364 clk_disable_unprepare(fpc->clk[fpc->cnt_select]); 354 clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
@@ -370,14 +360,12 @@ static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
370 u32 val; 360 u32 val;
371 361
372 mutex_lock(&fpc->lock); 362 mutex_lock(&fpc->lock);
373 val = readl(fpc->base + FTM_OUTMASK); 363 regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
374 val |= BIT(pwm->hwpwm); 364 BIT(pwm->hwpwm));
375 writel(val, fpc->base + FTM_OUTMASK);
376 365
377 fsl_counter_clock_disable(fpc); 366 fsl_counter_clock_disable(fpc);
378 367
379 val = readl(fpc->base + FTM_OUTMASK); 368 regmap_read(fpc->regmap, FTM_OUTMASK, &val);
380
381 if ((val & 0xFF) == 0xFF) 369 if ((val & 0xFF) == 0xFF)
382 fpc->period_ns = 0; 370 fpc->period_ns = 0;
383 371
@@ -402,19 +390,28 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
402 if (ret) 390 if (ret)
403 return ret; 391 return ret;
404 392
405 writel(0x00, fpc->base + FTM_CNTIN); 393 regmap_write(fpc->regmap, FTM_CNTIN, 0x00);
406 writel(0x00, fpc->base + FTM_OUTINIT); 394 regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
407 writel(0xFF, fpc->base + FTM_OUTMASK); 395 regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
408 396
409 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); 397 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
410 398
411 return 0; 399 return 0;
412} 400}
413 401
402static const struct regmap_config fsl_pwm_regmap_config = {
403 .reg_bits = 32,
404 .reg_stride = 4,
405 .val_bits = 32,
406
407 .max_register = FTM_PWMLOAD,
408};
409
414static int fsl_pwm_probe(struct platform_device *pdev) 410static int fsl_pwm_probe(struct platform_device *pdev)
415{ 411{
416 struct fsl_pwm_chip *fpc; 412 struct fsl_pwm_chip *fpc;
417 struct resource *res; 413 struct resource *res;
414 void __iomem *base;
418 int ret; 415 int ret;
419 416
420 fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL); 417 fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL);
@@ -426,9 +423,16 @@ static int fsl_pwm_probe(struct platform_device *pdev)
426 fpc->chip.dev = &pdev->dev; 423 fpc->chip.dev = &pdev->dev;
427 424
428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 425 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
429 fpc->base = devm_ioremap_resource(&pdev->dev, res); 426 base = devm_ioremap_resource(&pdev->dev, res);
430 if (IS_ERR(fpc->base)) 427 if (IS_ERR(base))
431 return PTR_ERR(fpc->base); 428 return PTR_ERR(base);
429
430 fpc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
431 &fsl_pwm_regmap_config);
432 if (IS_ERR(fpc->regmap)) {
433 dev_err(&pdev->dev, "regmap init failed\n");
434 return PTR_ERR(fpc->regmap);
435 }
432 436
433 fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys"); 437 fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys");
434 if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) { 438 if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) {
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 5449d9150d40..f8b5f109c1ab 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/delay.h>
17#include <linux/io.h> 18#include <linux/io.h>
18#include <linux/pwm.h> 19#include <linux/pwm.h>
19#include <linux/of.h> 20#include <linux/of.h>
@@ -21,24 +22,30 @@
21 22
22/* i.MX1 and i.MX21 share the same PWM function block: */ 23/* i.MX1 and i.MX21 share the same PWM function block: */
23 24
24#define MX1_PWMC 0x00 /* PWM Control Register */ 25#define MX1_PWMC 0x00 /* PWM Control Register */
25#define MX1_PWMS 0x04 /* PWM Sample Register */ 26#define MX1_PWMS 0x04 /* PWM Sample Register */
26#define MX1_PWMP 0x08 /* PWM Period Register */ 27#define MX1_PWMP 0x08 /* PWM Period Register */
27 28
28#define MX1_PWMC_EN (1 << 4) 29#define MX1_PWMC_EN (1 << 4)
29 30
30/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */ 31/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
31 32
32#define MX3_PWMCR 0x00 /* PWM Control Register */ 33#define MX3_PWMCR 0x00 /* PWM Control Register */
33#define MX3_PWMSAR 0x0C /* PWM Sample Register */ 34#define MX3_PWMSR 0x04 /* PWM Status Register */
34#define MX3_PWMPR 0x10 /* PWM Period Register */ 35#define MX3_PWMSAR 0x0C /* PWM Sample Register */
35#define MX3_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4) 36#define MX3_PWMPR 0x10 /* PWM Period Register */
36#define MX3_PWMCR_DOZEEN (1 << 24) 37#define MX3_PWMCR_PRESCALER(x) ((((x) - 1) & 0xFFF) << 4)
37#define MX3_PWMCR_WAITEN (1 << 23) 38#define MX3_PWMCR_DOZEEN (1 << 24)
39#define MX3_PWMCR_WAITEN (1 << 23)
38#define MX3_PWMCR_DBGEN (1 << 22) 40#define MX3_PWMCR_DBGEN (1 << 22)
39#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) 41#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
40#define MX3_PWMCR_CLKSRC_IPG (1 << 16) 42#define MX3_PWMCR_CLKSRC_IPG (1 << 16)
41#define MX3_PWMCR_EN (1 << 0) 43#define MX3_PWMCR_SWR (1 << 3)
44#define MX3_PWMCR_EN (1 << 0)
45#define MX3_PWMSR_FIFOAV_4WORDS 0x4
46#define MX3_PWMSR_FIFOAV_MASK 0x7
47
48#define MX3_PWM_SWR_LOOP 5
42 49
43struct imx_chip { 50struct imx_chip {
44 struct clk *clk_per; 51 struct clk *clk_per;
@@ -103,9 +110,43 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
103 struct pwm_device *pwm, int duty_ns, int period_ns) 110 struct pwm_device *pwm, int duty_ns, int period_ns)
104{ 111{
105 struct imx_chip *imx = to_imx_chip(chip); 112 struct imx_chip *imx = to_imx_chip(chip);
113 struct device *dev = chip->dev;
106 unsigned long long c; 114 unsigned long long c;
107 unsigned long period_cycles, duty_cycles, prescale; 115 unsigned long period_cycles, duty_cycles, prescale;
108 u32 cr; 116 unsigned int period_ms;
117 bool enable = test_bit(PWMF_ENABLED, &pwm->flags);
118 int wait_count = 0, fifoav;
119 u32 cr, sr;
120
121 /*
122 * i.MX PWMv2 has a 4-word sample FIFO.
123 * In order to avoid FIFO overflow issue, we do software reset
124 * to clear all sample FIFO if the controller is disabled or
125 * wait for a full PWM cycle to get a relinquished FIFO slot
126 * when the controller is enabled and the FIFO is fully loaded.
127 */
128 if (enable) {
129 sr = readl(imx->mmio_base + MX3_PWMSR);
130 fifoav = sr & MX3_PWMSR_FIFOAV_MASK;
131 if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
132 period_ms = DIV_ROUND_UP(pwm->period, NSEC_PER_MSEC);
133 msleep(period_ms);
134
135 sr = readl(imx->mmio_base + MX3_PWMSR);
136 if (fifoav == (sr & MX3_PWMSR_FIFOAV_MASK))
137 dev_warn(dev, "there is no free FIFO slot\n");
138 }
139 } else {
140 writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
141 do {
142 usleep_range(200, 1000);
143 cr = readl(imx->mmio_base + MX3_PWMCR);
144 } while ((cr & MX3_PWMCR_SWR) &&
145 (wait_count++ < MX3_PWM_SWR_LOOP));
146
147 if (cr & MX3_PWMCR_SWR)
148 dev_warn(dev, "software reset timeout\n");
149 }
109 150
110 c = clk_get_rate(imx->clk_per); 151 c = clk_get_rate(imx->clk_per);
111 c = c * period_ns; 152 c = c * period_ns;
@@ -135,7 +176,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
135 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | 176 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
136 MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH; 177 MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
137 178
138 if (test_bit(PWMF_ENABLED, &pwm->flags)) 179 if (enable)
139 cr |= MX3_PWMCR_EN; 180 cr |= MX3_PWMCR_EN;
140 181
141 writel(cr, imx->mmio_base + MX3_PWMCR); 182 writel(cr, imx->mmio_base + MX3_PWMCR);
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
new file mode 100644
index 000000000000..cf20d2beacdd
--- /dev/null
+++ b/drivers/pwm/pwm-lpss-pci.c
@@ -0,0 +1,64 @@
1/*
2 * Intel Low Power Subsystem PWM controller PCI driver
3 *
4 * Copyright (C) 2014, Intel Corporation
5 *
6 * Derived from the original pwm-lpss.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/pci.h>
16
17#include "pwm-lpss.h"
18
19static int pwm_lpss_probe_pci(struct pci_dev *pdev,
20 const struct pci_device_id *id)
21{
22 const struct pwm_lpss_boardinfo *info;
23 struct pwm_lpss_chip *lpwm;
24 int err;
25
26 err = pcim_enable_device(pdev);
27 if (err < 0)
28 return err;
29
30 info = (struct pwm_lpss_boardinfo *)id->driver_data;
31 lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info);
32 if (IS_ERR(lpwm))
33 return PTR_ERR(lpwm);
34
35 pci_set_drvdata(pdev, lpwm);
36 return 0;
37}
38
39static void pwm_lpss_remove_pci(struct pci_dev *pdev)
40{
41 struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev);
42
43 pwm_lpss_remove(lpwm);
44}
45
46static const struct pci_device_id pwm_lpss_pci_ids[] = {
47 { PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
48 { PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info},
49 { PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
50 { PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
51 { },
52};
53MODULE_DEVICE_TABLE(pci, pwm_lpss_pci_ids);
54
55static struct pci_driver pwm_lpss_driver_pci = {
56 .name = "pwm-lpss",
57 .id_table = pwm_lpss_pci_ids,
58 .probe = pwm_lpss_probe_pci,
59 .remove = pwm_lpss_remove_pci,
60};
61module_pci_driver(pwm_lpss_driver_pci);
62
63MODULE_DESCRIPTION("PWM PCI driver for Intel LPSS");
64MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
new file mode 100644
index 000000000000..18a9c880a76d
--- /dev/null
+++ b/drivers/pwm/pwm-lpss-platform.c
@@ -0,0 +1,68 @@
1/*
2 * Intel Low Power Subsystem PWM controller driver
3 *
4 * Copyright (C) 2014, Intel Corporation
5 *
6 * Derived from the original pwm-lpss.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/acpi.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17
18#include "pwm-lpss.h"
19
20static int pwm_lpss_probe_platform(struct platform_device *pdev)
21{
22 const struct pwm_lpss_boardinfo *info;
23 const struct acpi_device_id *id;
24 struct pwm_lpss_chip *lpwm;
25 struct resource *r;
26
27 id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
28 if (!id)
29 return -ENODEV;
30
31 info = (const struct pwm_lpss_boardinfo *)id->driver_data;
32 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
33
34 lpwm = pwm_lpss_probe(&pdev->dev, r, info);
35 if (IS_ERR(lpwm))
36 return PTR_ERR(lpwm);
37
38 platform_set_drvdata(pdev, lpwm);
39 return 0;
40}
41
42static int pwm_lpss_remove_platform(struct platform_device *pdev)
43{
44 struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
45
46 return pwm_lpss_remove(lpwm);
47}
48
49static const struct acpi_device_id pwm_lpss_acpi_match[] = {
50 { "80860F09", (unsigned long)&pwm_lpss_byt_info },
51 { "80862288", (unsigned long)&pwm_lpss_bsw_info },
52 { },
53};
54MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
55
56static struct platform_driver pwm_lpss_driver_platform = {
57 .driver = {
58 .name = "pwm-lpss",
59 .acpi_match_table = pwm_lpss_acpi_match,
60 },
61 .probe = pwm_lpss_probe_platform,
62 .remove = pwm_lpss_remove_platform,
63};
64module_platform_driver(pwm_lpss_driver_platform);
65
66MODULE_DESCRIPTION("PWM platform driver for Intel LPSS");
67MODULE_LICENSE("GPL v2");
68MODULE_ALIAS("platform:pwm-lpss");
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 4df994f72d96..e9798253a16f 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -13,15 +13,11 @@
13 * published by the Free Software Foundation. 13 * published by the Free Software Foundation.
14 */ 14 */
15 15
16#include <linux/acpi.h> 16#include <linux/io.h>
17#include <linux/device.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
19#include <linux/module.h> 18#include <linux/module.h>
20#include <linux/pwm.h>
21#include <linux/platform_device.h>
22#include <linux/pci.h>
23 19
24static int pci_drv, plat_drv; /* So we know which drivers registered */ 20#include "pwm-lpss.h"
25 21
26#define PWM 0x00000000 22#define PWM 0x00000000
27#define PWM_ENABLE BIT(31) 23#define PWM_ENABLE BIT(31)
@@ -39,14 +35,17 @@ struct pwm_lpss_chip {
39 unsigned long clk_rate; 35 unsigned long clk_rate;
40}; 36};
41 37
42struct pwm_lpss_boardinfo { 38/* BayTrail */
43 unsigned long clk_rate; 39const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
40 .clk_rate = 25000000
44}; 41};
42EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
45 43
46/* BayTrail */ 44/* Braswell */
47static const struct pwm_lpss_boardinfo byt_info = { 45const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
48 25000000 46 .clk_rate = 19200000
49}; 47};
48EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
50 49
51static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) 50static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
52{ 51{
@@ -118,9 +117,8 @@ static const struct pwm_ops pwm_lpss_ops = {
118 .owner = THIS_MODULE, 117 .owner = THIS_MODULE,
119}; 118};
120 119
121static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, 120struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
122 struct resource *r, 121 const struct pwm_lpss_boardinfo *info)
123 const struct pwm_lpss_boardinfo *info)
124{ 122{
125 struct pwm_lpss_chip *lpwm; 123 struct pwm_lpss_chip *lpwm;
126 int ret; 124 int ret;
@@ -147,8 +145,9 @@ static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev,
147 145
148 return lpwm; 146 return lpwm;
149} 147}
148EXPORT_SYMBOL_GPL(pwm_lpss_probe);
150 149
151static int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) 150int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
152{ 151{
153 u32 ctrl; 152 u32 ctrl;
154 153
@@ -157,114 +156,8 @@ static int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
157 156
158 return pwmchip_remove(&lpwm->chip); 157 return pwmchip_remove(&lpwm->chip);
159} 158}
160 159EXPORT_SYMBOL_GPL(pwm_lpss_remove);
161static int pwm_lpss_probe_pci(struct pci_dev *pdev,
162 const struct pci_device_id *id)
163{
164 const struct pwm_lpss_boardinfo *info;
165 struct pwm_lpss_chip *lpwm;
166 int err;
167
168 err = pci_enable_device(pdev);
169 if (err < 0)
170 return err;
171
172 info = (struct pwm_lpss_boardinfo *)id->driver_data;
173 lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info);
174 if (IS_ERR(lpwm))
175 return PTR_ERR(lpwm);
176
177 pci_set_drvdata(pdev, lpwm);
178 return 0;
179}
180
181static void pwm_lpss_remove_pci(struct pci_dev *pdev)
182{
183 struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev);
184
185 pwm_lpss_remove(lpwm);
186 pci_disable_device(pdev);
187}
188
189static struct pci_device_id pwm_lpss_pci_ids[] = {
190 { PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&byt_info},
191 { PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&byt_info},
192 { },
193};
194MODULE_DEVICE_TABLE(pci, pwm_lpss_pci_ids);
195
196static struct pci_driver pwm_lpss_driver_pci = {
197 .name = "pwm-lpss",
198 .id_table = pwm_lpss_pci_ids,
199 .probe = pwm_lpss_probe_pci,
200 .remove = pwm_lpss_remove_pci,
201};
202
203static int pwm_lpss_probe_platform(struct platform_device *pdev)
204{
205 const struct pwm_lpss_boardinfo *info;
206 const struct acpi_device_id *id;
207 struct pwm_lpss_chip *lpwm;
208 struct resource *r;
209
210 id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
211 if (!id)
212 return -ENODEV;
213
214 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
215
216 info = (struct pwm_lpss_boardinfo *)id->driver_data;
217 lpwm = pwm_lpss_probe(&pdev->dev, r, info);
218 if (IS_ERR(lpwm))
219 return PTR_ERR(lpwm);
220
221 platform_set_drvdata(pdev, lpwm);
222 return 0;
223}
224
225static int pwm_lpss_remove_platform(struct platform_device *pdev)
226{
227 struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
228
229 return pwm_lpss_remove(lpwm);
230}
231
232static const struct acpi_device_id pwm_lpss_acpi_match[] = {
233 { "80860F09", (unsigned long)&byt_info },
234 { },
235};
236MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
237
238static struct platform_driver pwm_lpss_driver_platform = {
239 .driver = {
240 .name = "pwm-lpss",
241 .acpi_match_table = pwm_lpss_acpi_match,
242 },
243 .probe = pwm_lpss_probe_platform,
244 .remove = pwm_lpss_remove_platform,
245};
246
247static int __init pwm_init(void)
248{
249 pci_drv = pci_register_driver(&pwm_lpss_driver_pci);
250 plat_drv = platform_driver_register(&pwm_lpss_driver_platform);
251 if (pci_drv && plat_drv)
252 return pci_drv;
253
254 return 0;
255}
256module_init(pwm_init);
257
258static void __exit pwm_exit(void)
259{
260 if (!pci_drv)
261 pci_unregister_driver(&pwm_lpss_driver_pci);
262 if (!plat_drv)
263 platform_driver_unregister(&pwm_lpss_driver_platform);
264}
265module_exit(pwm_exit);
266 160
267MODULE_DESCRIPTION("PWM driver for Intel LPSS"); 161MODULE_DESCRIPTION("PWM driver for Intel LPSS");
268MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 162MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
269MODULE_LICENSE("GPL v2"); 163MODULE_LICENSE("GPL v2");
270MODULE_ALIAS("platform:pwm-lpss");
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
new file mode 100644
index 000000000000..aa041bb1b67d
--- /dev/null
+++ b/drivers/pwm/pwm-lpss.h
@@ -0,0 +1,32 @@
1/*
2 * Intel Low Power Subsystem PWM controller driver
3 *
4 * Copyright (C) 2014, Intel Corporation
5 *
6 * Derived from the original pwm-lpss.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __PWM_LPSS_H
14#define __PWM_LPSS_H
15
16#include <linux/device.h>
17#include <linux/pwm.h>
18
19struct pwm_lpss_chip;
20
21struct pwm_lpss_boardinfo {
22 unsigned long clk_rate;
23};
24
25extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
26extern const struct pwm_lpss_boardinfo pwm_lpss_bsw_info;
27
28struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
29 const struct pwm_lpss_boardinfo *info);
30int pwm_lpss_remove(struct pwm_lpss_chip *lpwm);
31
32#endif /* __PWM_LPSS_H */
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index bdd8644c01cf..9442df244101 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -24,7 +24,9 @@
24#define PWM_ENABLE (1 << 0) 24#define PWM_ENABLE (1 << 0)
25#define PWM_CONTINUOUS (1 << 1) 25#define PWM_CONTINUOUS (1 << 1)
26#define PWM_DUTY_POSITIVE (1 << 3) 26#define PWM_DUTY_POSITIVE (1 << 3)
27#define PWM_DUTY_NEGATIVE (0 << 3)
27#define PWM_INACTIVE_NEGATIVE (0 << 4) 28#define PWM_INACTIVE_NEGATIVE (0 << 4)
29#define PWM_INACTIVE_POSITIVE (1 << 4)
28#define PWM_OUTPUT_LEFT (0 << 5) 30#define PWM_OUTPUT_LEFT (0 << 5)
29#define PWM_LP_DISABLE (0 << 8) 31#define PWM_LP_DISABLE (0 << 8)
30 32
@@ -45,8 +47,10 @@ struct rockchip_pwm_regs {
45struct rockchip_pwm_data { 47struct rockchip_pwm_data {
46 struct rockchip_pwm_regs regs; 48 struct rockchip_pwm_regs regs;
47 unsigned int prescaler; 49 unsigned int prescaler;
50 const struct pwm_ops *ops;
48 51
49 void (*set_enable)(struct pwm_chip *chip, bool enable); 52 void (*set_enable)(struct pwm_chip *chip,
53 struct pwm_device *pwm, bool enable);
50}; 54};
51 55
52static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) 56static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
@@ -54,7 +58,8 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
54 return container_of(c, struct rockchip_pwm_chip, chip); 58 return container_of(c, struct rockchip_pwm_chip, chip);
55} 59}
56 60
57static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable) 61static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
62 struct pwm_device *pwm, bool enable)
58{ 63{
59 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 64 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
60 u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; 65 u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
@@ -70,14 +75,19 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
70 writel_relaxed(val, pc->base + pc->data->regs.ctrl); 75 writel_relaxed(val, pc->base + pc->data->regs.ctrl);
71} 76}
72 77
73static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable) 78static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
79 struct pwm_device *pwm, bool enable)
74{ 80{
75 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 81 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
76 u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | 82 u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
77 PWM_CONTINUOUS | PWM_DUTY_POSITIVE | 83 PWM_CONTINUOUS;
78 PWM_INACTIVE_NEGATIVE;
79 u32 val; 84 u32 val;
80 85
86 if (pwm->polarity == PWM_POLARITY_INVERSED)
87 enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
88 else
89 enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
90
81 val = readl_relaxed(pc->base + pc->data->regs.ctrl); 91 val = readl_relaxed(pc->base + pc->data->regs.ctrl);
82 92
83 if (enable) 93 if (enable)
@@ -124,6 +134,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
124 return 0; 134 return 0;
125} 135}
126 136
137static int rockchip_pwm_set_polarity(struct pwm_chip *chip,
138 struct pwm_device *pwm,
139 enum pwm_polarity polarity)
140{
141 /*
142 * No action needed here because pwm->polarity will be set by the core
143 * and the core will only change polarity when the PWM is not enabled.
144 * We'll handle things in set_enable().
145 */
146
147 return 0;
148}
149
127static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 150static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
128{ 151{
129 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 152 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
@@ -133,7 +156,7 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
133 if (ret) 156 if (ret)
134 return ret; 157 return ret;
135 158
136 pc->data->set_enable(chip, true); 159 pc->data->set_enable(chip, pwm, true);
137 160
138 return 0; 161 return 0;
139} 162}
@@ -142,18 +165,26 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
142{ 165{
143 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 166 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
144 167
145 pc->data->set_enable(chip, false); 168 pc->data->set_enable(chip, pwm, false);
146 169
147 clk_disable(pc->clk); 170 clk_disable(pc->clk);
148} 171}
149 172
150static const struct pwm_ops rockchip_pwm_ops = { 173static const struct pwm_ops rockchip_pwm_ops_v1 = {
151 .config = rockchip_pwm_config, 174 .config = rockchip_pwm_config,
152 .enable = rockchip_pwm_enable, 175 .enable = rockchip_pwm_enable,
153 .disable = rockchip_pwm_disable, 176 .disable = rockchip_pwm_disable,
154 .owner = THIS_MODULE, 177 .owner = THIS_MODULE,
155}; 178};
156 179
180static const struct pwm_ops rockchip_pwm_ops_v2 = {
181 .config = rockchip_pwm_config,
182 .set_polarity = rockchip_pwm_set_polarity,
183 .enable = rockchip_pwm_enable,
184 .disable = rockchip_pwm_disable,
185 .owner = THIS_MODULE,
186};
187
157static const struct rockchip_pwm_data pwm_data_v1 = { 188static const struct rockchip_pwm_data pwm_data_v1 = {
158 .regs = { 189 .regs = {
159 .duty = 0x04, 190 .duty = 0x04,
@@ -162,6 +193,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = {
162 .ctrl = 0x0c, 193 .ctrl = 0x0c,
163 }, 194 },
164 .prescaler = 2, 195 .prescaler = 2,
196 .ops = &rockchip_pwm_ops_v1,
165 .set_enable = rockchip_pwm_set_enable_v1, 197 .set_enable = rockchip_pwm_set_enable_v1,
166}; 198};
167 199
@@ -173,6 +205,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
173 .ctrl = 0x0c, 205 .ctrl = 0x0c,
174 }, 206 },
175 .prescaler = 1, 207 .prescaler = 1,
208 .ops = &rockchip_pwm_ops_v2,
176 .set_enable = rockchip_pwm_set_enable_v2, 209 .set_enable = rockchip_pwm_set_enable_v2,
177}; 210};
178 211
@@ -184,6 +217,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
184 .ctrl = 0x00, 217 .ctrl = 0x00,
185 }, 218 },
186 .prescaler = 1, 219 .prescaler = 1,
220 .ops = &rockchip_pwm_ops_v2,
187 .set_enable = rockchip_pwm_set_enable_v2, 221 .set_enable = rockchip_pwm_set_enable_v2,
188}; 222};
189 223
@@ -227,10 +261,15 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
227 261
228 pc->data = id->data; 262 pc->data = id->data;
229 pc->chip.dev = &pdev->dev; 263 pc->chip.dev = &pdev->dev;
230 pc->chip.ops = &rockchip_pwm_ops; 264 pc->chip.ops = pc->data->ops;
231 pc->chip.base = -1; 265 pc->chip.base = -1;
232 pc->chip.npwm = 1; 266 pc->chip.npwm = 1;
233 267
268 if (pc->data->ops->set_polarity) {
269 pc->chip.of_xlate = of_pwm_xlate_with_flags;
270 pc->chip.of_pwm_n_cells = 3;
271 }
272
234 ret = pwmchip_add(&pc->chip); 273 ret = pwmchip_add(&pc->chip);
235 if (ret < 0) { 274 if (ret < 0) {
236 clk_unprepare(pc->clk); 275 clk_unprepare(pc->clk);