drivers/regulator/irq_helpers.c

Source file repositories/reference/linux-study-clean/drivers/regulator/irq_helpers.c

File Facts

System
Linux kernel
Corpus path
drivers/regulator/irq_helpers.c
Extension
.c
Size
11953 bytes
Lines
445
Domain
Driver Families
Bucket
drivers/regulator
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct regulator_irq {
	struct regulator_irq_data rdata;
	struct regulator_irq_desc desc;
	int irq;
	int retry_cnt;
	struct delayed_work isr_work;
};

/*
 * Should only be called from threaded handler to prevent potential deadlock
 */
static void rdev_flag_err(struct regulator_dev *rdev, int err)
{
	spin_lock(&rdev->err_lock);
	rdev->cached_err |= err;
	spin_unlock(&rdev->err_lock);
}

static void rdev_clear_err(struct regulator_dev *rdev, int err)
{
	spin_lock(&rdev->err_lock);
	rdev->cached_err &= ~err;
	spin_unlock(&rdev->err_lock);
}

static void regulator_notifier_isr_work(struct work_struct *work)
{
	struct regulator_irq *h;
	struct regulator_irq_desc *d;
	struct regulator_irq_data *rid;
	int ret = 0;
	int tmo, i;
	int num_rdevs;

	h = container_of(work, struct regulator_irq,
			    isr_work.work);
	d = &h->desc;
	rid = &h->rdata;
	num_rdevs = rid->num_states;

reread:
	if (d->fatal_cnt && h->retry_cnt > d->fatal_cnt) {
		if (!d->die)
			return hw_protection_trigger("Regulator HW failure? - no IC recovery",
						     REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS);
		ret = d->die(rid);
		/*
		 * If the 'last resort' IC recovery failed we will have
		 * nothing else left to do...
		 */
		if (ret)
			return hw_protection_trigger("Regulator HW failure. IC recovery failed",
						     REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS);

		/*
		 * If h->die() was implemented we assume recovery has been
		 * attempted (probably regulator was shut down) and we
		 * just enable IRQ and bail-out.
		 */
		goto enable_out;
	}
	if (d->renable) {
		ret = d->renable(rid);

		if (ret == REGULATOR_FAILED_RETRY) {
			/* Driver could not get current status */
			h->retry_cnt++;
			if (!d->reread_ms)
				goto reread;

			tmo = d->reread_ms;
			goto reschedule;
		}

		if (ret) {
			/*
			 * IC status reading succeeded. update error info
			 * just in case the renable changed it.
			 */
			for (i = 0; i < num_rdevs; i++) {
				struct regulator_err_state *stat;
				struct regulator_dev *rdev;

				stat = &rid->states[i];
				rdev = stat->rdev;
				rdev_clear_err(rdev, (~stat->errors) &
						      stat->possible_errs);
			}
			h->retry_cnt++;
			/*

Annotation

Implementation Notes