// SPDX-License-Identifier: GPL-2.0 // // Copyright (C) 2021 ROHM Semiconductors // regulator IRQ based event notification helpers // // Logic has been partially adapted from qcom-labibb driver. // // Author: Matti Vaittinen <[email protected]> #include <linux/device.h> #include <linux/err.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/reboot.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/regulator/driver.h> #include "internal.h" #define REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS … struct regulator_irq { … }; /* * Should only be called from threaded handler to prevent potential deadlock */ static void rdev_flag_err(struct regulator_dev *rdev, int err) { … } static void rdev_clear_err(struct regulator_dev *rdev, int err) { … } static void regulator_notifier_isr_work(struct work_struct *work) { … } static irqreturn_t regulator_notifier_isr(int irq, void *data) { … } static int init_rdev_state(struct device *dev, struct regulator_irq *h, struct regulator_dev **rdev, int common_err, int *rdev_err, int rdev_amount) { … } static void init_rdev_errors(struct regulator_irq *h) { … } /** * regulator_irq_helper - register IRQ based regulator event/error notifier * * @dev: device providing the IRQs * @d: IRQ helper descriptor. * @irq: IRQ used to inform events/errors to be notified. * @irq_flags: Extra IRQ flags to be OR'ed with the default * IRQF_ONESHOT when requesting the (threaded) irq. * @common_errs: Errors which can be flagged by this IRQ for all rdevs. * When IRQ is re-enabled these errors will be cleared * from all associated regulators. Use this instead of the * per_rdev_errs if you use * regulator_irq_map_event_simple() for event mapping. * @per_rdev_errs: Optional error flag array describing errors specific * for only some of the regulators. These errors will be * or'ed with common errors. If this is given the array * should contain rdev_amount flags. Can be set to NULL * if there is no regulator specific error flags for this * IRQ. * @rdev: Array of pointers to regulators associated with this * IRQ. * @rdev_amount: Amount of regulators associated with this IRQ. * * Return: handle to irq_helper or an ERR_PTR() encoded error code. */ void *regulator_irq_helper(struct device *dev, const struct regulator_irq_desc *d, int irq, int irq_flags, int common_errs, int *per_rdev_errs, struct regulator_dev **rdev, int rdev_amount) { … } EXPORT_SYMBOL_GPL(…); /** * regulator_irq_helper_cancel - drop IRQ based regulator event/error notifier * * @handle: Pointer to handle returned by a successful call to * regulator_irq_helper(). Will be NULLed upon return. * * The associated IRQ is released and work is cancelled when the function * returns. */ void regulator_irq_helper_cancel(void **handle) { … } EXPORT_SYMBOL_GPL(…); /** * regulator_irq_map_event_simple - regulator IRQ notification for trivial IRQs * * @irq: Number of IRQ that occurred * @rid: Information about the event IRQ indicates * @dev_mask: mask indicating the regulator originating the IRQ * * Regulators whose IRQ has single, well defined purpose (always indicate * exactly one event, and are relevant to exactly one regulator device) can * use this function as their map_event callbac for their regulator IRQ * notification helperk. Exactly one rdev and exactly one error (in * "common_errs"-field) can be given at IRQ helper registration for * regulator_irq_map_event_simple() to be viable. */ int regulator_irq_map_event_simple(int irq, struct regulator_irq_data *rid, unsigned long *dev_mask) { … } EXPORT_SYMBOL_GPL(…);