mmc: core: Export a function mmc_sw_reset() to allow soft reset of cards
authorUlf Hansson <ulf.hansson@linaro.org>
Thu, 5 Apr 2018 11:42:00 +0000 (13:42 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 8 May 2018 07:33:42 +0000 (09:33 +0200)
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>
drivers/mmc/core/core.c
drivers/mmc/core/core.h
include/linux/mmc/core.h

index 3e17c62eea86ce9f44b1fabbddc4552184e8099a..7a79dc1599e5bd0ef45f314a6dd0e3b9287ef954 100644 (file)
@@ -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;
index 367ed1127be24d570cac61e5c6b039776dade811..a141ec0e1ccc58ed96d05b49a3f4efc999a28e40 100644 (file)
@@ -33,6 +33,7 @@ struct mmc_bus_ops {
        int (*alive)(struct mmc_host *);
        int (*shutdown)(struct mmc_host *);
        int (*hw_reset)(struct mmc_host *);
+       int (*sw_reset)(struct mmc_host *);
 };
 
 void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
index 927519385482e4ab919a9e0dffd5181de450f5a4..134a6483347a1e565d91c812c1e1212e989463bb 100644 (file)
@@ -177,6 +177,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
                int retries);
 
 int mmc_hw_reset(struct mmc_host *host);
+int mmc_sw_reset(struct mmc_host *host);
 void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card);
 
 #endif /* LINUX_MMC_CORE_H */