diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml index d8b495f71282e5ba838e8f53bca9a29e289881fc..afec0bd2f1de47b3a04e12fa2cb77ff683510d09 100644 --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml @@ -85,6 +85,10 @@ properties: ec-pwm: $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#" + deprecated: true + + pwm: + $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#" keyboard-controller: $ref: "/schemas/input/google,cros-ec-keyb.yaml#" diff --git a/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml b/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml index 800d511502c4108ee564579e4812cc2ab2cef0ed..e93e935564fba6815518863e9ff8ef1a8c382d2b 100644 --- a/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml @@ -52,33 +52,36 @@ properties: resets: maxItems: 1 -if: - properties: - compatible: - contains: - const: allwinner,sun50i-h6-pwm - -then: - properties: - clocks: - maxItems: 2 - - clock-names: - items: - - const: mod - - const: bus - - required: - - clock-names - - resets - -else: - properties: - clocks: - maxItems: 1 + +allOf: + - $ref: pwm.yaml# + + - if: + properties: + compatible: + contains: + const: allwinner,sun50i-h6-pwm + + then: + properties: + clocks: + maxItems: 2 + + clock-names: + items: + - const: mod + - const: bus + + required: + - clock-names + - resets + + else: + properties: + clocks: + maxItems: 1 required: - - "#pwm-cells" - compatible - reg - clocks diff --git a/Documentation/devicetree/bindings/pwm/brcm,bcm7038-pwm.yaml b/Documentation/devicetree/bindings/pwm/brcm,bcm7038-pwm.yaml index 4080e098f7469c48649f0055b000bcf3210d27a2..119de3d7f9dd717f3b77d9f0a8ae82415542cbad 100644 --- a/Documentation/devicetree/bindings/pwm/brcm,bcm7038-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/brcm,bcm7038-pwm.yaml @@ -28,7 +28,6 @@ properties: required: - compatible - reg - - "#pwm-cells" - clocks additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml index 4cfbffd8414a5ae35e8b4dc3fcae4a071a671f85..7ab6912a845fcbf8a4fdefcde7fa96320d2761f8 100644 --- a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml @@ -16,6 +16,9 @@ description: | An EC PWM node should be only found as a sub-node of the EC node (see Documentation/devicetree/bindings/mfd/google,cros-ec.yaml). +allOf: + - $ref: pwm.yaml# + properties: compatible: const: google,cros-ec-pwm @@ -39,7 +42,7 @@ examples: compatible = "google,cros-ec-spi"; reg = <0>; - cros_ec_pwm: ec-pwm { + cros_ec_pwm: pwm { compatible = "google,cros-ec-pwm"; #pwm-cells = <1>; }; diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml index 379d693889f635ef901a0daaaf76aa5aab288295..b3da4e629341c03960896f5b7542ec7bcdc1d111 100644 --- a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml @@ -9,6 +9,9 @@ title: Freescale i.MX PWM controller maintainers: - Philipp Zabel <p.zabel@pengutronix.de> +allOf: + - $ref: pwm.yaml# + properties: "#pwm-cells": description: | @@ -59,7 +62,6 @@ properties: maxItems: 1 required: - - "#pwm-cells" - compatible - reg - clocks diff --git a/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml index fe9ef42544f1a97e1a212ff1a0035fa600570332..8bef9dfeba9a010e4841e14c96471b2cad5e2004 100644 --- a/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml @@ -13,6 +13,9 @@ description: | The TPM counter and period counter are shared between multiple channels, so all channels should use same period setting. +allOf: + - $ref: pwm.yaml# + properties: "#pwm-cells": const: 3 @@ -34,7 +37,6 @@ properties: maxItems: 1 required: - - "#pwm-cells" - compatible - reg - clocks diff --git a/Documentation/devicetree/bindings/pwm/intel,keembay-pwm.yaml b/Documentation/devicetree/bindings/pwm/intel,keembay-pwm.yaml index ff6880a02ce6d88478816b600151391658d265fc..ec9f6bab798ce5db90abc9c4730b6a014ee3837a 100644 --- a/Documentation/devicetree/bindings/pwm/intel,keembay-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/intel,keembay-pwm.yaml @@ -31,7 +31,6 @@ required: - compatible - reg - clocks - - '#pwm-cells' additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/intel,lgm-pwm.yaml b/Documentation/devicetree/bindings/pwm/intel,lgm-pwm.yaml index 11a606536169e7480487f8e3d2c1c359a05ca7f6..59d7c4d864c1ec6c9dd6f180e58ce41229d693a4 100644 --- a/Documentation/devicetree/bindings/pwm/intel,lgm-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/intel,lgm-pwm.yaml @@ -9,6 +9,9 @@ title: LGM SoC PWM fan controller maintainers: - Rahul Tanwar <rtanwar@maxlinear.com> +allOf: + - $ref: pwm.yaml# + properties: compatible: const: intel,lgm-pwm diff --git a/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml b/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml index 1d7c27be50da6780a65f84ae0b0ad0e87b5bb279..0a46af240d838199424377d6d6df578cddd1e4d8 100644 --- a/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml @@ -15,6 +15,9 @@ description: | Documentation/devicetree/bindings/mfd/iqs62x.yaml for further details as well as an example. +allOf: + - $ref: pwm.yaml# + properties: compatible: enum: @@ -25,7 +28,6 @@ properties: required: - compatible - - "#pwm-cells" additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml b/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml index 8740e076061e3868c3708215b420cca2b782e8bb..a34cbc13f691c5765577fba1311d060ed2c1c72c 100644 --- a/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml @@ -10,6 +10,9 @@ maintainers: - Shawn Guo <shawnguo@kernel.org> - Anson Huang <anson.huang@nxp.com> +allOf: + - $ref: pwm.yaml# + properties: compatible: enum: @@ -28,7 +31,6 @@ properties: required: - compatible - reg - - "#pwm-cells" - fsl,pwm-number additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt b/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt index 902b271891aeb6b7e75bb1f8d2d4a1e7a30294a7..691e58b6c223e36a2392799c5ad446f069a5f3a5 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt @@ -6,6 +6,7 @@ Required properties: - "mediatek,mt6595-disp-pwm": found on mt6595 SoC. - "mediatek,mt8167-disp-pwm", "mediatek,mt8173-disp-pwm": found on mt8167 SoC. - "mediatek,mt8173-disp-pwm": found on mt8173 SoC. + - "mediatek,mt8183-disp-pwm": found on mt8183 SoC.$ - reg: physical base address and length of the controller's registers. - #pwm-cells: must be 2. See pwm.yaml in this directory for a description of the cell format. diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml index 81a54a4e8e3e7c31b7a913d17c49a65bde1eb40a..a336ff9364a93cd05ac787b9e4f27f052afe1f12 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml +++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml @@ -51,42 +51,44 @@ properties: required: - compatible - reg - - "#pwm-cells" - -if: - properties: - compatible: - contains: - enum: - - rockchip,rk3328-pwm - - rockchip,rv1108-pwm - -then: - properties: - clocks: - items: - - description: Used to derive the functional clock for the device. - - description: Used as the APB bus clock. - - clock-names: - items: - - const: pwm - - const: pclk - - required: - - clocks - - clock-names - -else: - properties: - clocks: - maxItems: 1 - description: - Used both to derive the functional clock - for the device and as the bus clock. - - required: - - clocks + +allOf: + - $ref: pwm.yaml# + + - if: + properties: + compatible: + contains: + enum: + - rockchip,rk3328-pwm + - rockchip,rv1108-pwm + + then: + properties: + clocks: + items: + - description: Used to derive the functional clock for the device. + - description: Used as the APB bus clock. + + clock-names: + items: + - const: pwm + - const: pclk + + required: + - clocks + - clock-names + + else: + properties: + clocks: + maxItems: 1 + description: + Used both to derive the functional clock + for the device and as the bus clock. + + required: + - clocks additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/pwm-samsung.yaml b/Documentation/devicetree/bindings/pwm/pwm-samsung.yaml index 188679cb8b8c449c389c861bdf2ad105e0ffad52..fe603fb1b2cc32a9586876d59ba19c330c795598 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-samsung.yaml +++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.yaml @@ -86,7 +86,6 @@ required: - clocks - clock-names - compatible - - "#pwm-cells" - reg additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml b/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml index db41cd7bf1509ffdbac20a18706a8e369c85083e..605c1766dba891ae06da67465442c3bef7c8ef53 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml +++ b/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml @@ -21,6 +21,9 @@ description: https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/pwm +allOf: + - $ref: pwm.yaml# + properties: compatible: items: @@ -54,7 +57,6 @@ required: - compatible - reg - clocks - - "#pwm-cells" - interrupts additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml b/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml index ed35b6cc48d5cb128c23fccc20bc117bf458159c..3840ae709bc6d1dbc18fa9e3171f4a39e940f97d 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml +++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml @@ -47,7 +47,6 @@ properties: required: - compatible - reg - - "#pwm-cells" - clocks - clock-names diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml index ee312cb210e6ffddca2b0a188d5755dccd5e2ff9..70a8f766212eaf30f0d67d81ab284e98bb75955d 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml +++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml @@ -48,7 +48,6 @@ properties: required: - compatible - reg - - "#pwm-cells" - clocks - clock-names diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml index 7ea1070b4b3a82ecc5357a2a9112146f3505485b..1c94acbc2b4a03848cfa57124e91cc18d6a58a94 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml @@ -59,21 +59,23 @@ properties: required: - compatible - reg - - '#pwm-cells' - clocks - power-domains -if: - not: - properties: - compatible: - contains: - enum: - - renesas,pwm-r8a7778 - - renesas,pwm-r8a7779 -then: - required: - - resets +allOf: + - $ref: pwm.yaml# + + - if: + not: + properties: + compatible: + contains: + enum: + - renesas,pwm-r8a7778 + - renesas,pwm-r8a7779 + then: + required: + - resets additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.yaml b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.yaml index 1f5c6384182e013aa866b9e52336bbd72492b952..c6b2ab56b7feade737c86539e38d635388317c9d 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.yaml @@ -68,7 +68,6 @@ properties: required: - compatible - reg - - '#pwm-cells' - clocks - power-domains diff --git a/Documentation/devicetree/bindings/pwm/toshiba,pwm-visconti.yaml b/Documentation/devicetree/bindings/pwm/toshiba,pwm-visconti.yaml index d350f5edfb673daa52b0bca64877c4d917b7e84b..46622661e5fb6f271c4aacf0286c6b3a42388d99 100644 --- a/Documentation/devicetree/bindings/pwm/toshiba,pwm-visconti.yaml +++ b/Documentation/devicetree/bindings/pwm/toshiba,pwm-visconti.yaml @@ -9,6 +9,9 @@ title: Toshiba Visconti PWM Controller maintainers: - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> +allOf: + - $ref: pwm.yaml# + properties: compatible: items: @@ -23,7 +26,6 @@ properties: required: - compatible - reg - - '#pwm-cells' additionalProperties: false diff --git a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml index 7fb37eae9da7c8aa94312ff87d8aa178bc3b5e8b..d541cf2067bc1453fb8e395329aba7f01de9d205 100644 --- a/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml +++ b/Documentation/devicetree/bindings/timer/ingenic,tcu.yaml @@ -152,6 +152,7 @@ patternProperties: - enum: - ingenic,jz4740-pwm - ingenic,jz4725b-pwm + - ingenic,x1000-pwm - items: - enum: - ingenic,jz4760-pwm diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 98b34ea9f38e2245771f53f5a94b1f834ee6472f..8e00a4286145b8f6d028775f5659732a1120d8a9 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -271,7 +271,7 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, bool disable_clk) { struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); - unsigned long timeout = jiffies + 2 * HZ; + unsigned long timeout; atmel_pwm_wait_nonpending(atmel_pwm, pwm->hwpwm); diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c index 64148f5f81d08b6091e1fdbecc081e5f256e4372..f171169c1c1fd18a6b7acac1b5ff9a35765bbf5d 100644 --- a/drivers/pwm/pwm-bcm-kona.c +++ b/drivers/pwm/pwm-bcm-kona.c @@ -109,10 +109,10 @@ static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan) } static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct kona_pwmc *kp = to_kona_pwmc(chip); - u64 val, div, rate; + u64 div, rate; unsigned long prescale = PRESCALE_MIN, pc, dc; unsigned int value, chan = pwm->hwpwm; @@ -132,10 +132,8 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, while (1) { div = 1000000000; div *= 1 + prescale; - val = rate * period_ns; - pc = div64_u64(val, div); - val = rate * duty_ns; - dc = div64_u64(val, div); + pc = mul_u64_u64_div_u64(rate, period_ns, div); + dc = mul_u64_u64_div_u64(rate, duty_ns, div); /* If duty_ns or period_ns are not achievable then return */ if (pc < PERIOD_COUNT_MIN) @@ -150,25 +148,18 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, return -EINVAL; } - /* - * Don't apply settings if disabled. The period and duty cycle are - * always calculated above to ensure the new values are - * validated immediately instead of on enable. - */ - if (pwm_is_enabled(pwm)) { - kona_pwmc_prepare_for_settings(kp, chan); + kona_pwmc_prepare_for_settings(kp, chan); - value = readl(kp->base + PRESCALE_OFFSET); - value &= ~PRESCALE_MASK(chan); - value |= prescale << PRESCALE_SHIFT(chan); - writel(value, kp->base + PRESCALE_OFFSET); + value = readl(kp->base + PRESCALE_OFFSET); + value &= ~PRESCALE_MASK(chan); + value |= prescale << PRESCALE_SHIFT(chan); + writel(value, kp->base + PRESCALE_OFFSET); - writel(pc, kp->base + PERIOD_COUNT_OFFSET(chan)); + writel(pc, kp->base + PERIOD_COUNT_OFFSET(chan)); - writel(dc, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan)); + writel(dc, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan)); - kona_pwmc_apply_settings(kp, chan); - } + kona_pwmc_apply_settings(kp, chan); return 0; } @@ -216,13 +207,6 @@ static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm) return ret; } - ret = kona_pwmc_config(chip, pwm, pwm_get_duty_cycle(pwm), - pwm_get_period(pwm)); - if (ret < 0) { - clk_disable_unprepare(kp->clk); - return ret; - } - return 0; } @@ -248,11 +232,53 @@ static void kona_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm) clk_disable_unprepare(kp->clk); } +static int kona_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + struct kona_pwmc *kp = to_kona_pwmc(chip); + bool enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + if (enabled) { + kona_pwmc_disable(chip, pwm); + enabled = false; + } + + err = kona_pwmc_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + + pwm->state.polarity = state->polarity; + } + + if (!state->enabled) { + if (enabled) + kona_pwmc_disable(chip, pwm); + return 0; + } else if (!enabled) { + /* + * This is a bit special here, usually the PWM should only be + * enabled when duty and period are setup. But before this + * driver was converted to .apply it was done the other way + * around and so this behaviour was kept even though this might + * result in a glitch. This might be improvable by someone with + * hardware and/or documentation. + */ + err = kona_pwmc_enable(chip, pwm); + if (err) + return err; + } + + err = kona_pwmc_config(pwm->chip, pwm, state->duty_cycle, state->period); + if (err && !pwm->state.enabled) + clk_disable_unprepare(kp->clk); + + return err; +} + static const struct pwm_ops kona_pwm_ops = { - .config = kona_pwmc_config, - .set_polarity = kona_pwmc_set_polarity, - .enable = kona_pwmc_enable, - .disable = kona_pwmc_disable, + .apply = kona_pwmc_apply, .owner = THIS_MODULE, }; diff --git a/drivers/pwm/pwm-brcmstb.c b/drivers/pwm/pwm-brcmstb.c index 3b529f82b97c9c8638117a54881f5c992cc789a8..3db3f96edf78d77e50e74cb203f42951c93ccebb 100644 --- a/drivers/pwm/pwm-brcmstb.c +++ b/drivers/pwm/pwm-brcmstb.c @@ -53,7 +53,6 @@ struct brcmstb_pwm { void __iomem *base; - spinlock_t lock; struct clk *clk; struct pwm_chip chip; }; @@ -95,7 +94,7 @@ static inline struct brcmstb_pwm *to_brcmstb_pwm(struct pwm_chip *chip) * "on" time, so this translates directly into our HW programming here. */ static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct brcmstb_pwm *p = to_brcmstb_pwm(chip); unsigned long pc, dc, cword = CONST_VAR_F_MAX; @@ -114,22 +113,17 @@ static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } while (1) { - u64 rate, tmp; + u64 rate; /* * Calculate the base rate from base frequency and current * cword */ rate = (u64)clk_get_rate(p->clk) * (u64)cword; - do_div(rate, 1 << CWORD_BIT_SIZE); + rate >>= CWORD_BIT_SIZE; - tmp = period_ns * rate; - do_div(tmp, NSEC_PER_SEC); - pc = tmp; - - tmp = (duty_ns + 1) * rate; - do_div(tmp, NSEC_PER_SEC); - dc = tmp; + pc = mul_u64_u64_div_u64(period_ns, rate, NSEC_PER_SEC); + dc = mul_u64_u64_div_u64(duty_ns + 1, rate, NSEC_PER_SEC); /* * We can be called with separate duty and period updates, @@ -164,7 +158,6 @@ static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * generator output a base frequency for the constant frequency * generator to derive from. */ - spin_lock(&p->lock); brcmstb_pwm_writel(p, cword >> 8, PWM_CWORD_MSB(channel)); brcmstb_pwm_writel(p, cword & 0xff, PWM_CWORD_LSB(channel)); @@ -176,7 +169,6 @@ static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, /* Configure on and period value */ brcmstb_pwm_writel(p, pc, PWM_PERIOD(channel)); brcmstb_pwm_writel(p, dc, PWM_ON(channel)); - spin_unlock(&p->lock); return 0; } @@ -187,7 +179,6 @@ static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p, unsigned int shift = channel * CTRL_CHAN_OFFS; u32 value; - spin_lock(&p->lock); value = brcmstb_pwm_readl(p, PWM_CTRL); if (enable) { @@ -199,29 +190,36 @@ static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p, } brcmstb_pwm_writel(p, value, PWM_CTRL); - spin_unlock(&p->lock); } -static int brcmstb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +static int brcmstb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { struct brcmstb_pwm *p = to_brcmstb_pwm(chip); + int err; - brcmstb_pwm_enable_set(p, pwm->hwpwm, true); + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; - return 0; -} + if (!state->enabled) { + if (pwm->state.enabled) + brcmstb_pwm_enable_set(p, pwm->hwpwm, false); -static void brcmstb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct brcmstb_pwm *p = to_brcmstb_pwm(chip); + return 0; + } + + err = brcmstb_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + + if (!pwm->state.enabled) + brcmstb_pwm_enable_set(p, pwm->hwpwm, true); - brcmstb_pwm_enable_set(p, pwm->hwpwm, false); + return 0; } static const struct pwm_ops brcmstb_pwm_ops = { - .config = brcmstb_pwm_config, - .enable = brcmstb_pwm_enable, - .disable = brcmstb_pwm_disable, + .apply = brcmstb_pwm_apply, .owner = THIS_MODULE, }; @@ -240,8 +238,6 @@ static int brcmstb_pwm_probe(struct platform_device *pdev) if (!p) return -ENOMEM; - spin_lock_init(&p->lock); - p->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(p->clk)) { dev_err(&pdev->dev, "failed to obtain clock\n"); diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c index 5996049f66ece366e23d22be732b683874900f71..0fccf061ab958852b03f209dd133b5db735b022a 100644 --- a/drivers/pwm/pwm-img.c +++ b/drivers/pwm/pwm-img.c @@ -77,16 +77,15 @@ static inline struct img_pwm_chip *to_img_pwm_chip(struct pwm_chip *chip) return container_of(chip, struct img_pwm_chip, chip); } -static inline void img_pwm_writel(struct img_pwm_chip *chip, +static inline void img_pwm_writel(struct img_pwm_chip *imgchip, u32 reg, u32 val) { - writel(val, chip->base + reg); + writel(val, imgchip->base + reg); } -static inline u32 img_pwm_readl(struct img_pwm_chip *chip, - u32 reg) +static inline u32 img_pwm_readl(struct img_pwm_chip *imgchip, u32 reg) { - return readl(chip->base + reg); + return readl(imgchip->base + reg); } static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, @@ -94,17 +93,17 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, { u32 val, div, duty, timebase; unsigned long mul, output_clk_hz, input_clk_hz; - struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); - unsigned int max_timebase = pwm_chip->data->max_timebase; + struct img_pwm_chip *imgchip = to_img_pwm_chip(chip); + unsigned int max_timebase = imgchip->data->max_timebase; int ret; - if (period_ns < pwm_chip->min_period_ns || - period_ns > pwm_chip->max_period_ns) { + if (period_ns < imgchip->min_period_ns || + period_ns > imgchip->max_period_ns) { dev_err(chip->dev, "configured period not in range\n"); return -ERANGE; } - input_clk_hz = clk_get_rate(pwm_chip->pwm_clk); + input_clk_hz = clk_get_rate(imgchip->pwm_clk); output_clk_hz = DIV_ROUND_UP(NSEC_PER_SEC, period_ns); mul = DIV_ROUND_UP(input_clk_hz, output_clk_hz); @@ -132,15 +131,15 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (ret < 0) return ret; - val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); + val = img_pwm_readl(imgchip, PWM_CTRL_CFG); val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm)); val |= (div & PWM_CTRL_CFG_DIV_MASK) << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm); - img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); + img_pwm_writel(imgchip, PWM_CTRL_CFG, val); val = (duty << PWM_CH_CFG_DUTY_SHIFT) | (timebase << PWM_CH_CFG_TMBASE_SHIFT); - img_pwm_writel(pwm_chip, PWM_CH_CFG(pwm->hwpwm), val); + img_pwm_writel(imgchip, PWM_CH_CFG(pwm->hwpwm), val); pm_runtime_mark_last_busy(chip->dev); pm_runtime_put_autosuspend(chip->dev); @@ -151,18 +150,18 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { u32 val; - struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); + struct img_pwm_chip *imgchip = to_img_pwm_chip(chip); int ret; ret = pm_runtime_resume_and_get(chip->dev); if (ret < 0) return ret; - val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); + val = img_pwm_readl(imgchip, PWM_CTRL_CFG); val |= BIT(pwm->hwpwm); - img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); + img_pwm_writel(imgchip, PWM_CTRL_CFG, val); - regmap_update_bits(pwm_chip->periph_regs, PERIP_PWM_PDM_CONTROL, + regmap_update_bits(imgchip->periph_regs, PERIP_PWM_PDM_CONTROL, PERIP_PWM_PDM_CONTROL_CH_MASK << PERIP_PWM_PDM_CONTROL_CH_SHIFT(pwm->hwpwm), 0); @@ -172,11 +171,11 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) static void img_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { u32 val; - struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); + struct img_pwm_chip *imgchip = to_img_pwm_chip(chip); - val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); + val = img_pwm_readl(imgchip, PWM_CTRL_CFG); val &= ~BIT(pwm->hwpwm); - img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); + img_pwm_writel(imgchip, PWM_CTRL_CFG, val); pm_runtime_mark_last_busy(chip->dev); pm_runtime_put_autosuspend(chip->dev); @@ -227,29 +226,29 @@ MODULE_DEVICE_TABLE(of, img_pwm_of_match); static int img_pwm_runtime_suspend(struct device *dev) { - struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev); + struct img_pwm_chip *imgchip = dev_get_drvdata(dev); - clk_disable_unprepare(pwm_chip->pwm_clk); - clk_disable_unprepare(pwm_chip->sys_clk); + clk_disable_unprepare(imgchip->pwm_clk); + clk_disable_unprepare(imgchip->sys_clk); return 0; } static int img_pwm_runtime_resume(struct device *dev) { - struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev); + struct img_pwm_chip *imgchip = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(pwm_chip->sys_clk); + ret = clk_prepare_enable(imgchip->sys_clk); if (ret < 0) { dev_err(dev, "could not prepare or enable sys clock\n"); return ret; } - ret = clk_prepare_enable(pwm_chip->pwm_clk); + ret = clk_prepare_enable(imgchip->pwm_clk); if (ret < 0) { dev_err(dev, "could not prepare or enable pwm clock\n"); - clk_disable_unprepare(pwm_chip->sys_clk); + clk_disable_unprepare(imgchip->sys_clk); return ret; } @@ -261,42 +260,42 @@ static int img_pwm_probe(struct platform_device *pdev) int ret; u64 val; unsigned long clk_rate; - struct img_pwm_chip *pwm; + struct img_pwm_chip *imgchip; const struct of_device_id *of_dev_id; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) + imgchip = devm_kzalloc(&pdev->dev, sizeof(*imgchip), GFP_KERNEL); + if (!imgchip) return -ENOMEM; - pwm->dev = &pdev->dev; + imgchip->dev = &pdev->dev; - pwm->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->base)) - return PTR_ERR(pwm->base); + imgchip->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(imgchip->base)) + return PTR_ERR(imgchip->base); of_dev_id = of_match_device(img_pwm_of_match, &pdev->dev); if (!of_dev_id) return -ENODEV; - pwm->data = of_dev_id->data; + imgchip->data = of_dev_id->data; - pwm->periph_regs = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "img,cr-periph"); - if (IS_ERR(pwm->periph_regs)) - return PTR_ERR(pwm->periph_regs); + imgchip->periph_regs = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "img,cr-periph"); + if (IS_ERR(imgchip->periph_regs)) + return PTR_ERR(imgchip->periph_regs); - pwm->sys_clk = devm_clk_get(&pdev->dev, "sys"); - if (IS_ERR(pwm->sys_clk)) { + imgchip->sys_clk = devm_clk_get(&pdev->dev, "sys"); + if (IS_ERR(imgchip->sys_clk)) { dev_err(&pdev->dev, "failed to get system clock\n"); - return PTR_ERR(pwm->sys_clk); + return PTR_ERR(imgchip->sys_clk); } - pwm->pwm_clk = devm_clk_get(&pdev->dev, "pwm"); - if (IS_ERR(pwm->pwm_clk)) { - dev_err(&pdev->dev, "failed to get pwm clock\n"); - return PTR_ERR(pwm->pwm_clk); + imgchip->pwm_clk = devm_clk_get(&pdev->dev, "imgchip"); + if (IS_ERR(imgchip->pwm_clk)) { + dev_err(&pdev->dev, "failed to get imgchip clock\n"); + return PTR_ERR(imgchip->pwm_clk); } - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, imgchip); pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_PWM_PM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); @@ -307,27 +306,27 @@ static int img_pwm_probe(struct platform_device *pdev) goto err_pm_disable; } - clk_rate = clk_get_rate(pwm->pwm_clk); + clk_rate = clk_get_rate(imgchip->pwm_clk); if (!clk_rate) { - dev_err(&pdev->dev, "pwm clock has no frequency\n"); + dev_err(&pdev->dev, "imgchip clock has no frequency\n"); ret = -EINVAL; goto err_suspend; } /* The maximum input clock divider is 512 */ - val = (u64)NSEC_PER_SEC * 512 * pwm->data->max_timebase; + val = (u64)NSEC_PER_SEC * 512 * imgchip->data->max_timebase; do_div(val, clk_rate); - pwm->max_period_ns = val; + imgchip->max_period_ns = val; val = (u64)NSEC_PER_SEC * MIN_TMBASE_STEPS; do_div(val, clk_rate); - pwm->min_period_ns = val; + imgchip->min_period_ns = val; - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &img_pwm_ops; - pwm->chip.npwm = IMG_PWM_NPWM; + imgchip->chip.dev = &pdev->dev; + imgchip->chip.ops = &img_pwm_ops; + imgchip->chip.npwm = IMG_PWM_NPWM; - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&imgchip->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret); goto err_suspend; @@ -346,13 +345,13 @@ static int img_pwm_probe(struct platform_device *pdev) static int img_pwm_remove(struct platform_device *pdev) { - struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev); + struct img_pwm_chip *imgchip = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_pwm_runtime_suspend(&pdev->dev); - pwmchip_remove(&pwm_chip->chip); + pwmchip_remove(&imgchip->chip); return 0; } @@ -360,7 +359,7 @@ static int img_pwm_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int img_pwm_suspend(struct device *dev) { - struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev); + struct img_pwm_chip *imgchip = dev_get_drvdata(dev); int i, ret; if (pm_runtime_status_suspended(dev)) { @@ -369,11 +368,11 @@ static int img_pwm_suspend(struct device *dev) return ret; } - for (i = 0; i < pwm_chip->chip.npwm; i++) - pwm_chip->suspend_ch_cfg[i] = img_pwm_readl(pwm_chip, - PWM_CH_CFG(i)); + for (i = 0; i < imgchip->chip.npwm; i++) + imgchip->suspend_ch_cfg[i] = img_pwm_readl(imgchip, + PWM_CH_CFG(i)); - pwm_chip->suspend_ctrl_cfg = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); + imgchip->suspend_ctrl_cfg = img_pwm_readl(imgchip, PWM_CTRL_CFG); img_pwm_runtime_suspend(dev); @@ -382,7 +381,7 @@ static int img_pwm_suspend(struct device *dev) static int img_pwm_resume(struct device *dev) { - struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev); + struct img_pwm_chip *imgchip = dev_get_drvdata(dev); int ret; int i; @@ -390,15 +389,15 @@ static int img_pwm_resume(struct device *dev) if (ret) return ret; - for (i = 0; i < pwm_chip->chip.npwm; i++) - img_pwm_writel(pwm_chip, PWM_CH_CFG(i), - pwm_chip->suspend_ch_cfg[i]); + for (i = 0; i < imgchip->chip.npwm; i++) + img_pwm_writel(imgchip, PWM_CH_CFG(i), + imgchip->suspend_ch_cfg[i]); - img_pwm_writel(pwm_chip, PWM_CTRL_CFG, pwm_chip->suspend_ctrl_cfg); + img_pwm_writel(imgchip, PWM_CTRL_CFG, imgchip->suspend_ctrl_cfg); - for (i = 0; i < pwm_chip->chip.npwm; i++) - if (pwm_chip->suspend_ctrl_cfg & BIT(i)) - regmap_update_bits(pwm_chip->periph_regs, + for (i = 0; i < imgchip->chip.npwm; i++) + if (imgchip->suspend_ctrl_cfg & BIT(i)) + regmap_update_bits(imgchip->periph_regs, PERIP_PWM_PDM_CONTROL, PERIP_PWM_PDM_CONTROL_CH_MASK << PERIP_PWM_PDM_CONTROL_CH_SHIFT(i), diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c index bcd849496f8df6ba2573ab034ad9aac5c0974b6e..1f2eb1c8ff6c95c04c59a5e54596131a4ee0bff2 100644 --- a/drivers/pwm/pwm-imx1.c +++ b/drivers/pwm/pwm-imx1.c @@ -61,7 +61,7 @@ static void pwm_imx1_clk_disable_unprepare(struct pwm_chip *chip) } static int pwm_imx1_config(struct pwm_chip *chip, - struct pwm_device *pwm, int duty_ns, int period_ns) + struct pwm_device *pwm, u64 duty_ns, u64 period_ns) { struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip); u32 max, p; @@ -84,7 +84,7 @@ static int pwm_imx1_config(struct pwm_chip *chip, * (/2 .. /16). */ max = readl(imx->mmio_base + MX1_PWMP); - p = max * duty_ns / period_ns; + p = mul_u64_u64_div_u64(max, duty_ns, period_ns); writel(max - p, imx->mmio_base + MX1_PWMS); @@ -120,10 +120,33 @@ static void pwm_imx1_disable(struct pwm_chip *chip, struct pwm_device *pwm) pwm_imx1_clk_disable_unprepare(chip); } +static int pwm_imx1_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (!state->enabled) { + if (pwm->state.enabled) + pwm_imx1_disable(chip, pwm); + + return 0; + } + + err = pwm_imx1_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + + if (!pwm->state.enabled) + return pwm_imx1_enable(chip, pwm); + + return 0; +} + static const struct pwm_ops pwm_imx1_ops = { - .enable = pwm_imx1_enable, - .disable = pwm_imx1_disable, - .config = pwm_imx1_config, + .apply = pwm_imx1_apply, .owner = THIS_MODULE, }; diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 23dc1fb770e22a56031aa056e53e022f7e4fbf02..a5fdf97c0d2ec63c4c868fe3a874c05d442b86c1 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -256,10 +256,15 @@ static const struct soc_info __maybe_unused jz4725b_soc_info = { .num_pwms = 6, }; +static const struct soc_info __maybe_unused x1000_soc_info = { + .num_pwms = 5, +}; + #ifdef CONFIG_OF static const struct of_device_id jz4740_pwm_dt_ids[] = { { .compatible = "ingenic,jz4740-pwm", .data = &jz4740_soc_info }, { .compatible = "ingenic,jz4725b-pwm", .data = &jz4725b_soc_info }, + { .compatible = "ingenic,x1000-pwm", .data = &x1000_soc_info }, {}, }; MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids); diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c index 8e461f3baa05a9f32170194261ea9c392c3bdb21..b909096dba2fd4b67fbcc7150c4d4ddcb367cd43 100644 --- a/drivers/pwm/pwm-lpc18xx-sct.c +++ b/drivers/pwm/pwm-lpc18xx-sct.c @@ -76,6 +76,8 @@ #define LPC18XX_PWM_EVENT_PERIOD 0 #define LPC18XX_PWM_EVENT_MAX 16 +#define LPC18XX_NUM_PWMS 16 + /* SCT conflict resolution */ enum lpc18xx_pwm_res_action { LPC18XX_PWM_RES_NONE, @@ -101,6 +103,7 @@ struct lpc18xx_pwm_chip { unsigned long event_map; struct mutex res_lock; struct mutex period_lock; + struct lpc18xx_pwm_data channeldata[LPC18XX_NUM_PWMS]; }; static inline struct lpc18xx_pwm_chip * @@ -163,7 +166,7 @@ static void lpc18xx_pwm_config_duty(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns) { struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); - struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; u64 val; val = (u64)duty_ns * lpc18xx_pwm->clk_rate; @@ -233,7 +236,7 @@ static int lpc18xx_pwm_set_polarity(struct pwm_chip *chip, static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); - struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; enum lpc18xx_pwm_res_action res_action; unsigned int set_event, clear_event; @@ -268,7 +271,7 @@ static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); - struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0); @@ -279,7 +282,7 @@ static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); - struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; unsigned long event; event = find_first_zero_bit(&lpc18xx_pwm->event_map, @@ -300,7 +303,7 @@ static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) static void lpc18xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); - struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); + struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map); } @@ -324,8 +327,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match); static int lpc18xx_pwm_probe(struct platform_device *pdev) { struct lpc18xx_pwm_chip *lpc18xx_pwm; - struct pwm_device *pwm; - int ret, i; + int ret; u64 val; lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm), @@ -370,7 +372,7 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) lpc18xx_pwm->chip.dev = &pdev->dev; lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops; - lpc18xx_pwm->chip.npwm = 16; + lpc18xx_pwm->chip.npwm = LPC18XX_NUM_PWMS; /* SCT counter must be in unify (32 bit) mode */ lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, @@ -395,40 +397,23 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT, BIT(lpc18xx_pwm->period_event)); + val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL); + val &= ~LPC18XX_PWM_BIDIR; + val &= ~LPC18XX_PWM_CTRL_HALT; + val &= ~LPC18XX_PWM_PRE_MASK; + val |= LPC18XX_PWM_PRE(0); + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val); + ret = pwmchip_add(&lpc18xx_pwm->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret); goto disable_pwmclk; } - for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) { - struct lpc18xx_pwm_data *data; - - pwm = &lpc18xx_pwm->chip.pwms[i]; - - data = devm_kzalloc(lpc18xx_pwm->dev, sizeof(*data), - GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto remove_pwmchip; - } - - pwm_set_chip_data(pwm, data); - } - platform_set_drvdata(pdev, lpc18xx_pwm); - val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL); - val &= ~LPC18XX_PWM_BIDIR; - val &= ~LPC18XX_PWM_CTRL_HALT; - val &= ~LPC18XX_PWM_PRE_MASK; - val |= LPC18XX_PWM_PRE(0); - lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val); - return 0; -remove_pwmchip: - pwmchip_remove(&lpc18xx_pwm->chip); disable_pwmclk: clk_disable_unprepare(lpc18xx_pwm->pwm_clk); return ret; diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index 0d4dd80e9f07f608fe4cccc050aaa8a97b23a972..568b13a48717e76d6bda917c86b24ce3824d3b46 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -146,7 +146,7 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, if (clkdiv > PWM_CLK_DIV_MAX) { pwm_mediatek_clk_disable(chip, pwm); - dev_err(chip->dev, "period %d not supported\n", period_ns); + dev_err(chip->dev, "period of %d ns not supported\n", period_ns); return -EINVAL; } @@ -221,24 +221,20 @@ static int pwm_mediatek_probe(struct platform_device *pdev) if (IS_ERR(pc->regs)) return PTR_ERR(pc->regs); - pc->clk_pwms = devm_kcalloc(&pdev->dev, pc->soc->num_pwms, + pc->clk_pwms = devm_kmalloc_array(&pdev->dev, pc->soc->num_pwms, sizeof(*pc->clk_pwms), GFP_KERNEL); if (!pc->clk_pwms) return -ENOMEM; pc->clk_top = devm_clk_get(&pdev->dev, "top"); - if (IS_ERR(pc->clk_top)) { - dev_err(&pdev->dev, "clock: top fail: %ld\n", - PTR_ERR(pc->clk_top)); - return PTR_ERR(pc->clk_top); - } + if (IS_ERR(pc->clk_top)) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top), + "Failed to get top clock\n"); pc->clk_main = devm_clk_get(&pdev->dev, "main"); - if (IS_ERR(pc->clk_main)) { - dev_err(&pdev->dev, "clock: main fail: %ld\n", - PTR_ERR(pc->clk_main)); - return PTR_ERR(pc->clk_main); - } + if (IS_ERR(pc->clk_main)) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main), + "Failed to get main clock\n"); for (i = 0; i < pc->soc->num_pwms; i++) { char name[8]; @@ -246,11 +242,9 @@ static int pwm_mediatek_probe(struct platform_device *pdev) snprintf(name, sizeof(name), "pwm%d", i + 1); pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name); - if (IS_ERR(pc->clk_pwms[i])) { - dev_err(&pdev->dev, "clock: %s fail: %ld\n", - name, PTR_ERR(pc->clk_pwms[i])); - return PTR_ERR(pc->clk_pwms[i]); - } + if (IS_ERR(pc->clk_pwms[i])) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]), + "Failed to get %s clock\n", name); } pc->chip.dev = &pdev->dev; @@ -258,10 +252,8 @@ static int pwm_mediatek_probe(struct platform_device *pdev) pc->chip.npwm = pc->soc->num_pwms; ret = devm_pwmchip_add(&pdev->dev, &pc->chip); - if (ret < 0) { - dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n"); return 0; } diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 3cf3bcf5ddfccbd003fedc001231f2d16dd1cb38..57112f438c6dd349f9e24a8ce711fdd2b0f1803d 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -120,16 +120,10 @@ static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip) static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { struct meson_pwm *meson = to_meson_pwm(chip); - struct meson_pwm_channel *channel; + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; struct device *dev = chip->dev; int err; - channel = pwm_get_chip_data(pwm); - if (channel) - return 0; - - channel = &meson->channels[pwm->hwpwm]; - if (channel->clk_parent) { err = clk_set_parent(channel->clk, channel->clk_parent); if (err < 0) { @@ -147,21 +141,21 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) return err; } - return pwm_set_chip_data(pwm, channel); + return 0; } static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); + struct meson_pwm *meson = to_meson_pwm(chip); + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; - if (channel) - clk_disable_unprepare(channel->clk); + clk_disable_unprepare(channel->clk); } static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, const struct pwm_state *state) { - struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; unsigned int duty, period, pre_div, cnt, duty_cnt; unsigned long fin_freq; @@ -224,7 +218,7 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) { - struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; struct meson_pwm_channel_data *channel_data; unsigned long flags; u32 value; @@ -267,13 +261,10 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { - struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); struct meson_pwm *meson = to_meson_pwm(chip); + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; int err = 0; - if (!state) - return -EINVAL; - if (!state->enabled) { if (state->polarity == PWM_POLARITY_INVERSED) { /* diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index c56001a790d0548078351ce32e19444e0083d93c..c91fa7f9e33da975a73407e9bd4eac28c4109cfe 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -560,10 +560,10 @@ static int pca9685_pwm_probe(struct i2c_client *client, pca9685_write_reg(pca, PCA9685_MODE1, reg); /* Reset OFF/ON registers to POR default */ - pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, LED_FULL); + pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, 0); pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_H, LED_FULL); pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0); - pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, 0); + pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, LED_FULL); pca->chip.ops = &pca9685_pwm_ops; /* Add an extra channel for ALL_LED */ diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c index 238ec88c130bb76ba5f226752391aa12e7f0923d..0bcaa58c6a91e4b505aa4d0d53190e6dd995613b 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -58,7 +58,7 @@ static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip) * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE */ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); unsigned long long c; @@ -84,7 +84,7 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (duty_ns == period_ns) dc = PWMDCR_FD; else - dc = (pv + 1) * duty_ns / period_ns; + dc = mul_u64_u64_div_u64(pv + 1, duty_ns, period_ns); /* NOTE: the clock to PWM has to be enabled first * before writing to the registers @@ -115,10 +115,33 @@ static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) clk_disable_unprepare(pc->clk); } +static int pxa_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (!state->enabled) { + if (pwm->state.enabled) + pxa_pwm_disable(chip, pwm); + + return 0; + } + + err = pxa_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + + if (!pwm->state.enabled) + return pxa_pwm_enable(chip, pwm); + + return 0; +} + static const struct pwm_ops pxa_pwm_ops = { - .config = pxa_pwm_config, - .enable = pxa_pwm_enable, - .disable = pxa_pwm_disable, + .apply = pxa_pwm_apply, .owner = THIS_MODULE, }; diff --git a/drivers/pwm/pwm-raspberrypi-poe.c b/drivers/pwm/pwm-raspberrypi-poe.c index 579a15240e0a8da62ceeadea7a77d4ad35ff8185..e52e29fc8231f34ff20bfae3123bcea42e3851fc 100644 --- a/drivers/pwm/pwm-raspberrypi-poe.c +++ b/drivers/pwm/pwm-raspberrypi-poe.c @@ -163,7 +163,6 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev) rpipwm->firmware = firmware; rpipwm->chip.dev = dev; rpipwm->chip.ops = &raspberrypi_pwm_ops; - rpipwm->chip.base = -1; rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM; ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG, diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index b437192380e23520378e0ac1e726c6a616780453..55f46d09602b1907338400fb5887f99e5c87faca 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -110,7 +110,7 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns, unsigned long clk_rate = clk_get_rate(rp->clk); u32 cyc, ph; - one_cycle = (unsigned long long)NSEC_PER_SEC * 100ULL * (1 << div); + one_cycle = NSEC_PER_SEC * 100ULL << div; do_div(one_cycle, clk_rate); tmp = period_ns * 100ULL; diff --git a/drivers/pwm/pwm-stmpe.c b/drivers/pwm/pwm-stmpe.c index 9dc983a3cbf1b1f427396378e80e8de8940ad3ea..c4336d3bace326f91b04124c681a9f3c85dc419b 100644 --- a/drivers/pwm/pwm-stmpe.c +++ b/drivers/pwm/pwm-stmpe.c @@ -269,19 +269,19 @@ static const struct pwm_ops stmpe_24xx_pwm_ops = { static int __init stmpe_pwm_probe(struct platform_device *pdev) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); - struct stmpe_pwm *pwm; + struct stmpe_pwm *stmpe_pwm; int ret; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) + stmpe_pwm = devm_kzalloc(&pdev->dev, sizeof(*stmpe_pwm), GFP_KERNEL); + if (!stmpe_pwm) return -ENOMEM; - pwm->stmpe = stmpe; - pwm->chip.dev = &pdev->dev; + stmpe_pwm->stmpe = stmpe; + stmpe_pwm->chip.dev = &pdev->dev; if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) { - pwm->chip.ops = &stmpe_24xx_pwm_ops; - pwm->chip.npwm = 3; + stmpe_pwm->chip.ops = &stmpe_24xx_pwm_ops; + stmpe_pwm->chip.npwm = 3; } else { if (stmpe->partnum == STMPE1601) dev_err(&pdev->dev, "STMPE1601 not yet supported\n"); @@ -295,14 +295,12 @@ static int __init stmpe_pwm_probe(struct platform_device *pdev) if (ret) return ret; - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&stmpe_pwm->chip); if (ret) { stmpe_disable(stmpe, STMPE_BLOCK_PWM); return ret; } - platform_set_drvdata(pdev, pwm); - return 0; } diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 91ca67651abd5ebb7b92e3bd0b3b5ad398fd0321..16d75f9aa36a9f03c7a523713a5987f1aff14f45 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -390,20 +390,20 @@ MODULE_DEVICE_TABLE(of, sun4i_pwm_dt_ids); static int sun4i_pwm_probe(struct platform_device *pdev) { - struct sun4i_pwm_chip *pwm; + struct sun4i_pwm_chip *sun4ichip; int ret; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) + sun4ichip = devm_kzalloc(&pdev->dev, sizeof(*sun4ichip), GFP_KERNEL); + if (!sun4ichip) return -ENOMEM; - pwm->data = of_device_get_match_data(&pdev->dev); - if (!pwm->data) + sun4ichip->data = of_device_get_match_data(&pdev->dev); + if (!sun4ichip->data) return -ENODEV; - pwm->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->base)) - return PTR_ERR(pwm->base); + sun4ichip->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sun4ichip->base)) + return PTR_ERR(sun4ichip->base); /* * All hardware variants need a source clock that is divided and @@ -416,30 +416,30 @@ static int sun4i_pwm_probe(struct platform_device *pdev) * unnamed one of the PWM device) and if this is not found we fall * back to the first clock of the PWM. */ - pwm->clk = devm_clk_get_optional(&pdev->dev, "mod"); - if (IS_ERR(pwm->clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(pwm->clk), + sun4ichip->clk = devm_clk_get_optional(&pdev->dev, "mod"); + if (IS_ERR(sun4ichip->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->clk), "get mod clock failed\n"); - if (!pwm->clk) { - pwm->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(pwm->clk), + if (!sun4ichip->clk) { + sun4ichip->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sun4ichip->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->clk), "get unnamed clock failed\n"); } - pwm->bus_clk = devm_clk_get_optional(&pdev->dev, "bus"); - if (IS_ERR(pwm->bus_clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(pwm->bus_clk), + sun4ichip->bus_clk = devm_clk_get_optional(&pdev->dev, "bus"); + if (IS_ERR(sun4ichip->bus_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->bus_clk), "get bus clock failed\n"); - pwm->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); - if (IS_ERR(pwm->rst)) - return dev_err_probe(&pdev->dev, PTR_ERR(pwm->rst), + sun4ichip->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); + if (IS_ERR(sun4ichip->rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->rst), "get reset failed\n"); /* Deassert reset */ - ret = reset_control_deassert(pwm->rst); + ret = reset_control_deassert(sun4ichip->rst); if (ret) { dev_err(&pdev->dev, "cannot deassert reset control: %pe\n", ERR_PTR(ret)); @@ -450,45 +450,45 @@ static int sun4i_pwm_probe(struct platform_device *pdev) * We're keeping the bus clock on for the sake of simplicity. * Actually it only needs to be on for hardware register accesses. */ - ret = clk_prepare_enable(pwm->bus_clk); + ret = clk_prepare_enable(sun4ichip->bus_clk); if (ret) { dev_err(&pdev->dev, "cannot prepare and enable bus_clk %pe\n", ERR_PTR(ret)); goto err_bus; } - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &sun4i_pwm_ops; - pwm->chip.npwm = pwm->data->npwm; + sun4ichip->chip.dev = &pdev->dev; + sun4ichip->chip.ops = &sun4i_pwm_ops; + sun4ichip->chip.npwm = sun4ichip->data->npwm; - spin_lock_init(&pwm->ctrl_lock); + spin_lock_init(&sun4ichip->ctrl_lock); - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&sun4ichip->chip); if (ret < 0) { dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); goto err_pwm_add; } - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, sun4ichip); return 0; err_pwm_add: - clk_disable_unprepare(pwm->bus_clk); + clk_disable_unprepare(sun4ichip->bus_clk); err_bus: - reset_control_assert(pwm->rst); + reset_control_assert(sun4ichip->rst); return ret; } static int sun4i_pwm_remove(struct platform_device *pdev) { - struct sun4i_pwm_chip *pwm = platform_get_drvdata(pdev); + struct sun4i_pwm_chip *sun4ichip = platform_get_drvdata(pdev); - pwmchip_remove(&pwm->chip); + pwmchip_remove(&sun4ichip->chip); - clk_disable_unprepare(pwm->bus_clk); - reset_control_assert(pwm->rst); + clk_disable_unprepare(sun4ichip->bus_clk); + reset_control_assert(sun4ichip->rst); return 0; } diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 18cf974ac776b33ac5783e4322290529711d1b06..e5a9ffef4a71e5a127af129d3111098bacff2d36 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -85,15 +85,14 @@ static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip) return container_of(chip, struct tegra_pwm_chip, chip); } -static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num) +static inline u32 pwm_readl(struct tegra_pwm_chip *pc, unsigned int offset) { - return readl(chip->regs + (num << 4)); + return readl(pc->regs + (offset << 4)); } -static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num, - unsigned long val) +static inline void pwm_writel(struct tegra_pwm_chip *pc, unsigned int offset, u32 value) { - writel(val, chip->regs + (num << 4)); + writel(value, pc->regs + (offset << 4)); } static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, @@ -240,25 +239,25 @@ static const struct pwm_ops tegra_pwm_ops = { static int tegra_pwm_probe(struct platform_device *pdev) { - struct tegra_pwm_chip *pwm; + struct tegra_pwm_chip *pc; int ret; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (!pc) return -ENOMEM; - pwm->soc = of_device_get_match_data(&pdev->dev); - pwm->dev = &pdev->dev; + pc->soc = of_device_get_match_data(&pdev->dev); + pc->dev = &pdev->dev; - pwm->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->regs)) - return PTR_ERR(pwm->regs); + pc->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pc->regs)) + return PTR_ERR(pc->regs); - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, pc); - pwm->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) - return PTR_ERR(pwm->clk); + pc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pc->clk)) + return PTR_ERR(pc->clk); ret = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); if (ret) @@ -270,7 +269,7 @@ static int tegra_pwm_probe(struct platform_device *pdev) return ret; /* Set maximum frequency of the IP */ - ret = dev_pm_opp_set_rate(pwm->dev, pwm->soc->max_frequency); + ret = dev_pm_opp_set_rate(pc->dev, pc->soc->max_frequency); if (ret < 0) { dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret); goto put_pm; @@ -281,29 +280,29 @@ static int tegra_pwm_probe(struct platform_device *pdev) * clock register resolutions. Get the configured frequency * so that PWM period can be calculated more accurately. */ - pwm->clk_rate = clk_get_rate(pwm->clk); + pc->clk_rate = clk_get_rate(pc->clk); /* Set minimum limit of PWM period for the IP */ - pwm->min_period_ns = - (NSEC_PER_SEC / (pwm->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1; + pc->min_period_ns = + (NSEC_PER_SEC / (pc->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1; - pwm->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm"); - if (IS_ERR(pwm->rst)) { - ret = PTR_ERR(pwm->rst); + pc->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm"); + if (IS_ERR(pc->rst)) { + ret = PTR_ERR(pc->rst); dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); goto put_pm; } - reset_control_deassert(pwm->rst); + reset_control_deassert(pc->rst); - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &tegra_pwm_ops; - pwm->chip.npwm = pwm->soc->num_channels; + pc->chip.dev = &pdev->dev; + pc->chip.ops = &tegra_pwm_ops; + pc->chip.npwm = pc->soc->num_channels; - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&pc->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); - reset_control_assert(pwm->rst); + reset_control_assert(pc->rst); goto put_pm; } diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 5b723a48c5f1d646be9bdb5c38f121e64e035bef..48ca0ff690ae2b0833f64f2a51d7f55d16a2ddff 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -216,7 +216,7 @@ static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan) * duty_ns = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE */ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); u32 period_cycles, duty_cycles; @@ -401,12 +401,42 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) pc->period_cycles[pwm->hwpwm] = 0; } +static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + bool enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + if (enabled) { + ehrpwm_pwm_disable(chip, pwm); + enabled = false; + } + + err = ehrpwm_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + ehrpwm_pwm_disable(chip, pwm); + return 0; + } + + err = ehrpwm_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + + if (!enabled) + err = ehrpwm_pwm_enable(chip, pwm); + + return err; +} + static const struct pwm_ops ehrpwm_pwm_ops = { .free = ehrpwm_pwm_free, - .config = ehrpwm_pwm_config, - .set_polarity = ehrpwm_pwm_set_polarity, - .enable = ehrpwm_pwm_enable, - .disable = ehrpwm_pwm_disable, + .apply = ehrpwm_pwm_apply, .owner = THIS_MODULE, }; diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index 7170a315535bcfeb9cbecb0e1982e76b923e15b0..f1ff9940b37ce50ab86ee6fa548513a96a779637 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c @@ -235,7 +235,7 @@ MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids); static int vt8500_pwm_probe(struct platform_device *pdev) { - struct vt8500_chip *chip; + struct vt8500_chip *vt8500; struct device_node *np = pdev->dev.of_node; int ret; @@ -244,48 +244,48 @@ static int vt8500_pwm_probe(struct platform_device *pdev) return -EINVAL; } - chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + vt8500 = devm_kzalloc(&pdev->dev, sizeof(*vt8500), GFP_KERNEL); + if (vt8500 == NULL) return -ENOMEM; - chip->chip.dev = &pdev->dev; - chip->chip.ops = &vt8500_pwm_ops; - chip->chip.npwm = VT8500_NR_PWMS; + vt8500->chip.dev = &pdev->dev; + vt8500->chip.ops = &vt8500_pwm_ops; + vt8500->chip.npwm = VT8500_NR_PWMS; - chip->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(chip->clk)) { + vt8500->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(vt8500->clk)) { dev_err(&pdev->dev, "clock source not specified\n"); - return PTR_ERR(chip->clk); + return PTR_ERR(vt8500->clk); } - chip->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(chip->base)) - return PTR_ERR(chip->base); + vt8500->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(vt8500->base)) + return PTR_ERR(vt8500->base); - ret = clk_prepare(chip->clk); + ret = clk_prepare(vt8500->clk); if (ret < 0) { dev_err(&pdev->dev, "failed to prepare clock\n"); return ret; } - ret = pwmchip_add(&chip->chip); + ret = pwmchip_add(&vt8500->chip); if (ret < 0) { dev_err(&pdev->dev, "failed to add PWM chip\n"); - clk_unprepare(chip->clk); + clk_unprepare(vt8500->clk); return ret; } - platform_set_drvdata(pdev, chip); + platform_set_drvdata(pdev, vt8500); return ret; } static int vt8500_pwm_remove(struct platform_device *pdev) { - struct vt8500_chip *chip = platform_get_drvdata(pdev); + struct vt8500_chip *vt8500 = platform_get_drvdata(pdev); - pwmchip_remove(&chip->chip); + pwmchip_remove(&vt8500->chip); - clk_unprepare(chip->clk); + clk_unprepare(vt8500->clk); return 0; }