* [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S
@ 2026-01-10 1:07 Marco Schirrmeister
2026-01-10 1:07 ` [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm Marco Schirrmeister
` (3 more replies)
0 siblings, 4 replies; 21+ messages in thread
From: Marco Schirrmeister @ 2026-01-10 1:07 UTC (permalink / raw)
To: heiko, ulf.hansson
Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree,
linux-arm-kernel, 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
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(-)
--
2.52.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm 2026-01-10 1:07 [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S Marco Schirrmeister @ 2026-01-10 1:07 ` Marco Schirrmeister 2026-01-10 2:25 ` Rob Herring (Arm) 2026-01-11 9:41 ` Krzysztof Kozlowski 2026-01-10 1:07 ` [PATCH v1 2/3] mmc: host: dw_mmc-rockchip: add rockchip,disable-runtime-pm quirk Marco Schirrmeister ` (2 subsequent siblings) 3 siblings, 2 replies; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-10 1:07 UTC (permalink / raw) To: heiko, ulf.hansson Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, Marco Schirrmeister Add a new 'rockchip,disable-runtime-pm' property to allow boards to inhibit runtime power management. This is required for boards like the NanoPi R76S where the bus timing becomes unstable if the controller is runtime-suspended during idle periods. Signed-off-by: Marco Schirrmeister <mschirrmeister@gmail.com> --- .../devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index acb9fb9a92cd..41f2644ca2ef 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -100,6 +100,14 @@ properties: If not specified, the host will do tuning for 360 times, namely tuning for each degree. + rockchip,disable-runtime-pm: + type: boolean + description: + Inhibit runtime power management. This is required for boards + where the bus timing becomes unstable if the controller is + runtime-suspended. + + required: - compatible - reg -- 2.52.0 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm 2026-01-10 1:07 ` [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm Marco Schirrmeister @ 2026-01-10 2:25 ` Rob Herring (Arm) 2026-01-11 9:41 ` Krzysztof Kozlowski 1 sibling, 0 replies; 21+ messages in thread From: Rob Herring (Arm) @ 2026-01-10 2:25 UTC (permalink / raw) To: Marco Schirrmeister Cc: linux-mmc, conor+dt, krzk+dt, linux-arm-kernel, ulf.hansson, linux-rockchip, heiko, devicetree On Sat, 10 Jan 2026 02:07:13 +0100, Marco Schirrmeister wrote: > Add a new 'rockchip,disable-runtime-pm' property to allow boards to > inhibit runtime power management. This is required for boards like the > NanoPi R76S where the bus timing becomes unstable if the controller > is runtime-suspended during idle periods. > > Signed-off-by: Marco Schirrmeister <mschirrmeister@gmail.com> > --- > .../devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 8 ++++++++ > 1 file changed, 8 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: ./Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml:110:1: [warning] too many blank lines (2 > 1) (empty-lines) dtschema/dtc warnings/errors: doc reference errors (make refcheckdocs): See https://patchwork.kernel.org/project/devicetree/patch/20260110010715.1610159-2-mschirrmeister@gmail.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm 2026-01-10 1:07 ` [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm Marco Schirrmeister 2026-01-10 2:25 ` Rob Herring (Arm) @ 2026-01-11 9:41 ` Krzysztof Kozlowski 2026-01-11 23:51 ` Marco Schirrmeister 1 sibling, 1 reply; 21+ messages in thread From: Krzysztof Kozlowski @ 2026-01-11 9:41 UTC (permalink / raw) To: Marco Schirrmeister Cc: heiko, ulf.hansson, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel On Sat, Jan 10, 2026 at 02:07:13AM +0100, Marco Schirrmeister wrote: > Add a new 'rockchip,disable-runtime-pm' property to allow boards to > inhibit runtime power management. This is required for boards like the > NanoPi R76S where the bus timing becomes unstable if the controller > is runtime-suspended during idle periods. > > Signed-off-by: Marco Schirrmeister <mschirrmeister@gmail.com> > --- > .../devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml > index acb9fb9a92cd..41f2644ca2ef 100644 > --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml > +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml > @@ -100,6 +100,14 @@ properties: > If not specified, the host will do tuning for 360 times, > namely tuning for each degree. > > + rockchip,disable-runtime-pm: > + type: boolean > + description: > + Inhibit runtime power management. This is required for boards What is runtime power management? Like Linux PM? If anything phrased like that is it is a clear no go. Bindings describe hardware. > + where the bus timing becomes unstable if the controller is > + runtime-suspended. You described the desired Linux feature or behavior, not the actual hardware. The bindings are about the latter, so instead you need to rephrase the property and its description to match actual hardware capabilities/features/configuration etc. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm 2026-01-11 9:41 ` Krzysztof Kozlowski @ 2026-01-11 23:51 ` Marco Schirrmeister 2026-01-16 9:43 ` Heiko Stübner 0 siblings, 1 reply; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-11 23:51 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: heiko, ulf.hansson, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel Hi Krzysztof, Thank you for the feedback. On Sun, Jan 11, 2026 at 10:41 AM Krzysztof Kozlowski <krzk@kernel.org> wrote: > > + rockchip,disable-runtime-pm: > > + type: boolean > > + description: > > + Inhibit runtime power management. This is required for boards > > What is runtime power management? Like Linux PM? If anything phrased > like that is it is a clear no go. Bindings describe hardware. You are right. This refers to the Linux PM subsystem and describes software behavior. > > + where the bus timing becomes unstable if the controller is > > + runtime-suspended. > > You described the desired Linux feature or behavior, not the actual > hardware. The bindings are about the latter, so instead you need to > rephrase the property and its description to match actual hardware > capabilities/features/configuration etc. On this board, the bus timing becomes unstable when waking up from a low-power state. This causes a constant retraining loop. I will move this logic into the driver and handle it as a board specific quirk using of_machine_is_compatible("friendlyarm,nanopi-r76s") instead. I will send a v2. Best regards, Marco ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm 2026-01-11 23:51 ` Marco Schirrmeister @ 2026-01-16 9:43 ` Heiko Stübner 2026-01-16 10:20 ` Krzysztof Kozlowski 0 siblings, 1 reply; 21+ messages in thread From: Heiko Stübner @ 2026-01-16 9:43 UTC (permalink / raw) To: Krzysztof Kozlowski, Marco Schirrmeister Cc: ulf.hansson, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel Hi Marco, Am Montag, 12. Januar 2026, 00:51:24 Mitteleuropäische Normalzeit schrieb Marco Schirrmeister: > On Sun, Jan 11, 2026 at 10:41 AM Krzysztof Kozlowski <krzk@kernel.org> wrote: > > > + rockchip,disable-runtime-pm: > > > + type: boolean > > > + description: > > > + Inhibit runtime power management. This is required for boards > > > > What is runtime power management? Like Linux PM? If anything phrased > > like that is it is a clear no go. Bindings describe hardware. > > You are right. This refers to the Linux PM subsystem and describes > software behavior. > > > > + where the bus timing becomes unstable if the controller is > > > + runtime-suspended. > > > > You described the desired Linux feature or behavior, not the actual > > hardware. The bindings are about the latter, so instead you need to > > rephrase the property and its description to match actual hardware > > capabilities/features/configuration etc. > > On this board, the bus timing becomes unstable when waking up from > a low-power state. This causes a constant retraining loop. As you describe it here, it does sound like a real hardware quirk (which would be a dt-thing) ... it's just that the previous wording describes it in a non-hardware way - as Krzysztof pointed out in his reply. > I will move this logic into the driver and handle it as a board specific > quirk using of_machine_is_compatible("friendlyarm,nanopi-r76s") > instead. I will send a v2. This won't fly I think. We can't really have a (possibly long) list of If (boardA) foo(); if (boardB) bar(); if (boardC) bas(); That really is not sustainable and most likely won't get accepted. Heiko ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm 2026-01-16 9:43 ` Heiko Stübner @ 2026-01-16 10:20 ` Krzysztof Kozlowski 0 siblings, 0 replies; 21+ messages in thread From: Krzysztof Kozlowski @ 2026-01-16 10:20 UTC (permalink / raw) To: Heiko Stübner, Marco Schirrmeister Cc: ulf.hansson, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel On 16/01/2026 10:43, Heiko Stübner wrote: > Hi Marco, > > Am Montag, 12. Januar 2026, 00:51:24 Mitteleuropäische Normalzeit schrieb Marco Schirrmeister: >> On Sun, Jan 11, 2026 at 10:41 AM Krzysztof Kozlowski <krzk@kernel.org> wrote: >>>> + rockchip,disable-runtime-pm: >>>> + type: boolean >>>> + description: >>>> + Inhibit runtime power management. This is required for boards >>> >>> What is runtime power management? Like Linux PM? If anything phrased >>> like that is it is a clear no go. Bindings describe hardware. >> >> You are right. This refers to the Linux PM subsystem and describes >> software behavior. >> >>>> + where the bus timing becomes unstable if the controller is >>>> + runtime-suspended. >>> >>> You described the desired Linux feature or behavior, not the actual >>> hardware. The bindings are about the latter, so instead you need to >>> rephrase the property and its description to match actual hardware >>> capabilities/features/configuration etc. >> >> On this board, the bus timing becomes unstable when waking up from >> a low-power state. This causes a constant retraining loop. > > As you describe it here, it does sound like a real hardware quirk (which > would be a dt-thing) ... it's just that the previous wording describes it > in a non-hardware way - as Krzysztof pointed out in his reply. I can also imagine that you miss some register programming, clocks or regulator voltage, so "unstable" has to be actually analyzed. You should not really disable a Linux driver feature just because your hardware has issues. And even then it's more likely some MMC core part, not entire runtime PM, is problematic here. > > >> I will move this logic into the driver and handle it as a board specific >> quirk using of_machine_is_compatible("friendlyarm,nanopi-r76s") >> instead. I will send a v2. > > This won't fly I think. We can't really have a (possibly long) list of > > If (boardA) foo(); > if (boardB) bar(); > if (boardC) bas(); > > That really is not sustainable and most likely won't get accepted. Yep Best regards, Krzysztof ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v1 2/3] mmc: host: dw_mmc-rockchip: add rockchip,disable-runtime-pm quirk 2026-01-10 1:07 [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S Marco Schirrmeister 2026-01-10 1:07 ` [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm Marco Schirrmeister @ 2026-01-10 1:07 ` Marco Schirrmeister 2026-01-10 1:07 ` [PATCH v1 3/3] arm64: dts: rockchip: add stability quirk to NanoPi R76S Marco Schirrmeister 2026-01-12 1:32 ` [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for " Shawn Lin 3 siblings, 0 replies; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-10 1:07 UTC (permalink / raw) To: heiko, ulf.hansson Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, Marco Schirrmeister 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@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 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v1 3/3] arm64: dts: rockchip: add stability quirk to NanoPi R76S 2026-01-10 1:07 [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S Marco Schirrmeister 2026-01-10 1:07 ` [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm Marco Schirrmeister 2026-01-10 1:07 ` [PATCH v1 2/3] mmc: host: dw_mmc-rockchip: add rockchip,disable-runtime-pm quirk Marco Schirrmeister @ 2026-01-10 1:07 ` Marco Schirrmeister 2026-01-11 9:42 ` Krzysztof Kozlowski 2026-01-12 1:32 ` [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for " Shawn Lin 3 siblings, 1 reply; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-10 1:07 UTC (permalink / raw) To: heiko, ulf.hansson Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, Marco Schirrmeister Enable the 'rockchip,disable-runtime-pm' quirk for the SDMMC node on the NanoPi R76S to prevent bus instability and retraining loops during idle periods. Signed-off-by: Marco Schirrmeister <mschirrmeister@gmail.com> --- arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts index 31fbefaeceab..90a798ee9e68 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts @@ -754,6 +754,7 @@ &sdmmc { disable-wp; no-mmc; no-sdio; + rockchip,disable-runtime-pm; sd-uhs-sdr104; vmmc-supply = <&vcc_3v3_s3>; vqmmc-supply = <&vccio_sd_s0>; -- 2.52.0 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v1 3/3] arm64: dts: rockchip: add stability quirk to NanoPi R76S 2026-01-10 1:07 ` [PATCH v1 3/3] arm64: dts: rockchip: add stability quirk to NanoPi R76S Marco Schirrmeister @ 2026-01-11 9:42 ` Krzysztof Kozlowski 0 siblings, 0 replies; 21+ messages in thread From: Krzysztof Kozlowski @ 2026-01-11 9:42 UTC (permalink / raw) To: Marco Schirrmeister Cc: heiko, ulf.hansson, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel On Sat, Jan 10, 2026 at 02:07:15AM +0100, Marco Schirrmeister wrote: > Enable the 'rockchip,disable-runtime-pm' quirk for the SDMMC node on the > NanoPi R76S to prevent bus instability and retraining loops during > idle periods. You miss some other properties or fixing driver and solution is not adding such properties in DTS. Nothing like that belongs to DTS. > > Signed-off-by: Marco Schirrmeister <mschirrmeister@gmail.com> > --- > arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts > index 31fbefaeceab..90a798ee9e68 100644 > --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts > +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts > @@ -754,6 +754,7 @@ &sdmmc { > disable-wp; > no-mmc; > no-sdio; > + rockchip,disable-runtime-pm; Best regards, Krzysztof ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-10 1:07 [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S Marco Schirrmeister ` (2 preceding siblings ...) 2026-01-10 1:07 ` [PATCH v1 3/3] arm64: dts: rockchip: add stability quirk to NanoPi R76S Marco Schirrmeister @ 2026-01-12 1:32 ` Shawn Lin 2026-01-12 3:56 ` Shawn Lin 2026-01-12 19:04 ` Marco Schirrmeister 3 siblings, 2 replies; 21+ messages in thread From: Shawn Lin @ 2026-01-12 1:32 UTC (permalink / raw) To: Marco Schirrmeister Cc: shawn.lin, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson 在 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? > 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(-) > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-12 1:32 ` [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for " Shawn Lin @ 2026-01-12 3:56 ` Shawn Lin 2026-01-12 8:29 ` Chaoyi Chen 2026-01-14 8:08 ` Shawn Lin 2026-01-12 19:04 ` Marco Schirrmeister 1 sibling, 2 replies; 21+ messages in thread From: Shawn Lin @ 2026-01-12 3:56 UTC (permalink / raw) To: Marco Schirrmeister Cc: shawn.lin, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson 在 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@rock-chips.com/T/#t >> 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(-) >> > > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-12 3:56 ` Shawn Lin @ 2026-01-12 8:29 ` Chaoyi Chen 2026-01-12 8:58 ` Shawn Lin 2026-01-14 8:08 ` Shawn Lin 1 sibling, 1 reply; 21+ messages in thread From: Chaoyi Chen @ 2026-01-12 8:29 UTC (permalink / raw) To: Shawn Lin, Marco Schirrmeister Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson Hi Shawn, On 1/12/2026 11:56 AM, Shawn Lin wrote: > 在 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@rock-chips.com/T/#t > I encountered a similar issue on the RK3576 EVB2. It seems that the cd-gpios feature are broken, so SD card events cannot be detected. However, if the SD card is inserted before Linux boots, it can at least start up. I suspect that other boards may behave the same way :) -- Best, Chaoyi ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-12 8:29 ` Chaoyi Chen @ 2026-01-12 8:58 ` Shawn Lin 2026-01-12 19:09 ` Marco Schirrmeister 0 siblings, 1 reply; 21+ messages in thread From: Shawn Lin @ 2026-01-12 8:58 UTC (permalink / raw) To: Chaoyi Chen Cc: shawn.lin, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson, Marco Schirrmeister 在 2026/01/12 星期一 16:29, Chaoyi Chen 写道: > Hi Shawn, > > On 1/12/2026 11:56 AM, Shawn Lin wrote: >> 在 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@rock-chips.com/T/#t >> > > I encountered a similar issue on the RK3576 EVB2. > > It seems that the cd-gpios feature are broken, so SD card events Yes, cd-gpios method for RK3576 is broken now, so you need to apply my first 2 fix patches. > cannot be detected. However, if the SD card is inserted before Linux > boots, it can at least start up. I suspect that other boards may behave > the same way :) This is true, because .get_cd() returns card present when booting for the first time, you the only way for upstream RK3576 boards to use sd cards is to insert the card before booting. But then hot-plug case will not able to work. > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-12 8:58 ` Shawn Lin @ 2026-01-12 19:09 ` Marco Schirrmeister 0 siblings, 0 replies; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-12 19:09 UTC (permalink / raw) To: Shawn Lin Cc: Chaoyi Chen, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson On Mon, Jan 12, 2026 at 9:58 AM Shawn Lin <shawn.lin@rock-chips.com> wrote: > >> 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@rock-chips.com/T/#t I will give it a try on the NanoPi R76S. Have also ordered a Rock 4D. But it will take a while before it arrives. > > cannot be detected. However, if the SD card is inserted before Linux > > boots, it can at least start up. I suspect that other boards may behave > > the same way :) > > This is true, because .get_cd() returns card present when booting for > the first time, you the only way for upstream RK3576 boards to use sd > cards is to insert the card before booting. But then hot-plug case will > not able to work. I can confirm the same. sd card only works, when inserted before boot. No hotplug. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-12 3:56 ` Shawn Lin 2026-01-12 8:29 ` Chaoyi Chen @ 2026-01-14 8:08 ` Shawn Lin 2026-01-14 19:51 ` Marco Schirrmeister 1 sibling, 1 reply; 21+ messages in thread From: Shawn Lin @ 2026-01-14 8:08 UTC (permalink / raw) To: Marco Schirrmeister Cc: shawn.lin, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson 在 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@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(-) >>> >> >> > > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-14 8:08 ` Shawn Lin @ 2026-01-14 19:51 ` Marco Schirrmeister 2026-01-15 0:25 ` Shawn Lin 0 siblings, 1 reply; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-14 19:51 UTC (permalink / raw) To: Shawn Lin Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson Hello Shawn, On Wed, Jan 14, 2026 at 9:08 AM Shawn Lin <shawn.lin@rock-chips.com> wrote: > > 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: I tested your patch and the issue is still present. For verification I did add some debug statements and just to see what it saves and restores. The symbols are there. root@nanopi-r76s ~# grep dw_mci_rockchip_runtime /proc/kallsyms ffff800080bf27a0 t dw_mci_rockchip_runtime_suspend ffff800080bf29c0 t dw_mci_rockchip_runtime_resume # dmesg output [Wed Jan 14 20:13:46 2026] E220d: Restoring phases: sample=231, drv=180 [Wed Jan 14 20:13:46 2026] mmc_host mmc1: Bus speed (slot 0) = 400000Hz [Wed Jan 14 20:13:47 2026] mmc_host mmc1: Bus speed (slot 0) = 198000000Hz [Wed Jan 14 20:13:47 2026] dwmmc_rockchip 2a310000.mmc: Successfully tuned phase to 232 [Wed Jan 14 20:13:48 2026] E220d: Saving phases: sample=231, drv=180 [Wed Jan 14 20:13:48 2026] E220d: Restoring phases: sample=231, drv=180 [Wed Jan 14 20:13:48 2026] mmc_host mmc1: Bus speed (slot 0) = 400000Hz [Wed Jan 14 20:13:48 2026] mmc_host mmc1: Bus speed (slot 0) = 198000000Hz [Wed Jan 14 20:13:48 2026] dwmmc_rockchip 2a310000.mmc: Successfully tuned phase to 231 [Wed Jan 14 20:13:48 2026] E220d: Saving phases: sample=231, drv=180 Based on this, it makes me believe that power to the sd card is completely cut and when it wakes up and knows how to continue, it still must go through the retraining phase. > --- 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 = { ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-14 19:51 ` Marco Schirrmeister @ 2026-01-15 0:25 ` Shawn Lin 2026-01-15 19:39 ` Marco Schirrmeister 0 siblings, 1 reply; 21+ messages in thread From: Shawn Lin @ 2026-01-15 0:25 UTC (permalink / raw) To: Marco Schirrmeister Cc: shawn.lin, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson 在 2026/01/15 星期四 3:51, Marco Schirrmeister 写道: > Hello Shawn, > > On Wed, Jan 14, 2026 at 9:08 AM Shawn Lin <shawn.lin@rock-chips.com> wrote: >> >> 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: > > I tested your patch and the issue is still present. For verification I did > add some debug statements and just to see what it saves and restores. > > The symbols are there. > root@nanopi-r76s ~# grep dw_mci_rockchip_runtime /proc/kallsyms > ffff800080bf27a0 t dw_mci_rockchip_runtime_suspend > ffff800080bf29c0 t dw_mci_rockchip_runtime_resume > > # dmesg output > [Wed Jan 14 20:13:46 2026] E220d: Restoring phases: sample=231, drv=180 > [Wed Jan 14 20:13:46 2026] mmc_host mmc1: Bus speed (slot 0) = 400000Hz > [Wed Jan 14 20:13:47 2026] mmc_host mmc1: Bus speed (slot 0) = 198000000Hz > [Wed Jan 14 20:13:47 2026] dwmmc_rockchip 2a310000.mmc: Successfully > tuned phase to 232 > [Wed Jan 14 20:13:48 2026] E220d: Saving phases: sample=231, drv=180 > [Wed Jan 14 20:13:48 2026] E220d: Restoring phases: sample=231, drv=180 > [Wed Jan 14 20:13:48 2026] mmc_host mmc1: Bus speed (slot 0) = 400000Hz > [Wed Jan 14 20:13:48 2026] mmc_host mmc1: Bus speed (slot 0) = 198000000Hz > [Wed Jan 14 20:13:48 2026] dwmmc_rockchip 2a310000.mmc: Successfully > tuned phase to 231 > [Wed Jan 14 20:13:48 2026] E220d: Saving phases: sample=231, drv=180 > > Based on this, it makes me believe that power to the sd card is completely cut > and when it wakes up and knows how to continue, it still must go through the > retraining phase. > This is another mistake for your NanoPi R76S board. Before sent this patch, I already checked the dts and saw sdmmc uses vmmc-supply = <&vcc_3v3_s3> which is marked as regulator-always-on, but it's *NOT* actually per the shcematic[1][2]. So need another fix for your board to make it actually gpio-based power controller instaed of function IO based, as when powering off the power domain, the power control bit will not be able to maintain. [1] https://wiki.friendlyelec.com/wiki/images/6/60/NanoPi_R76S_LP4X_2411_SCH.pdf [2] https://wiki.friendlyelec.com/wiki/images/9/90/NanoPi_R76S_LP5_2411_SCH.pdf Except for the patches you have tested, please append the blow patch as well to test. --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts @@ -192,6 +192,18 @@ regulator-name = "vcc_3v3_s0"; vin-supply = <&vcc_3v3_s3>; }; + + vcc3v3_sd: regulator-vcc-3v3-sd { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwren>; + regulator-name = "vcc3v3_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s0>; + }; }; &combphy0_ps { @@ -726,6 +738,12 @@ }; }; + sdmmc { + sdmmc_pwren: sdmmc-pwren { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + usb { usb_otg0_pwren_h: usb-otg0-pwren-h { rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; @@ -751,11 +769,14 @@ bus-width = <4>; cap-mmc-highspeed; cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; disable-wp; no-mmc; no-sdio; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; sd-uhs-sdr104; - vmmc-supply = <&vcc_3v3_s3>; + vmmc-supply = <&vcc3v3_sd>; vqmmc-supply = <&vccio_sd_s0>; status = "okay"; >> --- 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 = { > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-15 0:25 ` Shawn Lin @ 2026-01-15 19:39 ` Marco Schirrmeister 2026-01-16 0:31 ` Shawn Lin 0 siblings, 1 reply; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-15 19:39 UTC (permalink / raw) To: Shawn Lin Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson Hello Shawn, On Thu, Jan 15, 2026 at 1:25 AM Shawn Lin <shawn.lin@rock-chips.com> wrote: > > > > Based on this, it makes me believe that power to the sd card is completely cut > > and when it wakes up and knows how to continue, it still must go through the > > retraining phase. > > > > This is another mistake for your NanoPi R76S board. Before sent this > patch, I already checked the dts and saw sdmmc uses vmmc-supply = > <&vcc_3v3_s3> which is marked as regulator-always-on, but it's *NOT* > actually per the shcematic[1][2]. So need another fix for your board > to make it actually gpio-based power controller instaed of function > IO based, as when powering off the power domain, the power control bit > will not be able to maintain. > > [1] > https://wiki.friendlyelec.com/wiki/images/6/60/NanoPi_R76S_LP4X_2411_SCH.pdf > [2] > https://wiki.friendlyelec.com/wiki/images/9/90/NanoPi_R76S_LP5_2411_SCH.pdf > > Except for the patches you have tested, please append the blow patch as > well to test. Bingo. These DTS additions fixed the power stability for the SD card. I have verified that the card now wakes up instantly with no errors and no retraining delay. I tested this both with and without your driver patch (the save/restore phases logic). This confirms the issue was indeed the power rail being cut during idle periods. Great find on the schematic! > --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts > +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts > @@ -192,6 +192,18 @@ > regulator-name = "vcc_3v3_s0"; > vin-supply = <&vcc_3v3_s3>; > }; > + > + vcc3v3_sd: regulator-vcc-3v3-sd { > + compatible = "regulator-fixed"; > + enable-active-high; > + gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; > + pinctrl-names = "default"; > + pinctrl-0 = <&sdmmc_pwren>; > + regulator-name = "vcc3v3_sd"; > + regulator-min-microvolt = <3300000>; > + regulator-max-microvolt = <3300000>; > + vin-supply = <&vcc_3v3_s0>; > + }; > }; > > &combphy0_ps { > @@ -726,6 +738,12 @@ > }; > }; > > + sdmmc { > + sdmmc_pwren: sdmmc-pwren { > + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO > &pcfg_pull_none>; > + }; > + }; > + > usb { > usb_otg0_pwren_h: usb-otg0-pwren-h { > rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO > &pcfg_pull_none>; > @@ -751,11 +769,14 @@ > bus-width = <4>; > cap-mmc-highspeed; > cap-sd-highspeed; > + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; > disable-wp; > no-mmc; > no-sdio; > + pinctrl-names = "default"; > + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; > sd-uhs-sdr104; > - vmmc-supply = <&vcc_3v3_s3>; > + vmmc-supply = <&vcc3v3_sd>; > vqmmc-supply = <&vccio_sd_s0>; > status = "okay"; > > > > > >> --- 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 = { > > > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-15 19:39 ` Marco Schirrmeister @ 2026-01-16 0:31 ` Shawn Lin 0 siblings, 0 replies; 21+ messages in thread From: Shawn Lin @ 2026-01-16 0:31 UTC (permalink / raw) To: Marco Schirrmeister Cc: shawn.lin, robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson 在 2026/01/16 星期五 3:39, Marco Schirrmeister 写道: > Hello Shawn, > > On Thu, Jan 15, 2026 at 1:25 AM Shawn Lin <shawn.lin@rock-chips.com> wrote: >>> >>> Based on this, it makes me believe that power to the sd card is completely cut >>> and when it wakes up and knows how to continue, it still must go through the >>> retraining phase. >>> >> >> This is another mistake for your NanoPi R76S board. Before sent this >> patch, I already checked the dts and saw sdmmc uses vmmc-supply = >> <&vcc_3v3_s3> which is marked as regulator-always-on, but it's *NOT* >> actually per the shcematic[1][2]. So need another fix for your board >> to make it actually gpio-based power controller instaed of function >> IO based, as when powering off the power domain, the power control bit >> will not be able to maintain. >> >> [1] >> https://wiki.friendlyelec.com/wiki/images/6/60/NanoPi_R76S_LP4X_2411_SCH.pdf >> [2] >> https://wiki.friendlyelec.com/wiki/images/9/90/NanoPi_R76S_LP5_2411_SCH.pdf >> >> Except for the patches you have tested, please append the blow patch as >> well to test. > > Bingo. These DTS additions fixed the power stability for the SD card. > I have verified that the card now wakes up instantly with no errors and > no retraining delay. > Thanks, I will fold these two patches into my thread of V4 to fix all these problems. > I tested this both with and without your driver patch (the save/restore > phases logic). > > This confirms the issue was indeed the power rail being cut during > idle periods. Great find on the schematic! > >> --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts >> +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts >> @@ -192,6 +192,18 @@ >> regulator-name = "vcc_3v3_s0"; >> vin-supply = <&vcc_3v3_s3>; >> }; >> + >> + vcc3v3_sd: regulator-vcc-3v3-sd { >> + compatible = "regulator-fixed"; >> + enable-active-high; >> + gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; >> + pinctrl-names = "default"; >> + pinctrl-0 = <&sdmmc_pwren>; >> + regulator-name = "vcc3v3_sd"; >> + regulator-min-microvolt = <3300000>; >> + regulator-max-microvolt = <3300000>; >> + vin-supply = <&vcc_3v3_s0>; >> + }; >> }; >> >> &combphy0_ps { >> @@ -726,6 +738,12 @@ >> }; >> }; >> >> + sdmmc { >> + sdmmc_pwren: sdmmc-pwren { >> + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO >> &pcfg_pull_none>; >> + }; >> + }; >> + >> usb { >> usb_otg0_pwren_h: usb-otg0-pwren-h { >> rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO >> &pcfg_pull_none>; >> @@ -751,11 +769,14 @@ >> bus-width = <4>; >> cap-mmc-highspeed; >> cap-sd-highspeed; >> + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; >> disable-wp; >> no-mmc; >> no-sdio; >> + pinctrl-names = "default"; >> + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; >> sd-uhs-sdr104; >> - vmmc-supply = <&vcc_3v3_s3>; >> + vmmc-supply = <&vcc3v3_sd>; >> vqmmc-supply = <&vccio_sd_s0>; >> status = "okay"; >> >> >> >> >>>> --- 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 = { >>> >> > ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S 2026-01-12 1:32 ` [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for " Shawn Lin 2026-01-12 3:56 ` Shawn Lin @ 2026-01-12 19:04 ` Marco Schirrmeister 1 sibling, 0 replies; 21+ messages in thread From: Marco Schirrmeister @ 2026-01-12 19:04 UTC (permalink / raw) To: Shawn Lin Cc: robh, krzk+dt, conor+dt, linux-rockchip, linux-mmc, devicetree, linux-arm-kernel, heiko, ulf.hansson On Mon, Jan 12, 2026 at 2:32 AM Shawn Lin <shawn.lin@rock-chips.com> wrote: > > > 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? I tested with multiple SanDisk Extreme and Ultra. Yes, I have tried to disable SDR104. Also others for testing. Nothing made a difference. ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-01-16 10:20 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-10 1:07 [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for NanoPi R76S Marco Schirrmeister 2026-01-10 1:07 ` [PATCH v1 1/3] dt-bindings: mmc: rockchip-dw-mshc: add rockchip,disable-runtime-pm Marco Schirrmeister 2026-01-10 2:25 ` Rob Herring (Arm) 2026-01-11 9:41 ` Krzysztof Kozlowski 2026-01-11 23:51 ` Marco Schirrmeister 2026-01-16 9:43 ` Heiko Stübner 2026-01-16 10:20 ` Krzysztof Kozlowski 2026-01-10 1:07 ` [PATCH v1 2/3] mmc: host: dw_mmc-rockchip: add rockchip,disable-runtime-pm quirk Marco Schirrmeister 2026-01-10 1:07 ` [PATCH v1 3/3] arm64: dts: rockchip: add stability quirk to NanoPi R76S Marco Schirrmeister 2026-01-11 9:42 ` Krzysztof Kozlowski 2026-01-12 1:32 ` [PATCH v1 0/3] mmc: dw_mmc-rockchip: Add stability quirk for " Shawn Lin 2026-01-12 3:56 ` Shawn Lin 2026-01-12 8:29 ` Chaoyi Chen 2026-01-12 8:58 ` Shawn Lin 2026-01-12 19:09 ` Marco Schirrmeister 2026-01-14 8:08 ` Shawn Lin 2026-01-14 19:51 ` Marco Schirrmeister 2026-01-15 0:25 ` Shawn Lin 2026-01-15 19:39 ` Marco Schirrmeister 2026-01-16 0:31 ` Shawn Lin 2026-01-12 19:04 ` Marco Schirrmeister
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox