Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 046db763 authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown
Browse files

regulator: core: Add devres versions of notifier registration



Add devm_regulator_register_notifier, this adds the resource against the
device for the consumer supply we are registering the notifier for. There
seem to be few use-cases where this wouldn't be the users intention and
this ensures the notifiers will always be removed at the correct time.

Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent c517d838
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -413,3 +413,88 @@ void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
		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);
+16 −0
Original line number Diff line number Diff line
@@ -252,8 +252,12 @@ int regulator_list_hardware_vsel(struct regulator *regulator,
/* regulator notifier block */
int regulator_register_notifier(struct regulator *regulator,
			      struct notifier_block *nb);
int devm_regulator_register_notifier(struct regulator *regulator,
				     struct notifier_block *nb);
int regulator_unregister_notifier(struct regulator *regulator,
				struct notifier_block *nb);
void devm_regulator_unregister_notifier(struct regulator *regulator,
					struct notifier_block *nb);

/* driver data - core doesn't touch */
void *regulator_get_drvdata(struct regulator *regulator);
@@ -515,12 +519,24 @@ static inline int regulator_register_notifier(struct regulator *regulator,
	return 0;
}

static inline int devm_regulator_register_notifier(struct regulator *regulator,
						   struct notifier_block *nb)
{
	return 0;
}

static inline int regulator_unregister_notifier(struct regulator *regulator,
				struct notifier_block *nb)
{
	return 0;
}

static inline int devm_regulator_unregister_notifier(struct regulator *regulator,
						     struct notifier_block *nb)
{
	return 0;
}

static inline void *regulator_get_drvdata(struct regulator *regulator)
{
	return NULL;