Skip to content

Commit 9925aa4

Browse files
tlebgregkh
authored andcommitted
usb: cdns3-ti: run HW init at resume() if HW was reset
At runtime_resume(), read the W1 (Wrapper Register 1) register to detect if an hardware reset occurred. If it did, run the hardware init sequence. This callback will be called at system-wide resume. Previously, if a reset occurred during suspend, we would crash. The wrapper config had not been written, leading to invalid register accesses inside cdns3. Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com> Link: https://lore.kernel.org/r/20250205-s2r-cdns-v7-6-13658a271c3c@bootlin.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 24346dc commit 9925aa4

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

drivers/usb/cdns3/cdns3-ti.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ static int cdns_ti_probe(struct platform_device *pdev)
186186
data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
187187
data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
188188

189+
/*
190+
* The call below to pm_runtime_get_sync() MIGHT reset hardware, if it
191+
* detects it as uninitialised. We want to enforce a reset at probe,
192+
* and so do it manually here. This means the first runtime_resume()
193+
* will be a no-op.
194+
*/
189195
cdns_ti_reset_and_init_hw(data);
190196

191197
pm_runtime_enable(dev);
@@ -230,6 +236,24 @@ static void cdns_ti_remove(struct platform_device *pdev)
230236
platform_set_drvdata(pdev, NULL);
231237
}
232238

239+
static int cdns_ti_runtime_resume(struct device *dev)
240+
{
241+
const u32 mask = USBSS_W1_PWRUP_RST | USBSS_W1_MODESTRAP_SEL;
242+
struct cdns_ti *data = dev_get_drvdata(dev);
243+
u32 w1;
244+
245+
w1 = cdns_ti_readl(data, USBSS_W1);
246+
if ((w1 & mask) != mask)
247+
cdns_ti_reset_and_init_hw(data);
248+
249+
return 0;
250+
}
251+
252+
static const struct dev_pm_ops cdns_ti_pm_ops = {
253+
RUNTIME_PM_OPS(NULL, cdns_ti_runtime_resume, NULL)
254+
SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
255+
};
256+
233257
static const struct of_device_id cdns_ti_of_match[] = {
234258
{ .compatible = "ti,j721e-usb", },
235259
{ .compatible = "ti,am64-usb", },
@@ -243,6 +267,7 @@ static struct platform_driver cdns_ti_driver = {
243267
.driver = {
244268
.name = "cdns3-ti",
245269
.of_match_table = cdns_ti_of_match,
270+
.pm = pm_ptr(&cdns_ti_pm_ops),
246271
},
247272
};
248273

0 commit comments

Comments
 (0)