Commit b04e68d1 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Lee Jones
Browse files

mfd: madera: Don't use regmap_read_poll_timeout to poll for BOOT_DONE



While polling for BOOT_DONE the chip could NAK a read because it is
still booting, which would terminate the regmap_read_poll_timeout()
with an error.

Instead implement a polling loop that ignores read errors so we
always poll until the chip signals boot or the loop times out.

Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 6b269a41
Loading
Loading
Loading
Loading
+20 −13
Original line number Diff line number Diff line
@@ -132,32 +132,39 @@ const char *madera_name_from_type(enum madera_type type)
}
EXPORT_SYMBOL_GPL(madera_name_from_type);

#define MADERA_BOOT_POLL_MAX_INTERVAL_US  5000
#define MADERA_BOOT_POLL_TIMEOUT_US	 25000
#define MADERA_BOOT_POLL_INTERVAL_USEC		5000
#define MADERA_BOOT_POLL_TIMEOUT_USEC		25000

static int madera_wait_for_boot(struct madera *madera)
{
	ktime_t timeout;
	unsigned int val;
	int ret;
	int ret = 0;

	/*
	 * We can't use an interrupt as we need to runtime resume to do so,
	 * so we poll the status bit. This won't race with the interrupt
	 * handler because it will be blocked on runtime resume.
	 * The chip could NAK a read request while it is booting so ignore
	 * errors from regmap_read.
	 */
	ret = regmap_read_poll_timeout(madera->regmap,
				       MADERA_IRQ1_RAW_STATUS_1,
				       val,
				       (val & MADERA_BOOT_DONE_STS1),
				       MADERA_BOOT_POLL_MAX_INTERVAL_US,
				       MADERA_BOOT_POLL_TIMEOUT_US);
	timeout = ktime_add_us(ktime_get(), MADERA_BOOT_POLL_TIMEOUT_USEC);
	regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
	while (!(val & MADERA_BOOT_DONE_STS1) &&
	       !ktime_after(ktime_get(), timeout)) {
		usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
			     MADERA_BOOT_POLL_INTERVAL_USEC);
		regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
	};

	if (ret)
		dev_err(madera->dev, "Polling BOOT_DONE_STS failed: %d\n", ret);
	if (!(val & MADERA_BOOT_DONE_STS1)) {
		dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
		ret = -ETIMEDOUT;
	}

	/*
	 * BOOT_DONE defaults to unmasked on boot so we must ack it.
	 * Do this unconditionally to avoid interrupt storms.
	 * Do this even after a timeout to avoid interrupt storms.
	 */
	regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
		     MADERA_BOOT_DONE_EINT1);