mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-07-02 12:47:15 +08:00
181 lines
5.6 KiB
Diff
181 lines
5.6 KiB
Diff
From 39b865a30715e3b5a6b17454c4a94b8276988d64 Mon Sep 17 00:00:00 2001
|
|
From: Liam Fraser <liam@raspberrypi.com>
|
|
Date: Thu, 14 Mar 2019 16:01:26 +0000
|
|
Subject: [PATCH] mmc: sdhci-of-dwcmshc: define sdio timeout clocks
|
|
|
|
Signed-off-by: Liam Fraser <liam@raspberrypi.com>
|
|
|
|
mmc: sdhci-of-dwcmshc: rp1 sdio changes
|
|
|
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
|
|
|
drivers: mmc: sdhci-of-dwcmshc: add RP1 dt ID and quirks
|
|
|
|
Differentiate the RP1 variant of the Designware MSHC controller(s).
|
|
|
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
|
---
|
|
drivers/mmc/host/sdhci-of-dwcmshc.c | 54 +++++++++++++++++++++++++++--
|
|
drivers/mmc/host/sdhci-pltfm.c | 8 +++++
|
|
drivers/mmc/host/sdhci-pltfm.h | 3 ++
|
|
3 files changed, 62 insertions(+), 3 deletions(-)
|
|
|
|
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
|
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
|
@@ -221,6 +221,7 @@ struct rk35xx_priv {
|
|
|
|
struct dwcmshc_priv {
|
|
struct clk *bus_clk;
|
|
+ struct clk *sdio_clk;
|
|
int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA1 reg */
|
|
int vendor_specific_area2; /* P_VENDOR_SPECIFIC_AREA2 reg */
|
|
|
|
@@ -289,6 +290,17 @@ static void dwcmshc_adma_write_desc(stru
|
|
sdhci_adma_write_desc(host, desc, addr, len, cmd);
|
|
}
|
|
|
|
+static void dwcmshc_set_clock(struct sdhci_host *host, unsigned int clock)
|
|
+{
|
|
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
|
+ struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
|
+
|
|
+ if (priv->sdio_clk)
|
|
+ clk_set_rate(priv->sdio_clk, clock);
|
|
+
|
|
+ sdhci_set_clock(host, clock);
|
|
+}
|
|
+
|
|
static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
|
|
{
|
|
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
|
@@ -1138,10 +1150,11 @@ static int sg2042_init(struct device *de
|
|
}
|
|
|
|
static const struct sdhci_ops sdhci_dwcmshc_ops = {
|
|
- .set_clock = sdhci_set_clock,
|
|
+ .set_clock = dwcmshc_set_clock,
|
|
.set_bus_width = sdhci_set_bus_width,
|
|
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
|
|
.get_max_clock = dwcmshc_get_max_clock,
|
|
+ .get_timeout_clock = sdhci_pltfm_clk_get_timeout_clock,
|
|
.reset = sdhci_reset,
|
|
.adma_write_desc = dwcmshc_adma_write_desc,
|
|
.irq = dwcmshc_cqe_irq_handler,
|
|
@@ -1214,8 +1227,10 @@ static const struct sdhci_ops sdhci_dwcm
|
|
static const struct dwcmshc_pltfm_data sdhci_dwcmshc_pdata = {
|
|
.pdata = {
|
|
.ops = &sdhci_dwcmshc_ops,
|
|
- .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
|
|
- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
|
|
+ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
|
+ SDHCI_QUIRK_BROKEN_CARD_DETECTION,
|
|
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
|
|
+ SDHCI_QUIRK2_BROKEN_HS200,
|
|
},
|
|
};
|
|
|
|
@@ -1230,6 +1245,15 @@ static const struct dwcmshc_pltfm_data s
|
|
};
|
|
#endif
|
|
|
|
+static const struct sdhci_pltfm_data sdhci_dwcmshc_rp1_pdata = {
|
|
+ .ops = &sdhci_dwcmshc_ops,
|
|
+ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
|
+ SDHCI_QUIRK_BROKEN_CARD_DETECTION,
|
|
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
|
|
+ SDHCI_QUIRK2_BROKEN_HS200 |
|
|
+ SDHCI_QUIRK2_SPURIOUS_INT_RESP,
|
|
+};
|
|
+
|
|
static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
|
|
.pdata = {
|
|
.ops = &sdhci_dwcmshc_rk35xx_ops,
|
|
@@ -1353,6 +1377,10 @@ dsbl_cqe_caps:
|
|
|
|
static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
|
|
{
|
|
+ .compatible = "raspberrypi,rp1-dwcmshc",
|
|
+ .data = &sdhci_dwcmshc_rp1_pdata,
|
|
+ },
|
|
+ {
|
|
.compatible = "rockchip,rk3588-dwcmshc",
|
|
.data = &sdhci_dwcmshc_rk35xx_pdata,
|
|
},
|
|
@@ -1445,13 +1473,32 @@ static int dwcmshc_probe(struct platform
|
|
priv->bus_clk = devm_clk_get(dev, "bus");
|
|
if (!IS_ERR(priv->bus_clk))
|
|
clk_prepare_enable(priv->bus_clk);
|
|
+
|
|
+ pltfm_host->timeout_clk = devm_clk_get(dev, "timeout");
|
|
+ if (!IS_ERR(pltfm_host->timeout_clk))
|
|
+ err = clk_prepare_enable(pltfm_host->timeout_clk);
|
|
+ if (err)
|
|
+ goto free_pltfm;
|
|
+
|
|
+ priv->sdio_clk = devm_clk_get_optional(&pdev->dev, "sdio");
|
|
+ }
|
|
+
|
|
+ pltfm_host->timeout_clk = devm_clk_get(&pdev->dev, "timeout");
|
|
+ if (IS_ERR(pltfm_host->timeout_clk)) {
|
|
+ err = PTR_ERR(pltfm_host->timeout_clk);
|
|
+ dev_err(&pdev->dev, "failed to get timeout clk: %d\n", err);
|
|
+ goto free_pltfm;
|
|
}
|
|
+ err = clk_prepare_enable(pltfm_host->timeout_clk);
|
|
+ if (err)
|
|
+ goto free_pltfm;
|
|
|
|
err = mmc_of_parse(host->mmc);
|
|
if (err)
|
|
goto err_clk;
|
|
|
|
sdhci_get_of_property(pdev);
|
|
+ sdhci_enable_v4_mode(host);
|
|
|
|
priv->vendor_specific_area1 =
|
|
sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK;
|
|
@@ -1511,6 +1558,7 @@ err_rpm:
|
|
pm_runtime_put_noidle(dev);
|
|
err_clk:
|
|
clk_disable_unprepare(pltfm_host->clk);
|
|
+ clk_disable_unprepare(pltfm_host->timeout_clk);
|
|
clk_disable_unprepare(priv->bus_clk);
|
|
clk_bulk_disable_unprepare(priv->num_other_clks, priv->other_clks);
|
|
free_pltfm:
|
|
--- a/drivers/mmc/host/sdhci-pltfm.c
|
|
+++ b/drivers/mmc/host/sdhci-pltfm.c
|
|
@@ -32,6 +32,14 @@ unsigned int sdhci_pltfm_clk_get_max_clo
|
|
}
|
|
EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
|
|
|
|
+unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host)
|
|
+{
|
|
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
|
+
|
|
+ return clk_get_rate(pltfm_host->timeout_clk);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_timeout_clock);
|
|
+
|
|
static const struct sdhci_ops sdhci_pltfm_ops = {
|
|
.set_clock = sdhci_set_clock,
|
|
.set_bus_width = sdhci_set_bus_width,
|
|
--- a/drivers/mmc/host/sdhci-pltfm.h
|
|
+++ b/drivers/mmc/host/sdhci-pltfm.h
|
|
@@ -20,6 +20,7 @@ struct sdhci_pltfm_data {
|
|
|
|
struct sdhci_pltfm_host {
|
|
struct clk *clk;
|
|
+ struct clk *timeout_clk;
|
|
|
|
/* migrate from sdhci_of_host */
|
|
unsigned int clock;
|
|
@@ -106,6 +107,8 @@ extern void sdhci_pltfm_remove(struct pl
|
|
|
|
extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
|
|
|
|
+extern unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host);
|
|
+
|
|
static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
|
|
{
|
|
return host->private;
|