Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: dwc3: Fix core validation in probe, move after clocks are enabled

The required clocks needs to be enabled before the first register
access. After commit fe8abf332b8f ("usb: dwc3: support clocks and resets
for DWC3 core"), this happens when the dwc3_core_is_valid function is
called, but the mentioned commit adds that call in the wrong place,
before the clocks are enabled. So, move that call after the
clk_bulk_enable() to ensure the clocks are enabled and the reset
deasserted.

I detected this while, as experiment, I tried to move the clocks and resets
from the glue layer to the DWC3 core on a Samsung Chromebook Plus.

That was not detected before because, in most cases, the glue layer
initializes SoC-specific things and then populates the child "snps,dwc3"
with those clocks already enabled.

Fixes: b873e2d0ea1ef ("usb: dwc3: Do core validation early on probe")
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>

authored by

Enric Balletbo i Serra and committed by
Felipe Balbi
dc1b5d9a 7f5d6a46

+7 -5
+7 -5
drivers/usb/dwc3/core.c
··· 1423 1423 dwc->regs = regs; 1424 1424 dwc->regs_size = resource_size(&dwc_res); 1425 1425 1426 - if (!dwc3_core_is_valid(dwc)) { 1427 - dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 1428 - return -ENODEV; 1429 - } 1430 - 1431 1426 dwc3_get_properties(dwc); 1432 1427 1433 1428 dwc->reset = devm_reset_control_get_optional_shared(dev, NULL); ··· 1454 1459 ret = clk_bulk_enable(dwc->num_clks, dwc->clks); 1455 1460 if (ret) 1456 1461 goto unprepare_clks; 1462 + 1463 + if (!dwc3_core_is_valid(dwc)) { 1464 + dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 1465 + ret = -ENODEV; 1466 + goto disable_clks; 1467 + } 1457 1468 1458 1469 platform_set_drvdata(pdev, dwc); 1459 1470 dwc3_cache_hwparams(dwc); ··· 1526 1525 pm_runtime_put_sync(&pdev->dev); 1527 1526 pm_runtime_disable(&pdev->dev); 1528 1527 1528 + disable_clks: 1529 1529 clk_bulk_disable(dwc->num_clks, dwc->clks); 1530 1530 unprepare_clks: 1531 1531 clk_bulk_unprepare(dwc->num_clks, dwc->clks);