[PATCH v1 2/3] mmc: host: dw_mmc-rockchip: add rockchip,disable-runtime-pm quirk

Marco Schirrmeister mschirrmeister at gmail.com
Fri Jan 9 17:07:14 PST 2026


The FriendlyElec NanoPi R76S (based on the Rockchip RK3576) suffers from 
a persistent bus-reset loop on the microSD (dw_mmc) interface during 
idle periods. When the microSD controller enters runtime-suspend, the 
subsequent transition back to an active state causes the bus timing to 
become unstable. This forces the driver to drop the bus speed to 400kHz 
to perform a full retraining of the SDR104 link.

Investigations using the runtime_status interface confirm that 
preventing the controller from entering a low-power state stabilizes 
the link and eliminates the reset loop entirely.

This patch introduces a new 'rockchip,disable-runtime-pm' Boolean 
property to the dw_mmc-rockchip driver. The property is used to:

- Bypass the 50ms autosuspend delay during the probe sequence.
- Explicitly increment the device usage count via pm_runtime_get_noresume()
  to keep the controller active and prevent it from being suspended 
  during idle periods.

Signed-off-by: Marco Schirrmeister <mschirrmeister at gmail.com>
---
 drivers/mmc/host/dw_mmc-rockchip.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 62c68cda1e21..d3e5c06d80ef 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -538,6 +538,7 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
 {
 	const struct dw_mci_drv_data *drv_data;
 	const struct of_device_id *match;
+	bool disable_rpm = of_property_read_bool(pdev->dev.of_node, "rockchip,disable-runtime-pm");
 	int ret;
 
 	if (!pdev->dev.of_node)
@@ -549,8 +550,13 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
 	pm_runtime_get_noresume(&pdev->dev);
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
-	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
-	pm_runtime_use_autosuspend(&pdev->dev);
+
+	/* Only setup autosuspend if the DTS hasn't prohibited it */
+	if (!disable_rpm) {
+		pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+		pm_runtime_use_autosuspend(&pdev->dev);
+	}
+
 
 	ret = dw_mci_pltfm_register(pdev, drv_data);
 	if (ret) {
@@ -560,7 +566,20 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	pm_runtime_put_autosuspend(&pdev->dev);
+	/*
+	 * For boards with sensitive signaling like the RK3576-based NanoPi R76S,
+	 * we inhibit runtime PM to prevent bus resets during idle transitions.
+	 */
+	if (disable_rpm) {
+		/*
+		 * Instead of nuclear option (pm_runtime_forbid), we use
+		 * the "soft" way by incrementing the usage count to
+		 * prevent the controller from ever hitting runtime_suspend.
+		 */
+		pm_runtime_get_noresume(&pdev->dev);
+	} else {
+		pm_runtime_put_autosuspend(&pdev->dev);
+	}
 
 	return 0;
 }
-- 
2.52.0




More information about the linux-arm-kernel mailing list