Skip to content

Commit 0c331fd

Browse files
stephan-ghbroonie
authored andcommitted
spi: qup: Request DMA before enabling clocks
It is usually better to request all necessary resources (clocks, regulators, ...) before starting to make use of them. That way they do not change state in case one of the resources is not available yet and probe deferral (-EPROBE_DEFER) is necessary. This is particularly important for DMA channels and IOMMUs which are not enforced by fw_devlink yet (unless you use fw_devlink.strict=1). spi-qup does this in the wrong order, the clocks are enabled and disabled again when the DMA channels are not available yet. This causes issues in some cases: On most SoCs one of the SPI QUP clocks is shared with the UART controller. When using earlycon UART is actively used during boot but might not have probed yet, usually for the same reason (waiting for the DMA controller). In this case, the brief enable/disable cycle ends up gating the clock and further UART console output will halt the system completely. Avoid this by requesting the DMA channels before changing the clock state. Fixes: 612762e ("spi: qup: Add DMA capabilities") Signed-off-by: Stephan Gerhold <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 4be47a5 commit 0c331fd

File tree

1 file changed

+18
-19
lines changed

1 file changed

+18
-19
lines changed

drivers/spi/spi-qup.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,23 +1028,8 @@ static int spi_qup_probe(struct platform_device *pdev)
10281028
return -ENXIO;
10291029
}
10301030

1031-
ret = clk_prepare_enable(cclk);
1032-
if (ret) {
1033-
dev_err(dev, "cannot enable core clock\n");
1034-
return ret;
1035-
}
1036-
1037-
ret = clk_prepare_enable(iclk);
1038-
if (ret) {
1039-
clk_disable_unprepare(cclk);
1040-
dev_err(dev, "cannot enable iface clock\n");
1041-
return ret;
1042-
}
1043-
10441031
master = spi_alloc_master(dev, sizeof(struct spi_qup));
10451032
if (!master) {
1046-
clk_disable_unprepare(cclk);
1047-
clk_disable_unprepare(iclk);
10481033
dev_err(dev, "cannot allocate master\n");
10491034
return -ENOMEM;
10501035
}
@@ -1092,6 +1077,19 @@ static int spi_qup_probe(struct platform_device *pdev)
10921077
spin_lock_init(&controller->lock);
10931078
init_completion(&controller->done);
10941079

1080+
ret = clk_prepare_enable(cclk);
1081+
if (ret) {
1082+
dev_err(dev, "cannot enable core clock\n");
1083+
goto error_dma;
1084+
}
1085+
1086+
ret = clk_prepare_enable(iclk);
1087+
if (ret) {
1088+
clk_disable_unprepare(cclk);
1089+
dev_err(dev, "cannot enable iface clock\n");
1090+
goto error_dma;
1091+
}
1092+
10951093
iomode = readl_relaxed(base + QUP_IO_M_MODES);
10961094

10971095
size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode);
@@ -1121,7 +1119,7 @@ static int spi_qup_probe(struct platform_device *pdev)
11211119
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
11221120
if (ret) {
11231121
dev_err(dev, "cannot set RESET state\n");
1124-
goto error_dma;
1122+
goto error_clk;
11251123
}
11261124

11271125
writel_relaxed(0, base + QUP_OPERATIONAL);
@@ -1145,7 +1143,7 @@ static int spi_qup_probe(struct platform_device *pdev)
11451143
ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
11461144
IRQF_TRIGGER_HIGH, pdev->name, controller);
11471145
if (ret)
1148-
goto error_dma;
1146+
goto error_clk;
11491147

11501148
pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
11511149
pm_runtime_use_autosuspend(dev);
@@ -1160,11 +1158,12 @@ static int spi_qup_probe(struct platform_device *pdev)
11601158

11611159
disable_pm:
11621160
pm_runtime_disable(&pdev->dev);
1161+
error_clk:
1162+
clk_disable_unprepare(cclk);
1163+
clk_disable_unprepare(iclk);
11631164
error_dma:
11641165
spi_qup_release_dma(master);
11651166
error:
1166-
clk_disable_unprepare(cclk);
1167-
clk_disable_unprepare(iclk);
11681167
spi_master_put(master);
11691168
return ret;
11701169
}

0 commit comments

Comments
 (0)