[PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S

Shawn Lin shawn.lin at rock-chips.com
Wed Jan 14 00:08:43 PST 2026


在 2026/01/12 星期一 11:56, Shawn Lin 写道:
> 在 2026/01/12 星期一 9:32, Shawn Lin 写道:
>> 在 2026/01/10 星期六 9:07, Marco Schirrmeister 写道:
>>> This series addresses a microSD stability issue on the FriendlyElec
>>> NanoPi R76S (RK3576). The board currently suffers from a 400kHz
>>> retuning loop when the controller attempts to enter runtime-suspend
>>> during idle periods.
>>>
>>> Evidence of the failure in dmesg:
>>> [Fri Jan  2 01:28:02 2026] mmc_host mmc1: Bus speed (slot 0) = 400000Hz
>>> [Fri Jan  2 01:28:03 2026] mmc_host mmc1: Bus speed (slot 0) = 
>>> 198000000Hz
>>> [Fri Jan  2 01:28:03 2026] dwmmc_rockchip 2a310000.mmc: Successfully 
>>> tuned phase to 233
>>> [Fri Jan  2 01:28:04 2026] mmc_host mmc1: Bus speed (slot 0) = 400000Hz
>>>
>>
>> Does this problem happen with all microSDs or just *a* microSD per
>> your description?
>> Have you ever tried to disable SDR104 support?
>>
> 
> A quick update.
> 
> I found several problems on RK3576 for supporting sd cards. I wondered
> how all upstream RK3576 boards claiming SD support work? Anyway, I sent
> a series to the list[1], not sure if it fixes the problem you faced, but
> these should be the right patches you should have a try.
> 
> 
> [1]https://lore.kernel.org/linux-rockchip/1768189768-96333-1-git-send- 
> email-shawn.lin at rock-chips.com/T/#t


Except for the patch mentioned above for fixing the hot-plug problem
which you confirmed to work fine. I looked the code a bit and see
a potential problem related to the runtime suspend + power-domain.
Please check the patch to see if it fixes your problem:

--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -36,6 +36,8 @@ struct dw_mci_rockchip_priv_data {
         int                     default_sample_phase;
         int                     num_phases;
         bool                    internal_phase;
+       int                     sample_phase;
+       int                     drv_phase;
  };

  /*
@@ -573,9 +575,43 @@ static void dw_mci_rockchip_remove(struct 
platform_device *pdev)
         dw_mci_pltfm_remove(pdev);
  }

+static int dw_mci_rockchip_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct dw_mci *host = platform_get_drvdata(pdev);
+       struct dw_mci_rockchip_priv_data *priv = host->priv;
+
+       if (priv->internal_phase) {
+               priv->sample_phase = rockchip_mmc_get_phase(host, true);
+               priv->drv_phase = rockchip_mmc_get_phase(host, false);
+       }
+
+       return dw_mci_runtime_suspend(dev);
+}
+
+static int dw_mci_rockchip_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct dw_mci *host = platform_get_drvdata(pdev);
+       struct dw_mci_rockchip_priv_data *priv = host->priv;
+       int ret;
+
+       ret = dw_mci_runtime_resume(dev);
+       if (ret)
+               return ret;
+
+       if (priv->internal_phase) {
+               rockchip_mmc_set_phase(host, true, priv->sample_phase);
+               rockchip_mmc_set_phase(host, false, priv->drv_phase);
+               mci_writel(host, MISC_CON, MEM_CLK_AUTOGATE_ENABLE);
+       }
+
+       return ret;
+}
+
  static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
         SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 
pm_runtime_force_resume)
-       RUNTIME_PM_OPS(dw_mci_runtime_suspend, dw_mci_runtime_resume, NULL)
+       RUNTIME_PM_OPS(dw_mci_rockchip_runtime_suspend, 
dw_mci_rockchip_runtime_resume, NULL)
  };

  static struct platform_driver dw_mci_rockchip_pltfm_driver = {




> 
>>> Testing confirmed that the issue can be manually addressed by
>>> disabling runtime PM via sysfs:
>>> echo on > /sys/devices/platform/soc/2a310000.mmc/power/control
>>>
>>> I experimented with various changes in the Device Tree, including
>>> lowering the bus frequency and attempting to keep the power domains
>>> active, but nothing stopped the retuning loop.
>>> The issue only went away when I forced the controller to stay active
>>> by disabling the runtime power management.
>>>
>>> This quirk is the only way I have found to keep the SDR104 link from
>>> crashing on the NanoPi R76S, I am open to suggestions if there is
>>> a better way to handle this in the driver or the DTS.
>>>
>>> Marco Schirrmeister (3):
>>>    dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm
>>>    mmc: host: dw_mmc-rockchip: add rockchip,disable-runtime-pm quirk
>>>    arm64: dts: rockchip: add stability quirk to NanoPi R76S
>>>
>>>   .../bindings/mmc/rockchip-dw-mshc.yaml        |  8 ++++++
>>>   .../boot/dts/rockchip/rk3576-nanopi-r76s.dts  |  1 +
>>>   drivers/mmc/host/dw_mmc-rockchip.c            | 25 ++++++++++++++++---
>>>   3 files changed, 31 insertions(+), 3 deletions(-)
>>>
>>
>>
> 
> 




More information about the linux-arm-kernel mailing list