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: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
This commit is contained in:
Richard Fitzgerald 2018-08-27 14:51:15 +01:00 committed by Lee Jones
parent 6b269a41a4
commit b04e68d166
1 changed files with 19 additions and 12 deletions

View File

@ -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);