Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'pwm/for-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm

Pull pwm updates from Thierry Reding:
"This set of changes adds support for more generations of the RCar
controller as well as runtime PM support. The JZ4740 driver gains
support for device tree and can now be used on all Ingenic SoCs.

Rounding things off is a random assortment of fixes and cleanups all
across the board"

* tag 'pwm/for-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (29 commits)
pwm: rcar: Add suspend/resume support
pwm: rcar: Use PM Runtime to control module clock
dt-bindings: pwm: rcar: Add bindings for R-Car M3N support
pwm: rcar: Fix a condition to prevent mismatch value setting to duty
pwm: sysfs: Use put_device() instead of kfree()
dt-bindings: pwm: sunxi: Add new compatible strings
pwm: sun4i: Simplify controller mapping
pwm: sun4i: Drop unused .has_rdy member
pwm: sun4i: Properly check current state
pwm: Remove depends on AVR32
pwm: stm32: LPTimer: Use 3 cells ->of_xlate()
dt-bindings: pwm-stm32-lp: Add #pwm-cells
pwm: stm32: Protect common prescaler for all channels
pwm: stm32: Remove unused struct device
pwm: mediatek: Improve precision in rate calculation
pwm: mediatek: Remove redundant MODULE_ALIAS entries
pwm: mediatek: Fix up PWM4 and PWM5 malfunction on MT7623
pwm: jz4740: Enable for all Ingenic SoCs
pwm: jz4740: Add support for devicetree
pwm: jz4740: Implement ->set_polarity()
...

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