Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * devres.c  --  Voltage/Current Regulator framework devres implementation.
0004  *
0005  * Copyright 2013 Linaro Ltd
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/err.h>
0010 #include <linux/regmap.h>
0011 #include <linux/regulator/consumer.h>
0012 #include <linux/regulator/driver.h>
0013 #include <linux/module.h>
0014 
0015 #include "internal.h"
0016 
0017 static void devm_regulator_release(struct device *dev, void *res)
0018 {
0019     regulator_put(*(struct regulator **)res);
0020 }
0021 
0022 static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
0023                          int get_type)
0024 {
0025     struct regulator **ptr, *regulator;
0026 
0027     ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
0028     if (!ptr)
0029         return ERR_PTR(-ENOMEM);
0030 
0031     regulator = _regulator_get(dev, id, get_type);
0032     if (!IS_ERR(regulator)) {
0033         *ptr = regulator;
0034         devres_add(dev, ptr);
0035     } else {
0036         devres_free(ptr);
0037     }
0038 
0039     return regulator;
0040 }
0041 
0042 /**
0043  * devm_regulator_get - Resource managed regulator_get()
0044  * @dev: device to supply
0045  * @id:  supply name or regulator ID.
0046  *
0047  * Managed regulator_get(). Regulators returned from this function are
0048  * automatically regulator_put() on driver detach. See regulator_get() for more
0049  * information.
0050  */
0051 struct regulator *devm_regulator_get(struct device *dev, const char *id)
0052 {
0053     return _devm_regulator_get(dev, id, NORMAL_GET);
0054 }
0055 EXPORT_SYMBOL_GPL(devm_regulator_get);
0056 
0057 /**
0058  * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
0059  * @dev: device to supply
0060  * @id:  supply name or regulator ID.
0061  *
0062  * Managed regulator_get_exclusive(). Regulators returned from this function
0063  * are automatically regulator_put() on driver detach. See regulator_get() for
0064  * more information.
0065  */
0066 struct regulator *devm_regulator_get_exclusive(struct device *dev,
0067                            const char *id)
0068 {
0069     return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
0070 }
0071 EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
0072 
0073 /**
0074  * devm_regulator_get_optional - Resource managed regulator_get_optional()
0075  * @dev: device to supply
0076  * @id:  supply name or regulator ID.
0077  *
0078  * Managed regulator_get_optional(). Regulators returned from this
0079  * function are automatically regulator_put() on driver detach. See
0080  * regulator_get_optional() for more information.
0081  */
0082 struct regulator *devm_regulator_get_optional(struct device *dev,
0083                           const char *id)
0084 {
0085     return _devm_regulator_get(dev, id, OPTIONAL_GET);
0086 }
0087 EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
0088 
0089 static int devm_regulator_match(struct device *dev, void *res, void *data)
0090 {
0091     struct regulator **r = res;
0092     if (!r || !*r) {
0093         WARN_ON(!r || !*r);
0094         return 0;
0095     }
0096     return *r == data;
0097 }
0098 
0099 /**
0100  * devm_regulator_put - Resource managed regulator_put()
0101  * @regulator: regulator to free
0102  *
0103  * Deallocate a regulator allocated with devm_regulator_get(). Normally
0104  * this function will not need to be called and the resource management
0105  * code will ensure that the resource is freed.
0106  */
0107 void devm_regulator_put(struct regulator *regulator)
0108 {
0109     int rc;
0110 
0111     rc = devres_release(regulator->dev, devm_regulator_release,
0112                 devm_regulator_match, regulator);
0113     if (rc != 0)
0114         WARN_ON(rc);
0115 }
0116 EXPORT_SYMBOL_GPL(devm_regulator_put);
0117 
0118 struct regulator_bulk_devres {
0119     struct regulator_bulk_data *consumers;
0120     int num_consumers;
0121 };
0122 
0123 static void devm_regulator_bulk_release(struct device *dev, void *res)
0124 {
0125     struct regulator_bulk_devres *devres = res;
0126 
0127     regulator_bulk_free(devres->num_consumers, devres->consumers);
0128 }
0129 
0130 /**
0131  * devm_regulator_bulk_get - managed get multiple regulator consumers
0132  *
0133  * @dev:           device to supply
0134  * @num_consumers: number of consumers to register
0135  * @consumers:     configuration of consumers; clients are stored here.
0136  *
0137  * @return 0 on success, an errno on failure.
0138  *
0139  * This helper function allows drivers to get several regulator
0140  * consumers in one operation with management, the regulators will
0141  * automatically be freed when the device is unbound.  If any of the
0142  * regulators cannot be acquired then any regulators that were
0143  * allocated will be freed before returning to the caller.
0144  */
0145 int devm_regulator_bulk_get(struct device *dev, int num_consumers,
0146                 struct regulator_bulk_data *consumers)
0147 {
0148     struct regulator_bulk_devres *devres;
0149     int ret;
0150 
0151     devres = devres_alloc(devm_regulator_bulk_release,
0152                   sizeof(*devres), GFP_KERNEL);
0153     if (!devres)
0154         return -ENOMEM;
0155 
0156     ret = regulator_bulk_get(dev, num_consumers, consumers);
0157     if (!ret) {
0158         devres->consumers = consumers;
0159         devres->num_consumers = num_consumers;
0160         devres_add(dev, devres);
0161     } else {
0162         devres_free(devres);
0163     }
0164 
0165     return ret;
0166 }
0167 EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
0168 
0169 /**
0170  * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data
0171  *
0172  * @dev:           device to supply
0173  * @num_consumers: number of consumers to register
0174  * @in_consumers:  const configuration of consumers
0175  * @out_consumers: in_consumers is copied here and this is passed to
0176  *         devm_regulator_bulk_get().
0177  *
0178  * This is a convenience function to allow bulk regulator configuration
0179  * to be stored "static const" in files.
0180  *
0181  * Return: 0 on success, an errno on failure.
0182  */
0183 int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
0184                   const struct regulator_bulk_data *in_consumers,
0185                   struct regulator_bulk_data **out_consumers)
0186 {
0187     *out_consumers = devm_kmemdup(dev, in_consumers,
0188                       num_consumers * sizeof(*in_consumers),
0189                       GFP_KERNEL);
0190     if (*out_consumers == NULL)
0191         return -ENOMEM;
0192 
0193     return devm_regulator_bulk_get(dev, num_consumers, *out_consumers);
0194 }
0195 EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
0196 
0197 static void devm_rdev_release(struct device *dev, void *res)
0198 {
0199     regulator_unregister(*(struct regulator_dev **)res);
0200 }
0201 
0202 /**
0203  * devm_regulator_register - Resource managed regulator_register()
0204  * @dev:            device to supply
0205  * @regulator_desc: regulator to register
0206  * @config:         runtime configuration for regulator
0207  *
0208  * Called by regulator drivers to register a regulator.  Returns a
0209  * valid pointer to struct regulator_dev on success or an ERR_PTR() on
0210  * error.  The regulator will automatically be released when the device
0211  * is unbound.
0212  */
0213 struct regulator_dev *devm_regulator_register(struct device *dev,
0214                   const struct regulator_desc *regulator_desc,
0215                   const struct regulator_config *config)
0216 {
0217     struct regulator_dev **ptr, *rdev;
0218 
0219     ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
0220                GFP_KERNEL);
0221     if (!ptr)
0222         return ERR_PTR(-ENOMEM);
0223 
0224     rdev = regulator_register(regulator_desc, config);
0225     if (!IS_ERR(rdev)) {
0226         *ptr = rdev;
0227         devres_add(dev, ptr);
0228     } else {
0229         devres_free(ptr);
0230     }
0231 
0232     return rdev;
0233 }
0234 EXPORT_SYMBOL_GPL(devm_regulator_register);
0235 
0236 struct regulator_supply_alias_match {
0237     struct device *dev;
0238     const char *id;
0239 };
0240 
0241 static int devm_regulator_match_supply_alias(struct device *dev, void *res,
0242                          void *data)
0243 {
0244     struct regulator_supply_alias_match *match = res;
0245     struct regulator_supply_alias_match *target = data;
0246 
0247     return match->dev == target->dev && strcmp(match->id, target->id) == 0;
0248 }
0249 
0250 static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
0251 {
0252     struct regulator_supply_alias_match *match = res;
0253 
0254     regulator_unregister_supply_alias(match->dev, match->id);
0255 }
0256 
0257 /**
0258  * devm_regulator_register_supply_alias - Resource managed
0259  * regulator_register_supply_alias()
0260  *
0261  * @dev:       device to supply
0262  * @id:        supply name or regulator ID
0263  * @alias_dev: device that should be used to lookup the supply
0264  * @alias_id:  supply name or regulator ID that should be used to lookup the
0265  * supply
0266  *
0267  * The supply alias will automatically be unregistered when the source
0268  * device is unbound.
0269  */
0270 int devm_regulator_register_supply_alias(struct device *dev, const char *id,
0271                      struct device *alias_dev,
0272                      const char *alias_id)
0273 {
0274     struct regulator_supply_alias_match *match;
0275     int ret;
0276 
0277     match = devres_alloc(devm_regulator_destroy_supply_alias,
0278                sizeof(struct regulator_supply_alias_match),
0279                GFP_KERNEL);
0280     if (!match)
0281         return -ENOMEM;
0282 
0283     match->dev = dev;
0284     match->id = id;
0285 
0286     ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
0287     if (ret < 0) {
0288         devres_free(match);
0289         return ret;
0290     }
0291 
0292     devres_add(dev, match);
0293 
0294     return 0;
0295 }
0296 EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
0297 
0298 static void devm_regulator_unregister_supply_alias(struct device *dev,
0299                            const char *id)
0300 {
0301     struct regulator_supply_alias_match match;
0302     int rc;
0303 
0304     match.dev = dev;
0305     match.id = id;
0306 
0307     rc = devres_release(dev, devm_regulator_destroy_supply_alias,
0308                 devm_regulator_match_supply_alias, &match);
0309     if (rc != 0)
0310         WARN_ON(rc);
0311 }
0312 
0313 /**
0314  * devm_regulator_bulk_register_supply_alias - Managed register
0315  * multiple aliases
0316  *
0317  * @dev:       device to supply
0318  * @id:        list of supply names or regulator IDs
0319  * @alias_dev: device that should be used to lookup the supply
0320  * @alias_id:  list of supply names or regulator IDs that should be used to
0321  *             lookup the supply
0322  * @num_id:    number of aliases to register
0323  *
0324  * @return 0 on success, an errno on failure.
0325  *
0326  * This helper function allows drivers to register several supply
0327  * aliases in one operation, the aliases will be automatically
0328  * unregisters when the source device is unbound.  If any of the
0329  * aliases cannot be registered any aliases that were registered
0330  * will be removed before returning to the caller.
0331  */
0332 int devm_regulator_bulk_register_supply_alias(struct device *dev,
0333                           const char *const *id,
0334                           struct device *alias_dev,
0335                           const char *const *alias_id,
0336                           int num_id)
0337 {
0338     int i;
0339     int ret;
0340 
0341     for (i = 0; i < num_id; ++i) {
0342         ret = devm_regulator_register_supply_alias(dev, id[i],
0343                                alias_dev,
0344                                alias_id[i]);
0345         if (ret < 0)
0346             goto err;
0347     }
0348 
0349     return 0;
0350 
0351 err:
0352     dev_err(dev,
0353         "Failed to create supply alias %s,%s -> %s,%s\n",
0354         id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
0355 
0356     while (--i >= 0)
0357         devm_regulator_unregister_supply_alias(dev, id[i]);
0358 
0359     return ret;
0360 }
0361 EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
0362 
0363 struct regulator_notifier_match {
0364     struct regulator *regulator;
0365     struct notifier_block *nb;
0366 };
0367 
0368 static int devm_regulator_match_notifier(struct device *dev, void *res,
0369                      void *data)
0370 {
0371     struct regulator_notifier_match *match = res;
0372     struct regulator_notifier_match *target = data;
0373 
0374     return match->regulator == target->regulator && match->nb == target->nb;
0375 }
0376 
0377 static void devm_regulator_destroy_notifier(struct device *dev, void *res)
0378 {
0379     struct regulator_notifier_match *match = res;
0380 
0381     regulator_unregister_notifier(match->regulator, match->nb);
0382 }
0383 
0384 /**
0385  * devm_regulator_register_notifier - Resource managed
0386  * regulator_register_notifier
0387  *
0388  * @regulator: regulator source
0389  * @nb:        notifier block
0390  *
0391  * The notifier will be registers under the consumer device and be
0392  * automatically be unregistered when the source device is unbound.
0393  */
0394 int devm_regulator_register_notifier(struct regulator *regulator,
0395                      struct notifier_block *nb)
0396 {
0397     struct regulator_notifier_match *match;
0398     int ret;
0399 
0400     match = devres_alloc(devm_regulator_destroy_notifier,
0401                  sizeof(struct regulator_notifier_match),
0402                  GFP_KERNEL);
0403     if (!match)
0404         return -ENOMEM;
0405 
0406     match->regulator = regulator;
0407     match->nb = nb;
0408 
0409     ret = regulator_register_notifier(regulator, nb);
0410     if (ret < 0) {
0411         devres_free(match);
0412         return ret;
0413     }
0414 
0415     devres_add(regulator->dev, match);
0416 
0417     return 0;
0418 }
0419 EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
0420 
0421 /**
0422  * devm_regulator_unregister_notifier - Resource managed
0423  * regulator_unregister_notifier()
0424  *
0425  * @regulator: regulator source
0426  * @nb:        notifier block
0427  *
0428  * Unregister a notifier registered with devm_regulator_register_notifier().
0429  * Normally this function will not need to be called and the resource
0430  * management code will ensure that the resource is freed.
0431  */
0432 void devm_regulator_unregister_notifier(struct regulator *regulator,
0433                     struct notifier_block *nb)
0434 {
0435     struct regulator_notifier_match match;
0436     int rc;
0437 
0438     match.regulator = regulator;
0439     match.nb = nb;
0440 
0441     rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
0442                 devm_regulator_match_notifier, &match);
0443     if (rc != 0)
0444         WARN_ON(rc);
0445 }
0446 EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
0447 
0448 static void regulator_irq_helper_drop(void *res)
0449 {
0450     regulator_irq_helper_cancel(&res);
0451 }
0452 
0453 /**
0454  * devm_regulator_irq_helper - resource managed registration of IRQ based
0455  * regulator event/error notifier
0456  *
0457  * @dev:        device to which lifetime the helper's lifetime is
0458  *          bound.
0459  * @d:          IRQ helper descriptor.
0460  * @irq:        IRQ used to inform events/errors to be notified.
0461  * @irq_flags:      Extra IRQ flags to be OR'ed with the default
0462  *          IRQF_ONESHOT when requesting the (threaded) irq.
0463  * @common_errs:    Errors which can be flagged by this IRQ for all rdevs.
0464  *          When IRQ is re-enabled these errors will be cleared
0465  *          from all associated regulators
0466  * @per_rdev_errs:  Optional error flag array describing errors specific
0467  *          for only some of the regulators. These errors will be
0468  *          or'ed with common errors. If this is given the array
0469  *          should contain rdev_amount flags. Can be set to NULL
0470  *          if there is no regulator specific error flags for this
0471  *          IRQ.
0472  * @rdev:       Array of pointers to regulators associated with this
0473  *          IRQ.
0474  * @rdev_amount:    Amount of regulators associated with this IRQ.
0475  *
0476  * Return: handle to irq_helper or an ERR_PTR() encoded error code.
0477  */
0478 void *devm_regulator_irq_helper(struct device *dev,
0479                 const struct regulator_irq_desc *d, int irq,
0480                 int irq_flags, int common_errs,
0481                 int *per_rdev_errs,
0482                 struct regulator_dev **rdev, int rdev_amount)
0483 {
0484     void *ptr;
0485     int ret;
0486 
0487     ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,
0488                     per_rdev_errs, rdev, rdev_amount);
0489     if (IS_ERR(ptr))
0490         return ptr;
0491 
0492     ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);
0493     if (ret)
0494         return ERR_PTR(ret);
0495 
0496     return ptr;
0497 }
0498 EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);