aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt25
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt3
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-sun4i.txt2
-rw-r--r--Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt11
-rw-r--r--Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt10
-rw-r--r--drivers/pwm/Kconfig6
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c1
-rw-r--r--drivers/pwm/pwm-imx.c3
-rw-r--r--drivers/pwm/pwm-jz4740.c41
-rw-r--r--drivers/pwm/pwm-mediatek.c36
-rw-r--r--drivers/pwm/pwm-puv3.c4
-rw-r--r--drivers/pwm/pwm-rcar.c58
-rw-r--r--drivers/pwm/pwm-stm32-lp.c5
-rw-r--r--drivers/pwm/pwm-stm32.c22
-rw-r--r--drivers/pwm/pwm-sun4i.c38
-rw-r--r--drivers/pwm/sysfs.c3
16 files changed, 205 insertions, 63 deletions
diff --git a/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt b/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt
new file mode 100644
index 000000000000..7d9d3f90641b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt
@@ -0,0 +1,25 @@
1Ingenic JZ47xx PWM Controller
2=============================
3
4Required properties:
5- compatible: One of:
6 * "ingenic,jz4740-pwm"
7 * "ingenic,jz4770-pwm"
8 * "ingenic,jz4780-pwm"
9- #pwm-cells: Should be 3. See pwm.txt in this directory for a description
10 of the cells format.
11- clocks : phandle to the external clock.
12- clock-names : Should be "ext".
13
14
15Example:
16
17 pwm: pwm@10002000 {
18 compatible = "ingenic,jz4740-pwm";
19 reg = <0x10002000 0x1000>;
20
21 #pwm-cells = <3>;
22
23 clocks = <&ext>;
24 clock-names = "ext";
25 };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt
index f8338d11fd2b..bd23302e84be 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt
@@ -7,6 +7,8 @@ See ../mfd/stm32-lptimer.txt for details about the parent node.
7 7
8Required parameters: 8Required parameters:
9- compatible: Must be "st,stm32-pwm-lp". 9- compatible: Must be "st,stm32-pwm-lp".
10- #pwm-cells: Should be set to 3. This PWM chip uses the default 3 cells
11 bindings defined in pwm.txt.
10 12
11Optional properties: 13Optional properties:
12- pinctrl-names: Set to "default". 14- pinctrl-names: Set to "default".
@@ -18,6 +20,7 @@ Example:
18 ... 20 ...
19 pwm { 21 pwm {
20 compatible = "st,stm32-pwm-lp"; 22 compatible = "st,stm32-pwm-lp";
23 #pwm-cells = <3>;
21 pinctrl-names = "default"; 24 pinctrl-names = "default";
22 pinctrl-0 = <&lppwm1_pins>; 25 pinctrl-0 = <&lppwm1_pins>;
23 }; 26 };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
index 51ff54c8b8ef..2a1affbff45e 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
@@ -7,6 +7,8 @@ Required properties:
7 - "allwinner,sun5i-a13-pwm" 7 - "allwinner,sun5i-a13-pwm"
8 - "allwinner,sun7i-a20-pwm" 8 - "allwinner,sun7i-a20-pwm"
9 - "allwinner,sun8i-h3-pwm" 9 - "allwinner,sun8i-h3-pwm"
10 - "allwinner,sun50i-a64-pwm", "allwinner,sun5i-a13-pwm"
11 - "allwinner,sun50i-h5-pwm", "allwinner,sun5i-a13-pwm"
10 - reg: physical base address and length of the controller's registers 12 - reg: physical base address and length of the controller's registers
11 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of 13 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
12 the cells format. 14 the cells format.
diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
index 74c118015980..35a3b9761ee5 100644
--- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
+++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
@@ -2,6 +2,8 @@
2 2
3Required Properties: 3Required Properties:
4- compatible: should be "renesas,pwm-rcar" and one of the following. 4- compatible: should be "renesas,pwm-rcar" and one of the following.
5 - "renesas,pwm-r8a7743": for RZ/G1M
6 - "renesas,pwm-r8a7745": for RZ/G1E
5 - "renesas,pwm-r8a7778": for R-Car M1A 7 - "renesas,pwm-r8a7778": for R-Car M1A
6 - "renesas,pwm-r8a7779": for R-Car H1 8 - "renesas,pwm-r8a7779": for R-Car H1
7 - "renesas,pwm-r8a7790": for R-Car H2 9 - "renesas,pwm-r8a7790": for R-Car H2
@@ -9,6 +11,7 @@ Required Properties:
9 - "renesas,pwm-r8a7794": for R-Car E2 11 - "renesas,pwm-r8a7794": for R-Car E2
10 - "renesas,pwm-r8a7795": for R-Car H3 12 - "renesas,pwm-r8a7795": for R-Car H3
11 - "renesas,pwm-r8a7796": for R-Car M3-W 13 - "renesas,pwm-r8a7796": for R-Car M3-W
14 - "renesas,pwm-r8a77965": for R-Car M3-N
12 - "renesas,pwm-r8a77995": for R-Car D3 15 - "renesas,pwm-r8a77995": for R-Car D3
13- reg: base address and length of the registers block for the PWM. 16- reg: base address and length of the registers block for the PWM.
14- #pwm-cells: should be 2. See pwm.txt in this directory for a description of 17- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
@@ -17,13 +20,15 @@ Required Properties:
17- pinctrl-0: phandle, referring to a default pin configuration node. 20- pinctrl-0: phandle, referring to a default pin configuration node.
18- pinctrl-names: Set to "default". 21- pinctrl-names: Set to "default".
19 22
20Example: R8A7790 (R-Car H2) PWM Timer node 23Example: R8A7743 (RZ/G1M) PWM Timer node
21 24
22 pwm0: pwm@e6e30000 { 25 pwm0: pwm@e6e30000 {
23 compatible = "renesas,pwm-r8a7790", "renesas,pwm-rcar"; 26 compatible = "renesas,pwm-r8a7743", "renesas,pwm-rcar";
24 reg = <0 0xe6e30000 0 0x8>; 27 reg = <0 0xe6e30000 0 0x8>;
28 clocks = <&cpg CPG_MOD 523>;
29 power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
30 resets = <&cpg 523>;
25 #pwm-cells = <2>; 31 #pwm-cells = <2>;
26 clocks = <&mstp5_clks R8A7790_CLK_PWM>;
27 pinctrl-0 = <&pwm0_pins>; 32 pinctrl-0 = <&pwm0_pins>;
28 pinctrl-names = "default"; 33 pinctrl-names = "default";
29 }; 34 };
diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt
index 1aadc804dae4..d53a16715da6 100644
--- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt
@@ -3,10 +3,12 @@
3Required Properties: 3Required Properties:
4 4
5 - compatible: should be one of the following. 5 - compatible: should be one of the following.
6 - "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller. 6 - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller.
7 - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. 7 - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller.
8 - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller.
9 - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller.
8 - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. 10 - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller.
9 - "renesas,tpu": for generic R-Car TPU PWM controller. 11 - "renesas,tpu": for generic R-Car and RZ/G1 TPU PWM controller.
10 12
11 - reg: Base address and length of each memory resource used by the PWM 13 - reg: Base address and length of each memory resource used by the PWM
12 controller hardware module. 14 controller hardware module.
@@ -18,10 +20,10 @@ Required Properties:
18Please refer to pwm.txt in this directory for details of the common PWM bindings 20Please refer to pwm.txt in this directory for details of the common PWM bindings
19used by client devices. 21used by client devices.
20 22
21Example: R8A7740 (R-Car A1) TPU controller node 23Example: R8A7740 (R-Mobile A1) TPU controller node
22 24
23 tpu: pwm@e6600000 { 25 tpu: pwm@e6600000 {
24 compatible = "renesas,tpu-r8a7740", "renesas,tpu"; 26 compatible = "renesas,tpu-r8a7740", "renesas,tpu";
25 reg = <0xe6600000 0x100>; 27 reg = <0xe6600000 0x148>;
26 #pwm-cells = <3>; 28 #pwm-cells = <3>;
27 }; 29 };
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 38d49dbbf9b7..4635cb35008c 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -200,10 +200,10 @@ config PWM_IMX
200 will be called pwm-imx. 200 will be called pwm-imx.
201 201
202config PWM_JZ4740 202config PWM_JZ4740
203 tristate "Ingenic JZ4740 PWM support" 203 tristate "Ingenic JZ47xx PWM support"
204 depends on MACH_JZ4740 204 depends on MACH_INGENIC
205 help 205 help
206 Generic PWM framework driver for Ingenic JZ4740 based 206 Generic PWM framework driver for Ingenic JZ47xx based
207 machines. 207 machines.
208 208
209 To compile this driver as a module, choose M here: the module 209 To compile this driver as a module, choose M here: the module
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index acd3ce8ecf3f..4fb1be246c44 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -401,7 +401,6 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
401 tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL); 401 tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL);
402 if (tcbpwm == NULL) { 402 if (tcbpwm == NULL) {
403 err = -ENOMEM; 403 err = -ENOMEM;
404 dev_err(&pdev->dev, "failed to allocate memory\n");
405 goto err_free_tc; 404 goto err_free_tc;
406 } 405 }
407 406
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 2ba5c3a398ff..08cbe8120588 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -35,6 +35,7 @@
35#define MX3_PWMSAR 0x0C /* PWM Sample Register */ 35#define MX3_PWMSAR 0x0C /* PWM Sample Register */
36#define MX3_PWMPR 0x10 /* PWM Period Register */ 36#define MX3_PWMPR 0x10 /* PWM Period Register */
37#define MX3_PWMCR_PRESCALER(x) ((((x) - 1) & 0xFFF) << 4) 37#define MX3_PWMCR_PRESCALER(x) ((((x) - 1) & 0xFFF) << 4)
38#define MX3_PWMCR_STOPEN (1 << 25)
38#define MX3_PWMCR_DOZEEN (1 << 24) 39#define MX3_PWMCR_DOZEEN (1 << 24)
39#define MX3_PWMCR_WAITEN (1 << 23) 40#define MX3_PWMCR_WAITEN (1 << 23)
40#define MX3_PWMCR_DBGEN (1 << 22) 41#define MX3_PWMCR_DBGEN (1 << 22)
@@ -210,7 +211,7 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
210 writel(period_cycles, imx->mmio_base + MX3_PWMPR); 211 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
211 212
212 cr = MX3_PWMCR_PRESCALER(prescale) | 213 cr = MX3_PWMCR_PRESCALER(prescale) |
213 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | 214 MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
214 MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH | 215 MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH |
215 MX3_PWMCR_EN; 216 MX3_PWMCR_EN;
216 217
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index a75ff3622450..a7b134af5e04 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -18,6 +18,7 @@
18#include <linux/gpio.h> 18#include <linux/gpio.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of_device.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/pwm.h> 23#include <linux/pwm.h>
23 24
@@ -71,9 +72,15 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
71{ 72{
72 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm); 73 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm);
73 74
75 /* Disable PWM output.
76 * In TCU2 mode (channel 1/2 on JZ4750+), this must be done before the
77 * counter is stopped, while in TCU1 mode the order does not matter.
78 */
74 ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE; 79 ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
75 jz4740_timer_disable(pwm->hwpwm);
76 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); 80 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
81
82 /* Stop counter */
83 jz4740_timer_disable(pwm->hwpwm);
77} 84}
78 85
79static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 86static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -124,10 +131,29 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
124 return 0; 131 return 0;
125} 132}
126 133
134static int jz4740_pwm_set_polarity(struct pwm_chip *chip,
135 struct pwm_device *pwm, enum pwm_polarity polarity)
136{
137 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
138
139 switch (polarity) {
140 case PWM_POLARITY_NORMAL:
141 ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW;
142 break;
143 case PWM_POLARITY_INVERSED:
144 ctrl |= JZ_TIMER_CTRL_PWM_ACTIVE_LOW;
145 break;
146 }
147
148 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
149 return 0;
150}
151
127static const struct pwm_ops jz4740_pwm_ops = { 152static const struct pwm_ops jz4740_pwm_ops = {
128 .request = jz4740_pwm_request, 153 .request = jz4740_pwm_request,
129 .free = jz4740_pwm_free, 154 .free = jz4740_pwm_free,
130 .config = jz4740_pwm_config, 155 .config = jz4740_pwm_config,
156 .set_polarity = jz4740_pwm_set_polarity,
131 .enable = jz4740_pwm_enable, 157 .enable = jz4740_pwm_enable,
132 .disable = jz4740_pwm_disable, 158 .disable = jz4740_pwm_disable,
133 .owner = THIS_MODULE, 159 .owner = THIS_MODULE,
@@ -149,6 +175,8 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
149 jz4740->chip.ops = &jz4740_pwm_ops; 175 jz4740->chip.ops = &jz4740_pwm_ops;
150 jz4740->chip.npwm = NUM_PWM; 176 jz4740->chip.npwm = NUM_PWM;
151 jz4740->chip.base = -1; 177 jz4740->chip.base = -1;
178 jz4740->chip.of_xlate = of_pwm_xlate_with_flags;
179 jz4740->chip.of_pwm_n_cells = 3;
152 180
153 platform_set_drvdata(pdev, jz4740); 181 platform_set_drvdata(pdev, jz4740);
154 182
@@ -162,9 +190,20 @@ static int jz4740_pwm_remove(struct platform_device *pdev)
162 return pwmchip_remove(&jz4740->chip); 190 return pwmchip_remove(&jz4740->chip);
163} 191}
164 192
193#ifdef CONFIG_OF
194static const struct of_device_id jz4740_pwm_dt_ids[] = {
195 { .compatible = "ingenic,jz4740-pwm", },
196 { .compatible = "ingenic,jz4770-pwm", },
197 { .compatible = "ingenic,jz4780-pwm", },
198 {},
199};
200MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids);
201#endif
202
165static struct platform_driver jz4740_pwm_driver = { 203static struct platform_driver jz4740_pwm_driver = {
166 .driver = { 204 .driver = {
167 .name = "jz4740-pwm", 205 .name = "jz4740-pwm",
206 .of_match_table = of_match_ptr(jz4740_pwm_dt_ids),
168 }, 207 },
169 .probe = jz4740_pwm_probe, 208 .probe = jz4740_pwm_probe,
170 .remove = jz4740_pwm_remove, 209 .remove = jz4740_pwm_remove,
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index f5d97e0ad52b..328c124773b2 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -29,7 +29,9 @@
29#define PWMGDUR 0x0c 29#define PWMGDUR 0x0c
30#define PWMWAVENUM 0x28 30#define PWMWAVENUM 0x28
31#define PWMDWIDTH 0x2c 31#define PWMDWIDTH 0x2c
32#define PWM45DWIDTH_FIXUP 0x30
32#define PWMTHRES 0x30 33#define PWMTHRES 0x30
34#define PWM45THRES_FIXUP 0x34
33 35
34#define PWM_CLK_DIV_MAX 7 36#define PWM_CLK_DIV_MAX 7
35 37
@@ -54,6 +56,7 @@ static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = {
54 56
55struct mtk_pwm_platform_data { 57struct mtk_pwm_platform_data {
56 unsigned int num_pwms; 58 unsigned int num_pwms;
59 bool pwm45_fixup;
57}; 60};
58 61
59/** 62/**
@@ -66,6 +69,7 @@ struct mtk_pwm_chip {
66 struct pwm_chip chip; 69 struct pwm_chip chip;
67 void __iomem *regs; 70 void __iomem *regs;
68 struct clk *clks[MTK_CLK_MAX]; 71 struct clk *clks[MTK_CLK_MAX];
72 const struct mtk_pwm_platform_data *soc;
69}; 73};
70 74
71static const unsigned int mtk_pwm_reg_offset[] = { 75static const unsigned int mtk_pwm_reg_offset[] = {
@@ -131,18 +135,25 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
131{ 135{
132 struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); 136 struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
133 struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]; 137 struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm];
134 u32 resolution, clkdiv = 0; 138 u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH,
139 reg_thres = PWMTHRES;
140 u64 resolution;
135 int ret; 141 int ret;
136 142
137 ret = mtk_pwm_clk_enable(chip, pwm); 143 ret = mtk_pwm_clk_enable(chip, pwm);
138 if (ret < 0) 144 if (ret < 0)
139 return ret; 145 return ret;
140 146
141 resolution = NSEC_PER_SEC / clk_get_rate(clk); 147 /* Using resolution in picosecond gets accuracy higher */
148 resolution = (u64)NSEC_PER_SEC * 1000;
149 do_div(resolution, clk_get_rate(clk));
142 150
143 while (period_ns / resolution > 8191) { 151 cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution);
152 while (cnt_period > 8191) {
144 resolution *= 2; 153 resolution *= 2;
145 clkdiv++; 154 clkdiv++;
155 cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000,
156 resolution);
146 } 157 }
147 158
148 if (clkdiv > PWM_CLK_DIV_MAX) { 159 if (clkdiv > PWM_CLK_DIV_MAX) {
@@ -151,9 +162,19 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
151 return -EINVAL; 162 return -EINVAL;
152 } 163 }
153 164
165 if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
166 /*
167 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
168 * from the other PWMs on MT7623.
169 */
170 reg_width = PWM45DWIDTH_FIXUP;
171 reg_thres = PWM45THRES_FIXUP;
172 }
173
174 cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution);
154 mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); 175 mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv);
155 mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); 176 mtk_pwm_writel(pc, pwm->hwpwm, reg_width, cnt_period);
156 mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); 177 mtk_pwm_writel(pc, pwm->hwpwm, reg_thres, cnt_duty);
157 178
158 mtk_pwm_clk_disable(chip, pwm); 179 mtk_pwm_clk_disable(chip, pwm);
159 180
@@ -211,6 +232,7 @@ static int mtk_pwm_probe(struct platform_device *pdev)
211 data = of_device_get_match_data(&pdev->dev); 232 data = of_device_get_match_data(&pdev->dev);
212 if (data == NULL) 233 if (data == NULL)
213 return -EINVAL; 234 return -EINVAL;
235 pc->soc = data;
214 236
215 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 237 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
216 pc->regs = devm_ioremap_resource(&pdev->dev, res); 238 pc->regs = devm_ioremap_resource(&pdev->dev, res);
@@ -251,14 +273,17 @@ static int mtk_pwm_remove(struct platform_device *pdev)
251 273
252static const struct mtk_pwm_platform_data mt2712_pwm_data = { 274static const struct mtk_pwm_platform_data mt2712_pwm_data = {
253 .num_pwms = 8, 275 .num_pwms = 8,
276 .pwm45_fixup = false,
254}; 277};
255 278
256static const struct mtk_pwm_platform_data mt7622_pwm_data = { 279static const struct mtk_pwm_platform_data mt7622_pwm_data = {
257 .num_pwms = 6, 280 .num_pwms = 6,
281 .pwm45_fixup = false,
258}; 282};
259 283
260static const struct mtk_pwm_platform_data mt7623_pwm_data = { 284static const struct mtk_pwm_platform_data mt7623_pwm_data = {
261 .num_pwms = 5, 285 .num_pwms = 5,
286 .pwm45_fixup = true,
262}; 287};
263 288
264static const struct of_device_id mtk_pwm_of_match[] = { 289static const struct of_device_id mtk_pwm_of_match[] = {
@@ -280,5 +305,4 @@ static struct platform_driver mtk_pwm_driver = {
280module_platform_driver(mtk_pwm_driver); 305module_platform_driver(mtk_pwm_driver);
281 306
282MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); 307MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
283MODULE_ALIAS("platform:mtk-pwm");
284MODULE_LICENSE("GPL"); 308MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
index ed6007b27585..754fd9a98f6b 100644
--- a/drivers/pwm/pwm-puv3.c
+++ b/drivers/pwm/pwm-puv3.c
@@ -107,10 +107,8 @@ static int pwm_probe(struct platform_device *pdev)
107 int ret; 107 int ret;
108 108
109 puv3 = devm_kzalloc(&pdev->dev, sizeof(*puv3), GFP_KERNEL); 109 puv3 = devm_kzalloc(&pdev->dev, sizeof(*puv3), GFP_KERNEL);
110 if (puv3 == NULL) { 110 if (!puv3)
111 dev_err(&pdev->dev, "failed to allocate memory\n");
112 return -ENOMEM; 111 return -ENOMEM;
113 }
114 112
115 puv3->clk = devm_clk_get(&pdev->dev, "OST_CLK"); 113 puv3->clk = devm_clk_get(&pdev->dev, "OST_CLK");
116 if (IS_ERR(puv3->clk)) 114 if (IS_ERR(puv3->clk))
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 1c85ecc9e7ac..91d11f2e2fef 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -134,16 +134,12 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns,
134 134
135static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) 135static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
136{ 136{
137 struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); 137 return pm_runtime_get_sync(chip->dev);
138
139 return clk_prepare_enable(rp->clk);
140} 138}
141 139
142static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 140static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
143{ 141{
144 struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); 142 pm_runtime_put(chip->dev);
145
146 clk_disable_unprepare(rp->clk);
147} 143}
148 144
149static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 145static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -156,8 +152,12 @@ static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
156 if (div < 0) 152 if (div < 0)
157 return div; 153 return div;
158 154
159 /* Let the core driver set pwm->period if disabled and duty_ns == 0 */ 155 /*
160 if (!pwm_is_enabled(pwm) && !duty_ns) 156 * Let the core driver set pwm->period if disabled and duty_ns == 0.
157 * But, this driver should prevent to set the new duty_ns if current
158 * duty_cycle is not set
159 */
160 if (!pwm_is_enabled(pwm) && !duty_ns && !pwm->state.duty_cycle)
161 return 0; 161 return 0;
162 162
163 rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR); 163 rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR);
@@ -258,11 +258,53 @@ static const struct of_device_id rcar_pwm_of_table[] = {
258}; 258};
259MODULE_DEVICE_TABLE(of, rcar_pwm_of_table); 259MODULE_DEVICE_TABLE(of, rcar_pwm_of_table);
260 260
261#ifdef CONFIG_PM_SLEEP
262static struct pwm_device *rcar_pwm_dev_to_pwm_dev(struct device *dev)
263{
264 struct platform_device *pdev = to_platform_device(dev);
265 struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev);
266 struct pwm_chip *chip = &rcar_pwm->chip;
267
268 return &chip->pwms[0];
269}
270
271static int rcar_pwm_suspend(struct device *dev)
272{
273 struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev);
274
275 if (!test_bit(PWMF_REQUESTED, &pwm->flags))
276 return 0;
277
278 pm_runtime_put(dev);
279
280 return 0;
281}
282
283static int rcar_pwm_resume(struct device *dev)
284{
285 struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev);
286
287 if (!test_bit(PWMF_REQUESTED, &pwm->flags))
288 return 0;
289
290 pm_runtime_get_sync(dev);
291
292 rcar_pwm_config(pwm->chip, pwm, pwm->state.duty_cycle,
293 pwm->state.period);
294 if (pwm_is_enabled(pwm))
295 rcar_pwm_enable(pwm->chip, pwm);
296
297 return 0;
298}
299#endif /* CONFIG_PM_SLEEP */
300static SIMPLE_DEV_PM_OPS(rcar_pwm_pm_ops, rcar_pwm_suspend, rcar_pwm_resume);
301
261static struct platform_driver rcar_pwm_driver = { 302static struct platform_driver rcar_pwm_driver = {
262 .probe = rcar_pwm_probe, 303 .probe = rcar_pwm_probe,
263 .remove = rcar_pwm_remove, 304 .remove = rcar_pwm_remove,
264 .driver = { 305 .driver = {
265 .name = "pwm-rcar", 306 .name = "pwm-rcar",
307 .pm = &rcar_pwm_pm_ops,
266 .of_match_table = of_match_ptr(rcar_pwm_of_table), 308 .of_match_table = of_match_ptr(rcar_pwm_of_table),
267 } 309 }
268}; 310};
diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 1ac9e4384142..7c13e2505080 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * STM32 Low-Power Timer PWM driver 3 * STM32 Low-Power Timer PWM driver
3 * 4 *
@@ -5,8 +6,6 @@
5 * 6 *
6 * Author: Gerald Baeza <gerald.baeza@st.com> 7 * Author: Gerald Baeza <gerald.baeza@st.com>
7 * 8 *
8 * License terms: GNU General Public License (GPL), version 2
9 *
10 * Inspired by Gerald Baeza's pwm-stm32 driver 9 * Inspired by Gerald Baeza's pwm-stm32 driver
11 */ 10 */
12 11
@@ -203,6 +202,8 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
203 priv->chip.dev = &pdev->dev; 202 priv->chip.dev = &pdev->dev;
204 priv->chip.ops = &stm32_pwm_lp_ops; 203 priv->chip.ops = &stm32_pwm_lp_ops;
205 priv->chip.npwm = 1; 204 priv->chip.npwm = 1;
205 priv->chip.of_xlate = of_pwm_xlate_with_flags;
206 priv->chip.of_pwm_n_cells = 3;
206 207
207 ret = pwmchip_add(&priv->chip); 208 ret = pwmchip_add(&priv->chip);
208 if (ret < 0) 209 if (ret < 0)
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 6139512aab7b..2708212933f7 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -1,10 +1,9 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) STMicroelectronics 2016 3 * Copyright (C) STMicroelectronics 2016
3 * 4 *
4 * Author: Gerald Baeza <gerald.baeza@st.com> 5 * Author: Gerald Baeza <gerald.baeza@st.com>
5 * 6 *
6 * License terms: GNU General Public License (GPL), version 2
7 *
8 * Inspired by timer-stm32.c from Maxime Coquelin 7 * Inspired by timer-stm32.c from Maxime Coquelin
9 * pwm-atmel.c from Bo Shen 8 * pwm-atmel.c from Bo Shen
10 */ 9 */
@@ -21,7 +20,7 @@
21 20
22struct stm32_pwm { 21struct stm32_pwm {
23 struct pwm_chip chip; 22 struct pwm_chip chip;
24 struct device *dev; 23 struct mutex lock; /* protect pwm config/enable */
25 struct clk *clk; 24 struct clk *clk;
26 struct regmap *regmap; 25 struct regmap *regmap;
27 u32 max_arr; 26 u32 max_arr;
@@ -214,9 +213,23 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
214 return ret; 213 return ret;
215} 214}
216 215
216static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
217 struct pwm_state *state)
218{
219 struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
220 int ret;
221
222 /* protect common prescaler for all active channels */
223 mutex_lock(&priv->lock);
224 ret = stm32_pwm_apply(chip, pwm, state);
225 mutex_unlock(&priv->lock);
226
227 return ret;
228}
229
217static const struct pwm_ops stm32pwm_ops = { 230static const struct pwm_ops stm32pwm_ops = {
218 .owner = THIS_MODULE, 231 .owner = THIS_MODULE,
219 .apply = stm32_pwm_apply, 232 .apply = stm32_pwm_apply_locked,
220}; 233};
221 234
222static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, 235static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
@@ -336,6 +349,7 @@ static int stm32_pwm_probe(struct platform_device *pdev)
336 if (!priv) 349 if (!priv)
337 return -ENOMEM; 350 return -ENOMEM;
338 351
352 mutex_init(&priv->lock);
339 priv->regmap = ddata->regmap; 353 priv->regmap = ddata->regmap;
340 priv->clk = ddata->clk; 354 priv->clk = ddata->clk;
341 priv->max_arr = ddata->max_arr; 355 priv->max_arr = ddata->max_arr;
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 334199c58f1d..470d4f71e7eb 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -73,7 +73,6 @@ static const u32 prescaler_table[] = {
73 73
74struct sun4i_pwm_data { 74struct sun4i_pwm_data {
75 bool has_prescaler_bypass; 75 bool has_prescaler_bypass;
76 bool has_rdy;
77 unsigned int npwm; 76 unsigned int npwm;
78}; 77};
79 78
@@ -117,7 +116,8 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
117 116
118 val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 117 val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
119 118
120 if ((val == PWM_PRESCAL_MASK) && sun4i_pwm->data->has_prescaler_bypass) 119 if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) &&
120 sun4i_pwm->data->has_prescaler_bypass)
121 prescaler = 1; 121 prescaler = 1;
122 else 122 else
123 prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)]; 123 prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)];
@@ -130,7 +130,8 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
130 else 130 else
131 state->polarity = PWM_POLARITY_INVERSED; 131 state->polarity = PWM_POLARITY_INVERSED;
132 132
133 if (val & BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) 133 if ((val & BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) ==
134 BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm))
134 state->enabled = true; 135 state->enabled = true;
135 else 136 else
136 state->enabled = false; 137 state->enabled = false;
@@ -311,52 +312,37 @@ static const struct pwm_ops sun4i_pwm_ops = {
311 .owner = THIS_MODULE, 312 .owner = THIS_MODULE,
312}; 313};
313 314
314static const struct sun4i_pwm_data sun4i_pwm_data_a10 = { 315static const struct sun4i_pwm_data sun4i_pwm_dual_nobypass = {
315 .has_prescaler_bypass = false, 316 .has_prescaler_bypass = false,
316 .has_rdy = false,
317 .npwm = 2, 317 .npwm = 2,
318}; 318};
319 319
320static const struct sun4i_pwm_data sun4i_pwm_data_a10s = { 320static const struct sun4i_pwm_data sun4i_pwm_dual_bypass = {
321 .has_prescaler_bypass = true, 321 .has_prescaler_bypass = true,
322 .has_rdy = true,
323 .npwm = 2, 322 .npwm = 2,
324}; 323};
325 324
326static const struct sun4i_pwm_data sun4i_pwm_data_a13 = { 325static const struct sun4i_pwm_data sun4i_pwm_single_bypass = {
327 .has_prescaler_bypass = true, 326 .has_prescaler_bypass = true,
328 .has_rdy = true,
329 .npwm = 1,
330};
331
332static const struct sun4i_pwm_data sun4i_pwm_data_a20 = {
333 .has_prescaler_bypass = true,
334 .has_rdy = true,
335 .npwm = 2,
336};
337
338static const struct sun4i_pwm_data sun4i_pwm_data_h3 = {
339 .has_prescaler_bypass = true,
340 .has_rdy = true,
341 .npwm = 1, 327 .npwm = 1,
342}; 328};
343 329
344static const struct of_device_id sun4i_pwm_dt_ids[] = { 330static const struct of_device_id sun4i_pwm_dt_ids[] = {
345 { 331 {
346 .compatible = "allwinner,sun4i-a10-pwm", 332 .compatible = "allwinner,sun4i-a10-pwm",
347 .data = &sun4i_pwm_data_a10, 333 .data = &sun4i_pwm_dual_nobypass,
348 }, { 334 }, {
349 .compatible = "allwinner,sun5i-a10s-pwm", 335 .compatible = "allwinner,sun5i-a10s-pwm",
350 .data = &sun4i_pwm_data_a10s, 336 .data = &sun4i_pwm_dual_bypass,
351 }, { 337 }, {
352 .compatible = "allwinner,sun5i-a13-pwm", 338 .compatible = "allwinner,sun5i-a13-pwm",
353 .data = &sun4i_pwm_data_a13, 339 .data = &sun4i_pwm_single_bypass,
354 }, { 340 }, {
355 .compatible = "allwinner,sun7i-a20-pwm", 341 .compatible = "allwinner,sun7i-a20-pwm",
356 .data = &sun4i_pwm_data_a20, 342 .data = &sun4i_pwm_dual_bypass,
357 }, { 343 }, {
358 .compatible = "allwinner,sun8i-h3-pwm", 344 .compatible = "allwinner,sun8i-h3-pwm",
359 .data = &sun4i_pwm_data_h3, 345 .data = &sun4i_pwm_single_bypass,
360 }, { 346 }, {
361 /* sentinel */ 347 /* sentinel */
362 }, 348 },
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 83f2b0b15712..7c71cdb8a9d8 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -273,7 +273,8 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
273 ret = device_register(&export->child); 273 ret = device_register(&export->child);
274 if (ret) { 274 if (ret) {
275 clear_bit(PWMF_EXPORTED, &pwm->flags); 275 clear_bit(PWMF_EXPORTED, &pwm->flags);
276 kfree(export); 276 put_device(&export->child);
277 export = NULL;
277 return ret; 278 return ret;
278 } 279 }
279 280