Re: kexec on rk3399
From: Felipe Balbi <balbi@kernel.org>
Date: 2019-08-15 06:06:08
Also in:
linux-rockchip, linux-usb, lkml
Subsystem:
designware usb3 drd ip driver, the rest, usb subsystem · Maintainers:
Thinh Nguyen, Linus Torvalds, Greg Kroah-Hartman
Hi, Vicente Bergas [off-list ref] writes:
On Wednesday, August 14, 2019 3:12:26 PM CEST, Robin Murphy wrote:quoted
On 14/08/2019 13:53, Vicente Bergas wrote:quoted
On Monday, July 22, 2019 4:31:27 PM CEST, Vicente Bergas wrote: ...This particular change looks like it's implicitly specific to RK3399, which wouldn't be ideal. Presumably if the core dwc3 driver implemented shutdown correctly (echoing parts of dwc3_remove(), I guess) then the glue layers shouldn't need anything special anyway. Robin.I just checked simple->resets from dwc3-of-simple.c and it is an array with multiple resets whereas dwc->reset from core.c is NULL. So the reset seems specific to the glue layers. Is there another way than resetting the thing that is generic enough to go to core.c and allows kexec?
This is a really odd 'failure'. We do full soft reset during driver
initialization on dwc3. We shouldn't need to assert reset on shutdown,
really.
I think the problem is here:
if (simple->pulse_resets) {
ret = reset_control_reset(simple->resets);
if (ret)
goto err_resetc_put;
} else {
ret = reset_control_deassert(simple->resets);
if (ret)
goto err_resetc_put;
}
Note that if pulse_resets is set, we will run a reset. But if
pulse_resets is false and need_reset is true, we deassert the reset.
I think below patch is enough:
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index bdac3e7d7b18..9a2f3e09aa2e 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c@@ -72,7 +72,15 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) ret = reset_control_reset(simple->resets); if (ret) goto err_resetc_put; - } else { + } + + if (simple->need_reset) { + ret = reset_control_assert(simple->resets); + if (ret) + goto err_resetc_put; + + usleep_range(1000, 2000); + ret = reset_control_deassert(simple->resets); if (ret) goto err_resetc_put;
@@ -121,9 +129,6 @@ static int dwc3_of_simple_remove(struct platform_device *pdev) clk_bulk_put_all(simple->num_clocks, simple->clks); simple->num_clocks = 0; - if (!simple->pulse_resets) - reset_control_assert(simple->resets); - reset_control_put(simple->resets); pm_runtime_disable(dev);
Can you test? -- balbi _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel