diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-08 12:18:04 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-08 12:18:04 -0700 |
commit | 8c1bfd746030a14435c9b60d08a81af61332089b (patch) | |
tree | 91f3cf34eac8b319342dd54c600d3adf8cf3e0b3 /drivers | |
parent | b0dfd9af28b60d7ec42c359ae84c1ba97e093100 (diff) | |
parent | bebedf2bb4a9e0cb4ffa72cbc960728051b338a4 (diff) |
Merge tag 'pwm/for-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm updates from Thierry Reding:
"This contains mostly various fixes, cleanups and some conversions to
the atomic API. One noteworthy change is that PWM consumers can now
pass a hint to the PWM core about the PWM usage, enabling PWM
providers to implement various optimizations.
There's also a fair bit of simplification here with the addition of
some device-managed helpers as well as unification between the DT and
ACPI firmware interfaces"
* tag 'pwm/for-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (50 commits)
pwm: Remove redundant assignment to pointer pwm
pwm: ep93xx: Fix read of uninitialized variable ret
pwm: ep93xx: Prepare clock before using it
pwm: ep93xx: Unfold legacy callbacks into ep93xx_pwm_apply()
pwm: ep93xx: Implement .apply callback
pwm: vt8500: Only unprepare the clock after the pwmchip was removed
pwm: vt8500: Drop if with an always false condition
pwm: tegra: Assert reset only after the PWM was unregistered
pwm: tegra: Don't needlessly enable and disable the clock in .remove()
pwm: tegra: Don't modify HW state in .remove callback
pwm: tegra: Drop an if block with an always false condition
pwm: core: Simplify some devm_*pwm*() functions
pwm: core: Remove unused devm_pwm_put()
pwm: core: Unify fwnode checks in the module
pwm: core: Reuse fwnode_to_pwmchip() in ACPI case
pwm: core: Convert to use fwnode for matching
docs: firmware-guide: ACPI: Add a PWM example
dt-bindings: pwm: pwm-tiecap: Add compatible string for AM64 SoC
dt-bindings: pwm: pwm-tiecap: Convert to json schema
pwm: sprd: Don't check the return code of pwmchip_remove()
...
Diffstat (limited to 'drivers')
42 files changed, 531 insertions, 534 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index c4d5c0667137..35e894f4a379 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -126,8 +126,7 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) { struct pwm_device *pwm; - /* check, whether the driver supports a third cell for flags */ - if (pc->of_pwm_n_cells < 3) + if (pc->of_pwm_n_cells < 2) return ERR_PTR(-EINVAL); /* flags in the third cell are optional */ @@ -144,46 +143,29 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) pwm->args.period = args->args[1]; pwm->args.polarity = PWM_POLARITY_NORMAL; - if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) - pwm->args.polarity = PWM_POLARITY_INVERSED; + if (pc->of_pwm_n_cells >= 3) { + if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) + pwm->args.polarity = PWM_POLARITY_INVERSED; + } return pwm; } EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags); -static struct pwm_device * -of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) -{ - struct pwm_device *pwm; - - /* sanity check driver support */ - if (pc->of_pwm_n_cells < 2) - return ERR_PTR(-EINVAL); - - /* all cells are required */ - if (args->args_count != pc->of_pwm_n_cells) - return ERR_PTR(-EINVAL); - - if (args->args[0] >= pc->npwm) - return ERR_PTR(-EINVAL); - - pwm = pwm_request_from_chip(pc, args->args[0], NULL); - if (IS_ERR(pwm)) - return pwm; - - pwm->args.period = args->args[1]; - - return pwm; -} - static void of_pwmchip_add(struct pwm_chip *chip) { if (!chip->dev || !chip->dev->of_node) return; if (!chip->of_xlate) { - chip->of_xlate = of_pwm_simple_xlate; - chip->of_pwm_n_cells = 2; + u32 pwm_cells; + + if (of_property_read_u32(chip->dev->of_node, "#pwm-cells", + &pwm_cells)) + pwm_cells = 2; + + chip->of_xlate = of_pwm_xlate_with_flags; + chip->of_pwm_n_cells = pwm_cells; } of_node_get(chip->dev->of_node); @@ -324,22 +306,10 @@ EXPORT_SYMBOL_GPL(pwmchip_add); */ int pwmchip_remove(struct pwm_chip *chip) { - unsigned int i; - int ret = 0; - pwmchip_sysfs_unexport(chip); mutex_lock(&pwm_lock); - for (i = 0; i < chip->npwm; i++) { - struct pwm_device *pwm = &chip->pwms[i]; - - if (test_bit(PWMF_REQUESTED, &pwm->flags)) { - ret = -EBUSY; - goto out; - } - } - list_del_init(&chip->list); if (IS_ENABLED(CONFIG_OF)) @@ -347,12 +317,31 @@ int pwmchip_remove(struct pwm_chip *chip) free_pwms(chip); -out: mutex_unlock(&pwm_lock); - return ret; + + return 0; } EXPORT_SYMBOL_GPL(pwmchip_remove); +static void devm_pwmchip_remove(void *data) +{ + struct pwm_chip *chip = data; + + pwmchip_remove(chip); +} + +int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip) +{ + int ret; + + ret = pwmchip_add(chip); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip); +} +EXPORT_SYMBOL_GPL(devm_pwmchip_add); + /** * pwm_request() - request a PWM device * @pwm: global PWM device index @@ -554,7 +543,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) if (state->period == pwm->state.period && state->duty_cycle == pwm->state.duty_cycle && state->polarity == pwm->state.polarity && - state->enabled == pwm->state.enabled) + state->enabled == pwm->state.enabled && + state->usage_power == pwm->state.usage_power) return 0; if (chip->ops->apply) { @@ -709,14 +699,14 @@ int pwm_adjust_config(struct pwm_device *pwm) } EXPORT_SYMBOL_GPL(pwm_adjust_config); -static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) +static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode) { struct pwm_chip *chip; mutex_lock(&pwm_lock); list_for_each_entry(chip, &pwm_chips, list) - if (chip->dev && chip->dev->of_node == np) { + if (chip->dev && dev_fwnode(chip->dev) == fwnode) { mutex_unlock(&pwm_lock); return chip; } @@ -795,7 +785,7 @@ struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, return ERR_PTR(err); } - pc = of_node_to_pwmchip(args.np); + pc = fwnode_to_pwmchip(of_fwnode_handle(args.np)); if (IS_ERR(pc)) { if (PTR_ERR(pc) != -EPROBE_DEFER) pr_err("%s(): PWM chip not found\n", __func__); @@ -837,31 +827,9 @@ put: } EXPORT_SYMBOL_GPL(of_pwm_get); -#if IS_ENABLED(CONFIG_ACPI) -static struct pwm_chip *device_to_pwmchip(struct device *dev) -{ - struct pwm_chip *chip; - - mutex_lock(&pwm_lock); - - list_for_each_entry(chip, &pwm_chips, list) { - struct acpi_device *adev = ACPI_COMPANION(chip->dev); - - if ((chip->dev == dev) || (adev && &adev->dev == dev)) { - mutex_unlock(&pwm_lock); - return chip; - } - } - - mutex_unlock(&pwm_lock); - - return ERR_PTR(-EPROBE_DEFER); -} -#endif - /** * acpi_pwm_get() - request a PWM via parsing "pwms" property in ACPI - * @fwnode: firmware node to get the "pwm" property from + * @fwnode: firmware node to get the "pwms" property from * * Returns the PWM device parsed from the fwnode and index specified in the * "pwms" property or a negative error-code on failure. @@ -876,12 +844,10 @@ static struct pwm_chip *device_to_pwmchip(struct device *dev) * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded * error code on failure. */ -static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) +static struct pwm_device *acpi_pwm_get(const struct fwnode_handle *fwnode) { - struct pwm_device *pwm = ERR_PTR(-ENODEV); -#if IS_ENABLED(CONFIG_ACPI) + struct pwm_device *pwm; struct fwnode_reference_args args; - struct acpi_device *acpi; struct pwm_chip *chip; int ret; @@ -891,14 +857,10 @@ static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) if (ret < 0) return ERR_PTR(ret); - acpi = to_acpi_device_node(args.fwnode); - if (!acpi) - return ERR_PTR(-EINVAL); - if (args.nargs < 2) return ERR_PTR(-EPROTO); - chip = device_to_pwmchip(&acpi->dev); + chip = fwnode_to_pwmchip(args.fwnode); if (IS_ERR(chip)) return ERR_CAST(chip); @@ -911,7 +873,6 @@ static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) if (args.nargs > 2 && args.args[2] & PWM_POLARITY_INVERTED) pwm->args.polarity = PWM_POLARITY_INVERSED; -#endif return pwm; } @@ -967,6 +928,7 @@ void pwm_remove_table(struct pwm_lookup *table, size_t num) */ struct pwm_device *pwm_get(struct device *dev, const char *con_id) { + const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL; const char *dev_id = dev ? dev_name(dev) : NULL; struct pwm_device *pwm; struct pwm_chip *chip; @@ -977,12 +939,12 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) int err; /* look up via DT first */ - if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) - return of_pwm_get(dev, dev->of_node, con_id); + if (is_of_node(fwnode)) + return of_pwm_get(dev, to_of_node(fwnode), con_id); /* then lookup via ACPI */ - if (dev && is_acpi_node(dev->fwnode)) { - pwm = acpi_pwm_get(dev->fwnode); + if (is_acpi_node(fwnode)) { + pwm = acpi_pwm_get(fwnode); if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT) return pwm; } @@ -1103,9 +1065,9 @@ out: } EXPORT_SYMBOL_GPL(pwm_put); -static void devm_pwm_release(struct device *dev, void *res) +static void devm_pwm_release(void *pwm) { - pwm_put(*(struct pwm_device **)res); + pwm_put(pwm); } /** @@ -1121,19 +1083,16 @@ static void devm_pwm_release(struct device *dev, void *res) */ struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id) { - struct pwm_device **ptr, *pwm; - - ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pwm_device *pwm; + int ret; pwm = pwm_get(dev, con_id); - if (!IS_ERR(pwm)) { - *ptr = pwm; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + if (IS_ERR(pwm)) + return pwm; + + ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); + if (ret) + return ERR_PTR(ret); return pwm; } @@ -1154,19 +1113,16 @@ EXPORT_SYMBOL_GPL(devm_pwm_get); struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, const char *con_id) { - struct pwm_device **ptr, *pwm; - - ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pwm_device *pwm; + int ret; pwm = of_pwm_get(dev, np, con_id); - if (!IS_ERR(pwm)) { - *ptr = pwm; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + if (IS_ERR(pwm)) + return pwm; + + ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); + if (ret) + return ERR_PTR(ret); return pwm; } @@ -1188,53 +1144,24 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode, const char *con_id) { - struct pwm_device **ptr, *pwm = ERR_PTR(-ENODEV); - - ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pwm_device *pwm = ERR_PTR(-ENODEV); + int ret; if (is_of_node(fwnode)) pwm = of_pwm_get(dev, to_of_node(fwnode), con_id); else if (is_acpi_node(fwnode)) pwm = acpi_pwm_get(fwnode); + if (IS_ERR(pwm)) + return pwm; - if (!IS_ERR(pwm)) { - *ptr = pwm; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); + if (ret) + return ERR_PTR(ret); return pwm; } EXPORT_SYMBOL_GPL(devm_fwnode_pwm_get); -static int devm_pwm_match(struct device *dev, void *res, void *data) -{ - struct pwm_device **p = res; - - if (WARN_ON(!p || !*p)) - return 0; - - return *p == data; -} - -/** - * devm_pwm_put() - resource managed pwm_put() - * @dev: device for PWM consumer - * @pwm: PWM device - * - * Release a PWM previously allocated using devm_pwm_get(). Calling this - * function is usually not needed because devm-allocated resources are - * automatically released on driver detach. - */ -void devm_pwm_put(struct device *dev, struct pwm_device *pwm) -{ - WARN_ON(devres_release(dev, devm_pwm_release, devm_pwm_match, pwm)); -} -EXPORT_SYMBOL_GPL(devm_pwm_put); - #ifdef CONFIG_DEBUG_FS static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) { @@ -1259,6 +1186,9 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) seq_printf(s, " polarity: %s", state.polarity ? "inverse" : "normal"); + if (state.usage_power) + seq_puts(s, " usage_power"); + seq_puts(s, "\n"); } } diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index 6ab597e54005..4459325d3650 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -266,8 +266,6 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev) chip->chip.ops = &atmel_hlcdc_pwm_ops; chip->chip.dev = dev; chip->chip.npwm = 1; - chip->chip.of_xlate = of_pwm_xlate_with_flags; - chip->chip.of_pwm_n_cells = 3; ret = pwmchip_add(&chip->chip); if (ret) { diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 8451d3e846be..bf398f21484d 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -469,8 +469,6 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) tcbpwm->chip.dev = &pdev->dev; tcbpwm->chip.ops = &atmel_tcb_pwm_ops; - tcbpwm->chip.of_xlate = of_pwm_xlate_with_flags; - tcbpwm->chip.of_pwm_n_cells = 3; tcbpwm->chip.npwm = NPWM; tcbpwm->channel = channel; tcbpwm->regmap = regmap; diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 29b5ad03f715..a8162bae3e8a 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -436,8 +436,6 @@ static int atmel_pwm_probe(struct platform_device *pdev) atmel_pwm->chip.dev = &pdev->dev; atmel_pwm->chip.ops = &atmel_pwm_ops; - atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags; - atmel_pwm->chip.of_pwm_n_cells = 3; atmel_pwm->chip.npwm = 4; ret = pwmchip_add(&atmel_pwm->chip); diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c index edd2ce1760ab..0226bf697f09 100644 --- a/drivers/pwm/pwm-bcm-iproc.c +++ b/drivers/pwm/pwm-bcm-iproc.c @@ -210,8 +210,6 @@ static int iproc_pwmc_probe(struct platform_device *pdev) ip->chip.dev = &pdev->dev; ip->chip.ops = &iproc_pwm_ops; ip->chip.npwm = 4; - ip->chip.of_xlate = of_pwm_xlate_with_flags; - ip->chip.of_pwm_n_cells = 3; ip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ip->base)) diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c index 800b9edf2e71..8c85c66ea5c9 100644 --- a/drivers/pwm/pwm-bcm-kona.c +++ b/drivers/pwm/pwm-bcm-kona.c @@ -272,8 +272,6 @@ static int kona_pwmc_probe(struct platform_device *pdev) kp->chip.dev = &pdev->dev; kp->chip.ops = &kona_pwm_ops; kp->chip.npwm = 6; - kp->chip.of_xlate = of_pwm_xlate_with_flags; - kp->chip.of_pwm_n_cells = 3; kp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kp->base)) diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c index fc240d5b8121..50b8594be31d 100644 --- a/drivers/pwm/pwm-bcm2835.c +++ b/drivers/pwm/pwm-bcm2835.c @@ -159,8 +159,6 @@ static int bcm2835_pwm_probe(struct platform_device *pdev) pc->chip.dev = &pdev->dev; pc->chip.ops = &bcm2835_pwm_ops; pc->chip.npwm = 2; - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; platform_set_drvdata(pdev, pc); diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c index acb6fbc3cc32..5537b5f6dd5d 100644 --- a/drivers/pwm/pwm-berlin.c +++ b/drivers/pwm/pwm-berlin.c @@ -56,17 +56,17 @@ static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip) return container_of(chip, struct berlin_pwm_chip, chip); } -static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip, +static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *bpc, unsigned int channel, unsigned long offset) { - return readl_relaxed(chip->base + channel * 0x10 + offset); + return readl_relaxed(bpc->base + channel * 0x10 + offset); } -static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip, +static inline void berlin_pwm_writel(struct berlin_pwm_chip *bpc, unsigned int channel, u32 value, unsigned long offset) { - writel_relaxed(value, chip->base + channel * 0x10 + offset); + writel_relaxed(value, bpc->base + channel * 0x10 + offset); } static int berlin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) @@ -87,15 +87,15 @@ static void berlin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) kfree(channel); } -static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, - int duty_ns, int period_ns) +static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + u64 duty_ns, u64 period_ns) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); bool prescale_4096 = false; u32 value, duty, period; u64 cycles; - cycles = clk_get_rate(pwm->clk); + cycles = clk_get_rate(bpc->clk); cycles *= period_ns; do_div(cycles, NSEC_PER_SEC); @@ -112,68 +112,101 @@ static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, do_div(cycles, period_ns); duty = cycles; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_CONTROL); if (prescale_4096) value |= BERLIN_PWM_PRESCALE_4096; else value &= ~BERLIN_PWM_PRESCALE_4096; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_CONTROL); - berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY); - berlin_pwm_writel(pwm, pwm_dev->hwpwm, period, BERLIN_PWM_TCNT); + berlin_pwm_writel(bpc, pwm->hwpwm, duty, BERLIN_PWM_DUTY); + berlin_pwm_writel(bpc, pwm->hwpwm, period, BERLIN_PWM_TCNT); return 0; } static int berlin_pwm_set_polarity(struct pwm_chip *chip, - struct pwm_device *pwm_dev, + struct pwm_device *pwm, enum pwm_polarity polarity) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); u32 value; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_CONTROL); if (polarity == PWM_POLARITY_NORMAL) value &= ~BERLIN_PWM_INVERT_POLARITY; else value |= BERLIN_PWM_INVERT_POLARITY; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_CONTROL); return 0; } -static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev) +static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); u32 value; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_EN); value |= BERLIN_PWM_ENABLE; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_EN); return 0; } static void berlin_pwm_disable(struct pwm_chip *chip, - struct pwm_device *pwm_dev) + struct pwm_device *pwm) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); u32 value; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_EN); value &= ~BERLIN_PWM_ENABLE; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_EN); +} + +static int berlin_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) { + berlin_pwm_disable(chip, pwm); + enabled = false; + } + + err = berlin_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + berlin_pwm_disable(chip, pwm); + return 0; + } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + err = berlin_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + } + + if (!enabled) + return berlin_pwm_enable(chip, pwm); + + return 0; } static const struct pwm_ops berlin_pwm_ops = { .request = berlin_pwm_request, .free = berlin_pwm_free, - .config = berlin_pwm_config, - .set_polarity = berlin_pwm_set_polarity, - .enable = berlin_pwm_enable, - .disable = berlin_pwm_disable, + .apply = berlin_pwm_apply, .owner = THIS_MODULE, }; @@ -185,99 +218,97 @@ MODULE_DEVICE_TABLE(of, berlin_pwm_match); static int berlin_pwm_probe(struct platform_device *pdev) { - struct berlin_pwm_chip *pwm; + struct berlin_pwm_chip *bpc; int ret; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) + bpc = devm_kzalloc(&pdev->dev, sizeof(*bpc), GFP_KERNEL); + if (!bpc) return -ENOMEM; - pwm->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->base)) - return PTR_ERR(pwm->base); + bpc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(bpc->base)) + return PTR_ERR(bpc->base); - pwm->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) - return PTR_ERR(pwm->clk); + bpc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(bpc->clk)) + return PTR_ERR(bpc->clk); - ret = clk_prepare_enable(pwm->clk); + ret = clk_prepare_enable(bpc->clk); if (ret) return ret; - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &berlin_pwm_ops; - pwm->chip.npwm = 4; - pwm->chip.of_xlate = of_pwm_xlate_with_flags; - pwm->chip.of_pwm_n_cells = 3; + bpc->chip.dev = &pdev->dev; + bpc->chip.ops = &berlin_pwm_ops; + bpc->chip.npwm = 4; - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&bpc->chip); if (ret < 0) { dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); - clk_disable_unprepare(pwm->clk); + clk_disable_unprepare(bpc->clk); return ret; } - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, bpc); return 0; } static int berlin_pwm_remove(struct platform_device *pdev) { - struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev); - int ret; + struct berlin_pwm_chip *bpc = platform_get_drvdata(pdev); + + pwmchip_remove(&bpc->chip); - ret = pwmchip_remove(&pwm->chip); - clk_disable_unprepare(pwm->clk); + clk_disable_unprepare(bpc->clk); - return ret; + return 0; } #ifdef CONFIG_PM_SLEEP static int berlin_pwm_suspend(struct device *dev) { - struct berlin_pwm_chip *pwm = dev_get_drvdata(dev); + struct berlin_pwm_chip *bpc = dev_get_drvdata(dev); unsigned int i; - for (i = 0; i < pwm->chip.npwm; i++) { + for (i = 0; i < bpc->chip.npwm; i++) { struct berlin_pwm_channel *channel; - channel = pwm_get_chip_data(&pwm->chip.pwms[i]); + channel = pwm_get_chip_data(&bpc->chip.pwms[i]); if (!channel) continue; - channel->enable = berlin_pwm_readl(pwm, i, BERLIN_PWM_ENABLE); - channel->ctrl = berlin_pwm_readl(pwm, i, BERLIN_PWM_CONTROL); - channel->duty = berlin_pwm_readl(pwm, i, BERLIN_PWM_DUTY); - channel->tcnt = berlin_pwm_readl(pwm, i, BERLIN_PWM_TCNT); + channel->enable = berlin_pwm_readl(bpc, i, BERLIN_PWM_ENABLE); + channel->ctrl = berlin_pwm_readl(bpc, i, BERLIN_PWM_CONTROL); + channel->duty = berlin_pwm_readl(bpc, i, BERLIN_PWM_DUTY); + channel->tcnt = berlin_pwm_readl(bpc, i, BERLIN_PWM_TCNT); } - clk_disable_unprepare(pwm->clk); + clk_disable_unprepare(bpc->clk); return 0; } static int berlin_pwm_resume(struct device *dev) { - struct berlin_pwm_chip *pwm = dev_get_drvdata(dev); + struct berlin_pwm_chip *bpc = dev_get_drvdata(dev); unsigned int i; int ret; - ret = clk_prepare_enable(pwm->clk); + ret = clk_prepare_enable(bpc->clk); if (ret) return ret; - for (i = 0; i < pwm->chip.npwm; i++) { + for (i = 0; i < bpc->chip.npwm; i++) { struct berlin_pwm_channel *channel; - channel = pwm_get_chip_data(&pwm->chip.pwms[i]); + channel = pwm_get_chip_data(&bpc->chip.pwms[i]); if (!channel) continue; - berlin_pwm_writel(pwm, i, channel->ctrl, BERLIN_PWM_CONTROL); - berlin_pwm_writel(pwm, i, channel->duty, BERLIN_PWM_DUTY); - berlin_pwm_writel(pwm, i, channel->tcnt, BERLIN_PWM_TCNT); - berlin_pwm_writel(pwm, i, channel->enable, BERLIN_PWM_ENABLE); + berlin_pwm_writel(bpc, i, channel->ctrl, BERLIN_PWM_CONTROL); + berlin_pwm_writel(bpc, i, channel->duty, BERLIN_PWM_DUTY); + berlin_pwm_writel(bpc, i, channel->tcnt, BERLIN_PWM_TCNT); + berlin_pwm_writel(bpc, i, channel->enable, BERLIN_PWM_ENABLE); } return 0; diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c index f3d17a590305..d7ad88685830 100644 --- a/drivers/pwm/pwm-clps711x.c +++ b/drivers/pwm/pwm-clps711x.c @@ -134,16 +134,7 @@ static int clps711x_pwm_probe(struct platform_device *pdev) spin_lock_init(&priv->lock); - platform_set_drvdata(pdev, priv); - - return pwmchip_add(&priv->chip); -} - -static int clps711x_pwm_remove(struct platform_device *pdev) -{ - struct clps711x_chip *priv = platform_get_drvdata(pdev); - - return pwmchip_remove(&priv->chip); + return devm_pwmchip_add(&pdev->dev, &priv->chip); } static const struct of_device_id __maybe_unused clps711x_pwm_dt_ids[] = { @@ -158,7 +149,6 @@ static struct platform_driver clps711x_pwm_driver = { .of_match_table = of_match_ptr(clps711x_pwm_dt_ids), }, .probe = clps711x_pwm_probe, - .remove = clps711x_pwm_remove, }; module_platform_driver(clps711x_pwm_driver); diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index 02522a9a3073..7b357d1cf642 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -173,21 +173,11 @@ static int crystalcove_pwm_probe(struct platform_device *pdev) /* get the PMIC regmap */ pwm->regmap = pmic->regmap; - platform_set_drvdata(pdev, pwm); - - return pwmchip_add(&pwm->chip); -} - -static int crystalcove_pwm_remove(struct platform_device *pdev) -{ - struct crystalcove_pwm *pwm = platform_get_drvdata(pdev); - - return pwmchip_remove(&pwm->chip); + return devm_pwmchip_add(&pdev->dev, &pwm->chip); } static struct platform_driver crystalcove_pwm_driver = { .probe = crystalcove_pwm_probe, - .remove = crystalcove_pwm_remove, .driver = { .name = "crystal_cove_pwm", }, diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c index 4ca70794ad96..8a3d781e6514 100644 --- a/drivers/pwm/pwm-ep93xx.c +++ b/drivers/pwm/pwm-ep93xx.c @@ -58,111 +58,112 @@ static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) ep93xx_pwm_release_gpio(pdev); } -static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) +static int ep93xx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { + int ret; struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - void __iomem *base = ep93xx_pwm->base; - unsigned long long c; - unsigned long period_cycles; - unsigned long duty_cycles; - unsigned long term; - int ret = 0; - - /* - * The clock needs to be enabled to access the PWM registers. - * Configuration can be changed at any time. - */ - if (!pwm_is_enabled(pwm)) { - ret = clk_enable(ep93xx_pwm->clk); - if (ret) - return ret; - } + bool enabled = state->enabled; - c = clk_get_rate(ep93xx_pwm->clk); - c *= period_ns; - do_div(c, 1000000000); - period_cycles = c; + if (state->polarity != pwm->state.polarity) { + if (enabled) { + writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + clk_disable_unprepare(ep93xx_pwm->clk); + enabled = false; + } - c = period_cycles; - c *= duty_ns; - do_div(c, period_ns); - duty_cycles = c; + /* + * The clock needs to be enabled to access the PWM registers. + * Polarity can only be changed when the PWM is disabled. + */ + ret = clk_prepare_enable(ep93xx_pwm->clk); + if (ret) + return ret; - if (period_cycles < 0x10000 && duty_cycles < 0x10000) { - term = readw(base + EP93XX_PWMx_TERM_COUNT); + if (state->polarity == PWM_POLARITY_INVERSED) + writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT); + else + writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT); - /* Order is important if PWM is running */ - if (period_cycles > term) { - writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); - writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); - } else { - writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); - writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); - } - } else { - ret = -EINVAL; + clk_disable_unprepare(ep93xx_pwm->clk); } - if (!pwm_is_enabled(pwm)) - clk_disable(ep93xx_pwm->clk); - - return ret; -} - -static int ep93xx_pwm_polarity(struct pwm_chip *chip, struct pwm_device *pwm, - enum pwm_polarity polarity) -{ - struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - int ret; + if (!state->enabled) { + if (enabled) { + writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + clk_disable_unprepare(ep93xx_pwm->clk); + } - /* - * The clock needs to be enabled to access the PWM registers. - * Polarity can only be changed when the PWM is disabled. - */ - ret = clk_enable(ep93xx_pwm->clk); - if (ret) - return ret; + return 0; + } - if (polarity == PWM_POLARITY_INVERSED) - writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT); - else - writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT); + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); + void __iomem *base = ep93xx_pwm->base; + unsigned long long c; + unsigned long period_cycles; + unsigned long duty_cycles; + unsigned long term; + + /* + * The clock needs to be enabled to access the PWM registers. + * Configuration can be changed at any time. + */ + if (!pwm_is_enabled(pwm)) { + ret = clk_prepare_enable(ep93xx_pwm->clk); + if (ret) + return ret; + } - clk_disable(ep93xx_pwm->clk); + c = clk_get_rate(ep93xx_pwm->clk); + c *= state->period; + do_div(c, 1000000000); + period_cycles = c; + + c = period_cycles; + c *= state->duty_cycle; + do_div(c, state->period); + duty_cycles = c; + + if (period_cycles < 0x10000 && duty_cycles < 0x10000) { + term = readw(base + EP93XX_PWMx_TERM_COUNT); + + /* Order is important if PWM is running */ + if (period_cycles > term) { + writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); + writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); + } else { + writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); + writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); + } + ret = 0; + } else { + ret = -EINVAL; + } - return 0; -} + if (!pwm_is_enabled(pwm)) + clk_disable_unprepare(ep93xx_pwm->clk); -static int ep93xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - int ret; + if (ret) + return ret; + } - ret = clk_enable(ep93xx_pwm->clk); - if (ret) - return ret; + if (!enabled) { + ret = clk_prepare_enable(ep93xx_pwm->clk); + if (ret) + return ret; - writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + } return 0; } -static void ep93xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - - writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); - clk_disable(ep93xx_pwm->clk); -} - static const struct pwm_ops ep93xx_pwm_ops = { .request = ep93xx_pwm_request, .free = ep93xx_pwm_free, - .config = ep93xx_pwm_config, - .set_polarity = ep93xx_pwm_polarity, - .enable = ep93xx_pwm_enable, - .disable = ep93xx_pwm_disable, + .apply = ep93xx_pwm_apply, .owner = THIS_MODULE, }; diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index 0e1ae9469eda..96ccd772280c 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c @@ -451,8 +451,6 @@ static int fsl_pwm_probe(struct platform_device *pdev) fpc->chip.ops = &fsl_pwm_ops; - fpc->chip.of_xlate = of_pwm_xlate_with_flags; - fpc->chip.of_pwm_n_cells = 3; fpc->chip.npwm = 8; ret = pwmchip_add(&fpc->chip); diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c index 82d17fc75c21..4a6e9ad3c0ff 100644 --- a/drivers/pwm/pwm-hibvt.c +++ b/drivers/pwm/pwm-hibvt.c @@ -206,8 +206,6 @@ static int hibvt_pwm_probe(struct platform_device *pdev) pwm_chip->chip.ops = &hibvt_pwm_ops; pwm_chip->chip.dev = &pdev->dev; pwm_chip->chip.npwm = soc->num_pwms; - pwm_chip->chip.of_xlate = of_pwm_xlate_with_flags; - pwm_chip->chip.of_pwm_n_cells = 3; pwm_chip->soc = soc; pwm_chip->base = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c index cc37054589cc..11b16ecc4f96 100644 --- a/drivers/pwm/pwm-img.c +++ b/drivers/pwm/pwm-img.c @@ -156,7 +156,7 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); int ret; - ret = pm_runtime_get_sync(chip->dev); + ret = pm_runtime_resume_and_get(chip->dev); if (ret < 0) return ret; diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index 97c9133b6876..dbb50493abdd 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -363,8 +363,6 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev) tpm->chip.dev = &pdev->dev; tpm->chip.ops = &imx_tpm_pwm_ops; - tpm->chip.of_xlate = of_pwm_xlate_with_flags; - tpm->chip.of_pwm_n_cells = 3; /* get number of channels */ val = readl(tpm->base + PWM_IMX_TPM_PARAM); diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c index c957b365448e..bcd849496f8d 100644 --- a/drivers/pwm/pwm-imx1.c +++ b/drivers/pwm/pwm-imx1.c @@ -141,8 +141,6 @@ static int pwm_imx1_probe(struct platform_device *pdev) if (!imx) return -ENOMEM; - platform_set_drvdata(pdev, imx); - imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(imx->clk_ipg)) return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_ipg), @@ -161,16 +159,7 @@ static int pwm_imx1_probe(struct platform_device *pdev) if (IS_ERR(imx->mmio_base)) return PTR_ERR(imx->mmio_base); - return pwmchip_add(&imx->chip); -} - -static int pwm_imx1_remove(struct platform_device *pdev) -{ - struct pwm_imx1_chip *imx = platform_get_drvdata(pdev); - - pwm_imx1_clk_disable_unprepare(&imx->chip); - - return pwmchip_remove(&imx->chip); + return devm_pwmchip_add(&pdev->dev, &imx->chip); } static struct platform_driver pwm_imx1_driver = { @@ -179,7 +168,6 @@ static struct platform_driver pwm_imx1_driver = { .of_match_table = pwm_imx1_dt_ids, }, .probe = pwm_imx1_probe, - .remove = pwm_imx1_remove, }; module_platform_driver(pwm_imx1_driver); diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index ba695115c160..f6588a96fbd9 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -329,9 +329,6 @@ static int pwm_imx27_probe(struct platform_device *pdev) imx->chip.dev = &pdev->dev; imx->chip.npwm = 1; - imx->chip.of_xlate = of_pwm_xlate_with_flags; - imx->chip.of_pwm_n_cells = 3; - imx->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(imx->mmio_base)) return PTR_ERR(imx->mmio_base); diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 5b6bdcdcecf5..990e7904c7f1 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -244,8 +244,6 @@ static int jz4740_pwm_probe(struct platform_device *pdev) jz4740->chip.dev = dev; jz4740->chip.ops = &jz4740_pwm_ops; jz4740->chip.npwm = info->num_pwms; - jz4740->chip.of_xlate = of_pwm_xlate_with_flags; - jz4740->chip.of_pwm_n_cells = 3; platform_set_drvdata(pdev, jz4740); diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c index b643ac61a2e7..8e461f3baa05 100644 --- a/drivers/pwm/pwm-lpc18xx-sct.c +++ b/drivers/pwm/pwm-lpc18xx-sct.c @@ -371,8 +371,6 @@ 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.of_xlate = of_pwm_xlate_with_flags; - lpc18xx_pwm->chip.of_pwm_n_cells = 3; /* SCT counter must be in unify (32 bit) mode */ lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c index cf749ea0de9f..c893ec3d2fb4 100644 --- a/drivers/pwm/pwm-lpss-pci.c +++ b/drivers/pwm/pwm-lpss-pci.c @@ -69,12 +69,8 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev, static void pwm_lpss_remove_pci(struct pci_dev *pdev) { - struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev); - pm_runtime_forbid(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - - pwm_lpss_remove(lpwm); } #ifdef CONFIG_PM diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 986786be1e49..928570430cef 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -85,10 +85,8 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) static int pwm_lpss_remove_platform(struct platform_device *pdev) { - struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev); - pm_runtime_disable(&pdev->dev); - return pwm_lpss_remove(lpwm); + return 0; } static const struct acpi_device_id pwm_lpss_acpi_match[] = { diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 58b4031524af..36d4e83e6b79 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -236,7 +236,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, lpwm->chip.ops = &pwm_lpss_ops; lpwm->chip.npwm = info->npwm; - ret = pwmchip_add(&lpwm->chip); + ret = devm_pwmchip_add(dev, &lpwm->chip); if (ret) { dev_err(dev, "failed to add PWM chip: %d\n", ret); return ERR_PTR(ret); @@ -252,12 +252,6 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, } EXPORT_SYMBOL_GPL(pwm_lpss_probe); -int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) -{ - return pwmchip_remove(&lpwm->chip); -} -EXPORT_SYMBOL_GPL(pwm_lpss_remove); - MODULE_DESCRIPTION("PWM driver for Intel LPSS"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 70db7e389d66..8b3476f25e06 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -35,6 +35,5 @@ struct pwm_lpss_boardinfo { struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, const struct pwm_lpss_boardinfo *info); -int pwm_lpss_remove(struct pwm_lpss_chip *lpwm); #endif /* __PWM_LPSS_H */ diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 9eb060613cb4..3cf3bcf5ddfc 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -551,8 +551,6 @@ static int meson_pwm_probe(struct platform_device *pdev) meson->chip.dev = &pdev->dev; meson->chip.ops = &meson_pwm_ops; meson->chip.npwm = MESON_NUM_PWMS; - meson->chip.of_xlate = of_pwm_xlate_with_flags; - meson->chip.of_pwm_n_cells = 3; meson->data = of_device_get_match_data(&pdev->dev); @@ -560,31 +558,21 @@ static int meson_pwm_probe(struct platform_device *pdev) if (err < 0) return err; - err = pwmchip_add(&meson->chip); + err = devm_pwmchip_add(&pdev->dev, &meson->chip); if (err < 0) { dev_err(&pdev->dev, "failed to register PWM chip: %d\n", err); return err; } - platform_set_drvdata(pdev, meson); - return 0; } -static int meson_pwm_remove(struct platform_device *pdev) -{ - struct meson_pwm *meson = platform_get_drvdata(pdev); - - return pwmchip_remove(&meson->chip); -} - static struct platform_driver meson_pwm_driver = { .driver = { .name = "meson-pwm", .of_match_table = meson_pwm_matches, }, .probe = meson_pwm_probe, - .remove = meson_pwm_remove, }; module_platform_driver(meson_pwm_driver); diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index 0266e84e982c..a22180803bd7 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c @@ -138,8 +138,6 @@ static int mxs_pwm_probe(struct platform_device *pdev) mxs->chip.dev = &pdev->dev; mxs->chip.ops = &mxs_pwm_ops; - mxs->chip.of_xlate = of_pwm_xlate_with_flags; - mxs->chip.of_pwm_n_cells = 3; ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm); if (ret < 0) { diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 612b3c859295..507a2d945b90 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -404,8 +404,6 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) omap->chip.dev = &pdev->dev; omap->chip.ops = &pwm_omap_dmtimer_ops; omap->chip.npwm = 1; - omap->chip.of_xlate = of_pwm_xlate_with_flags; - omap->chip.of_pwm_n_cells = 3; mutex_init(&omap->mutex); diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 7c9f174de64e..42ed770b432c 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -23,11 +23,11 @@ #include <linux/bitmap.h> /* - * Because the PCA9685 has only one prescaler per chip, changing the period of - * one channel affects the period of all 16 PWM outputs! - * However, the ratio between each configured duty cycle and the chip-wide - * period remains constant, because the OFF time is set in proportion to the - * counter range. + * Because the PCA9685 has only one prescaler per chip, only the first channel + * that is enabled is allowed to change the prescale register. + * PWM channels requested afterwards must use a period that results in the same + * prescale setting as the one set by the first requested channel. + * GPIOs do not count as enabled PWMs as they are not using the prescaler. */ #define PCA9685_MODE1 0x00 @@ -78,8 +78,9 @@ struct pca9685 { struct pwm_chip chip; struct regmap *regmap; -#if IS_ENABLED(CONFIG_GPIOLIB) struct mutex lock; + DECLARE_BITMAP(pwms_enabled, PCA9685_MAXCHAN + 1); +#if IS_ENABLED(CONFIG_GPIOLIB) struct gpio_chip gpio; DECLARE_BITMAP(pwms_inuse, PCA9685_MAXCHAN + 1); #endif @@ -90,51 +91,120 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip) return container_of(chip, struct pca9685, chip); } +/* This function is supposed to be called with the lock mutex held */ +static bool pca9685_prescaler_can_change(struct pca9685 *pca, int channel) +{ + /* No PWM enabled: Change allowed */ + if (bitmap_empty(pca->pwms_enabled, PCA9685_MAXCHAN + 1)) + return true; + /* More than one PWM enabled: Change not allowed */ + if (bitmap_weight(pca->pwms_enabled, PCA9685_MAXCHAN + 1) > 1) + return false; + /* + * Only one PWM enabled: Change allowed if the PWM about to + * be changed is the one that is already enabled + */ + return test_bit(channel, pca->pwms_enabled); +} + +static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int *val) +{ + struct device *dev = pca->chip.dev; + int err; + + err = regmap_read(pca->regmap, reg, val); + if (err) + dev_err(dev, "regmap_read of register 0x%x failed: %pe\n", reg, ERR_PTR(err)); + + return err; +} + +static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int val) +{ + struct device *dev = pca->chip.dev; + int err; + + err = regmap_write(pca->regmap, reg, val); + if (err) + dev_err(dev, "regmap_write to register 0x%x failed: %pe\n", reg, ERR_PTR(err)); + + return err; +} + /* Helper function to set the duty cycle ratio to duty/4096 (e.g. duty=2048 -> 50%) */ static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int duty) { + struct pwm_device *pwm = &pca->chip.pwms[channel]; + unsigned int on, off; + if (duty == 0) { /* Set the full OFF bit, which has the highest precedence */ - regmap_write(pca->regmap, REG_OFF_H(channel), LED_FULL); + pca9685_write_reg(pca, REG_OFF_H(channel), LED_FULL); + return; } else if (duty >= PCA9685_COUNTER_RANGE) { /* Set the full ON bit and clear the full OFF bit */ - regmap_write(pca->regmap, REG_ON_H(channel), LED_FULL); - regmap_write(pca->regmap, REG_OFF_H(channel), 0); - } else { - /* Set OFF time (clears the full OFF bit) */ - regmap_write(pca->regmap, REG_OFF_L(channel), duty & 0xff); - regmap_write(pca->regmap, REG_OFF_H(channel), (duty >> 8) & 0xf); - /* Clear the full ON bit */ - regmap_write(pca->regmap, REG_ON_H(channel), 0); + pca9685_write_reg(pca, REG_ON_H(channel), LED_FULL); + pca9685_write_reg(pca, REG_OFF_H(channel), 0); + return; } + + + if (pwm->state.usage_power && channel < PCA9685_MAXCHAN) { + /* + * If usage_power is set, the pca9685 driver will phase shift + * the individual channels relative to their channel number. + * This improves EMI because the enabled channels no longer + * turn on at the same time, while still maintaining the + * configured duty cycle / power output. + */ + on = channel * PCA9685_COUNTER_RANGE / PCA9685_MAXCHAN; + } else + on = 0; + + off = (on + duty) % PCA9685_COUNTER_RANGE; + + /* Set ON time (clears full ON bit) */ + pca9685_write_reg(pca, REG_ON_L(channel), on & 0xff); + pca9685_write_reg(pca, REG_ON_H(channel), (on >> 8) & 0xf); + /* Set OFF time (clears full OFF bit) */ + pca9685_write_reg(pca, REG_OFF_L(channel), off & 0xff); + pca9685_write_reg(pca, REG_OFF_H(channel), (off >> 8) & 0xf); } static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel) { - unsigned int off_h = 0, val = 0; + struct pwm_device *pwm = &pca->chip.pwms[channel]; + unsigned int off = 0, on = 0, val = 0; if (WARN_ON(channel >= PCA9685_MAXCHAN)) { /* HW does not support reading state of "all LEDs" channel */ return 0; } - regmap_read(pca->regmap, LED_N_OFF_H(channel), &off_h); - if (off_h & LED_FULL) { + pca9685_read_reg(pca, LED_N_OFF_H(channel), &off); + if (off & LED_FULL) { /* Full OFF bit is set */ return 0; } - regmap_read(pca->regmap, LED_N_ON_H(channel), &val); - if (val & LED_FULL) { + pca9685_read_reg(pca, LED_N_ON_H(channel), &on); + if (on & LED_FULL) { /* Full ON bit is set */ return PCA9685_COUNTER_RANGE; } - if (regmap_read(pca->regmap, LED_N_OFF_L(channel), &val)) { - /* Reset val to 0 in case reading LED_N_OFF_L failed */ + pca9685_read_reg(pca, LED_N_OFF_L(channel), &val); + off = ((off & 0xf) << 8) | (val & 0xff); + if (!pwm->state.usage_power) + return off; + + /* Read ON register to calculate duty cycle of staggered output */ + if (pca9685_read_reg(pca, LED_N_ON_L(channel), &val)) { + /* Reset val to 0 in case reading LED_N_ON_L failed */ val = 0; } - return ((off_h & 0xf) << 8) | (val & 0xff); + on = ((on & 0xf) << 8) | (val & 0xff); + return (off - on) & (PCA9685_COUNTER_RANGE - 1); } #if IS_ENABLED(CONFIG_GPIOLIB) @@ -240,8 +310,6 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca) { struct device *dev = pca->chip.dev; - mutex_init(&pca->lock); - pca->gpio.label = dev_name(dev); pca->gpio.parent = dev; pca->gpio.request = pca9685_pwm_gpio_request; @@ -277,16 +345,23 @@ static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca) static void pca9685_set_sleep_mode(struct pca9685 *pca, bool enable) { - regmap_update_bits(pca->regmap, PCA9685_MODE1, - MODE1_SLEEP, enable ? MODE1_SLEEP : 0); + struct device *dev = pca->chip.dev; + int err = regmap_update_bits(pca->regmap, PCA9685_MODE1, + MODE1_SLEEP, enable ? MODE1_SLEEP : 0); + if (err) { + dev_err(dev, "regmap_update_bits of register 0x%x failed: %pe\n", + PCA9685_MODE1, ERR_PTR(err)); + return; + } + if (!enable) { /* Wait 500us for the oscillator to be back up */ udelay(500); } } -static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, - const struct pwm_state *state) +static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { struct pca9685 *pca = to_pca(chip); unsigned long long duty, prescale; @@ -307,8 +382,14 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } - regmap_read(pca->regmap, PCA9685_PRESCALE, &val); + pca9685_read_reg(pca, PCA9685_PRESCALE, &val); if (prescale != val) { + if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) { + dev_err(chip->dev, + "pwm not changed: periods of enabled pwms must match!\n"); + return -EBUSY; + } + /* * Putting the chip briefly into SLEEP mode * at this point won't interfere with the @@ -319,7 +400,7 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, pca9685_set_sleep_mode(pca, true); /* Change the chip-wide output frequency */ - regmap_write(pca->regmap, PCA9685_PRESCALE, prescale); + pca9685_write_reg(pca, PCA9685_PRESCALE, prescale); /* Wake the chip up */ pca9685_set_sleep_mode(pca, false); @@ -331,6 +412,25 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct pca9685 *pca = to_pca(chip); + int ret; + + mutex_lock(&pca->lock); + ret = __pca9685_pwm_apply(chip, pwm, state); + if (ret == 0) { + if (state->enabled) + set_bit(pwm->hwpwm, pca->pwms_enabled); + else + clear_bit(pwm->hwpwm, pca->pwms_enabled); + } + mutex_unlock(&pca->lock); + + return ret; +} + static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { @@ -339,7 +439,7 @@ static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, unsigned int val = 0; /* Calculate (chip-wide) period from prescale value */ - regmap_read(pca->regmap, PCA9685_PRESCALE, &val); + pca9685_read_reg(pca, PCA9685_PRESCALE, &val); /* * PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000. * The following calculation is therefore only a multiplication @@ -372,6 +472,14 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) if (pca9685_pwm_test_and_set_inuse(pca, pwm->hwpwm)) return -EBUSY; + + if (pwm->hwpwm < PCA9685_MAXCHAN) { + /* PWMs - except the "all LEDs" channel - default to enabled */ + mutex_lock(&pca->lock); + set_bit(pwm->hwpwm, pca->pwms_enabled); + mutex_unlock(&pca->lock); + } + pm_runtime_get_sync(chip->dev); return 0; @@ -381,7 +489,11 @@ static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct pca9685 *pca = to_pca(chip); + mutex_lock(&pca->lock); pca9685_pwm_set_duty(pca, pwm->hwpwm, 0); + clear_bit(pwm->hwpwm, pca->pwms_enabled); + mutex_unlock(&pca->lock); + pm_runtime_put(chip->dev); pca9685_pwm_clear_inuse(pca, pwm->hwpwm); } @@ -422,7 +534,11 @@ static int pca9685_pwm_probe(struct i2c_client *client, i2c_set_clientdata(client, pca); - regmap_read(pca->regmap, PCA9685_MODE2, ®); + mutex_init(&pca->lock); + + ret = pca9685_read_reg(pca, PCA9685_MODE2, ®); + if (ret) + return ret; if (device_property_read_bool(&client->dev, "invert")) reg |= MODE2_INVRT; @@ -434,16 +550,20 @@ static int pca9685_pwm_probe(struct i2c_client *client, else reg |= MODE2_OUTDRV; - regmap_write(pca->regmap, PCA9685_MODE2, reg); + ret = pca9685_write_reg(pca, PCA9685_MODE2, reg); + if (ret) + return ret; /* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */ - regmap_read(pca->regmap, PCA9685_MODE1, ®); + pca9685_read_reg(pca, PCA9685_MODE1, ®); reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3); - regmap_write(pca->regmap, PCA9685_MODE1, reg); + pca9685_write_reg(pca, PCA9685_MODE1, reg); - /* Reset OFF registers to POR default */ - regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, LED_FULL); - regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, LED_FULL); + /* 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_H, LED_FULL); + pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0); + pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, 0); 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 cfb683827d32..e091a528e33c 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -165,7 +165,7 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) static int pwm_probe(struct platform_device *pdev) { const struct platform_device_id *id = platform_get_device_id(pdev); - struct pxa_pwm_chip *pwm; + struct pxa_pwm_chip *pc; int ret = 0; if (IS_ENABLED(CONFIG_OF) && id == NULL) @@ -174,46 +174,44 @@ static int pwm_probe(struct platform_device *pdev) if (id == NULL) return -EINVAL; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (pwm == NULL) + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (pc == NULL) return -ENOMEM; - 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); - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &pxa_pwm_ops; - pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; + pc->chip.dev = &pdev->dev; + pc->chip.ops = &pxa_pwm_ops; + pc->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; if (IS_ENABLED(CONFIG_OF)) { - pwm->chip.of_xlate = pxa_pwm_of_xlate; - pwm->chip.of_pwm_n_cells = 1; + pc->chip.of_xlate = pxa_pwm_of_xlate; + pc->chip.of_pwm_n_cells = 1; } - pwm->mmio_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->mmio_base)) - return PTR_ERR(pwm->mmio_base); + pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pc->mmio_base)) + return PTR_ERR(pc->mmio_base); - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&pc->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); return ret; } - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, pc); return 0; } static int pwm_remove(struct platform_device *pdev) { - struct pxa_pwm_chip *chip; + struct pxa_pwm_chip *pc; - chip = platform_get_drvdata(pdev); - if (chip == NULL) - return -ENODEV; + pc = platform_get_drvdata(pdev); - return pwmchip_remove(&chip->chip); + return pwmchip_remove(&pc->chip); } static struct platform_driver pwm_driver = { diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index e2959fae0969..b853e7942605 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -408,8 +408,6 @@ static int tpu_probe(struct platform_device *pdev) tpu->chip.dev = &pdev->dev; tpu->chip.ops = &tpu_pwm_ops; - tpu->chip.of_xlate = of_pwm_xlate_with_flags; - tpu->chip.of_pwm_n_cells = 3; tpu->chip.npwm = TPU_CHANNEL_MAX; pm_runtime_enable(&pdev->dev); diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 301785fa293e..cbe900877724 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -354,11 +354,6 @@ static int rockchip_pwm_probe(struct platform_device *pdev) pc->chip.ops = &rockchip_pwm_ops; pc->chip.npwm = 1; - if (pc->data->supports_polarity) { - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; - } - enable_conf = pc->data->enable_conf; ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); enabled = (ctrl & enable_conf) == enable_conf; diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c index 515489fa4f6d..f6c528f02d43 100644 --- a/drivers/pwm/pwm-samsung.c +++ b/drivers/pwm/pwm-samsung.c @@ -526,9 +526,6 @@ static int pwm_samsung_probe(struct platform_device *pdev) ret = pwm_samsung_parse_dt(chip); if (ret) return ret; - - chip->chip.of_xlate = of_pwm_xlate_with_flags; - chip->chip.of_pwm_n_cells = 3; } else { if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "no platform data specified\n"); diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index 688737f091ac..420edc4aa94a 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c @@ -242,8 +242,6 @@ static int pwm_sifive_probe(struct platform_device *pdev) chip = &ddata->chip; chip->dev = dev; chip->ops = &pwm_sifive_ops; - chip->of_xlate = of_pwm_xlate_with_flags; - chip->of_pwm_n_cells = 3; chip->npwm = 4; ddata->regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c index 1a1cedfd11ce..48c31dac2f32 100644 --- a/drivers/pwm/pwm-spear.c +++ b/drivers/pwm/pwm-spear.c @@ -75,7 +75,7 @@ static inline void spear_pwm_writel(struct spear_pwm_chip *chip, } static int spear_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct spear_pwm_chip *pc = to_spear_pwm_chip(chip); u64 val, div, clk_rate; @@ -163,10 +163,35 @@ static void spear_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) clk_disable(pc->clk); } +static int spear_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) + spear_pwm_disable(chip, pwm); + return 0; + } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + err = spear_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + } + + if (!pwm->state.enabled) + return spear_pwm_enable(chip, pwm); + + return 0; +} + static const struct pwm_ops spear_pwm_ops = { - .config = spear_pwm_config, - .enable = spear_pwm_enable, - .disable = spear_pwm_disable, + .apply = spear_pwm_apply, .owner = THIS_MODULE, }; @@ -228,14 +253,13 @@ static int spear_pwm_probe(struct platform_device *pdev) static int spear_pwm_remove(struct platform_device *pdev) { struct spear_pwm_chip *pc = platform_get_drvdata(pdev); - int i; - for (i = 0; i < NUM_PWM; i++) - pwm_disable(&pc->chip.pwms[i]); + pwmchip_remove(&pc->chip); /* clk was prepared in probe, hence unprepare it here */ clk_unprepare(pc->clk); - return pwmchip_remove(&pc->chip); + + return 0; } static const struct of_device_id spear_pwm_of_match[] = { diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c index 98c479dfae31..f2a85e8dd941 100644 --- a/drivers/pwm/pwm-sprd.c +++ b/drivers/pwm/pwm-sprd.c @@ -284,7 +284,9 @@ static int sprd_pwm_remove(struct platform_device *pdev) { struct sprd_pwm_chip *spc = platform_get_drvdata(pdev); - return pwmchip_remove(&spc->chip); + pwmchip_remove(&spc->chip); + + return 0; } static const struct of_device_id sprd_pwm_of_match[] = { diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index af08f564ef1d..93dd03618465 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -208,8 +208,6 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev) priv->chip.dev = &pdev->dev; priv->chip.ops = &stm32_pwm_lp_ops; priv->chip.npwm = 1; - priv->chip.of_xlate = of_pwm_xlate_with_flags; - priv->chip.of_pwm_n_cells = 3; ret = pwmchip_add(&priv->chip); if (ret < 0) diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index c46fb90036ab..794ca5b02968 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -621,8 +621,6 @@ static int stm32_pwm_probe(struct platform_device *pdev) priv->regmap = ddata->regmap; priv->clk = ddata->clk; priv->max_arr = ddata->max_arr; - priv->chip.of_xlate = of_pwm_xlate_with_flags; - priv->chip.of_pwm_n_cells = 3; if (!priv->regmap || !priv->clk) return -EINVAL; diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index e01becd102c0..c952604e91f3 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -460,8 +460,6 @@ static int sun4i_pwm_probe(struct platform_device *pdev) pwm->chip.dev = &pdev->dev; pwm->chip.ops = &sun4i_pwm_ops; pwm->chip.npwm = pwm->data->npwm; - pwm->chip.of_xlate = of_pwm_xlate_with_flags; - pwm->chip.of_pwm_n_cells = 3; spin_lock_init(&pwm->ctrl_lock); diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index c529a170bcdd..11a10b575ace 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -300,32 +300,12 @@ static int tegra_pwm_probe(struct platform_device *pdev) static int tegra_pwm_remove(struct platform_device *pdev) { struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); - unsigned int i; - int err; - - if (WARN_ON(!pc)) - return -ENODEV; - - err = clk_prepare_enable(pc->clk); - if (err < 0) - return err; - - for (i = 0; i < pc->chip.npwm; i++) { - struct pwm_device *pwm = &pc->chip.pwms[i]; - - if (!pwm_is_enabled(pwm)) - if (clk_prepare_enable(pc->clk) < 0) - continue; - pwm_writel(pc, i, 0); - - clk_disable_unprepare(pc->clk); - } + pwmchip_remove(&pc->chip); reset_control_assert(pc->rst); - clk_disable_unprepare(pc->clk); - return pwmchip_remove(&pc->chip); + return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index b9a17ab0c202..dec3f1fb150c 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -48,16 +48,13 @@ static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip) * duty_ns = 10^9 * duty_cycles / PWM_CLK_RATE */ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + int duty_ns, int period_ns, int enabled) { struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); u32 period_cycles, duty_cycles; unsigned long long c; u16 value; - if (period_ns > NSEC_PER_SEC) - return -ERANGE; - c = pc->clk_rate; c = c * period_ns; do_div(c, NSEC_PER_SEC); @@ -82,7 +79,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writew(value, pc->mmio_base + ECCTL2); - if (!pwm_is_enabled(pwm)) { + if (!enabled) { /* Update active registers if not running */ writel(duty_cycles, pc->mmio_base + CAP2); writel(period_cycles, pc->mmio_base + CAP1); @@ -96,7 +93,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } - if (!pwm_is_enabled(pwm)) { + if (!enabled) { value = readw(pc->mmio_base + ECCTL2); /* Disable APWM mode to put APWM output Low */ value &= ~ECCTL2_APWM_MODE; @@ -168,20 +165,49 @@ static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) pm_runtime_put_sync(pc->chip.dev); } -static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +static int ecap_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { - if (pwm_is_enabled(pwm)) { - dev_warn(chip->dev, "Removing PWM device without disabling\n"); - pm_runtime_put_sync(chip->dev); + int err; + int enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + + if (enabled) { + ecap_pwm_disable(chip, pwm); + enabled = false; + } + + err = ecap_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + ecap_pwm_disable(chip, pwm); + return 0; } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + if (state->period > NSEC_PER_SEC) + return -ERANGE; + + err = ecap_pwm_config(chip, pwm, state->duty_cycle, + state->period, enabled); + if (err) + return err; + } + + if (!enabled) + return ecap_pwm_enable(chip, pwm); + + return 0; } static const struct pwm_ops ecap_pwm_ops = { - .free = ecap_pwm_free, - .config = ecap_pwm_config, - .set_polarity = ecap_pwm_set_polarity, - .enable = ecap_pwm_enable, - .disable = ecap_pwm_disable, + .apply = ecap_pwm_apply, .owner = THIS_MODULE, }; @@ -224,8 +250,6 @@ static int ecap_pwm_probe(struct platform_device *pdev) pc->chip.dev = &pdev->dev; pc->chip.ops = &ecap_pwm_ops; - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; pc->chip.npwm = 1; pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 90095a19bf2d..17909fa53211 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -447,8 +447,6 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) pc->chip.dev = &pdev->dev; pc->chip.ops = &ehrpwm_pwm_ops; - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; pc->chip.npwm = NUM_PWM_CHANNEL; pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-visconti.c b/drivers/pwm/pwm-visconti.c index 46d903786366..af4e37d3e3a6 100644 --- a/drivers/pwm/pwm-visconti.c +++ b/drivers/pwm/pwm-visconti.c @@ -82,17 +82,14 @@ static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return -ERANGE; /* - * PWMC controls a divider that divides the input clk by a - * power of two between 1 and 8. As a smaller divider yields - * higher precision, pick the smallest possible one. + * PWMC controls a divider that divides the input clk by a power of two + * between 1 and 8. As a smaller divider yields higher precision, pick + * the smallest possible one. As period is at most 0xffff << 3, pwmc0 is + * in the intended range [0..3]. */ - if (period > 0xffff) { - pwmc0 = ilog2(period >> 16); - if (WARN_ON(pwmc0 > 3)) - return -EINVAL; - } else { - pwmc0 = 0; - } + pwmc0 = fls(period >> 16); + if (WARN_ON(pwmc0 > 3)) + return -EINVAL; period >>= pwmc0; duty_cycle >>= pwmc0; diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index 52fe5d19473a..ea2aa151080a 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c @@ -207,8 +207,6 @@ static int vt8500_pwm_probe(struct platform_device *pdev) chip->chip.dev = &pdev->dev; chip->chip.ops = &vt8500_pwm_ops; - chip->chip.of_xlate = of_pwm_xlate_with_flags; - chip->chip.of_pwm_n_cells = 3; chip->chip.npwm = VT8500_NR_PWMS; chip->clk = devm_clk_get(&pdev->dev, NULL); @@ -240,15 +238,13 @@ static int vt8500_pwm_probe(struct platform_device *pdev) static int vt8500_pwm_remove(struct platform_device *pdev) { - struct vt8500_chip *chip; + struct vt8500_chip *chip = platform_get_drvdata(pdev); - chip = platform_get_drvdata(pdev); - if (chip == NULL) - return -ENODEV; + pwmchip_remove(&chip->chip); clk_unprepare(chip->clk); - return pwmchip_remove(&chip->chip); + return 0; } static struct platform_driver vt8500_pwm_driver = { |