Merge branch 'misc.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / drivers / pwm / core.c
index c4d5c06..4527f09 100644 (file)
@@ -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);
@@ -322,24 +304,12 @@ EXPORT_SYMBOL_GPL(pwmchip_add);
  *
  * Returns: 0 on success or a negative error code on failure.
  */
-int pwmchip_remove(struct pwm_chip *chip)
+void 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,29 @@ int pwmchip_remove(struct pwm_chip *chip)
 
        free_pwms(chip);
 
-out:
        mutex_unlock(&pwm_lock);
-       return ret;
 }
 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 +541,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 +697,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 +783,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 +825,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 +842,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 +855,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 +871,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 +926,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 +937,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 +1063,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 +1081,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 +1111,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 +1142,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 +1184,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");
        }
 }