summaryrefslogtreecommitdiff
path: root/drivers/mmc/core/core.c
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2018-04-05 13:42:00 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2018-05-08 09:33:42 +0200
commit1433269c4d2461be1f36db5dbb453976b38996ff (patch)
treee9f58931e1bdc1fd357e8ce7061003264ff4b666 /drivers/mmc/core/core.c
parent3a3db6030b64ceb4b4e41a6811168c5d90a9f7f8 (diff)
mmc: core: Export a function mmc_sw_reset() to allow soft reset of cards
It's rather common that a firmware is loaded into an SDIO func device memory, by the corresponding SDIO func driver during ->probe() time. However, to actually start running the new firmware, sometimes a soft reset (no power cycle) and a re-initialization of the card is needed. This is for example the case with the Espressif ESP8089 WiFi chips, when connected to an SDIO interface. To cope with this scenario, let's add a new exported function, mmc_sw_reset(), which may be called when a soft reset and re-initialization of the card are needed. The mmc_sw_reset() is implemented on top of a new bus ops callback, similar to how the mmc_hw_reset() has been implemented. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Quentin Schulz <quentin.schulz@bootlin.com> Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r--drivers/mmc/core/core.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 3e17c62eea86..7a79dc1599e5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2451,6 +2451,30 @@ int mmc_hw_reset(struct mmc_host *host)
}
EXPORT_SYMBOL(mmc_hw_reset);
+int mmc_sw_reset(struct mmc_host *host)
+{
+ int ret;
+
+ if (!host->card)
+ return -EINVAL;
+
+ mmc_bus_get(host);
+ if (!host->bus_ops || host->bus_dead || !host->bus_ops->sw_reset) {
+ mmc_bus_put(host);
+ return -EOPNOTSUPP;
+ }
+
+ ret = host->bus_ops->sw_reset(host);
+ mmc_bus_put(host);
+
+ if (ret)
+ pr_warn("%s: tried to SW reset card, got error %d\n",
+ mmc_hostname(host), ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(mmc_sw_reset);
+
static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
{
host->f_init = freq;