Commit 74164d28 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pwm/for-5.18-rc1' of...

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

Pull pwm updates from Thierry Reding:
 "This contains conversions of some more drivers to the atomic API as
  well as the addition of new chip support for some existing drivers.

  There are also various minor fixes and cleanups across the board, from
  drivers to device tree bindings"

* tag 'pwm/for-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (45 commits)
  pwm: rcar: Simplify multiplication/shift logic
  dt-bindings: pwm: renesas,tpu: Do not require pwm-cells twice
  dt-bindings: pwm: tiehrpwm: Do not require pwm-cells twice
  dt-bindings: pwm: tiecap: Do not require pwm-cells twice
  dt-bindings: pwm: samsung: Do not require pwm-cells twice
  dt-bindings: pwm: intel,keembay: Do not require pwm-cells twice
  dt-bindings: pwm: brcm,bcm7038: Do not require pwm-cells twice
  dt-bindings: pwm: toshiba,visconti: Include generic PWM schema
  dt-bindings: pwm: renesas,pwm: Include generic PWM schema
  dt-bindings: pwm: sifive: Include generic PWM schema
  dt-bindings: pwm: rockchip: Include generic PWM schema
  dt-bindings: pwm: mxs: Include generic PWM schema
  dt-bindings: pwm: iqs620a: Include generic PWM schema
  dt-bindings: pwm: intel,lgm: Include generic PWM schema
  dt-bindings: pwm: imx: Include generic PWM schema
  dt-bindings: pwm: allwinner,sun4i-a10: Include generic PWM schema
  pwm: pwm-mediatek: Beautify error messages text
  pwm: pwm-mediatek: Allocate clk_pwms with devm_kmalloc_array
  pwm: pwm-mediatek: Simplify error handling with dev_err_probe()
  pwm: brcmstb: Remove useless locking
  ...
