Commit b2325370 authored by Tony Lindgren's avatar Tony Lindgren

soc: ti: omap-prm: Fix external abort for am335x pruss

Starting with v5.15-rc1, we may now see some am335x beaglebone black
device produce the following error on pruss probe:

Unhandled fault: external abort on non-linefetch (0x1008) at 0xe0326000

This has started with the enabling of pruss for am335x in the dts files.

Turns out the is caused by the PRM reset handling not waiting for the
reset bit to clear. To fix the issue, let's always wait for the reset
bit to clear, even if there is a separate reset status register.

We attempted to fix a similar issue for dra7 iva with a udelay() in
commit effe89e4 ("soc: ti: omap-prm: Fix occasional abort on reset
deassert for dra7 iva"). There is no longer a need for the udelay()
for dra7 iva reset either with the check added for reset bit clearing.

Cc: Drew Fustini <pdp7pdp7@gmail.com>
Cc: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: "H. Nikolaus Schaller" <hns@goldelico.com>
Cc: Robert Nelson <robertcnelson@gmail.com>
Cc: Yongqin Liu <yongqin.liu@linaro.org>
Fixes: effe89e4 ("soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva")
Reported-by: default avatarMatti Vaittinen <mazziesaccount@gmail.com>
Tested-by: default avatarMatti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 6880fa6c
...@@ -825,10 +825,17 @@ static int omap_reset_deassert(struct reset_controller_dev *rcdev, ...@@ -825,10 +825,17 @@ static int omap_reset_deassert(struct reset_controller_dev *rcdev,
writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
spin_unlock_irqrestore(&reset->lock, flags); spin_unlock_irqrestore(&reset->lock, flags);
if (!has_rstst) /* wait for the reset bit to clear */
goto exit; ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
reset->prm->data->rstctrl,
v, !(v & BIT(id)), 1,
OMAP_RESET_MAX_WAIT);
if (ret)
pr_err("%s: timedout waiting for %s:%lu\n", __func__,
reset->prm->data->name, id);
/* wait for the status to be set */ /* wait for the status to be set */
if (has_rstst) {
ret = readl_relaxed_poll_timeout_atomic(reset->prm->base + ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
reset->prm->data->rstst, reset->prm->data->rstst,
v, v & BIT(st_bit), 1, v, v & BIT(st_bit), 1,
...@@ -836,14 +843,10 @@ static int omap_reset_deassert(struct reset_controller_dev *rcdev, ...@@ -836,14 +843,10 @@ static int omap_reset_deassert(struct reset_controller_dev *rcdev,
if (ret) if (ret)
pr_err("%s: timedout waiting for %s:%lu\n", __func__, pr_err("%s: timedout waiting for %s:%lu\n", __func__,
reset->prm->data->name, id); reset->prm->data->name, id);
}
exit: if (reset->clkdm)
if (reset->clkdm) {
/* At least dra7 iva needs a delay before clkdm idle */
if (has_rstst)
udelay(1);
pdata->clkdm_allow_idle(reset->clkdm); pdata->clkdm_allow_idle(reset->clkdm);
}
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment