mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-19 14:13:30 +00:00
rockchip: fix mmc sdhci of dwcmshc pd workaround on rk3576 in kernel 6.12
This commit is contained in:
parent
b9c1373a04
commit
fb3d3ed80e
@ -0,0 +1,83 @@
|
||||
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
|
||||
---
|
||||
Changes in v2:
|
||||
- Rewrite patch to use dev_pm_genpd_rpm_always_on in sdhci driver
|
||||
instead, after Ulf Hansson made me aware of its existence
|
||||
- Link to v1: https://lore.kernel.org/r/20250408-rk3576-emmc-fix-v1-1-3009828b1b31@collabora.com
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 39 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
index 09b9ab15e4995f0bddf57dd309c010c849be40d9..a00aec05eff2da8197cc64690ba9665be756e54a 100644
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/sizes.h>
|
||||
@@ -745,6 +746,28 @@ static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv
|
||||
}
|
||||
}
|
||||
|
||||
+static void dwcmshc_rk3576_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
|
||||
+{
|
||||
+ struct device *dev = mmc_dev(host->mmc);
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * This works around what appears to be a silicon bug, which makes the
|
||||
+ * PD_NVM power domain, which the sdhci controller on the RK3576 is in,
|
||||
+ * never come back the same way once it's turned off once. This can
|
||||
+ * happen during early kernel boot if no driver is using either PD_NVM
|
||||
+ * or its child power domain PD_SDGMAC for a short moment, leading to it
|
||||
+ * being turned off to save power. By keeping it on, sdhci suspending
|
||||
+ * won't lead to PD_NVM becoming a candidate for getting turned off.
|
||||
+ */
|
||||
+ ret = dev_pm_genpd_rpm_always_on(dev, true);
|
||||
+ if (ret && ret != -EOPNOTSUPP)
|
||||
+ dev_warn(dev, "failed to set PD rpm always on, SoC may hang later: %pe\n",
|
||||
+ ERR_PTR(ret));
|
||||
+
|
||||
+ dwcmshc_rk35xx_postinit(host, dwc_priv);
|
||||
+}
|
||||
+
|
||||
static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
@@ -1176,6 +1199,18 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
|
||||
.postinit = dwcmshc_rk35xx_postinit,
|
||||
};
|
||||
|
||||
+static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk3576_pdata = {
|
||||
+ .pdata = {
|
||||
+ .ops = &sdhci_dwcmshc_rk35xx_ops,
|
||||
+ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
||||
+ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
|
||||
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
|
||||
+ SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
|
||||
+ },
|
||||
+ .init = dwcmshc_rk35xx_init,
|
||||
+ .postinit = dwcmshc_rk3576_postinit,
|
||||
+};
|
||||
+
|
||||
static const struct dwcmshc_pltfm_data sdhci_dwcmshc_th1520_pdata = {
|
||||
.pdata = {
|
||||
.ops = &sdhci_dwcmshc_th1520_ops,
|
||||
@@ -1274,6 +1309,10 @@ static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
|
||||
.compatible = "rockchip,rk3588-dwcmshc",
|
||||
.data = &sdhci_dwcmshc_rk35xx_pdata,
|
||||
},
|
||||
+ {
|
||||
+ .compatible = "rockchip,rk3576-dwcmshc",
|
||||
+ .data = &sdhci_dwcmshc_rk3576_pdata,
|
||||
+ },
|
||||
{
|
||||
.compatible = "rockchip,rk3568-dwcmshc",
|
||||
.data = &sdhci_dwcmshc_rk35xx_pdata,
|
||||
|
||||
---
|
Loading…
Reference in New Issue
Block a user