parents 4f373011 ed14d364
...@@ -85,6 +85,10 @@ properties: ...@@ -85,6 +85,10 @@ properties:
ec-pwm: ec-pwm:
$ref: "/schemas/pwm/google,cros-ec-pwm.yaml#" $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
deprecated: true
pwm:
$ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
keyboard-controller: keyboard-controller:
$ref: "/schemas/input/google,cros-ec-keyb.yaml#" $ref: "/schemas/input/google,cros-ec-keyb.yaml#"
......
...@@ -52,33 +52,36 @@ properties: ...@@ -52,33 +52,36 @@ properties:
resets: resets:
maxItems: 1 maxItems: 1
if:
properties: allOf:
compatible: - $ref: pwm.yaml#
contains:
const: allwinner,sun50i-h6-pwm - if:
properties:
then: compatible:
properties: contains:
clocks: const: allwinner,sun50i-h6-pwm
maxItems: 2
then:
clock-names: properties:
items: clocks:
- const: mod maxItems: 2
- const: bus
clock-names:
required: items:
- clock-names - const: mod
- resets - const: bus
else: required:
properties: - clock-names
clocks: - resets
maxItems: 1
else:
properties:
clocks:
maxItems: 1
required: required:
- "#pwm-cells"
- compatible - compatible
- reg - reg
- clocks - clocks
......
...@@ -28,7 +28,6 @@ properties: ...@@ -28,7 +28,6 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- "#pwm-cells"
- clocks - clocks
additionalProperties: false additionalProperties: false
......
...@@ -16,6 +16,9 @@ description: | ...@@ -16,6 +16,9 @@ description: |
An EC PWM node should be only found as a sub-node of the EC node (see 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). Documentation/devicetree/bindings/mfd/google,cros-ec.yaml).
allOf:
- $ref: pwm.yaml#
properties: properties:
compatible: compatible:
const: google,cros-ec-pwm const: google,cros-ec-pwm
...@@ -39,7 +42,7 @@ examples: ...@@ -39,7 +42,7 @@ examples:
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
cros_ec_pwm: ec-pwm { cros_ec_pwm: pwm {
compatible = "google,cros-ec-pwm"; compatible = "google,cros-ec-pwm";
#pwm-cells = <1>; #pwm-cells = <1>;
}; };
......
...@@ -9,6 +9,9 @@ title: Freescale i.MX PWM controller ...@@ -9,6 +9,9 @@ title: Freescale i.MX PWM controller
maintainers: maintainers:
- Philipp Zabel <p.zabel@pengutronix.de> - Philipp Zabel <p.zabel@pengutronix.de>
allOf:
- $ref: pwm.yaml#
properties: properties:
"#pwm-cells": "#pwm-cells":
description: | description: |
...@@ -59,7 +62,6 @@ properties: ...@@ -59,7 +62,6 @@ properties:
maxItems: 1 maxItems: 1
required: required:
- "#pwm-cells"
- compatible - compatible
- reg - reg
- clocks - clocks
......
...@@ -13,6 +13,9 @@ description: | ...@@ -13,6 +13,9 @@ description: |
The TPM counter and period counter are shared between multiple The TPM counter and period counter are shared between multiple
channels, so all channels should use same period setting. channels, so all channels should use same period setting.
allOf:
- $ref: pwm.yaml#
properties: properties:
"#pwm-cells": "#pwm-cells":
const: 3 const: 3
...@@ -34,7 +37,6 @@ properties: ...@@ -34,7 +37,6 @@ properties:
maxItems: 1 maxItems: 1
required: required:
- "#pwm-cells"
- compatible - compatible
- reg - reg
- clocks - clocks
......
...@@ -31,7 +31,6 @@ required: ...@@ -31,7 +31,6 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- '#pwm-cells'
additionalProperties: false additionalProperties: false
......
...@@ -9,6 +9,9 @@ title: LGM SoC PWM fan controller ...@@ -9,6 +9,9 @@ title: LGM SoC PWM fan controller
maintainers: maintainers:
- Rahul Tanwar <rtanwar@maxlinear.com> - Rahul Tanwar <rtanwar@maxlinear.com>
allOf:
- $ref: pwm.yaml#
properties: properties:
compatible: compatible:
const: intel,lgm-pwm const: intel,lgm-pwm
......
...@@ -15,6 +15,9 @@ description: | ...@@ -15,6 +15,9 @@ description: |
Documentation/devicetree/bindings/mfd/iqs62x.yaml for further details as Documentation/devicetree/bindings/mfd/iqs62x.yaml for further details as
well as an example. well as an example.
allOf:
- $ref: pwm.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -25,7 +28,6 @@ properties: ...@@ -25,7 +28,6 @@ properties:
required: required:
- compatible - compatible
- "#pwm-cells"
additionalProperties: false additionalProperties: false
......
...@@ -10,6 +10,9 @@ maintainers: ...@@ -10,6 +10,9 @@ maintainers:
- Shawn Guo <shawnguo@kernel.org> - Shawn Guo <shawnguo@kernel.org>
- Anson Huang <anson.huang@nxp.com> - Anson Huang <anson.huang@nxp.com>
allOf:
- $ref: pwm.yaml#
properties: properties:
compatible: compatible:
enum: enum:
...@@ -28,7 +31,6 @@ properties: ...@@ -28,7 +31,6 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- "#pwm-cells"
- fsl,pwm-number - fsl,pwm-number
additionalProperties: false additionalProperties: false
......
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
- "mediatek,mt6595-disp-pwm": found on mt6595 SoC. - "mediatek,mt6595-disp-pwm": found on mt6595 SoC.
- "mediatek,mt8167-disp-pwm", "mediatek,mt8173-disp-pwm": found on mt8167 SoC. - "mediatek,mt8167-disp-pwm", "mediatek,mt8173-disp-pwm": found on mt8167 SoC.
- "mediatek,mt8173-disp-pwm": found on mt8173 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. - 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 - #pwm-cells: must be 2. See pwm.yaml in this directory for a description of
the cell format. the cell format.
......
...@@ -51,42 +51,44 @@ properties: ...@@ -51,42 +51,44 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- "#pwm-cells"
allOf:
if: - $ref: pwm.yaml#
properties:
compatible: - if:
contains: properties:
enum: compatible:
- rockchip,rk3328-pwm contains:
- rockchip,rv1108-pwm enum:
- rockchip,rk3328-pwm
then: - rockchip,rv1108-pwm
properties:
clocks: then:
items: properties:
- description: Used to derive the functional clock for the device. clocks:
- description: Used as the APB bus clock. items:
- description: Used to derive the functional clock for the device.
clock-names: - description: Used as the APB bus clock.
items:
- const: pwm clock-names:
- const: pclk items:
- const: pwm
required: - const: pclk
- clocks
- clock-names required:
- clocks
else: - clock-names
properties:
clocks: else:
maxItems: 1 properties:
description: clocks:
Used both to derive the functional clock maxItems: 1
for the device and as the bus clock. description:
Used both to derive the functional clock
required: for the device and as the bus clock.
- clocks
required:
- clocks
additionalProperties: false additionalProperties: false
......
...@@ -86,7 +86,6 @@ required: ...@@ -86,7 +86,6 @@ required:
- clocks - clocks
- clock-names - clock-names
- compatible - compatible
- "#pwm-cells"
- reg - reg
additionalProperties: false additionalProperties: false
......
...@@ -21,6 +21,9 @@ description: ...@@ -21,6 +21,9 @@ description:
https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/pwm https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/pwm
allOf:
- $ref: pwm.yaml#
properties: properties:
compatible: compatible:
items: items:
...@@ -54,7 +57,6 @@ required: ...@@ -54,7 +57,6 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- "#pwm-cells"
- interrupts - interrupts
additionalProperties: false additionalProperties: false
......
...@@ -47,7 +47,6 @@ properties: ...@@ -47,7 +47,6 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- "#pwm-cells"
- clocks - clocks
- clock-names - clock-names
......
...@@ -48,7 +48,6 @@ properties: ...@@ -48,7 +48,6 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- "#pwm-cells"
- clocks - clocks
- clock-names - clock-names
......
...@@ -59,21 +59,23 @@ properties: ...@@ -59,21 +59,23 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- '#pwm-cells'
- clocks - clocks
- power-domains - power-domains
if: allOf:
not: - $ref: pwm.yaml#
properties:
compatible: - if:
contains: not:
enum: properties:
- renesas,pwm-r8a7778 compatible:
- renesas,pwm-r8a7779 contains:
then: enum:
required: - renesas,pwm-r8a7778
- resets - renesas,pwm-r8a7779
then:
required:
- resets
additionalProperties: false additionalProperties: false
......
...@@ -68,7 +68,6 @@ properties: ...@@ -68,7 +68,6 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- '#pwm-cells'
- clocks - clocks
- power-domains - power-domains
......
...@@ -9,6 +9,9 @@ title: Toshiba Visconti PWM Controller ...@@ -9,6 +9,9 @@ title: Toshiba Visconti PWM Controller
maintainers: maintainers:
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
allOf:
- $ref: pwm.yaml#
properties: properties:
compatible: compatible:
items: items:
...@@ -23,7 +26,6 @@ properties: ...@@ -23,7 +26,6 @@ properties:
required: required:
- compatible - compatible
- reg - reg
- '#pwm-cells'
additionalProperties: false additionalProperties: false
......
...@@ -152,6 +152,7 @@ patternProperties: ...@@ -152,6 +152,7 @@ patternProperties:
- enum: - enum:
- ingenic,jz4740-pwm - ingenic,jz4740-pwm
- ingenic,jz4725b-pwm - ingenic,jz4725b-pwm
- ingenic,x1000-pwm
- items: - items:
- enum: - enum:
- ingenic,jz4760-pwm - ingenic,jz4760-pwm
......
...@@ -271,7 +271,7 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -271,7 +271,7 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
bool disable_clk) bool disable_clk)
{ {
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); 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); atmel_pwm_wait_nonpending(atmel_pwm, pwm->hwpwm);
......
...@@ -109,10 +109,10 @@ static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan) ...@@ -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, 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); struct kona_pwmc *kp = to_kona_pwmc(chip);
u64 val, div, rate; u64 div, rate;
unsigned long prescale = PRESCALE_MIN, pc, dc; unsigned long prescale = PRESCALE_MIN, pc, dc;
unsigned int value, chan = pwm->hwpwm; unsigned int value, chan = pwm->hwpwm;
...@@ -132,10 +132,8 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -132,10 +132,8 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
while (1) { while (1) {
div = 1000000000; div = 1000000000;
div *= 1 + prescale; div *= 1 + prescale;
val = rate * period_ns; pc = mul_u64_u64_div_u64(rate, period_ns, div);
pc = div64_u64(val, div); dc = mul_u64_u64_div_u64(rate, duty_ns, div);
val = rate * duty_ns;
dc = div64_u64(val, div);
/* If duty_ns or period_ns are not achievable then return */ /* If duty_ns or period_ns are not achievable then return */
if (pc < PERIOD_COUNT_MIN) if (pc < PERIOD_COUNT_MIN)
...@@ -150,25 +148,18 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -150,25 +148,18 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
return -EINVAL; return -EINVAL;
} }
/* kona_pwmc_prepare_for_settings(kp, chan);
* 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);
value = readl(kp->base + PRESCALE_OFFSET); value = readl(kp->base + PRESCALE_OFFSET);
value &= ~PRESCALE_MASK(chan); value &= ~PRESCALE_MASK(chan);
value |= prescale << PRESCALE_SHIFT(chan); value |= prescale << PRESCALE_SHIFT(chan);
writel(value, kp->base + PRESCALE_OFFSET); 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; return 0;
} }
...@@ -216,13 +207,6 @@ static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -216,13 +207,6 @@ static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm)
return ret; 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; return 0;
} }
...@@ -248,11 +232,53 @@ static void kona_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -248,11 +232,53 @@ static void kona_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm)
clk_disable_unprepare(kp->clk); 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 = { static const struct pwm_ops kona_pwm_ops = {
.config = kona_pwmc_config, .apply = kona_pwmc_apply,
.set_polarity = kona_pwmc_set_polarity,
.enable = kona_pwmc_enable,
.disable = kona_pwmc_disable,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -53,7 +53,6 @@ ...@@ -53,7 +53,6 @@
struct brcmstb_pwm { struct brcmstb_pwm {
void __iomem *base; void __iomem *base;
spinlock_t lock;
struct clk *clk; struct clk *clk;
struct pwm_chip chip; struct pwm_chip chip;
}; };
...@@ -95,7 +94,7 @@ static inline struct brcmstb_pwm *to_brcmstb_pwm(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. * "on" time, so this translates directly into our HW programming here.
*/ */
static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 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); struct brcmstb_pwm *p = to_brcmstb_pwm(chip);
unsigned long pc, dc, cword = CONST_VAR_F_MAX; 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, ...@@ -114,22 +113,17 @@ static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
} }
while (1) { while (1) {
u64 rate, tmp; u64 rate;
/* /*
* Calculate the base rate from base frequency and current * Calculate the base rate from base frequency and current
* cword * cword
*/ */
rate = (u64)clk_get_rate(p->clk) * (u64)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; pc = mul_u64_u64_div_u64(period_ns, rate, NSEC_PER_SEC);
do_div(tmp, NSEC_PER_SEC); dc = mul_u64_u64_div_u64(duty_ns + 1, rate, NSEC_PER_SEC);
pc = tmp;
tmp = (duty_ns + 1) * rate;
do_div(tmp, NSEC_PER_SEC);
dc = tmp;
/* /*
* We can be called with separate duty and period updates, * 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, ...@@ -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 output a base frequency for the constant frequency
* generator to derive from. * generator to derive from.
*/ */
spin_lock(&p->lock);
brcmstb_pwm_writel(p, cword >> 8, PWM_CWORD_MSB(channel)); brcmstb_pwm_writel(p, cword >> 8, PWM_CWORD_MSB(channel));
brcmstb_pwm_writel(p, cword & 0xff, PWM_CWORD_LSB(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, ...@@ -176,7 +169,6 @@ static int brcmstb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* Configure on and period value */ /* Configure on and period value */
brcmstb_pwm_writel(p, pc, PWM_PERIOD(channel)); brcmstb_pwm_writel(p, pc, PWM_PERIOD(channel));
brcmstb_pwm_writel(p, dc, PWM_ON(channel)); brcmstb_pwm_writel(p, dc, PWM_ON(channel));
spin_unlock(&p->lock);
return 0; return 0;
} }
...@@ -187,7 +179,6 @@ static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p, ...@@ -187,7 +179,6 @@ static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p,
unsigned int shift = channel * CTRL_CHAN_OFFS; unsigned int shift = channel * CTRL_CHAN_OFFS;
u32 value; u32 value;
spin_lock(&p->lock);
value = brcmstb_pwm_readl(p, PWM_CTRL); value = brcmstb_pwm_readl(p, PWM_CTRL);
if (enable) { if (enable) {
...@@ -199,29 +190,36 @@ static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p, ...@@ -199,29 +190,36 @@ static inline void brcmstb_pwm_enable_set(struct brcmstb_pwm *p,
} }
brcmstb_pwm_writel(p, value, PWM_CTRL); 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); 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) return 0;
{ }
struct brcmstb_pwm *p = to_brcmstb_pwm(chip);
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 = { static const struct pwm_ops brcmstb_pwm_ops = {
.config = brcmstb_pwm_config, .apply = brcmstb_pwm_apply,
.enable = brcmstb_pwm_enable,
.disable = brcmstb_pwm_disable,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
...@@ -240,8 +238,6 @@ static int brcmstb_pwm_probe(struct platform_device *pdev) ...@@ -240,8 +238,6 @@ static int brcmstb_pwm_probe(struct platform_device *pdev)
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&p->lock);
p->clk = devm_clk_get(&pdev->dev, NULL); p->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(p->clk)) { if (IS_ERR(p->clk)) {
dev_err(&pdev->dev, "failed to obtain clock\n"); dev_err(&pdev->dev, "failed to obtain clock\n");
......
This diff is collapsed.
...@@ -61,7 +61,7 @@ static void pwm_imx1_clk_disable_unprepare(struct pwm_chip *chip) ...@@ -61,7 +61,7 @@ static void pwm_imx1_clk_disable_unprepare(struct pwm_chip *chip)
} }
static int pwm_imx1_config(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); struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip);
u32 max, p; u32 max, p;
...@@ -84,7 +84,7 @@ static int pwm_imx1_config(struct pwm_chip *chip, ...@@ -84,7 +84,7 @@ static int pwm_imx1_config(struct pwm_chip *chip,
* (/2 .. /16). * (/2 .. /16).
*/ */
max = readl(imx->mmio_base + MX1_PWMP); 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); 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) ...@@ -120,10 +120,33 @@ static void pwm_imx1_disable(struct pwm_chip *chip, struct pwm_device *pwm)
pwm_imx1_clk_disable_unprepare(chip); 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 = { static const struct pwm_ops pwm_imx1_ops = {
.enable = pwm_imx1_enable, .apply = pwm_imx1_apply,
.disable = pwm_imx1_disable,
.config = pwm_imx1_config,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -256,10 +256,15 @@ static const struct soc_info __maybe_unused jz4725b_soc_info = { ...@@ -256,10 +256,15 @@ static const struct soc_info __maybe_unused jz4725b_soc_info = {
.num_pwms = 6, .num_pwms = 6,
}; };
static const struct soc_info __maybe_unused x1000_soc_info = {
.num_pwms = 5,
};
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id jz4740_pwm_dt_ids[] = { static const struct of_device_id jz4740_pwm_dt_ids[] = {
{ .compatible = "ingenic,jz4740-pwm", .data = &jz4740_soc_info }, { .compatible = "ingenic,jz4740-pwm", .data = &jz4740_soc_info },
{ .compatible = "ingenic,jz4725b-pwm", .data = &jz4725b_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); MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids);
......
...@@ -76,6 +76,8 @@ ...@@ -76,6 +76,8 @@
#define LPC18XX_PWM_EVENT_PERIOD 0 #define LPC18XX_PWM_EVENT_PERIOD 0
#define LPC18XX_PWM_EVENT_MAX 16 #define LPC18XX_PWM_EVENT_MAX 16
#define LPC18XX_NUM_PWMS 16
/* SCT conflict resolution */ /* SCT conflict resolution */
enum lpc18xx_pwm_res_action { enum lpc18xx_pwm_res_action {
LPC18XX_PWM_RES_NONE, LPC18XX_PWM_RES_NONE,
...@@ -101,6 +103,7 @@ struct lpc18xx_pwm_chip { ...@@ -101,6 +103,7 @@ struct lpc18xx_pwm_chip {
unsigned long event_map; unsigned long event_map;
struct mutex res_lock; struct mutex res_lock;
struct mutex period_lock; struct mutex period_lock;
struct lpc18xx_pwm_data channeldata[LPC18XX_NUM_PWMS];
}; };
static inline struct lpc18xx_pwm_chip * static inline struct lpc18xx_pwm_chip *
...@@ -163,7 +166,7 @@ static void lpc18xx_pwm_config_duty(struct pwm_chip *chip, ...@@ -163,7 +166,7 @@ static void lpc18xx_pwm_config_duty(struct pwm_chip *chip,
struct pwm_device *pwm, int duty_ns) struct pwm_device *pwm, int duty_ns)
{ {
struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); 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; u64 val;
val = (u64)duty_ns * lpc18xx_pwm->clk_rate; val = (u64)duty_ns * lpc18xx_pwm->clk_rate;
...@@ -233,7 +236,7 @@ static int lpc18xx_pwm_set_polarity(struct pwm_chip *chip, ...@@ -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) 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_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; enum lpc18xx_pwm_res_action res_action;
unsigned int set_event, clear_event; unsigned int set_event, clear_event;
...@@ -268,7 +271,7 @@ static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -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) 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_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_writel(lpc18xx_pwm,
LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0); 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) ...@@ -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) 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_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; unsigned long event;
event = find_first_zero_bit(&lpc18xx_pwm->event_map, 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) ...@@ -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) 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_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); clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map);
} }
...@@ -324,8 +327,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match); ...@@ -324,8 +327,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match);
static int lpc18xx_pwm_probe(struct platform_device *pdev) static int lpc18xx_pwm_probe(struct platform_device *pdev)
{ {
struct lpc18xx_pwm_chip *lpc18xx_pwm; struct lpc18xx_pwm_chip *lpc18xx_pwm;
struct pwm_device *pwm; int ret;
int ret, i;
u64 val; u64 val;
lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm), lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm),
...@@ -370,7 +372,7 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) ...@@ -370,7 +372,7 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
lpc18xx_pwm->chip.dev = &pdev->dev; lpc18xx_pwm->chip.dev = &pdev->dev;
lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops; 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 */ /* SCT counter must be in unify (32 bit) mode */
lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG,
...@@ -395,40 +397,23 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) ...@@ -395,40 +397,23 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT, lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT,
BIT(lpc18xx_pwm->period_event)); 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); ret = pwmchip_add(&lpc18xx_pwm->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret); dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
goto disable_pwmclk; 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); 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; return 0;
remove_pwmchip:
pwmchip_remove(&lpc18xx_pwm->chip);
disable_pwmclk: disable_pwmclk:
clk_disable_unprepare(lpc18xx_pwm->pwm_clk); clk_disable_unprepare(lpc18xx_pwm->pwm_clk);
return ret; return ret;
......
...@@ -146,7 +146,7 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -146,7 +146,7 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (clkdiv > PWM_CLK_DIV_MAX) { if (clkdiv > PWM_CLK_DIV_MAX) {
pwm_mediatek_clk_disable(chip, pwm); 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; return -EINVAL;
} }
...@@ -221,24 +221,20 @@ static int pwm_mediatek_probe(struct platform_device *pdev) ...@@ -221,24 +221,20 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
if (IS_ERR(pc->regs)) if (IS_ERR(pc->regs))
return PTR_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); sizeof(*pc->clk_pwms), GFP_KERNEL);
if (!pc->clk_pwms) if (!pc->clk_pwms)
return -ENOMEM; return -ENOMEM;
pc->clk_top = devm_clk_get(&pdev->dev, "top"); pc->clk_top = devm_clk_get(&pdev->dev, "top");
if (IS_ERR(pc->clk_top)) { if (IS_ERR(pc->clk_top))
dev_err(&pdev->dev, "clock: top fail: %ld\n", return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
PTR_ERR(pc->clk_top)); "Failed to get top clock\n");
return PTR_ERR(pc->clk_top);
}
pc->clk_main = devm_clk_get(&pdev->dev, "main"); pc->clk_main = devm_clk_get(&pdev->dev, "main");
if (IS_ERR(pc->clk_main)) { if (IS_ERR(pc->clk_main))
dev_err(&pdev->dev, "clock: main fail: %ld\n", return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
PTR_ERR(pc->clk_main)); "Failed to get main clock\n");
return PTR_ERR(pc->clk_main);
}
for (i = 0; i < pc->soc->num_pwms; i++) { for (i = 0; i < pc->soc->num_pwms; i++) {
char name[8]; char name[8];
...@@ -246,11 +242,9 @@ static int pwm_mediatek_probe(struct platform_device *pdev) ...@@ -246,11 +242,9 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
snprintf(name, sizeof(name), "pwm%d", i + 1); snprintf(name, sizeof(name), "pwm%d", i + 1);
pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name); pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name);
if (IS_ERR(pc->clk_pwms[i])) { if (IS_ERR(pc->clk_pwms[i]))
dev_err(&pdev->dev, "clock: %s fail: %ld\n", return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]),
name, PTR_ERR(pc->clk_pwms[i])); "Failed to get %s clock\n", name);
return PTR_ERR(pc->clk_pwms[i]);
}
} }
pc->chip.dev = &pdev->dev; pc->chip.dev = &pdev->dev;
...@@ -258,10 +252,8 @@ static int pwm_mediatek_probe(struct platform_device *pdev) ...@@ -258,10 +252,8 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
pc->chip.npwm = pc->soc->num_pwms; pc->chip.npwm = pc->soc->num_pwms;
ret = devm_pwmchip_add(&pdev->dev, &pc->chip); ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
if (ret < 0) { if (ret < 0)
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
return ret;
}
return 0; return 0;
} }
......
...@@ -120,16 +120,10 @@ static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip) ...@@ -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) static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{ {
struct meson_pwm *meson = to_meson_pwm(chip); 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; struct device *dev = chip->dev;
int err; int err;
channel = pwm_get_chip_data(pwm);
if (channel)
return 0;
channel = &meson->channels[pwm->hwpwm];
if (channel->clk_parent) { if (channel->clk_parent) {
err = clk_set_parent(channel->clk, channel->clk_parent); err = clk_set_parent(channel->clk, channel->clk_parent);
if (err < 0) { if (err < 0) {
...@@ -147,21 +141,21 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -147,21 +141,21 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
return err; return err;
} }
return pwm_set_chip_data(pwm, channel); return 0;
} }
static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 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, static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
const struct pwm_state *state) 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 int duty, period, pre_div, cnt, duty_cnt;
unsigned long fin_freq; unsigned long fin_freq;
...@@ -224,7 +218,7 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, ...@@ -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) 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; struct meson_pwm_channel_data *channel_data;
unsigned long flags; unsigned long flags;
u32 value; u32 value;
...@@ -267,13 +261,10 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) ...@@ -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, static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state) 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 *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
int err = 0; int err = 0;
if (!state)
return -EINVAL;
if (!state->enabled) { if (!state->enabled) {
if (state->polarity == PWM_POLARITY_INVERSED) { if (state->polarity == PWM_POLARITY_INVERSED) {
/* /*
......
...@@ -560,10 +560,10 @@ static int pca9685_pwm_probe(struct i2c_client *client, ...@@ -560,10 +560,10 @@ static int pca9685_pwm_probe(struct i2c_client *client,
pca9685_write_reg(pca, PCA9685_MODE1, reg); pca9685_write_reg(pca, PCA9685_MODE1, reg);
/* Reset OFF/ON registers to POR default */ /* 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_OFF_H, LED_FULL);
pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0); 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; pca->chip.ops = &pca9685_pwm_ops;
/* Add an extra channel for ALL_LED */ /* Add an extra channel for ALL_LED */
......
...@@ -58,7 +58,7 @@ static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip) ...@@ -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 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
*/ */
static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 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); struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip);
unsigned long long c; unsigned long long c;
...@@ -84,7 +84,7 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -84,7 +84,7 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (duty_ns == period_ns) if (duty_ns == period_ns)
dc = PWMDCR_FD; dc = PWMDCR_FD;
else 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 /* NOTE: the clock to PWM has to be enabled first
* before writing to the registers * before writing to the registers
...@@ -115,10 +115,33 @@ static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -115,10 +115,33 @@ static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
clk_disable_unprepare(pc->clk); 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 = { static const struct pwm_ops pxa_pwm_ops = {
.config = pxa_pwm_config, .apply = pxa_pwm_apply,
.enable = pxa_pwm_enable,
.disable = pxa_pwm_disable,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -163,7 +163,6 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev) ...@@ -163,7 +163,6 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
rpipwm->firmware = firmware; rpipwm->firmware = firmware;
rpipwm->chip.dev = dev; rpipwm->chip.dev = dev;
rpipwm->chip.ops = &raspberrypi_pwm_ops; rpipwm->chip.ops = &raspberrypi_pwm_ops;
rpipwm->chip.base = -1;
rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM; rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM;
ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG, ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
......
...@@ -110,7 +110,7 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns, ...@@ -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); unsigned long clk_rate = clk_get_rate(rp->clk);
u32 cyc, ph; 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); do_div(one_cycle, clk_rate);
tmp = period_ns * 100ULL; tmp = period_ns * 100ULL;
......
...@@ -269,19 +269,19 @@ static const struct pwm_ops stmpe_24xx_pwm_ops = { ...@@ -269,19 +269,19 @@ static const struct pwm_ops stmpe_24xx_pwm_ops = {
static int __init stmpe_pwm_probe(struct platform_device *pdev) static int __init stmpe_pwm_probe(struct platform_device *pdev)
{ {
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
struct stmpe_pwm *pwm; struct stmpe_pwm *stmpe_pwm;
int ret; int ret;
pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); stmpe_pwm = devm_kzalloc(&pdev->dev, sizeof(*stmpe_pwm), GFP_KERNEL);
if (!pwm) if (!stmpe_pwm)
return -ENOMEM; return -ENOMEM;
pwm->stmpe = stmpe; stmpe_pwm->stmpe = stmpe;
pwm->chip.dev = &pdev->dev; stmpe_pwm->chip.dev = &pdev->dev;
if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) { if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) {
pwm->chip.ops = &stmpe_24xx_pwm_ops; stmpe_pwm->chip.ops = &stmpe_24xx_pwm_ops;
pwm->chip.npwm = 3; stmpe_pwm->chip.npwm = 3;
} else { } else {
if (stmpe->partnum == STMPE1601) if (stmpe->partnum == STMPE1601)
dev_err(&pdev->dev, "STMPE1601 not yet supported\n"); dev_err(&pdev->dev, "STMPE1601 not yet supported\n");
...@@ -295,14 +295,12 @@ static int __init stmpe_pwm_probe(struct platform_device *pdev) ...@@ -295,14 +295,12 @@ static int __init stmpe_pwm_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
ret = pwmchip_add(&pwm->chip); ret = pwmchip_add(&stmpe_pwm->chip);
if (ret) { if (ret) {
stmpe_disable(stmpe, STMPE_BLOCK_PWM); stmpe_disable(stmpe, STMPE_BLOCK_PWM);
return ret; return ret;
} }
platform_set_drvdata(pdev, pwm);
return 0; return 0;
} }
......
...@@ -390,20 +390,20 @@ MODULE_DEVICE_TABLE(of, sun4i_pwm_dt_ids); ...@@ -390,20 +390,20 @@ MODULE_DEVICE_TABLE(of, sun4i_pwm_dt_ids);
static int sun4i_pwm_probe(struct platform_device *pdev) static int sun4i_pwm_probe(struct platform_device *pdev)
{ {
struct sun4i_pwm_chip *pwm; struct sun4i_pwm_chip *sun4ichip;
int ret; int ret;
pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); sun4ichip = devm_kzalloc(&pdev->dev, sizeof(*sun4ichip), GFP_KERNEL);
if (!pwm) if (!sun4ichip)
return -ENOMEM; return -ENOMEM;
pwm->data = of_device_get_match_data(&pdev->dev); sun4ichip->data = of_device_get_match_data(&pdev->dev);
if (!pwm->data) if (!sun4ichip->data)
return -ENODEV; return -ENODEV;
pwm->base = devm_platform_ioremap_resource(pdev, 0); sun4ichip->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pwm->base)) if (IS_ERR(sun4ichip->base))
return PTR_ERR(pwm->base); return PTR_ERR(sun4ichip->base);
/* /*
* All hardware variants need a source clock that is divided and * All hardware variants need a source clock that is divided and
...@@ -416,30 +416,30 @@ static int sun4i_pwm_probe(struct platform_device *pdev) ...@@ -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 * unnamed one of the PWM device) and if this is not found we fall
* back to the first clock of the PWM. * back to the first clock of the PWM.
*/ */
pwm->clk = devm_clk_get_optional(&pdev->dev, "mod"); sun4ichip->clk = devm_clk_get_optional(&pdev->dev, "mod");
if (IS_ERR(pwm->clk)) if (IS_ERR(sun4ichip->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->clk), return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->clk),
"get mod clock failed\n"); "get mod clock failed\n");
if (!pwm->clk) { if (!sun4ichip->clk) {
pwm->clk = devm_clk_get(&pdev->dev, NULL); sun4ichip->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pwm->clk)) if (IS_ERR(sun4ichip->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->clk), return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->clk),
"get unnamed clock failed\n"); "get unnamed clock failed\n");
} }
pwm->bus_clk = devm_clk_get_optional(&pdev->dev, "bus"); sun4ichip->bus_clk = devm_clk_get_optional(&pdev->dev, "bus");
if (IS_ERR(pwm->bus_clk)) if (IS_ERR(sun4ichip->bus_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->bus_clk), return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->bus_clk),
"get bus clock failed\n"); "get bus clock failed\n");
pwm->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); sun4ichip->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
if (IS_ERR(pwm->rst)) if (IS_ERR(sun4ichip->rst))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->rst), return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->rst),
"get reset failed\n"); "get reset failed\n");
/* Deassert reset */ /* Deassert reset */
ret = reset_control_deassert(pwm->rst); ret = reset_control_deassert(sun4ichip->rst);
if (ret) { if (ret) {
dev_err(&pdev->dev, "cannot deassert reset control: %pe\n", dev_err(&pdev->dev, "cannot deassert reset control: %pe\n",
ERR_PTR(ret)); ERR_PTR(ret));
...@@ -450,45 +450,45 @@ static int sun4i_pwm_probe(struct platform_device *pdev) ...@@ -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. * We're keeping the bus clock on for the sake of simplicity.
* Actually it only needs to be on for hardware register accesses. * 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) { if (ret) {
dev_err(&pdev->dev, "cannot prepare and enable bus_clk %pe\n", dev_err(&pdev->dev, "cannot prepare and enable bus_clk %pe\n",
ERR_PTR(ret)); ERR_PTR(ret));
goto err_bus; goto err_bus;
} }
pwm->chip.dev = &pdev->dev; sun4ichip->chip.dev = &pdev->dev;
pwm->chip.ops = &sun4i_pwm_ops; sun4ichip->chip.ops = &sun4i_pwm_ops;
pwm->chip.npwm = pwm->data->npwm; 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) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
goto err_pwm_add; goto err_pwm_add;
} }
platform_set_drvdata(pdev, pwm); platform_set_drvdata(pdev, sun4ichip);
return 0; return 0;
err_pwm_add: err_pwm_add:
clk_disable_unprepare(pwm->bus_clk); clk_disable_unprepare(sun4ichip->bus_clk);
err_bus: err_bus:
reset_control_assert(pwm->rst); reset_control_assert(sun4ichip->rst);
return ret; return ret;
} }
static int sun4i_pwm_remove(struct platform_device *pdev) 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); clk_disable_unprepare(sun4ichip->bus_clk);
reset_control_assert(pwm->rst); reset_control_assert(sun4ichip->rst);
return 0; return 0;
} }
......
...@@ -85,15 +85,14 @@ static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip) ...@@ -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); 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, static inline void pwm_writel(struct tegra_pwm_chip *pc, unsigned int offset, u32 value)
unsigned long val)
{ {
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, 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 = { ...@@ -240,25 +239,25 @@ static const struct pwm_ops tegra_pwm_ops = {
static int tegra_pwm_probe(struct platform_device *pdev) static int tegra_pwm_probe(struct platform_device *pdev)
{ {
struct tegra_pwm_chip *pwm; struct tegra_pwm_chip *pc;
int ret; int ret;
pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
if (!pwm) if (!pc)
return -ENOMEM; return -ENOMEM;
pwm->soc = of_device_get_match_data(&pdev->dev); pc->soc = of_device_get_match_data(&pdev->dev);
pwm->dev = &pdev->dev; pc->dev = &pdev->dev;
pwm->regs = devm_platform_ioremap_resource(pdev, 0); pc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pwm->regs)) if (IS_ERR(pc->regs))
return PTR_ERR(pwm->regs); return PTR_ERR(pc->regs);
platform_set_drvdata(pdev, pwm); platform_set_drvdata(pdev, pc);
pwm->clk = devm_clk_get(&pdev->dev, NULL); pc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pwm->clk)) if (IS_ERR(pc->clk))
return PTR_ERR(pwm->clk); return PTR_ERR(pc->clk);
ret = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); ret = devm_tegra_core_dev_init_opp_table_common(&pdev->dev);
if (ret) if (ret)
...@@ -270,7 +269,7 @@ static int tegra_pwm_probe(struct platform_device *pdev) ...@@ -270,7 +269,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
return ret; return ret;
/* Set maximum frequency of the IP */ /* 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) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret); dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret);
goto put_pm; goto put_pm;
...@@ -281,29 +280,29 @@ static int tegra_pwm_probe(struct platform_device *pdev) ...@@ -281,29 +280,29 @@ static int tegra_pwm_probe(struct platform_device *pdev)
* clock register resolutions. Get the configured frequency * clock register resolutions. Get the configured frequency
* so that PWM period can be calculated more accurately. * 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 */ /* Set minimum limit of PWM period for the IP */
pwm->min_period_ns = pc->min_period_ns =
(NSEC_PER_SEC / (pwm->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1; (NSEC_PER_SEC / (pc->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1;
pwm->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm"); pc->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm");
if (IS_ERR(pwm->rst)) { if (IS_ERR(pc->rst)) {
ret = PTR_ERR(pwm->rst); ret = PTR_ERR(pc->rst);
dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); dev_err(&pdev->dev, "Reset control is not found: %d\n", ret);
goto put_pm; goto put_pm;
} }
reset_control_deassert(pwm->rst); reset_control_deassert(pc->rst);
pwm->chip.dev = &pdev->dev; pc->chip.dev = &pdev->dev;
pwm->chip.ops = &tegra_pwm_ops; pc->chip.ops = &tegra_pwm_ops;
pwm->chip.npwm = pwm->soc->num_channels; pc->chip.npwm = pc->soc->num_channels;
ret = pwmchip_add(&pwm->chip); ret = pwmchip_add(&pc->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
reset_control_assert(pwm->rst); reset_control_assert(pc->rst);
goto put_pm; goto put_pm;
} }
......
...@@ -216,7 +216,7 @@ static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan) ...@@ -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 * duty_ns = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE
*/ */
static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 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); struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
u32 period_cycles, duty_cycles; u32 period_cycles, duty_cycles;
...@@ -401,12 +401,42 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -401,12 +401,42 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
pc->period_cycles[pwm->hwpwm] = 0; 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 = { static const struct pwm_ops ehrpwm_pwm_ops = {
.free = ehrpwm_pwm_free, .free = ehrpwm_pwm_free,
.config = ehrpwm_pwm_config, .apply = ehrpwm_pwm_apply,
.set_polarity = ehrpwm_pwm_set_polarity,
.enable = ehrpwm_pwm_enable,
.disable = ehrpwm_pwm_disable,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -235,7 +235,7 @@ MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids); ...@@ -235,7 +235,7 @@ MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids);
static int vt8500_pwm_probe(struct platform_device *pdev) 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; struct device_node *np = pdev->dev.of_node;
int ret; int ret;
...@@ -244,48 +244,48 @@ static int vt8500_pwm_probe(struct platform_device *pdev) ...@@ -244,48 +244,48 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); vt8500 = devm_kzalloc(&pdev->dev, sizeof(*vt8500), GFP_KERNEL);
if (chip == NULL) if (vt8500 == NULL)
return -ENOMEM; return -ENOMEM;
chip->chip.dev = &pdev->dev; vt8500->chip.dev = &pdev->dev;
chip->chip.ops = &vt8500_pwm_ops; vt8500->chip.ops = &vt8500_pwm_ops;
chip->chip.npwm = VT8500_NR_PWMS; vt8500->chip.npwm = VT8500_NR_PWMS;
chip->clk = devm_clk_get(&pdev->dev, NULL); vt8500->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(chip->clk)) { if (IS_ERR(vt8500->clk)) {
dev_err(&pdev->dev, "clock source not specified\n"); 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); vt8500->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(chip->base)) if (IS_ERR(vt8500->base))
return PTR_ERR(chip->base); return PTR_ERR(vt8500->base);
ret = clk_prepare(chip->clk); ret = clk_prepare(vt8500->clk);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to prepare clock\n"); dev_err(&pdev->dev, "failed to prepare clock\n");
return ret; return ret;
} }
ret = pwmchip_add(&chip->chip); ret = pwmchip_add(&vt8500->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip\n"); dev_err(&pdev->dev, "failed to add PWM chip\n");
clk_unprepare(chip->clk); clk_unprepare(vt8500->clk);
return ret; return ret;
} }
platform_set_drvdata(pdev, chip); platform_set_drvdata(pdev, vt8500);
return ret; return ret;
} }
static int vt8500_pwm_remove(struct platform_device *pdev) 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment