Skip to content

Commit 7111c6d

Browse files
M-Vaittinenbroonie
authored andcommitted
regulator: IRQ based event/error notification helpers
Provide helper function for IC's implementing regulator notifications when an IRQ fires. The helper also works for IRQs which can not be acked. Helper can be set to disable the IRQ at handler and then re-enabling it on delayed work later. The helper also adds regulator_get_error_flags() errors in cache for the duration of IRQ disabling. Signed-off-by: Matti Vaittinen <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/ebdf86d8c22b924667ec2385330e30fcbfac0119.1622628334.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Mark Brown <[email protected]>
1 parent 157d223 commit 7111c6d

File tree

5 files changed

+607
-8
lines changed

5 files changed

+607
-8
lines changed

drivers/regulator/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55

66

7-
obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o
7+
obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o irq_helpers.o
88
obj-$(CONFIG_OF) += of_regulator.o
99
obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
1010
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o

drivers/regulator/core.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4370,22 +4370,36 @@ unsigned int regulator_get_mode(struct regulator *regulator)
43704370
}
43714371
EXPORT_SYMBOL_GPL(regulator_get_mode);
43724372

4373+
static int rdev_get_cached_err_flags(struct regulator_dev *rdev)
4374+
{
4375+
int ret = 0;
4376+
4377+
if (rdev->use_cached_err) {
4378+
spin_lock(&rdev->err_lock);
4379+
ret = rdev->cached_err;
4380+
spin_unlock(&rdev->err_lock);
4381+
}
4382+
return ret;
4383+
}
4384+
43734385
static int _regulator_get_error_flags(struct regulator_dev *rdev,
43744386
unsigned int *flags)
43754387
{
4376-
int ret;
4388+
int cached_flags, ret = 0;
43774389

43784390
regulator_lock(rdev);
43794391

4380-
/* sanity check */
4381-
if (!rdev->desc->ops->get_error_flags) {
4392+
cached_flags = rdev_get_cached_err_flags(rdev);
4393+
4394+
if (rdev->desc->ops->get_error_flags)
4395+
ret = rdev->desc->ops->get_error_flags(rdev, flags);
4396+
else if (!rdev->use_cached_err)
43824397
ret = -EINVAL;
4383-
goto out;
4384-
}
43854398

4386-
ret = rdev->desc->ops->get_error_flags(rdev, flags);
4387-
out:
4399+
*flags |= cached_flags;
4400+
43884401
regulator_unlock(rdev);
4402+
43894403
return ret;
43904404
}
43914405

@@ -5218,6 +5232,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
52185232
goto rinse;
52195233
}
52205234
device_initialize(&rdev->dev);
5235+
spin_lock_init(&rdev->err_lock);
52215236

52225237
/*
52235238
* Duplicate the config so the driver could override it after

drivers/regulator/devres.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,3 +481,55 @@ void devm_regulator_unregister_notifier(struct regulator *regulator,
481481
WARN_ON(rc);
482482
}
483483
EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
484+
485+
static void regulator_irq_helper_drop(void *res)
486+
{
487+
regulator_irq_helper_cancel(&res);
488+
}
489+
490+
/**
491+
* devm_regulator_irq_helper - resource managed registration of IRQ based
492+
* regulator event/error notifier
493+
*
494+
* @dev: device to which lifetime the helper's lifetime is
495+
* bound.
496+
* @d: IRQ helper descriptor.
497+
* @irq: IRQ used to inform events/errors to be notified.
498+
* @irq_flags: Extra IRQ flags to be OR'ed with the default
499+
* IRQF_ONESHOT when requesting the (threaded) irq.
500+
* @common_errs: Errors which can be flagged by this IRQ for all rdevs.
501+
* When IRQ is re-enabled these errors will be cleared
502+
* from all associated regulators
503+
* @per_rdev_errs: Optional error flag array describing errors specific
504+
* for only some of the regulators. These errors will be
505+
* or'ed with common errors. If this is given the array
506+
* should contain rdev_amount flags. Can be set to NULL
507+
* if there is no regulator specific error flags for this
508+
* IRQ.
509+
* @rdev: Array of pointers to regulators associated with this
510+
* IRQ.
511+
* @rdev_amount: Amount of regulators associated with this IRQ.
512+
*
513+
* Return: handle to irq_helper or an ERR_PTR() encoded error code.
514+
*/
515+
void *devm_regulator_irq_helper(struct device *dev,
516+
const struct regulator_irq_desc *d, int irq,
517+
int irq_flags, int common_errs,
518+
int *per_rdev_errs,
519+
struct regulator_dev **rdev, int rdev_amount)
520+
{
521+
void *ptr;
522+
int ret;
523+
524+
ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,
525+
per_rdev_errs, rdev, rdev_amount);
526+
if (IS_ERR(ptr))
527+
return ptr;
528+
529+
ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);
530+
if (ret)
531+
return ERR_PTR(ret);
532+
533+
return ptr;
534+
}
535+
EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);

0 commit comments

Comments
 (0)