diff options
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt | 25 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt | 3 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/pwm-sun4i.txt | 2 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 11 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 10 | ||||
| -rw-r--r-- | drivers/pwm/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/pwm/pwm-atmel-tcb.c | 1 | ||||
| -rw-r--r-- | drivers/pwm/pwm-imx.c | 3 | ||||
| -rw-r--r-- | drivers/pwm/pwm-jz4740.c | 41 | ||||
| -rw-r--r-- | drivers/pwm/pwm-mediatek.c | 36 | ||||
| -rw-r--r-- | drivers/pwm/pwm-puv3.c | 4 | ||||
| -rw-r--r-- | drivers/pwm/pwm-rcar.c | 58 | ||||
| -rw-r--r-- | drivers/pwm/pwm-stm32-lp.c | 5 | ||||
| -rw-r--r-- | drivers/pwm/pwm-stm32.c | 22 | ||||
| -rw-r--r-- | drivers/pwm/pwm-sun4i.c | 38 | ||||
| -rw-r--r-- | drivers/pwm/sysfs.c | 3 |
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 @@ | |||
| 1 | Ingenic JZ47xx PWM Controller | ||
| 2 | ============================= | ||
| 3 | |||
| 4 | Required 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 | |||
| 15 | Example: | ||
| 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 | ||
| 8 | Required parameters: | 8 | Required 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 | ||
| 11 | Optional properties: | 13 | Optional 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 | ||
| 3 | Required Properties: | 3 | Required 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 | ||
| 20 | Example: R8A7790 (R-Car H2) PWM Timer node | 23 | Example: 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 @@ | |||
| 3 | Required Properties: | 3 | Required 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: | |||
| 18 | Please refer to pwm.txt in this directory for details of the common PWM bindings | 20 | Please refer to pwm.txt in this directory for details of the common PWM bindings |
| 19 | used by client devices. | 21 | used by client devices. |
| 20 | 22 | ||
| 21 | Example: R8A7740 (R-Car A1) TPU controller node | 23 | Example: 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 | ||
| 202 | config PWM_JZ4740 | 202 | config 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 | ||
| 79 | static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 86 | static 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 | ||
| 134 | static 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 | |||
| 127 | static const struct pwm_ops jz4740_pwm_ops = { | 152 | static 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 | ||
| 194 | static 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 | }; | ||
| 200 | MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids); | ||
| 201 | #endif | ||
| 202 | |||
| 165 | static struct platform_driver jz4740_pwm_driver = { | 203 | static 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 | ||
| 55 | struct mtk_pwm_platform_data { | 57 | struct 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 | ||
| 71 | static const unsigned int mtk_pwm_reg_offset[] = { | 75 | static 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 | ||
| 252 | static const struct mtk_pwm_platform_data mt2712_pwm_data = { | 274 | static 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 | ||
| 256 | static const struct mtk_pwm_platform_data mt7622_pwm_data = { | 279 | static 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 | ||
| 260 | static const struct mtk_pwm_platform_data mt7623_pwm_data = { | 284 | static 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 | ||
| 264 | static const struct of_device_id mtk_pwm_of_match[] = { | 289 | static const struct of_device_id mtk_pwm_of_match[] = { |
| @@ -280,5 +305,4 @@ static struct platform_driver mtk_pwm_driver = { | |||
| 280 | module_platform_driver(mtk_pwm_driver); | 305 | module_platform_driver(mtk_pwm_driver); |
| 281 | 306 | ||
| 282 | MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | 307 | MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); |
| 283 | MODULE_ALIAS("platform:mtk-pwm"); | ||
| 284 | MODULE_LICENSE("GPL"); | 308 | MODULE_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 | ||
| 135 | static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | 135 | static 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 | ||
| 142 | static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | 140 | static 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 | ||
| 149 | static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 145 | static 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 | }; |
| 259 | MODULE_DEVICE_TABLE(of, rcar_pwm_of_table); | 259 | MODULE_DEVICE_TABLE(of, rcar_pwm_of_table); |
| 260 | 260 | ||
| 261 | #ifdef CONFIG_PM_SLEEP | ||
| 262 | static 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 | |||
| 271 | static 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 | |||
| 283 | static 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 */ | ||
| 300 | static SIMPLE_DEV_PM_OPS(rcar_pwm_pm_ops, rcar_pwm_suspend, rcar_pwm_resume); | ||
| 301 | |||
| 261 | static struct platform_driver rcar_pwm_driver = { | 302 | static 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 | ||
| 22 | struct stm32_pwm { | 21 | struct 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 | ||
| 216 | static 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 | |||
| 217 | static const struct pwm_ops stm32pwm_ops = { | 230 | static 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 | ||
| 222 | static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, | 235 | static 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 | ||
| 74 | struct sun4i_pwm_data { | 74 | struct 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 | ||
| 314 | static const struct sun4i_pwm_data sun4i_pwm_data_a10 = { | 315 | static 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 | ||
| 320 | static const struct sun4i_pwm_data sun4i_pwm_data_a10s = { | 320 | static 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 | ||
| 326 | static const struct sun4i_pwm_data sun4i_pwm_data_a13 = { | 325 | static 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 | |||
| 332 | static const struct sun4i_pwm_data sun4i_pwm_data_a20 = { | ||
| 333 | .has_prescaler_bypass = true, | ||
| 334 | .has_rdy = true, | ||
| 335 | .npwm = 2, | ||
| 336 | }; | ||
| 337 | |||
| 338 | static 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 | ||
| 344 | static const struct of_device_id sun4i_pwm_dt_ids[] = { | 330 | static 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 | ||
