cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

devres.c (12972B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * devres.c  --  Voltage/Current Regulator framework devres implementation.
      4 *
      5 * Copyright 2013 Linaro Ltd
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/err.h>
     10#include <linux/regmap.h>
     11#include <linux/regulator/consumer.h>
     12#include <linux/regulator/driver.h>
     13#include <linux/module.h>
     14
     15#include "internal.h"
     16
     17static void devm_regulator_release(struct device *dev, void *res)
     18{
     19	regulator_put(*(struct regulator **)res);
     20}
     21
     22static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
     23					     int get_type)
     24{
     25	struct regulator **ptr, *regulator;
     26
     27	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
     28	if (!ptr)
     29		return ERR_PTR(-ENOMEM);
     30
     31	regulator = _regulator_get(dev, id, get_type);
     32	if (!IS_ERR(regulator)) {
     33		*ptr = regulator;
     34		devres_add(dev, ptr);
     35	} else {
     36		devres_free(ptr);
     37	}
     38
     39	return regulator;
     40}
     41
     42/**
     43 * devm_regulator_get - Resource managed regulator_get()
     44 * @dev: device to supply
     45 * @id:  supply name or regulator ID.
     46 *
     47 * Managed regulator_get(). Regulators returned from this function are
     48 * automatically regulator_put() on driver detach. See regulator_get() for more
     49 * information.
     50 */
     51struct regulator *devm_regulator_get(struct device *dev, const char *id)
     52{
     53	return _devm_regulator_get(dev, id, NORMAL_GET);
     54}
     55EXPORT_SYMBOL_GPL(devm_regulator_get);
     56
     57/**
     58 * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
     59 * @dev: device to supply
     60 * @id:  supply name or regulator ID.
     61 *
     62 * Managed regulator_get_exclusive(). Regulators returned from this function
     63 * are automatically regulator_put() on driver detach. See regulator_get() for
     64 * more information.
     65 */
     66struct regulator *devm_regulator_get_exclusive(struct device *dev,
     67					       const char *id)
     68{
     69	return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
     70}
     71EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
     72
     73/**
     74 * devm_regulator_get_optional - Resource managed regulator_get_optional()
     75 * @dev: device to supply
     76 * @id:  supply name or regulator ID.
     77 *
     78 * Managed regulator_get_optional(). Regulators returned from this
     79 * function are automatically regulator_put() on driver detach. See
     80 * regulator_get_optional() for more information.
     81 */
     82struct regulator *devm_regulator_get_optional(struct device *dev,
     83					      const char *id)
     84{
     85	return _devm_regulator_get(dev, id, OPTIONAL_GET);
     86}
     87EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
     88
     89static int devm_regulator_match(struct device *dev, void *res, void *data)
     90{
     91	struct regulator **r = res;
     92	if (!r || !*r) {
     93		WARN_ON(!r || !*r);
     94		return 0;
     95	}
     96	return *r == data;
     97}
     98
     99/**
    100 * devm_regulator_put - Resource managed regulator_put()
    101 * @regulator: regulator to free
    102 *
    103 * Deallocate a regulator allocated with devm_regulator_get(). Normally
    104 * this function will not need to be called and the resource management
    105 * code will ensure that the resource is freed.
    106 */
    107void devm_regulator_put(struct regulator *regulator)
    108{
    109	int rc;
    110
    111	rc = devres_release(regulator->dev, devm_regulator_release,
    112			    devm_regulator_match, regulator);
    113	if (rc != 0)
    114		WARN_ON(rc);
    115}
    116EXPORT_SYMBOL_GPL(devm_regulator_put);
    117
    118struct regulator_bulk_devres {
    119	struct regulator_bulk_data *consumers;
    120	int num_consumers;
    121};
    122
    123static void devm_regulator_bulk_release(struct device *dev, void *res)
    124{
    125	struct regulator_bulk_devres *devres = res;
    126
    127	regulator_bulk_free(devres->num_consumers, devres->consumers);
    128}
    129
    130/**
    131 * devm_regulator_bulk_get - managed get multiple regulator consumers
    132 *
    133 * @dev:           device to supply
    134 * @num_consumers: number of consumers to register
    135 * @consumers:     configuration of consumers; clients are stored here.
    136 *
    137 * @return 0 on success, an errno on failure.
    138 *
    139 * This helper function allows drivers to get several regulator
    140 * consumers in one operation with management, the regulators will
    141 * automatically be freed when the device is unbound.  If any of the
    142 * regulators cannot be acquired then any regulators that were
    143 * allocated will be freed before returning to the caller.
    144 */
    145int devm_regulator_bulk_get(struct device *dev, int num_consumers,
    146			    struct regulator_bulk_data *consumers)
    147{
    148	struct regulator_bulk_devres *devres;
    149	int ret;
    150
    151	devres = devres_alloc(devm_regulator_bulk_release,
    152			      sizeof(*devres), GFP_KERNEL);
    153	if (!devres)
    154		return -ENOMEM;
    155
    156	ret = regulator_bulk_get(dev, num_consumers, consumers);
    157	if (!ret) {
    158		devres->consumers = consumers;
    159		devres->num_consumers = num_consumers;
    160		devres_add(dev, devres);
    161	} else {
    162		devres_free(devres);
    163	}
    164
    165	return ret;
    166}
    167EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
    168
    169static void devm_rdev_release(struct device *dev, void *res)
    170{
    171	regulator_unregister(*(struct regulator_dev **)res);
    172}
    173
    174/**
    175 * devm_regulator_register - Resource managed regulator_register()
    176 * @dev:            device to supply
    177 * @regulator_desc: regulator to register
    178 * @config:         runtime configuration for regulator
    179 *
    180 * Called by regulator drivers to register a regulator.  Returns a
    181 * valid pointer to struct regulator_dev on success or an ERR_PTR() on
    182 * error.  The regulator will automatically be released when the device
    183 * is unbound.
    184 */
    185struct regulator_dev *devm_regulator_register(struct device *dev,
    186				  const struct regulator_desc *regulator_desc,
    187				  const struct regulator_config *config)
    188{
    189	struct regulator_dev **ptr, *rdev;
    190
    191	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
    192			   GFP_KERNEL);
    193	if (!ptr)
    194		return ERR_PTR(-ENOMEM);
    195
    196	rdev = regulator_register(regulator_desc, config);
    197	if (!IS_ERR(rdev)) {
    198		*ptr = rdev;
    199		devres_add(dev, ptr);
    200	} else {
    201		devres_free(ptr);
    202	}
    203
    204	return rdev;
    205}
    206EXPORT_SYMBOL_GPL(devm_regulator_register);
    207
    208struct regulator_supply_alias_match {
    209	struct device *dev;
    210	const char *id;
    211};
    212
    213static int devm_regulator_match_supply_alias(struct device *dev, void *res,
    214					     void *data)
    215{
    216	struct regulator_supply_alias_match *match = res;
    217	struct regulator_supply_alias_match *target = data;
    218
    219	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
    220}
    221
    222static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
    223{
    224	struct regulator_supply_alias_match *match = res;
    225
    226	regulator_unregister_supply_alias(match->dev, match->id);
    227}
    228
    229/**
    230 * devm_regulator_register_supply_alias - Resource managed
    231 * regulator_register_supply_alias()
    232 *
    233 * @dev:       device to supply
    234 * @id:        supply name or regulator ID
    235 * @alias_dev: device that should be used to lookup the supply
    236 * @alias_id:  supply name or regulator ID that should be used to lookup the
    237 * supply
    238 *
    239 * The supply alias will automatically be unregistered when the source
    240 * device is unbound.
    241 */
    242int devm_regulator_register_supply_alias(struct device *dev, const char *id,
    243					 struct device *alias_dev,
    244					 const char *alias_id)
    245{
    246	struct regulator_supply_alias_match *match;
    247	int ret;
    248
    249	match = devres_alloc(devm_regulator_destroy_supply_alias,
    250			   sizeof(struct regulator_supply_alias_match),
    251			   GFP_KERNEL);
    252	if (!match)
    253		return -ENOMEM;
    254
    255	match->dev = dev;
    256	match->id = id;
    257
    258	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
    259	if (ret < 0) {
    260		devres_free(match);
    261		return ret;
    262	}
    263
    264	devres_add(dev, match);
    265
    266	return 0;
    267}
    268EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
    269
    270static void devm_regulator_unregister_supply_alias(struct device *dev,
    271						   const char *id)
    272{
    273	struct regulator_supply_alias_match match;
    274	int rc;
    275
    276	match.dev = dev;
    277	match.id = id;
    278
    279	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
    280			    devm_regulator_match_supply_alias, &match);
    281	if (rc != 0)
    282		WARN_ON(rc);
    283}
    284
    285/**
    286 * devm_regulator_bulk_register_supply_alias - Managed register
    287 * multiple aliases
    288 *
    289 * @dev:       device to supply
    290 * @id:        list of supply names or regulator IDs
    291 * @alias_dev: device that should be used to lookup the supply
    292 * @alias_id:  list of supply names or regulator IDs that should be used to
    293 *             lookup the supply
    294 * @num_id:    number of aliases to register
    295 *
    296 * @return 0 on success, an errno on failure.
    297 *
    298 * This helper function allows drivers to register several supply
    299 * aliases in one operation, the aliases will be automatically
    300 * unregisters when the source device is unbound.  If any of the
    301 * aliases cannot be registered any aliases that were registered
    302 * will be removed before returning to the caller.
    303 */
    304int devm_regulator_bulk_register_supply_alias(struct device *dev,
    305					      const char *const *id,
    306					      struct device *alias_dev,
    307					      const char *const *alias_id,
    308					      int num_id)
    309{
    310	int i;
    311	int ret;
    312
    313	for (i = 0; i < num_id; ++i) {
    314		ret = devm_regulator_register_supply_alias(dev, id[i],
    315							   alias_dev,
    316							   alias_id[i]);
    317		if (ret < 0)
    318			goto err;
    319	}
    320
    321	return 0;
    322
    323err:
    324	dev_err(dev,
    325		"Failed to create supply alias %s,%s -> %s,%s\n",
    326		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
    327
    328	while (--i >= 0)
    329		devm_regulator_unregister_supply_alias(dev, id[i]);
    330
    331	return ret;
    332}
    333EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
    334
    335struct regulator_notifier_match {
    336	struct regulator *regulator;
    337	struct notifier_block *nb;
    338};
    339
    340static int devm_regulator_match_notifier(struct device *dev, void *res,
    341					 void *data)
    342{
    343	struct regulator_notifier_match *match = res;
    344	struct regulator_notifier_match *target = data;
    345
    346	return match->regulator == target->regulator && match->nb == target->nb;
    347}
    348
    349static void devm_regulator_destroy_notifier(struct device *dev, void *res)
    350{
    351	struct regulator_notifier_match *match = res;
    352
    353	regulator_unregister_notifier(match->regulator, match->nb);
    354}
    355
    356/**
    357 * devm_regulator_register_notifier - Resource managed
    358 * regulator_register_notifier
    359 *
    360 * @regulator: regulator source
    361 * @nb:        notifier block
    362 *
    363 * The notifier will be registers under the consumer device and be
    364 * automatically be unregistered when the source device is unbound.
    365 */
    366int devm_regulator_register_notifier(struct regulator *regulator,
    367				     struct notifier_block *nb)
    368{
    369	struct regulator_notifier_match *match;
    370	int ret;
    371
    372	match = devres_alloc(devm_regulator_destroy_notifier,
    373			     sizeof(struct regulator_notifier_match),
    374			     GFP_KERNEL);
    375	if (!match)
    376		return -ENOMEM;
    377
    378	match->regulator = regulator;
    379	match->nb = nb;
    380
    381	ret = regulator_register_notifier(regulator, nb);
    382	if (ret < 0) {
    383		devres_free(match);
    384		return ret;
    385	}
    386
    387	devres_add(regulator->dev, match);
    388
    389	return 0;
    390}
    391EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
    392
    393/**
    394 * devm_regulator_unregister_notifier - Resource managed
    395 * regulator_unregister_notifier()
    396 *
    397 * @regulator: regulator source
    398 * @nb:        notifier block
    399 *
    400 * Unregister a notifier registered with devm_regulator_register_notifier().
    401 * Normally this function will not need to be called and the resource
    402 * management code will ensure that the resource is freed.
    403 */
    404void devm_regulator_unregister_notifier(struct regulator *regulator,
    405					struct notifier_block *nb)
    406{
    407	struct regulator_notifier_match match;
    408	int rc;
    409
    410	match.regulator = regulator;
    411	match.nb = nb;
    412
    413	rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
    414			    devm_regulator_match_notifier, &match);
    415	if (rc != 0)
    416		WARN_ON(rc);
    417}
    418EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
    419
    420static void regulator_irq_helper_drop(void *res)
    421{
    422	regulator_irq_helper_cancel(&res);
    423}
    424
    425/**
    426 * devm_regulator_irq_helper - resource managed registration of IRQ based
    427 * regulator event/error notifier
    428 *
    429 * @dev:		device to which lifetime the helper's lifetime is
    430 *			bound.
    431 * @d:			IRQ helper descriptor.
    432 * @irq:		IRQ used to inform events/errors to be notified.
    433 * @irq_flags:		Extra IRQ flags to be OR'ed with the default
    434 *			IRQF_ONESHOT when requesting the (threaded) irq.
    435 * @common_errs:	Errors which can be flagged by this IRQ for all rdevs.
    436 *			When IRQ is re-enabled these errors will be cleared
    437 *			from all associated regulators
    438 * @per_rdev_errs:	Optional error flag array describing errors specific
    439 *			for only some of the regulators. These errors will be
    440 *			or'ed with common errors. If this is given the array
    441 *			should contain rdev_amount flags. Can be set to NULL
    442 *			if there is no regulator specific error flags for this
    443 *			IRQ.
    444 * @rdev:		Array of pointers to regulators associated with this
    445 *			IRQ.
    446 * @rdev_amount:	Amount of regulators associated with this IRQ.
    447 *
    448 * Return: handle to irq_helper or an ERR_PTR() encoded error code.
    449 */
    450void *devm_regulator_irq_helper(struct device *dev,
    451				const struct regulator_irq_desc *d, int irq,
    452				int irq_flags, int common_errs,
    453				int *per_rdev_errs,
    454				struct regulator_dev **rdev, int rdev_amount)
    455{
    456	void *ptr;
    457	int ret;
    458
    459	ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,
    460				    per_rdev_errs, rdev, rdev_amount);
    461	if (IS_ERR(ptr))
    462		return ptr;
    463
    464	ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);
    465	if (ret)
    466		return ERR_PTR(ret);
    467
    468	return ptr;
    469}
    470EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);