drm/rockchip: vop: fixup color space table
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / devres.c
index 2672a029fa2506b671eb719653ebc92df5a9a6ac..6ad8ab4c578d679ae753ec240b4ae518f6eb35ca 100644 (file)
@@ -164,8 +164,11 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
                consumers[i].consumer = NULL;
 
        for (i = 0; i < num_consumers; i++) {
-               consumers[i].consumer = devm_regulator_get(dev,
-                                                          consumers[i].supply);
+               consumers[i].consumer = _devm_regulator_get(dev,
+                                                           consumers[i].supply,
+                                                           consumers[i].optional ?
+                                                               OPTIONAL_GET :
+                                                               NORMAL_GET);
                if (IS_ERR(consumers[i].consumer)) {
                        ret = PTR_ERR(consumers[i].consumer);
                        dev_err(dev, "Failed to get supply '%s': %d\n",
@@ -250,3 +253,251 @@ void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
                WARN_ON(rc);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_unregister);
+
+struct regulator_supply_alias_match {
+       struct device *dev;
+       const char *id;
+};
+
+static int devm_regulator_match_supply_alias(struct device *dev, void *res,
+                                            void *data)
+{
+       struct regulator_supply_alias_match *match = res;
+       struct regulator_supply_alias_match *target = data;
+
+       return match->dev == target->dev && strcmp(match->id, target->id) == 0;
+}
+
+static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
+{
+       struct regulator_supply_alias_match *match = res;
+
+       regulator_unregister_supply_alias(match->dev, match->id);
+}
+
+/**
+ * devm_regulator_register_supply_alias - Resource managed
+ * regulator_register_supply_alias()
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: Supply name or regulator ID that should be used to lookup the
+ * supply
+ *
+ * The supply alias will automatically be unregistered when the source
+ * device is unbound.
+ */
+int devm_regulator_register_supply_alias(struct device *dev, const char *id,
+                                        struct device *alias_dev,
+                                        const char *alias_id)
+{
+       struct regulator_supply_alias_match *match;
+       int ret;
+
+       match = devres_alloc(devm_regulator_destroy_supply_alias,
+                          sizeof(struct regulator_supply_alias_match),
+                          GFP_KERNEL);
+       if (!match)
+               return -ENOMEM;
+
+       match->dev = dev;
+       match->id = id;
+
+       ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
+       if (ret < 0) {
+               devres_free(match);
+               return ret;
+       }
+
+       devres_add(dev, match);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
+
+/**
+ * devm_regulator_unregister_supply_alias - Resource managed
+ * regulator_unregister_supply_alias()
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ *
+ * Unregister an alias registered with
+ * devm_regulator_register_supply_alias(). Normally this function
+ * will not need to be called and the resource management code
+ * will ensure that the resource is freed.
+ */
+void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
+{
+       struct regulator_supply_alias_match match;
+       int rc;
+
+       match.dev = dev;
+       match.id = id;
+
+       rc = devres_release(dev, devm_regulator_destroy_supply_alias,
+                           devm_regulator_match_supply_alias, &match);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
+
+/**
+ * devm_regulator_bulk_register_supply_alias - Managed register
+ * multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: List of supply names or regulator IDs that should be used to
+ * lookup the supply
+ * @num_id: Number of aliases to register
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to register several supply
+ * aliases in one operation, the aliases will be automatically
+ * unregisters when the source device is unbound.  If any of the
+ * aliases cannot be registered any aliases that were registered
+ * will be removed before returning to the caller.
+ */
+int devm_regulator_bulk_register_supply_alias(struct device *dev,
+                                             const char *const *id,
+                                             struct device *alias_dev,
+                                             const char *const *alias_id,
+                                             int num_id)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < num_id; ++i) {
+               ret = devm_regulator_register_supply_alias(dev, id[i],
+                                                          alias_dev,
+                                                          alias_id[i]);
+               if (ret < 0)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       dev_err(dev,
+               "Failed to create supply alias %s,%s -> %s,%s\n",
+               id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
+
+       while (--i >= 0)
+               devm_regulator_unregister_supply_alias(dev, id[i]);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
+
+/**
+ * devm_regulator_bulk_unregister_supply_alias - Managed unregister
+ * multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @num_id: Number of aliases to unregister
+ *
+ * Unregister aliases registered with
+ * devm_regulator_bulk_register_supply_alias(). Normally this function
+ * will not need to be called and the resource management code
+ * will ensure that the resource is freed.
+ */
+void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
+                                                const char *const *id,
+                                                int num_id)
+{
+       int i;
+
+       for (i = 0; i < num_id; ++i)
+               devm_regulator_unregister_supply_alias(dev, id[i]);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
+
+struct regulator_notifier_match {
+       struct regulator *regulator;
+       struct notifier_block *nb;
+};
+
+static int devm_regulator_match_notifier(struct device *dev, void *res,
+                                        void *data)
+{
+       struct regulator_notifier_match *match = res;
+       struct regulator_notifier_match *target = data;
+
+       return match->regulator == target->regulator && match->nb == target->nb;
+}
+
+static void devm_regulator_destroy_notifier(struct device *dev, void *res)
+{
+       struct regulator_notifier_match *match = res;
+
+       regulator_unregister_notifier(match->regulator, match->nb);
+}
+
+/**
+ * devm_regulator_register_notifier - Resource managed
+ * regulator_register_notifier
+ *
+ * @regulator: regulator source
+ * @nb: notifier block
+ *
+ * The notifier will be registers under the consumer device and be
+ * automatically be unregistered when the source device is unbound.
+ */
+int devm_regulator_register_notifier(struct regulator *regulator,
+                                    struct notifier_block *nb)
+{
+       struct regulator_notifier_match *match;
+       int ret;
+
+       match = devres_alloc(devm_regulator_destroy_notifier,
+                            sizeof(struct regulator_notifier_match),
+                            GFP_KERNEL);
+       if (!match)
+               return -ENOMEM;
+
+       match->regulator = regulator;
+       match->nb = nb;
+
+       ret = regulator_register_notifier(regulator, nb);
+       if (ret < 0) {
+               devres_free(match);
+               return ret;
+       }
+
+       devres_add(regulator->dev, match);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
+
+/**
+ * devm_regulator_unregister_notifier - Resource managed
+ * regulator_unregister_notifier()
+ *
+ * @regulator: regulator source
+ * @nb: notifier block
+ *
+ * Unregister a notifier registered with devm_regulator_register_notifier().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_regulator_unregister_notifier(struct regulator *regulator,
+                                       struct notifier_block *nb)
+{
+       struct regulator_notifier_match match;
+       int rc;
+
+       match.regulator = regulator;
+       match.nb = nb;
+
+       rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
+                           devm_regulator_match_notifier, &match);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);