summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mfd/google,cros-ec.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml53
-rw-r--r--Documentation/devicetree/bindings/pwm/brcm,bcm7038-pwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml5
-rw-r--r--Documentation/devicetree/bindings/pwm/imx-pwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/intel,keembay-pwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/intel,lgm-pwm.yaml3
-rw-r--r--Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/mxs-pwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt1
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml74
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-samsung.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-sifive.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml26
-rw-r--r--Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/toshiba,pwm-visconti.yaml4
-rw-r--r--Documentation/devicetree/bindings/timer/ingenic,tcu.yaml1
-rw-r--r--drivers/pwm/pwm-atmel.c2
-rw-r--r--drivers/pwm/pwm-bcm-kona.c90
-rw-r--r--drivers/pwm/pwm-brcmstb.c52
-rw-r--r--drivers/pwm/pwm-img.c141
-rw-r--r--drivers/pwm/pwm-imx1.c33
-rw-r--r--drivers/pwm/pwm-jz4740.c5
-rw-r--r--drivers/pwm/pwm-lpc18xx-sct.c49
-rw-r--r--drivers/pwm/pwm-mediatek.c34
-rw-r--r--drivers/pwm/pwm-meson.c25
-rw-r--r--drivers/pwm/pwm-pca9685.c4
-rw-r--r--drivers/pwm/pwm-pxa.c33
-rw-r--r--drivers/pwm/pwm-raspberrypi-poe.c1
-rw-r--r--drivers/pwm/pwm-rcar.c2
-rw-r--r--drivers/pwm/pwm-stmpe.c18
-rw-r--r--drivers/pwm/pwm-sun4i.c70
-rw-r--r--drivers/pwm/pwm-tegra.c59
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c40
-rw-r--r--drivers/pwm/pwm-vt8500.c38
38 files changed, 492 insertions, 401 deletions
diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
index d8b495f71282..afec0bd2f1de 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 800d511502c4..e93e935564fb 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 4080e098f746..119de3d7f9dd 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 4cfbffd8414a..7ab6912a845f 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 379d693889f6..b3da4e629341 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 fe9ef42544f1..8bef9dfeba9a 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 ff6880a02ce6..ec9f6bab798c 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 11a606536169..59d7c4d864c1 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 1d7c27be50da..0a46af240d83 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 8740e076061e..a34cbc13f691 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 902b271891ae..691e58b6c223 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 81a54a4e8e3e..a336ff9364a9 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 188679cb8b8c..fe603fb1b2cc 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 db41cd7bf150..605c1766dba8 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 ed35b6cc48d5..3840ae709bc6 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 ee312cb210e6..70a8f766212e 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 7ea1070b4b3a..1c94acbc2b4a 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 1f5c6384182e..c6b2ab56b7fe 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 d350f5edfb67..46622661e5fb 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 7fb37eae9da7..d541cf2067bc 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 98b34ea9f38e..8e00a4286145 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 64148f5f81d0..f171169c1c1f 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 3b529f82b97c..3db3f96edf78 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 @@ done:
* 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 @@ done:
/* 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 5996049f66ec..0fccf061ab95 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 @@ err_pm_disable:
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 bcd849496f8d..1f2eb1c8ff6c 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 23dc1fb770e2..a5fdf97c0d2e 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 8e461f3baa05..b909096dba2f 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 0d4dd80e9f07..568b13a48717 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 3cf3bcf5ddfc..57112f438c6d 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 c56001a790d0..c91fa7f9e33d 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 238ec88c130b..0bcaa58c6a91 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 579a15240e0a..e52e29fc8231 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 b437192380e2..55f46d09602b 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 9dc983a3cbf1..c4336d3bace3 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 91ca67651abd..16d75f9aa36a 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 18cf974ac776..e5a9ffef4a71 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 5b723a48c5f1..48ca0ff690ae 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 7170a315535b..f1ff9940b37c 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;
}