diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-01 09:46:02 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-01 09:46:02 -0800 |
commit | 545b2820c4a48245412d97030134cc1d38918726 (patch) | |
tree | 78d1b3d0555cd265c3a7830a3dc041b9d1595885 /drivers/pwm/core.c | |
parent | 3437f9f0a69c7c9e926f702fb0d1abd1f750a40e (diff) | |
parent | 38b0a526ec33314ee1d9926e3a347078f63eac8e (diff) | |
download | talos-op-linux-545b2820c4a48245412d97030134cc1d38918726.tar.gz talos-op-linux-545b2820c4a48245412d97030134cc1d38918726.zip |
Merge tag 'pwm/for-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm updates from Thierry Reding:
"This set contains mostly fixes to existing drivers as well as cleanup
of code that's not been in active use for a while"
* tag 'pwm/for-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (27 commits)
acpi: lpss: call pwm_add_table() for BSW PWM device
pwm: Try to load modules during pwm_get()
pwm: Don't hold pwm_lookup_lock longer than necessary
pwm: Make the PWM_POLARITY flag in DTB optional
pwm: Print error messages with pr_err() instead of pr_debug()
pwm: imx: Add polarity inversion support to i.MX's PWMv2
pwm: imx: doc: Update imx-pwm.txt documentation entry
pwm: imx: Remove redundant i.MX PWMv2 code
pwm: imx: Provide atomic PWM support for i.MX PWMv2
pwm: imx: Move PWMv2 wait for fifo slot code to a separate function
pwm: imx: Move PWMv2 software reset code to a separate function
pwm: imx: Rewrite v1 code to facilitate switch to atomic PWM
pwm: imx: Add separate set of PWM ops for v1 and v2
pwm: imx: Remove ipg clock and enable per clock when required
pwm: lpss: Add Intel Gemini Lake PCI ID
pwm: lpss: Do not export board infos for different PWM types
pwm: lpss: Avoid reconfiguring while UPDATE bit is still enabled
pwm: lpss: Switch to new atomic API
pwm: lpss: Allow duty cycle to be 0
pwm: lpss: Avoid potential overflow of base_unit
...
Diffstat (limited to 'drivers/pwm/core.c')
-rw-r--r-- | drivers/pwm/core.c | 70 |
1 files changed, 36 insertions, 34 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 172ef8245811..a0860b30bd93 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -137,9 +137,14 @@ 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) return ERR_PTR(-EINVAL); + /* flags in the third cell are optional */ + if (args->args_count < 2) + return ERR_PTR(-EINVAL); + if (args->args[0] >= pc->npwm) return ERR_PTR(-EINVAL); @@ -148,11 +153,10 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) return pwm; pwm->args.period = args->args[1]; + pwm->args.polarity = PWM_POLARITY_NORMAL; - if (args->args[2] & PWM_POLARITY_INVERTED) + if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) pwm->args.polarity = PWM_POLARITY_INVERSED; - else - pwm->args.polarity = PWM_POLARITY_NORMAL; return pwm; } @@ -163,9 +167,14 @@ 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); @@ -663,24 +672,17 @@ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id) err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index, &args); if (err) { - pr_debug("%s(): can't parse \"pwms\" property\n", __func__); + pr_err("%s(): can't parse \"pwms\" property\n", __func__); return ERR_PTR(err); } pc = of_node_to_pwmchip(args.np); if (IS_ERR(pc)) { - pr_debug("%s(): PWM chip not found\n", __func__); + pr_err("%s(): PWM chip not found\n", __func__); pwm = ERR_CAST(pc); goto put; } - if (args.args_count != pc->of_pwm_n_cells) { - pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name, - args.np->full_name); - pwm = ERR_PTR(-EINVAL); - goto put; - } - pwm = pc->of_xlate(pc, &args); if (IS_ERR(pwm)) goto put; @@ -757,12 +759,13 @@ void pwm_remove_table(struct pwm_lookup *table, size_t num) */ struct pwm_device *pwm_get(struct device *dev, const char *con_id) { - struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); const char *dev_id = dev ? dev_name(dev) : NULL; - struct pwm_chip *chip = NULL; + struct pwm_device *pwm; + struct pwm_chip *chip; unsigned int best = 0; struct pwm_lookup *p, *chosen = NULL; unsigned int match; + int err; /* look up via DT first */ if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) @@ -817,24 +820,35 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) } } - if (!chosen) { - pwm = ERR_PTR(-ENODEV); - goto out; - } + mutex_unlock(&pwm_lookup_lock); + + if (!chosen) + return ERR_PTR(-ENODEV); chip = pwmchip_find_by_name(chosen->provider); + + /* + * If the lookup entry specifies a module, load the module and retry + * the PWM chip lookup. This can be used to work around driver load + * ordering issues if driver's can't be made to properly support the + * deferred probe mechanism. + */ + if (!chip && chosen->module) { + err = request_module(chosen->module); + if (err == 0) + chip = pwmchip_find_by_name(chosen->provider); + } + if (!chip) - goto out; + return ERR_PTR(-EPROBE_DEFER); pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id); if (IS_ERR(pwm)) - goto out; + return pwm; pwm->args.period = chosen->period; pwm->args.polarity = chosen->polarity; -out: - mutex_unlock(&pwm_lookup_lock); return pwm; } EXPORT_SYMBOL_GPL(pwm_get); @@ -960,18 +974,6 @@ void devm_pwm_put(struct device *dev, struct pwm_device *pwm) } EXPORT_SYMBOL_GPL(devm_pwm_put); -/** - * pwm_can_sleep() - report whether PWM access will sleep - * @pwm: PWM device - * - * Returns: True if accessing the PWM can sleep, false otherwise. - */ -bool pwm_can_sleep(struct pwm_device *pwm) -{ - return true; -} -EXPORT_SYMBOL_GPL(pwm_can_sleep); - #ifdef CONFIG_DEBUG_FS static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) { |