]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/pwm/core.c
Merge tag 'dm-4.11-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
[mirror_ubuntu-artful-kernel.git] / drivers / pwm / core.c
index 172ef82458112c268782d24f55cd882904340ea8..a0860b30bd931760480ca6800d539d08d6433478 100644 (file)
@@ -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)
 {