summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/block.c11
-rw-r--r--drivers/mmc/core/core.c29
-rw-r--r--drivers/mmc/core/core.h9
-rw-r--r--drivers/mmc/core/debugfs.c1
-rw-r--r--drivers/mmc/core/host.c3
-rw-r--r--drivers/mmc/core/mmc.c68
-rw-r--r--drivers/mmc/core/mmc_ops.c163
-rw-r--r--drivers/mmc/core/mmc_ops.h12
-rw-r--r--drivers/mmc/core/sd.c481
-rw-r--r--drivers/mmc/core/sd_ops.c38
-rw-r--r--drivers/mmc/core/sdio.c6
-rw-r--r--drivers/mmc/host/Kconfig6
-rw-r--r--drivers/mmc/host/cqhci-core.c21
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c1
-rw-r--r--drivers/mmc/host/jz4740_mmc.c6
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c50
-rw-r--r--drivers/mmc/host/mmc_spi.c12
-rw-r--r--drivers/mmc/host/mtk-sd.c25
-rw-r--r--drivers/mmc/host/of_mmc_spi.c2
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c2
-rw-r--r--drivers/mmc/host/s3cmci.c7
-rw-r--r--drivers/mmc/host/sdhci-acpi.c11
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c18
-rw-r--r--drivers/mmc/host/sdhci-iproc.c30
-rw-r--r--drivers/mmc/host/sdhci-of-arasan.c14
-rw-r--r--drivers/mmc/host/sdhci-of-aspeed-test.c34
-rw-r--r--drivers/mmc/host/sdhci-of-aspeed.c50
-rw-r--r--drivers/mmc/host/sdhci-omap.c5
-rw-r--r--drivers/mmc/host/sdhci-pci-gli.c4
-rw-r--r--drivers/mmc/host/sdhci-sprd.c1
-rw-r--r--drivers/mmc/host/sdhci.c12
-rw-r--r--drivers/mmc/host/sdhci.h3
-rw-r--r--drivers/mmc/host/sdhci_am654.c6
-rw-r--r--drivers/mmc/host/usdhi6rol0.c1
-rw-r--r--drivers/mmc/host/via-sdmmc.c3
-rw-r--r--drivers/mmc/host/vub300.c2
36 files changed, 876 insertions, 271 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 689eb9afeeed..88f4c215caa6 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Block driver for media (i.e., flash cards)
*
@@ -1004,6 +1005,12 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
switch (mq_rq->drv_op) {
case MMC_DRV_OP_IOCTL:
+ if (card->ext_csd.cmdq_en) {
+ ret = mmc_cmdq_disable(card);
+ if (ret)
+ break;
+ }
+ fallthrough;
case MMC_DRV_OP_IOCTL_RPMB:
idata = mq_rq->drv_op_data;
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
@@ -1014,6 +1021,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
/* Always switch back to main area after RPMB access */
if (rpmb_ioctl)
mmc_blk_part_switch(card, 0);
+ else if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
+ mmc_cmdq_enable(card);
break;
case MMC_DRV_OP_BOOT_WP:
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
@@ -1159,7 +1168,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
struct mmc_card *card = md->queue.card;
int ret = 0;
- ret = mmc_flush_cache(card);
+ ret = mmc_flush_cache(card->host);
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f194940c5974..95fedcf56e4a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -937,11 +937,14 @@ int mmc_execute_tuning(struct mmc_card *card)
err = host->ops->execute_tuning(host, opcode);
- if (err)
+ if (err) {
pr_err("%s: tuning execution failed: %d\n",
mmc_hostname(host), err);
- else
+ } else {
+ host->retune_now = 0;
+ host->need_retune = 0;
mmc_retune_enable(host);
+ }
return err;
}
@@ -1582,7 +1585,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
{
struct mmc_command cmd = {};
unsigned int qty = 0, busy_timeout = 0;
- bool use_r1b_resp = false;
+ bool use_r1b_resp;
int err;
mmc_retune_hold(card->host);
@@ -1650,23 +1653,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.opcode = MMC_ERASE;
cmd.arg = arg;
busy_timeout = mmc_erase_timeout(card, arg, qty);
- /*
- * If the host controller supports busy signalling and the timeout for
- * the erase operation does not exceed the max_busy_timeout, we should
- * use R1B response. Or we need to prevent the host from doing hw busy
- * detection, which is done by converting to a R1 response instead.
- * Note, some hosts requires R1B, which also means they are on their own
- * when it comes to deal with the busy timeout.
- */
- if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) &&
- card->host->max_busy_timeout &&
- busy_timeout > card->host->max_busy_timeout) {
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
- } else {
- cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- cmd.busy_timeout = busy_timeout;
- use_r1b_resp = true;
- }
+ use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout);
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
@@ -1687,7 +1674,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
goto out;
/* Let's poll to find out when the erase operation completes. */
- err = mmc_poll_for_busy(card, busy_timeout, MMC_BUSY_ERASE);
+ err = mmc_poll_for_busy(card, busy_timeout, false, MMC_BUSY_ERASE);
out:
mmc_retune_release(card->host);
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index db3c9c68875d..0c4de2030b3f 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -30,6 +30,7 @@ struct mmc_bus_ops {
int (*hw_reset)(struct mmc_host *);
int (*sw_reset)(struct mmc_host *);
bool (*cache_enabled)(struct mmc_host *);
+ int (*flush_cache)(struct mmc_host *);
};
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
@@ -172,4 +173,12 @@ static inline bool mmc_cache_enabled(struct mmc_host *host)
return false;
}
+static inline int mmc_flush_cache(struct mmc_host *host)
+{
+ if (host->bus_ops->flush_cache)
+ return host->bus_ops->flush_cache(host);
+
+ return 0;
+}
+
#endif
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 9ec84c86c46a..3fdbc801e64a 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -26,6 +26,7 @@
static DECLARE_FAULT_ATTR(fail_default_attr);
static char *fail_request;
module_param(fail_request, charp, 0);
+MODULE_PARM_DESC(fail_request, "default fault injection attributes");
#endif /* CONFIG_FAIL_MMC_REQUEST */
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 0b0577990ddc..eda4a1892c33 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -388,6 +388,9 @@ int mmc_of_parse(struct mmc_host *host)
host->caps2 |= MMC_CAP2_NO_SD;
if (device_property_read_bool(dev, "no-mmc"))
host->caps2 |= MMC_CAP2_NO_MMC;
+ if (device_property_read_bool(dev, "no-mmc-hs400"))
+ host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V |
+ MMC_CAP2_HS400_ES);
/* Must be after "non-removable" check */
if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) {
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 8674c3e0c02c..838726b68ff3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -28,6 +28,7 @@
#define DEFAULT_CMD6_TIMEOUT_MS 500
#define MIN_CACHE_EN_TIMEOUT_MS 1600
+#define CACHE_FLUSH_TIMEOUT_MS 30000 /* 30s */
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
@@ -1905,11 +1906,20 @@ static int mmc_can_sleep(struct mmc_card *card)
return card->ext_csd.rev >= 3;
}
+static int mmc_sleep_busy_cb(void *cb_data, bool *busy)
+{
+ struct mmc_host *host = cb_data;
+
+ *busy = host->ops->card_busy(host);
+ return 0;
+}
+
static int mmc_sleep(struct mmc_host *host)
{
struct mmc_command cmd = {};
struct mmc_card *card = host->card;
unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
+ bool use_r1b_resp;
int err;
/* Re-tuning can't be done once the card is deselected */
@@ -1922,35 +1932,27 @@ static int mmc_sleep(struct mmc_host *host)
cmd.opcode = MMC_SLEEP_AWAKE;
cmd.arg = card->rca << 16;
cmd.arg |= 1 << 15;
-
- /*
- * If the max_busy_timeout of the host is specified, validate it against
- * the sleep cmd timeout. A failure means we need to prevent the host
- * from doing hw busy detection, which is done by converting to a R1
- * response instead of a R1B. Note, some hosts requires R1B, which also
- * means they are on their own when it comes to deal with the busy
- * timeout.
- */
- if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
- (timeout_ms > host->max_busy_timeout)) {
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- } else {
- cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
- cmd.busy_timeout = timeout_ms;
- }
+ use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms);
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
goto out_release;
/*
- * If the host does not wait while the card signals busy, then we will
- * will have to wait the sleep/awake timeout. Note, we cannot use the
- * SEND_STATUS command to poll the status because that command (and most
- * others) is invalid while the card sleeps.
+ * If the host does not wait while the card signals busy, then we can
+ * try to poll, but only if the host supports HW polling, as the
+ * SEND_STATUS cmd is not allowed. If we can't poll, then we simply need
+ * to wait the sleep/awake timeout.
*/
- if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY && use_r1b_resp)
+ goto out_release;
+
+ if (!host->ops->card_busy) {
mmc_delay(timeout_ms);
+ goto out_release;
+ }
+
+ err = __mmc_poll_for_busy(card, timeout_ms, &mmc_sleep_busy_cb, host);
out_release:
mmc_retune_release(host);
@@ -2035,6 +2037,25 @@ static bool _mmc_cache_enabled(struct mmc_host *host)
host->card->ext_csd.cache_ctrl & 1;
}
+/*
+ * Flush the internal cache of the eMMC to non-volatile storage.
+ */
+static int _mmc_flush_cache(struct mmc_host *host)
+{
+ int err = 0;
+
+ if (_mmc_cache_enabled(host)) {
+ err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_FLUSH_CACHE, 1,
+ CACHE_FLUSH_TIMEOUT_MS);
+ if (err)
+ pr_err("%s: cache flush error %d\n",
+ mmc_hostname(host), err);
+ }
+
+ return err;
+}
+
static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
{
int err = 0;
@@ -2046,7 +2067,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
if (mmc_card_suspended(host->card))
goto out;
- err = mmc_flush_cache(host->card);
+ err = _mmc_flush_cache(host);
if (err)
goto out;
@@ -2187,7 +2208,7 @@ static int _mmc_hw_reset(struct mmc_host *host)
* In the case of recovery, we can't expect flushing the cache to work
* always, but we have a go and ignore errors.
*/
- mmc_flush_cache(host->card);
+ _mmc_flush_cache(host);
if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset &&
mmc_can_reset(card)) {
@@ -2215,6 +2236,7 @@ static const struct mmc_bus_ops mmc_ops = {
.shutdown = mmc_shutdown,
.hw_reset = _mmc_hw_reset,
.cache_enabled = _mmc_cache_enabled,
+ .flush_cache = _mmc_flush_cache,
};
/*
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 5756781fef37..973756ed4016 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -20,7 +20,6 @@
#include "mmc_ops.h"
#define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */
-#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */
#define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */
static const u8 tuning_blk_pattern_4bit[] = {
@@ -53,6 +52,12 @@ static const u8 tuning_blk_pattern_8bit[] = {
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};
+struct mmc_busy_data {
+ struct mmc_card *card;
+ bool retry_crc_err;
+ enum mmc_busy_cmd busy_cmd;
+};
+
int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries)
{
int err;
@@ -246,9 +251,8 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
* NOTE: void *buf, caller for the buf is required to use DMA-capable
* buffer or on-stack buffer (with some overhead in callee).
*/
-static int
-mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
- u32 opcode, void *buf, unsigned len)
+int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode,
+ u32 args, void *buf, unsigned len)
{
struct mmc_request mrq = {};
struct mmc_command cmd = {};
@@ -259,7 +263,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
mrq.data = &data;
cmd.opcode = opcode;
- cmd.arg = 0;
+ cmd.arg = args;
/* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we
* rely on callers to never use this with "native" calls for reading
@@ -305,7 +309,7 @@ static int mmc_spi_send_cxd(struct mmc_host *host, u32 *cxd, u32 opcode)
if (!cxd_tmp)
return -ENOMEM;
- ret = mmc_send_cxd_data(NULL, host, opcode, cxd_tmp, 16);
+ ret = mmc_send_adtc_data(NULL, host, opcode, 0, cxd_tmp, 16);
if (ret)
goto err;
@@ -353,7 +357,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
if (!ext_csd)
return -ENOMEM;
- err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd,
+ err = mmc_send_adtc_data(card, card->host, MMC_SEND_EXT_CSD, 0, ext_csd,
512);
if (err)
kfree(ext_csd);
@@ -424,10 +428,10 @@ int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal)
return mmc_switch_status_error(card->host, status);
}
-static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
- enum mmc_busy_cmd busy_cmd, bool *busy)
+static int mmc_busy_cb(void *cb_data, bool *busy)
{
- struct mmc_host *host = card->host;
+ struct mmc_busy_data *data = cb_data;
+ struct mmc_host *host = data->card->host;
u32 status = 0;
int err;
@@ -436,22 +440,23 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
return 0;
}
- err = mmc_send_status(card, &status);
- if (retry_crc_err && err == -EILSEQ) {
+ err = mmc_send_status(data->card, &status);
+ if (data->retry_crc_err && err == -EILSEQ) {
*busy = true;
return 0;
}
if (err)
return err;
- switch (busy_cmd) {
+ switch (data->busy_cmd) {
case MMC_BUSY_CMD6:
- err = mmc_switch_status_error(card->host, status);
+ err = mmc_switch_status_error(host, status);
break;
case MMC_BUSY_ERASE:
err = R1_STATUS(status) ? -EIO : 0;
break;
case MMC_BUSY_HPI:
+ case MMC_BUSY_EXTR_SINGLE:
break;
default:
err = -EINVAL;
@@ -464,9 +469,9 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
return 0;
}
-static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
- bool send_status, bool retry_crc_err,
- enum mmc_busy_cmd busy_cmd)
+int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+ int (*busy_cb)(void *cb_data, bool *busy),
+ void *cb_data)
{
struct mmc_host *host = card->host;
int err;
@@ -475,16 +480,6 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
bool expired = false;
bool busy = false;
- /*
- * In cases when not allowed to poll by using CMD13 or because we aren't
- * capable of polling by using ->card_busy(), then rely on waiting the
- * stated timeout to be sufficient.
- */
- if (!send_status && !host->ops->card_busy) {
- mmc_delay(timeout_ms);
- return 0;
- }
-
timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
do {
/*
@@ -493,7 +488,7 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
*/
expired = time_after(jiffies, timeout);
- err = mmc_busy_status(card, retry_crc_err, busy_cmd, &busy);
+ err = (*busy_cb)(cb_data, &busy);
if (err)
return err;
@@ -516,9 +511,36 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
}
int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
- enum mmc_busy_cmd busy_cmd)
+ bool retry_crc_err, enum mmc_busy_cmd busy_cmd)
+{
+ struct mmc_busy_data cb_data;
+
+ cb_data.card = card;
+ cb_data.retry_crc_err = retry_crc_err;
+ cb_data.busy_cmd = busy_cmd;
+
+ return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data);
+}
+
+bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd,
+ unsigned int timeout_ms)
{
- return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd);
+ /*
+ * If the max_busy_timeout of the host is specified, make sure it's
+ * enough to fit the used timeout_ms. In case it's not, let's instruct
+ * the host to avoid HW busy detection, by converting to a R1 response
+ * instead of a R1B. Note, some hosts requires R1B, which also means
+ * they are on their own when it comes to deal with the busy timeout.
+ */
+ if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
+ (timeout_ms > host->max_busy_timeout)) {
+ cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1 | MMC_RSP_R1;
+ return false;
+ }
+
+ cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1B | MMC_RSP_R1B;
+ cmd->busy_timeout = timeout_ms;
+ return true;
}
/**
@@ -543,7 +565,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
struct mmc_host *host = card->host;
int err;
struct mmc_command cmd = {};
- bool use_r1b_resp = true;
+ bool use_r1b_resp;
unsigned char old_timing = host->ios.timing;
mmc_retune_hold(host);
@@ -554,29 +576,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
timeout_ms = card->ext_csd.generic_cmd6_time;
}
- /*
- * If the max_busy_timeout of the host is specified, make sure it's
- * enough to fit the used timeout_ms. In case it's not, let's instruct
- * the host to avoid HW busy detection, by converting to a R1 response
- * instead of a R1B. Note, some hosts requires R1B, which also means
- * they are on their own when it comes to deal with the busy timeout.
- */
- if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
- (timeout_ms > host->max_busy_timeout))
- use_r1b_resp = false;
-
cmd.opcode = MMC_SWITCH;
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
(index << 16) |
(value << 8) |
set;
- cmd.flags = MMC_CMD_AC;
- if (use_r1b_resp) {
- cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
- cmd.busy_timeout = timeout_ms;
- } else {
- cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
- }
+ use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms);
err = mmc_wait_for_cmd(host, &cmd, retries);
if (err)
@@ -587,9 +592,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
mmc_host_is_spi(host))
goto out_tim;
+ /*
+ * If the host doesn't support HW polling via the ->card_busy() ops and
+ * when it's not allowed to poll by using CMD13, then we need to rely on
+ * waiting the stated timeout to be sufficient.
+ */
+ if (!send_status && !host->ops->card_busy) {
+ mmc_delay(timeout_ms);
+ goto out_tim;
+ }
+
/* Let's try to poll to find out when the command is completed. */
- err = __mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err,
- MMC_BUSY_CMD6);
+ err = mmc_poll_for_busy(card, timeout_ms, retry_crc_err, MMC_BUSY_CMD6);
if (err)
goto out;
@@ -686,7 +700,7 @@ out:
}
EXPORT_SYMBOL_GPL(mmc_send_tuning);
-int mmc_abort_tuning(struct mmc_host *host, u32 opcode)
+int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode)
{
struct mmc_command cmd = {};
@@ -709,7 +723,7 @@ int mmc_abort_tuning(struct mmc_host *host, u32 opcode)
return mmc_wait_for_cmd(host, &cmd, 0);
}
-EXPORT_SYMBOL_GPL(mmc_abort_tuning);
+EXPORT_SYMBOL_GPL(mmc_send_abort_tuning);
static int
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
@@ -813,28 +827,17 @@ static int mmc_send_hpi_cmd(struct mmc_card *card)
{
unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time;
struct mmc_host *host = card->host;
- bool use_r1b_resp = true;
+ bool use_r1b_resp = false;
struct mmc_command cmd = {};
int err;
cmd.opcode = card->ext_csd.hpi_cmd;
cmd.arg = card->rca << 16 | 1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- /*
- * Make sure the host's max_busy_timeout fit the needed timeout for HPI.
- * In case it doesn't, let's instruct the host to avoid HW busy
- * detection, by using a R1 response instead of R1B.
- */
- if (host->max_busy_timeout && busy_timeout_ms > host->max_busy_timeout)
- use_r1b_resp = false;
-
- if (cmd.opcode == MMC_STOP_TRANSMISSION && use_r1b_resp) {
- cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
- cmd.busy_timeout = busy_timeout_ms;
- } else {
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- use_r1b_resp = false;
- }
+ if (cmd.opcode == MMC_STOP_TRANSMISSION)
+ use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd,
+ busy_timeout_ms);
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err) {
@@ -848,7 +851,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card)
return 0;
/* Let's poll to find out when the HPI request completes. */
- return mmc_poll_for_busy(card, busy_timeout_ms, MMC_BUSY_HPI);
+ return mmc_poll_for_busy(card, busy_timeout_ms, false, MMC_BUSY_HPI);
}
/**
@@ -961,26 +964,6 @@ void mmc_run_bkops(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_run_bkops);
-/*
- * Flush the cache to the non-volatile storage.
- */
-int mmc_flush_cache(struct mmc_card *card)
-{
- int err = 0;
-
- if (mmc_cache_enabled(card->host)) {
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_FLUSH_CACHE, 1,
- MMC_CACHE_FLUSH_TIMEOUT_MS);
- if (err)
- pr_err("%s: cache flush error %d\n",
- mmc_hostname(card->host), err);
- }
-
- return err;
-}
-EXPORT_SYMBOL(mmc_flush_cache);
-
static int mmc_cmdq_switch(struct mmc_card *card, bool enable)
{
u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 7bc1cfb0654c..41ab4f573a31 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -14,10 +14,12 @@ enum mmc_busy_cmd {
MMC_BUSY_CMD6,
MMC_BUSY_ERASE,
MMC_BUSY_HPI,
+ MMC_BUSY_EXTR_SINGLE,
};
struct mmc_host;
struct mmc_card;
+struct mmc_command;
int mmc_select_card(struct mmc_card *card);
int mmc_deselect_cards(struct mmc_host *host);
@@ -25,6 +27,8 @@ int mmc_set_dsr(struct mmc_host *host);
int mmc_go_idle(struct mmc_host *host);
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_set_relative_addr(struct mmc_card *card);
+int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode,
+ u32 args, void *buf, unsigned len);
int mmc_send_csd(struct mmc_card *card, u32 *csd);
int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries);
int mmc_send_status(struct mmc_card *card, u32 *status);
@@ -35,15 +39,19 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width);
int mmc_can_ext_csd(struct mmc_card *card);
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
+bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd,
+ unsigned int timeout_ms);
+int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+ int (*busy_cb)(void *cb_data, bool *busy),
+ void *cb_data);
int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
- enum mmc_busy_cmd busy_cmd);
+ bool retry_crc_err, enum mmc_busy_cmd busy_cmd);
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms, unsigned char timing,
bool send_status, bool retry_crc_err, unsigned int retries);
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms);
void mmc_run_bkops(struct mmc_card *card);
-int mmc_flush_cache(struct mmc_card *card);
int mmc_cmdq_enable(struct mmc_card *card);
int mmc_cmdq_disable(struct mmc_card *card);
int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 2c48d6504101..4646b7a03db6 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -66,6 +66,14 @@ static const unsigned int sd_au_size[] = {
__res & __mask; \
})
+#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000
+#define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000
+
+struct sd_busy_data {
+ struct mmc_card *card;
+ u8 *reg_buf;
+};
+
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
@@ -222,7 +230,9 @@ static int mmc_decode_scr(struct mmc_card *card)
else
card->erased_byte = 0x0;
- if (scr->sda_spec3)
+ if (scr->sda_spec4)
+ scr->cmds = UNSTUFF_BITS(resp, 32, 4);
+ else if (scr->sda_spec3)
scr->cmds = UNSTUFF_BITS(resp, 32, 2);
/* SD Spec says: any SD Card shall set at least bits 0 and 2 */
@@ -847,11 +857,13 @@ try_again:
return err;
/*
- * In case CCS and S18A in the response is set, start Signal Voltage
- * Switch procedure. SPI mode doesn't support CMD11.
+ * In case the S18A bit is set in the response, let's start the signal
+ * voltage switch procedure. SPI mode doesn't support CMD11.
+ * Note that, according to the spec, the S18A bit is not valid unless
+ * the CCS bit is set as well. We deliberately deviate from the spec in
+ * regards to this, which allows UHS-I to be supported for SDSC cards.
*/
- if (!mmc_host_is_spi(host) && rocr &&
- ((*rocr & 0x41000000) == 0x41000000)) {
+ if (!mmc_host_is_spi(host) && rocr && (*rocr & 0x01000000)) {
err = mmc_set_uhs_voltage(host, pocr);
if (err == -EAGAIN) {
retries--;
@@ -994,6 +1006,380 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card)
(SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50);
}
+static int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
+ u8 reg_data)
+{
+ struct mmc_host *host = card->host;
+ struct mmc_request mrq = {};
+ struct mmc_command cmd = {};
+ struct mmc_data data = {};
+ struct scatterlist sg;
+ u8 *reg_buf;
+
+ reg_buf = kzalloc(512, GFP_KERNEL);
+ if (!reg_buf)
+ return -ENOMEM;
+
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+ /*
+ * Arguments of CMD49:
+ * [31:31] MIO (0 = memory).
+ * [30:27] FNO (function number).
+ * [26:26] MW - mask write mode (0 = disable).
+ * [25:18] page number.
+ * [17:9] offset address.
+ * [8:0] length (0 = 1 byte).
+ */
+ cmd.arg = fno << 27 | page << 18 | offset << 9;
+
+ /* The first byte in the buffer is the data to be written. */
+ reg_buf[0] = reg_data;
+
+ data.flags = MMC_DATA_WRITE;
+ data.blksz = 512;
+ data.blocks = 1;
+ data.sg = &sg;
+ data.sg_len = 1;
+ sg_init_one(&sg, reg_buf, 512);
+
+ cmd.opcode = SD_WRITE_EXTR_SINGLE;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ mmc_set_data_timeout(&data, card);
+ mmc_wait_for_req(host, &mrq);
+
+ kfree(reg_buf);
+
+ /*
+ * Note that, the SD card is allowed to signal busy on DAT0 up to 1s
+ * after the CMD49. Although, let's leave this to be managed by the
+ * caller.
+ */
+
+ if (cmd.error)
+ return cmd.error;
+ if (data.error)
+ return data.error;
+
+ return 0;
+}
+
+static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page,
+ u16 offset, u16 len, u8 *reg_buf)
+{
+ u32 cmd_args;
+
+ /*
+ * Command arguments of CMD48:
+ * [31:31] MIO (0 = memory).
+ * [30:27] FNO (function number).
+ * [26:26] reserved (0).
+ * [25:18] page number.
+ * [17:9] offset address.
+ * [8:0] length (0 = 1 byte, 1ff = 512 bytes).
+ */
+ cmd_args = fno << 27 | page << 18 | offset << 9 | (len -1);
+
+ return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE,
+ cmd_args, reg_buf, 512);
+}
+
+static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page,
+ u16 offset)
+{
+ int err;
+ u8 *reg_buf;
+
+ reg_buf = kzalloc(512, GFP_KERNEL);
+ if (!reg_buf)
+ return -ENOMEM;
+
+ /* Read the extension register for power management function. */
+ err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf);
+ if (err) {
+ pr_warn("%s: error %d reading PM func of ext reg\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ /* PM revision consists of 4 bits. */
+ card->ext_power.rev = reg_buf[0] & 0xf;
+
+ /* Power Off Notification support at bit 4. */
+ if (reg_buf[1] & BIT(4))
+ card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY;
+
+ /* Power Sustenance support at bit 5. */
+ if (reg_buf[1] & BIT(5))
+ card->ext_power.feature_support |= SD_EXT_POWER_SUSTENANCE;
+
+ /* Power Down Mode support at bit 6. */
+ if (reg_buf[1] & BIT(6))
+ card->ext_power.feature_support |= SD_EXT_POWER_DOWN_MODE;
+
+ card->ext_power.fno = fno;
+ card->ext_power.page = page;
+ card->ext_power.offset = offset;
+
+out:
+ kfree(reg_buf);
+ return err;
+}
+
+static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page,
+ u16 offset)
+{
+ int err;
+ u8 *reg_buf;
+
+ reg_buf = kzalloc(512, GFP_KERNEL);
+ if (!reg_buf)
+ return -ENOMEM;
+
+ err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf);
+ if (err) {
+ pr_warn("%s: error %d reading PERF func of ext reg\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ /* PERF revision. */
+ card->ext_perf.rev = reg_buf[0];
+
+ /* FX_EVENT support at bit 0. */
+ if (reg_buf[1] & BIT(0))
+ card->ext_perf.feature_support |= SD_EXT_PERF_FX_EVENT;
+
+ /* Card initiated self-maintenance support at bit 0. */
+ if (reg_buf[2] & BIT(0))
+ card->ext_perf.feature_support |= SD_EXT_PERF_CARD_MAINT;
+
+ /* Host initiated self-maintenance support at bit 1. */
+ if (reg_buf[2] & BIT(1))
+ card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT;
+
+ /* Cache support at bit 0. */
+ if (reg_buf[4] & BIT(0))
+ card->ext_perf.feature_support |= SD_EXT_PERF_CACHE;
+
+ /* Command queue support indicated via queue depth bits (0 to 4). */
+ if (reg_buf[6] & 0x1f)
+ card->ext_perf.feature_support |= SD_EXT_PERF_CMD_QUEUE;
+
+ card->ext_perf.fno = fno;
+ card->ext_perf.page = page;
+ card->ext_perf.offset = offset;
+
+out:
+ kfree(reg_buf);
+ return err;
+}
+
+static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf,
+ u16 *next_ext_addr)
+{
+ u8 num_regs, fno, page;
+ u16 sfc, offset, ext = *next_ext_addr;
+ u32 reg_addr;
+
+ /*
+ * Parse only one register set per extension, as that is sufficient to
+ * support the standard functions. This means another 48 bytes in the
+ * buffer must be available.
+ */
+ if (ext + 48 > 512)
+ return -EFAULT;
+
+ /* Standard Function Code */
+ memcpy(&sfc, &gen_info_buf[ext], 2);
+
+ /* Address to the next extension. */
+ memcpy(next_ext_addr, &gen_info_buf[ext + 40], 2);
+
+ /* Number of registers for this extension. */
+ num_regs = gen_info_buf[ext + 42];
+
+ /* We support only one register per extension. */
+ if (num_regs != 1)
+ return 0;
+
+ /* Extension register address. */
+ memcpy(&reg_addr, &gen_info_buf[ext + 44], 4);
+
+ /* 9 bits (0 to 8) contains the offset address. */
+ offset = reg_addr & 0x1ff;
+
+ /* 8 bits (9 to 16) contains the page number. */
+ page = reg_addr >> 9 & 0xff ;
+
+ /* 4 bits (18 to 21) contains the function number. */
+ fno = reg_addr >> 18 & 0xf;
+
+ /* Standard Function Code for power management. */
+ if (sfc == 0x1)
+ return sd_parse_ext_reg_power(card, fno, page, offset);
+
+ /* Standard Function Code for performance enhancement. */
+ if (sfc == 0x2)
+ return sd_parse_ext_reg_perf(card, fno, page, offset);
+
+ return 0;
+}
+
+static int sd_read_ext_regs(struct mmc_card *card)
+{
+ int err, i;
+ u8 num_ext, *gen_info_buf;
+ u16 rev, len, next_ext_addr;
+
+ if (mmc_host_is_spi(card->host))
+ return 0;
+
+ if (!(card->scr.cmds & SD_SCR_CMD48_SUPPORT))
+ return 0;
+
+ gen_info_buf = kzalloc(512, GFP_KERNEL);
+ if (!gen_info_buf)
+ return -ENOMEM;
+
+ /*
+ * Read 512 bytes of general info, which is found at function number 0,
+ * at page 0 and with no offset.
+ */
+ err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf);
+ if (err) {
+ pr_warn("%s: error %d reading general info of SD ext reg\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ /* General info structure revision. */
+ memcpy(&rev, &gen_info_buf[0], 2);
+
+ /* Length of general info in bytes. */
+ memcpy(&len, &gen_info_buf[2], 2);
+
+ /* Number of extensions to be find. */
+ num_ext = gen_info_buf[4];
+
+ /* We support revision 0, but limit it to 512 bytes for simplicity. */
+ if (rev != 0 || len > 512) {
+ pr_warn("%s: non-supported SD ext reg layout\n",
+ mmc_hostname(card->host));
+ goto out;
+ }
+
+ /*
+ * Parse the extension registers. The first extension should start
+ * immediately after the general info header (16 bytes).
+ */
+ next_ext_addr = 16;
+ for (i = 0; i < num_ext; i++) {
+ err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr);
+ if (err) {
+ pr_warn("%s: error %d parsing SD ext reg\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+ }
+
+out:
+ kfree(gen_info_buf);
+ return err;
+}
+
+static bool sd_cache_enabled(struct mmc_host *host)
+{
+ return host->card->ext_perf.feature_enabled & SD_EXT_PERF_CACHE;
+}
+
+static int sd_flush_cache(struct mmc_host *host)
+{
+ struct mmc_card *card = host->card;
+ u8 *reg_buf, fno, page;
+ u16 offset;
+ int err;
+
+ if (!sd_cache_enabled(host))
+ return 0;
+
+ reg_buf = kzalloc(512, GFP_KERNEL);
+ if (!reg_buf)
+ return -ENOMEM;
+
+ /*
+ * Set Flush Cache at bit 0 in the performance enhancement register at
+ * 261 bytes offset.
+ */
+ fno = card->ext_perf.fno;
+ page = card->ext_perf.page;
+ offset = card->ext_perf.offset + 261;
+
+ err = sd_write_ext_reg(card, fno, page, offset, BIT(0));
+ if (err) {
+ pr_warn("%s: error %d writing Cache Flush bit\n",
+ mmc_hostname(host), err);
+ goto out;
+ }
+
+ err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false,
+ MMC_BUSY_EXTR_SINGLE);
+ if (err)
+ goto out;
+
+ /*
+ * Read the Flush Cache bit. The card shall reset it, to confirm that
+ * it's has completed the flushing of the cache.
+ */
+ err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf);
+ if (err) {
+ pr_warn("%s: error %d reading Cache Flush bit\n",
+ mmc_hostname(host), err);
+ goto out;
+ }
+
+ if (reg_buf[0] & BIT(0))
+ err = -ETIMEDOUT;
+out:
+ kfree(reg_buf);
+ return err;
+}
+
+static int sd_enable_cache(struct mmc_card *card)
+{
+ u8 *reg_buf;
+ int err;
+
+ card->ext_perf.feature_enabled &= ~SD_EXT_PERF_CACHE;
+
+ reg_buf = kzalloc(512, GFP_KERNEL);
+ if (!reg_buf)
+ return -ENOMEM;
+
+ /*
+ * Set Cache Enable at bit 0 in the performance enhancement register at
+ * 260 bytes offset.
+ */
+ err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page,
+ card->ext_perf.offset + 260, BIT(0));
+ if (err) {
+ pr_warn("%s: error %d writing Cache Enable bit\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false,
+ MMC_BUSY_EXTR_SINGLE);
+ if (!err)
+ card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE;
+
+out:
+ kfree(reg_buf);
+ return err;
+}
+
/*
* Handle the detection and initialisation of a card.
*
@@ -1142,6 +1528,20 @@ retry:
}
}
+ if (!oldcard) {
+ /* Read/parse the extension registers. */
+ err = sd_read_ext_regs(card);
+ if (err)
+ goto free_card;
+ }
+
+ /* Enable internal SD cache if supported. */
+ if (card->ext_perf.feature_support & SD_EXT_PERF_CACHE) {
+ err = sd_enable_cache(card);
+ if (err)
+ goto free_card;
+ }
+
if (host->cqe_ops && !host->cqe_enabled) {
err = host->cqe_ops->cqe_enable(host, card);
if (!err) {
@@ -1213,21 +1613,84 @@ static void mmc_sd_detect(struct mmc_host *host)
}
}
+static int sd_can_poweroff_notify(struct mmc_card *card)
+{
+ return card->ext_power.feature_support & SD_EXT_POWER_OFF_NOTIFY;
+}
+
+static int sd_busy_poweroff_notify_cb(void *cb_data, bool *busy)
+{
+ struct sd_busy_data *data = cb_data;
+ struct mmc_card *card = data->card;
+ int err;
+
+ /*
+ * Read the status register for the power management function. It's at
+ * one byte offset and is one byte long. The Power Off Notification
+ * Ready is bit 0.
+ */
+ err = sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page,
+ card->ext_power.offset + 1, 1, data->reg_buf);
+ if (err) {
+ pr_warn("%s: error %d reading status reg of PM func\n",
+ mmc_hostname(card->host), err);
+ return err;
+ }
+
+ *busy = !(data->reg_buf[0] & BIT(0));
+ return 0;
+}
+
+static int sd_poweroff_notify(struct mmc_card *card)
+{
+ struct sd_busy_data cb_data;
+ u8 *reg_buf;
+ int err;
+
+ reg_buf = kzalloc(512, GFP_KERNEL);
+ if (!reg_buf)
+ return -ENOMEM;
+
+ /*
+ * Set the Power Off Notification bit in the power management settings
+ * register at 2 bytes offset.
+ */
+ err = sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page,
+ card->ext_power.offset + 2, BIT(0));
+ if (err) {
+ pr_warn("%s: error %d writing Power Off Notify bit\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ cb_data.card = card;
+ cb_data.reg_buf = reg_buf;
+ err = __mmc_poll_for_busy(card, SD_POWEROFF_NOTIFY_TIMEOUT_MS,
+ &sd_busy_poweroff_notify_cb, &cb_data);
+
+out:
+ kfree(reg_buf);
+ return err;
+}
+
static int _mmc_sd_suspend(struct mmc_host *host)
{
+ struct mmc_card *card = host->card;
int err = 0;
mmc_claim_host(host);
- if (mmc_card_suspended(host->card))
+ if (mmc_card_suspended(card))
goto out;
- if (!mmc_host_is_spi(host))
+ if (sd_can_poweroff_notify(card))
+ err = sd_poweroff_notify(card);
+ else if (!mmc_host_is_spi(host))
err = mmc_deselect_cards(host);
if (!err) {
mmc_power_off(host);
- mmc_card_set_suspended(host->card);
+ mmc_card_set_suspended(card);
}
out:
@@ -1331,6 +1794,8 @@ static const struct mmc_bus_ops mmc_sd_ops = {
.alive = mmc_sd_alive,
.shutdown = mmc_sd_suspend,
.hw_reset = mmc_sd_hw_reset,
+ .cache_enabled = sd_cache_enabled,
+ .flush_cache = sd_flush_cache,
};
/*
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index d61ff811218c..ef8d1dce5af1 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -17,6 +17,7 @@
#include "core.h"
#include "sd_ops.h"
+#include "mmc_ops.h"
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
{
@@ -309,43 +310,18 @@ int mmc_app_send_scr(struct mmc_card *card)
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp)
{
- struct mmc_request mrq = {};
- struct mmc_command cmd = {};
- struct mmc_data data = {};
- struct scatterlist sg;
+ u32 cmd_args;
/* NOTE: caller guarantees resp is heap-allocated */
mode = !!mode;
value &= 0xF;
+ cmd_args = mode << 31 | 0x00FFFFFF;
+ cmd_args &= ~(0xF << (group * 4));
+ cmd_args |= value << (group * 4);
- mrq.cmd = &cmd;
- mrq.data = &data;
-
- cmd.opcode = SD_SWITCH;
- cmd.arg = mode << 31 | 0x00FFFFFF;
- cmd.arg &= ~(0xF << (group * 4));
- cmd.arg |= value << (group * 4);
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-
- data.blksz = 64;
- data.blocks = 1;
- data.flags = MMC_DATA_READ;
- data.sg = &sg;
- data.sg_len = 1;
-
- sg_init_one(&sg, resp, 64);
-
- mmc_set_data_timeout(&data, card);
-
- mmc_wait_for_req(card->host, &mrq);
-
- if (cmd.error)
- return cmd.error;
- if (data.error)
- return data.error;
-
- return 0;
+ return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp,
+ 64);
}
int mmc_app_sd_status(struct mmc_card *card, void *ssr)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 3eb94ac2712e..68edf7a615be 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -937,11 +937,9 @@ static void mmc_sdio_detect(struct mmc_host *host)
/* Make sure card is powered before detecting it */
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
- err = pm_runtime_get_sync(&host->card->dev);
- if (err < 0) {
- pm_runtime_put_noidle(&host->card->dev);
+ err = pm_runtime_resume_and_get(&host->card->dev);
+ if (err < 0)
goto out;
- }
}
mmc_claim_host(host);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index a4d4c757eea0..71313961cc54 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -329,7 +329,7 @@ config MMC_SDHCI_S3C
config MMC_SDHCI_PXAV3
tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
- depends on CLKDEV_LOOKUP
+ depends on HAVE_CLK
depends on MMC_SDHCI_PLTFM
depends on ARCH_BERLIN || ARCH_MMP || ARCH_MVEBU || COMPILE_TEST
default CPU_MMP2
@@ -342,7 +342,7 @@ config MMC_SDHCI_PXAV3
config MMC_SDHCI_PXAV2
tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
- depends on CLKDEV_LOOKUP
+ depends on HAVE_CLK
depends on MMC_SDHCI_PLTFM
depends on ARCH_MMP || COMPILE_TEST
default CPU_PXA910
@@ -412,7 +412,7 @@ config MMC_SDHCI_MILBEAUT
config MMC_SDHCI_IPROC
tristate "SDHCI support for the BCM2835 & iProc SD/MMC Controller"
- depends on ARCH_BCM2835 || ARCH_BCM_IPROC || COMPILE_TEST
+ depends on ARCH_BCM2835 || ARCH_BCM_IPROC || ARCH_BRCMSTB || COMPILE_TEST
depends on MMC_SDHCI_PLTFM
depends on OF || ACPI
default ARCH_BCM_IPROC
diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c
index 93b0432bb601..38559a956330 100644
--- a/drivers/mmc/host/cqhci-core.c
+++ b/drivers/mmc/host/cqhci-core.c
@@ -45,17 +45,23 @@ static inline u8 *get_link_desc(struct cqhci_host *cq_host, u8 tag)
return desc + cq_host->task_desc_len;
}
+static inline size_t get_trans_desc_offset(struct cqhci_host *cq_host, u8 tag)
+{
+ return cq_host->trans_desc_len * cq_host->mmc->max_segs * tag;
+}
+
static inline dma_addr_t get_trans_desc_dma(struct cqhci_host *cq_host, u8 tag)
{
- return cq_host->trans_desc_dma_base +
- (cq_host->mmc->max_segs * tag *
- cq_host->trans_desc_len);
+ size_t offset = get_trans_desc_offset(cq_host, tag);
+
+ return cq_host->trans_desc_dma_base + offset;
}
static inline u8 *get_trans_desc(struct cqhci_host *cq_host, u8 tag)
{
- return cq_host->trans_desc_base +
- (cq_host->trans_desc_len * cq_host->mmc->max_segs * tag);
+ size_t offset = get_trans_desc_offset(cq_host, tag);
+
+ return cq_host->trans_desc_base + offset;
}
static void setup_trans_desc(struct cqhci_host *cq_host, u8 tag)
@@ -146,7 +152,7 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host)
}
/*
- * The allocated descriptor table for task, link & transfer descritors
+ * The allocated descriptor table for task, link & transfer descriptors
* looks like:
* |----------|
* |task desc | |->|----------|
@@ -194,8 +200,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)
cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots;
- cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs *
- cq_host->mmc->cqe_qdepth;
+ cq_host->data_size = get_trans_desc_offset(cq_host, cq_host->mmc->cqe_qdepth);
pr_debug("%s: cqhci: desc_size: %zu data_sz: %zu slot-sz: %d\n",
mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size,
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 73731cd3ba23..9901208be797 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -17,7 +17,6 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/of.h>
-#include <linux/clk.h>
#include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index b3c636edbb46..0db17bcc9c16 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -674,7 +674,7 @@ static void jz4740_mmc_send_command(struct jz4740_mmc_host *host,
cmdat |= JZ_MMC_CMDAT_WRITE;
if (host->use_dma) {
/*
- * The 4780's MMC controller has integrated DMA ability
+ * The JZ4780's MMC controller has integrated DMA ability
* in addition to being able to use the external DMA
* controller. It moves DMA control bits to a separate
* register. The DMA_SEL bit chooses the external
@@ -866,7 +866,7 @@ static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate)
writew(div, host->base + JZ_REG_MMC_CLKRT);
if (real_rate > 25000000) {
- if (host->version >= JZ_MMC_X1000) {
+ if (host->version >= JZ_MMC_JZ4780) {
writel(JZ_MMC_LPM_DRV_RISING_QTR_PHASE_DLY |
JZ_MMC_LPM_SMP_RISING_QTR_OR_HALF_PHASE_DLY |
JZ_MMC_LPM_LOW_POWER_MODE_EN,
@@ -959,6 +959,7 @@ static const struct of_device_id jz4740_mmc_of_match[] = {
{ .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
{ .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B },
{ .compatible = "ingenic,jz4760-mmc", .data = (void *) JZ_MMC_JZ4760 },
+ { .compatible = "ingenic,jz4775-mmc", .data = (void *) JZ_MMC_JZ4780 },
{ .compatible = "ingenic,jz4780-mmc", .data = (void *) JZ_MMC_JZ4780 },
{ .compatible = "ingenic,x1000-mmc", .data = (void *) JZ_MMC_X1000 },
{},
@@ -1013,7 +1014,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
host->base = devm_ioremap_resource(&pdev->dev, host->mem_res);
if (IS_ERR(host->base)) {
ret = PTR_ERR(host->base);
- dev_err(&pdev->dev, "Failed to ioremap base memory\n");
goto err_free_host;
}
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 016a6106151a..3f28eb4d17fe 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -165,6 +165,7 @@ struct meson_host {
unsigned int bounce_buf_size;
void *bounce_buf;
+ void __iomem *bounce_iomem_buf;
dma_addr_t bounce_dma_addr;
struct sd_emmc_desc *descs;
dma_addr_t descs_dma_addr;
@@ -745,6 +746,47 @@ static void meson_mmc_desc_chain_transfer(struct mmc_host *mmc, u32 cmd_cfg)
writel(start, host->regs + SD_EMMC_START);
}
+/* local sg copy to buffer version with _to/fromio usage for dram_access_quirk */
+static void meson_mmc_copy_buffer(struct meson_host *host, struct mmc_data *data,
+ size_t buflen, bool to_buffer)
+{
+ unsigned int sg_flags = SG_MITER_ATOMIC;
+ struct scatterlist *sgl = data->sg;
+ unsigned int nents = data->sg_len;
+ struct sg_mapping_iter miter;
+ unsigned int offset = 0;
+
+ if (to_buffer)
+ sg_flags |= SG_MITER_FROM_SG;
+ else
+ sg_flags |= SG_MITER_TO_SG;
+
+ sg_miter_start(&miter, sgl, nents, sg_flags);
+
+ while ((offset < buflen) && sg_miter_next(&miter)) {
+ unsigned int len;
+
+ len = min(miter.length, buflen - offset);
+
+ /* When dram_access_quirk, the bounce buffer is a iomem mapping */
+ if (host->dram_access_quirk) {
+ if (to_buffer)
+ memcpy_toio(host->bounce_iomem_buf + offset, miter.addr, len);
+ else
+ memcpy_fromio(miter.addr, host->bounce_iomem_buf + offset, len);
+ } else {
+ if (to_buffer)
+ memcpy(host->bounce_buf + offset, miter.addr, len);
+ else
+ memcpy(miter.addr, host->bounce_buf + offset, len);
+ }
+
+ offset += len;
+ }
+
+ sg_miter_stop(&miter);
+}
+
static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
{
struct meson_host *host = mmc_priv(mmc);
@@ -788,8 +830,7 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
if (data->flags & MMC_DATA_WRITE) {
cmd_cfg |= CMD_CFG_DATA_WR;
WARN_ON(xfer_bytes > host->bounce_buf_size);
- sg_copy_to_buffer(data->sg, data->sg_len,
- host->bounce_buf, xfer_bytes);
+ meson_mmc_copy_buffer(host, data, xfer_bytes, true);
dma_wmb();
}
@@ -958,8 +999,7 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
if (meson_mmc_bounce_buf_read(data)) {
xfer_bytes = data->blksz * data->blocks;
WARN_ON(xfer_bytes > host->bounce_buf_size);
- sg_copy_from_buffer(data->sg, data->sg_len,
- host->bounce_buf, xfer_bytes);
+ meson_mmc_copy_buffer(host, data, xfer_bytes, false);
}
next_cmd = meson_mmc_get_next_command(cmd);
@@ -1179,7 +1219,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
* instead of the DDR memory
*/
host->bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN;
- host->bounce_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF;
+ host->bounce_iomem_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF;
host->bounce_dma_addr = res->start + SD_EMMC_SRAM_DATA_BUF_OFF;
} else {
/* data bounce buffer */
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 9776a03a10f5..65c65bb5737f 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -504,7 +504,7 @@ mmc_spi_command_send(struct mmc_spi_host *host,
/* else: R1 (most commands) */
}
- dev_dbg(&host->spi->dev, " mmc_spi: CMD%d, resp %s\n",
+ dev_dbg(&host->spi->dev, " CMD%d, resp %s\n",
cmd->opcode, maptype(cmd));
/* send command, leaving chipselect active */
@@ -928,8 +928,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
while (length) {
t->len = min(length, blk_size);
- dev_dbg(&host->spi->dev,
- " mmc_spi: %s block, %d bytes\n",
+ dev_dbg(&host->spi->dev, " %s block, %d bytes\n",
(direction == DMA_TO_DEVICE) ? "write" : "read",
t->len);
@@ -974,7 +973,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
int tmp;
const unsigned statlen = sizeof(scratch->status);
- dev_dbg(&spi->dev, " mmc_spi: STOP_TRAN\n");
+ dev_dbg(&spi->dev, " STOP_TRAN\n");
/* Tweak the per-block message we set up earlier by morphing
* it to hold single buffer with the token followed by some
@@ -1175,7 +1174,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
canpower = host->pdata && host->pdata->setpower;
- dev_dbg(&host->spi->dev, "mmc_spi: power %s (%d)%s\n",
+ dev_dbg(&host->spi->dev, "power %s (%d)%s\n",
mmc_powerstring(ios->power_mode),
ios->vdd,
canpower ? ", can switch" : "");
@@ -1248,8 +1247,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->spi->max_speed_hz = ios->clock;
status = spi_setup(host->spi);
- dev_dbg(&host->spi->dev,
- "mmc_spi: clock to %d Hz, %d\n",
+ dev_dbg(&host->spi->dev, " clock to %d Hz, %d\n",
host->spi->max_speed_hz, status);
}
}
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 898ed1b023df..4dfc246c5f95 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -724,10 +724,8 @@ static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
writel(lower_32_bits(dma->gpd_addr), host->base + MSDC_DMA_SA);
}
-static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
+static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data)
{
- struct mmc_data *data = mrq->data;
-
if (!(data->host_cookie & MSDC_PREPARE_FLAG)) {
data->host_cookie |= MSDC_PREPARE_FLAG;
data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len,
@@ -735,10 +733,8 @@ static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
}
}
-static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
+static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data)
{
- struct mmc_data *data = mrq->data;
-
if (data->host_cookie & MSDC_ASYNC_FLAG)
return;
@@ -1140,7 +1136,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
msdc_track_cmd_data(host, mrq->cmd, mrq->data);
if (mrq->data)
- msdc_unprepare_data(host, mrq);
+ msdc_unprepare_data(host, mrq->data);
if (host->error)
msdc_reset_hw(host);
mmc_request_done(mmc_from_priv(host), mrq);
@@ -1311,7 +1307,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->mrq = mrq;
if (mrq->data)
- msdc_prepare_data(host, mrq);
+ msdc_prepare_data(host, mrq->data);
/* if SBC is required, we have HW option and SW option.
* if HW option is enabled, and SBC does not have "special" flags,
@@ -1332,7 +1328,7 @@ static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
if (!data)
return;
- msdc_prepare_data(host, mrq);
+ msdc_prepare_data(host, data);
data->host_cookie |= MSDC_ASYNC_FLAG;
}
@@ -1340,19 +1336,18 @@ static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
int err)
{
struct msdc_host *host = mmc_priv(mmc);
- struct mmc_data *data;
+ struct mmc_data *data = mrq->data;
- data = mrq->data;
if (!data)
return;
+
if (data->host_cookie) {
data->host_cookie &= ~MSDC_ASYNC_FLAG;
- msdc_unprepare_data(host, mrq);
+ msdc_unprepare_data(host, data);
}
}
-static void msdc_data_xfer_next(struct msdc_host *host,
- struct mmc_request *mrq, struct mmc_data *data)
+static void msdc_data_xfer_next(struct msdc_host *host, struct mmc_request *mrq)
{
if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error &&
!mrq->sbc)
@@ -1411,7 +1406,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
(int)data->error, data->bytes_xfered);
}
- msdc_data_xfer_next(host, mrq, data);
+ msdc_data_xfer_next(host, mrq);
done = true;
}
return done;
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index 9d480a05f655..3629550528b6 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -22,8 +22,8 @@
MODULE_LICENSE("GPL");
struct of_mmc_spi {
- int detect_irq;
struct mmc_spi_platform_data pdata;
+ int detect_irq;
};
static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index baab4c2e1b53..e49ca0f7fe9a 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -704,7 +704,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode)
set_bit(i, priv->smpcmp);
if (cmd_error)
- mmc_abort_tuning(mmc, opcode);
+ mmc_send_abort_tuning(mmc, opcode);
}
ret = renesas_sdhi_select_tuning(host);
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 0ca6f6d30b75..8d5929a32d34 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1578,17 +1578,12 @@ static int s3cmci_probe(struct platform_device *pdev)
goto probe_iounmap;
}
- if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
+ if (request_irq(host->irq, s3cmci_irq, IRQF_NO_AUTOEN, DRIVER_NAME, host)) {
dev_err(&pdev->dev, "failed to request mci interrupt.\n");
ret = -ENOENT;
goto probe_iounmap;
}
- /* We get spurious interrupts even when we have set the IMSK
- * register to ignore everything, so use disable_irq() to make
- * ensure we don't lock the system with un-serviceable requests. */
-
- disable_irq(host->irq);
host->irq_state = false;
/* Depending on the dma state, get a DMA channel to use. */
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index c3fbf8c825c4..8fe65f172a61 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -822,6 +822,17 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = {
},
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
},
+ {
+ /*
+ * The Toshiba WT8-B's microSD slot always reports the card being
+ * write-protected.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA ENCORE 2 WT8-B"),
+ },
+ .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
+ },
{} /* Terminating entry */
};
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index b991cf0e60c5..72c0bf0c1887 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -324,11 +324,6 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
return data->socdata == &esdhc_imx53_data;
}
-static inline int is_imx6q_usdhc(struct pltfm_imx_data *data)
-{
- return data->socdata == &usdhc_imx6q_data;
-}
-
static inline int esdhc_is_usdhc(struct pltfm_imx_data *data)
{
return !!(data->socdata->flags & ESDHC_FLAG_USDHC);
@@ -427,9 +422,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
| FIELD_PREP(SDHCI_RETUNING_MODE_MASK,
SDHCI_TUNING_MODE_3);
- if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
- val |= SDHCI_SUPPORT_HS400;
-
/*
* Do not advertise faster UHS modes if there are no
* pinctrl states for 100MHz/200MHz.
@@ -1591,7 +1583,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
- host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
+ host->mmc->caps2 |= MMC_CAP2_HS400;
if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;
@@ -1628,6 +1620,14 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (err)
goto disable_ahb_clk;
+ /*
+ * Setup the wakeup capability here, let user to decide
+ * whether need to enable this wakeup through sysfs interface.
+ */
+ if ((host->mmc->pm_caps & MMC_PM_KEEP_POWER) &&
+ (host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ))
+ device_set_wakeup_capable(&pdev->dev, true);
+
pm_runtime_set_active(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev);
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index ddeaf8e1f72f..cce390fe9cf3 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -286,11 +286,35 @@ static const struct sdhci_iproc_data bcm2711_data = {
.mmc_caps = MMC_CAP_3_3V_DDR,
};
+static const struct sdhci_pltfm_data sdhci_bcm7211a0_pltfm_data = {
+ .quirks = SDHCI_QUIRK_MISSING_CAPS |
+ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ SDHCI_QUIRK_BROKEN_DMA |
+ SDHCI_QUIRK_BROKEN_ADMA,
+ .ops = &sdhci_iproc_ops,
+};
+
+#define BCM7211A0_BASE_CLK_MHZ 100
+static const struct sdhci_iproc_data bcm7211a0_data = {
+ .pdata = &sdhci_bcm7211a0_pltfm_data,
+ .caps = ((BCM7211A0_BASE_CLK_MHZ / 2) << SDHCI_TIMEOUT_CLK_SHIFT) |
+ (BCM7211A0_BASE_CLK_MHZ << SDHCI_CLOCK_BASE_SHIFT) |
+ ((0x2 << SDHCI_MAX_BLOCK_SHIFT)
+ & SDHCI_MAX_BLOCK_MASK) |
+ SDHCI_CAN_VDD_330 |
+ SDHCI_CAN_VDD_180 |
+ SDHCI_CAN_DO_SUSPEND |
+ SDHCI_CAN_DO_HISPD,
+ .caps1 = SDHCI_DRIVER_TYPE_C |
+ SDHCI_DRIVER_TYPE_D,
+};
+
static const struct of_device_id sdhci_iproc_of_match[] = {
{ .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
{ .compatible = "brcm,bcm2711-emmc2", .data = &bcm2711_data },
{ .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
{ .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
+ { .compatible = "brcm,bcm7211a0-sdhci", .data = &bcm7211a0_data },
{ }
};
MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match);
@@ -384,6 +408,11 @@ err:
return ret;
}
+static void sdhci_iproc_shutdown(struct platform_device *pdev)
+{
+ sdhci_pltfm_suspend(&pdev->dev);
+}
+
static struct platform_driver sdhci_iproc_driver = {
.driver = {
.name = "sdhci-iproc",
@@ -394,6 +423,7 @@ static struct platform_driver sdhci_iproc_driver = {
},
.probe = sdhci_iproc_probe,
.remove = sdhci_pltfm_unregister,
+ .shutdown = sdhci_iproc_shutdown,
};
module_platform_driver(sdhci_iproc_driver);
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index 839965f7c717..0e7c07ed9690 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -1542,6 +1542,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
}
}
+ sdhci_get_of_property(pdev);
+
sdhci_arasan->clk_ahb = devm_clk_get(dev, "clk_ahb");
if (IS_ERR(sdhci_arasan->clk_ahb)) {
ret = dev_err_probe(dev, PTR_ERR(sdhci_arasan->clk_ahb),
@@ -1561,14 +1563,22 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
goto err_pltfm_free;
}
+ /* If clock-frequency property is set, use the provided value */
+ if (pltfm_host->clock &&
+ pltfm_host->clock != clk_get_rate(clk_xin)) {
+ ret = clk_set_rate(clk_xin, pltfm_host->clock);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to set SD clock rate\n");
+ goto clk_dis_ahb;
+ }
+ }
+
ret = clk_prepare_enable(clk_xin);
if (ret) {
dev_err(dev, "Unable to enable SD clock.\n");
goto clk_dis_ahb;
}
- sdhci_get_of_property(pdev);
-
if (of_property_read_bool(np, "xlnx,fails-without-test-cd"))
sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST;
diff --git a/drivers/mmc/host/sdhci-of-aspeed-test.c b/drivers/mmc/host/sdhci-of-aspeed-test.c
index bb67d159b7d8..1ed4f86291f2 100644
--- a/drivers/mmc/host/sdhci-of-aspeed-test.c
+++ b/drivers/mmc/host/sdhci-of-aspeed-test.c
@@ -26,23 +26,23 @@ static void aspeed_sdhci_phase_ddr52(struct kunit *test)
KUNIT_EXPECT_EQ(test, 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 25));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 0,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 0,
aspeed_sdhci_phase_to_tap(NULL, rate, 180));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 0,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 0,
aspeed_sdhci_phase_to_tap(NULL, rate, 181));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
aspeed_sdhci_phase_to_tap(NULL, rate, 182));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
aspeed_sdhci_phase_to_tap(NULL, rate, 183));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 2,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 2,
aspeed_sdhci_phase_to_tap(NULL, rate, 184));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 3,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 3,
aspeed_sdhci_phase_to_tap(NULL, rate, 185));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 14,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 14,
aspeed_sdhci_phase_to_tap(NULL, rate, 203));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 204));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 205));
}
@@ -67,21 +67,21 @@ static void aspeed_sdhci_phase_hs200(struct kunit *test)
KUNIT_EXPECT_EQ(test, 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 96));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK,
aspeed_sdhci_phase_to_tap(NULL, rate, 180));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK,
aspeed_sdhci_phase_to_tap(NULL, rate, 185));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
aspeed_sdhci_phase_to_tap(NULL, rate, 186));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
aspeed_sdhci_phase_to_tap(NULL, rate, 187));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 14,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 14,
aspeed_sdhci_phase_to_tap(NULL, rate, 269));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 270));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 271));
- KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+ KUNIT_EXPECT_EQ(test, ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
aspeed_sdhci_phase_to_tap(NULL, rate, 276));
}
diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c
index d001c51074a0..6e4e132903a6 100644
--- a/drivers/mmc/host/sdhci-of-aspeed.c
+++ b/drivers/mmc/host/sdhci-of-aspeed.c
@@ -31,6 +31,11 @@
#define ASPEED_SDC_S0_PHASE_OUT_EN GENMASK(1, 0)
#define ASPEED_SDC_PHASE_MAX 31
+/* SDIO{10,20} */
+#define ASPEED_SDC_CAP1_1_8V (0 * 32 + 26)
+/* SDIO{14,24} */
+#define ASPEED_SDC_CAP2_SDR104 (1 * 32 + 1)
+
struct aspeed_sdc {
struct clk *clk;
struct resource *res;
@@ -72,6 +77,37 @@ struct aspeed_sdhci {
const struct aspeed_sdhci_phase_desc *phase_desc;
};
+/*
+ * The function sets the mirror register for updating
+ * capbilities of the current slot.
+ *
+ * slot | capability | caps_reg | mirror_reg
+ * -----|-------------|----------|------------
+ * 0 | CAP1_1_8V | SDIO140 | SDIO10
+ * 0 | CAP2_SDR104 | SDIO144 | SDIO14
+ * 1 | CAP1_1_8V | SDIO240 | SDIO20
+ * 1 | CAP2_SDR104 | SDIO244 | SDIO24
+ */
+static void aspeed_sdc_set_slot_capability(struct sdhci_host *host, struct aspeed_sdc *sdc,
+ int capability, bool enable, u8 slot)
+{
+ u32 mirror_reg_offset;
+ u32 cap_val;
+ u8 cap_reg;
+
+ if (slot > 1)
+ return;
+
+ cap_reg = capability / 32;
+ cap_val = sdhci_readl(host, 0x40 + (cap_reg * 4));
+ if (enable)
+ cap_val |= BIT(capability % 32);
+ else
+ cap_val &= ~BIT(capability % 32);
+ mirror_reg_offset = ((slot + 1) * 0x10) + (cap_reg * 4);
+ writel(cap_val, sdc->regs + mirror_reg_offset);
+}
+
static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc,
struct aspeed_sdhci *sdhci,
bool bus8)
@@ -150,7 +186,7 @@ static int aspeed_sdhci_phase_to_tap(struct device *dev, unsigned long rate_hz,
tap = div_u64(phase_period_ps, prop_delay_ps);
if (tap > ASPEED_SDHCI_NR_TAPS) {
- dev_warn(dev,
+ dev_dbg(dev,
"Requested out of range phase tap %d for %d degrees of phase compensation at %luHz, clamping to tap %d\n",
tap, phase_deg, rate_hz, ASPEED_SDHCI_NR_TAPS);
tap = ASPEED_SDHCI_NR_TAPS;
@@ -328,6 +364,7 @@ static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev,
static int aspeed_sdhci_probe(struct platform_device *pdev)
{
const struct aspeed_sdhci_pdata *aspeed_pdata;
+ struct device_node *np = pdev->dev.of_node;
struct sdhci_pltfm_host *pltfm_host;
struct aspeed_sdhci *dev;
struct sdhci_host *host;
@@ -372,6 +409,17 @@ static int aspeed_sdhci_probe(struct platform_device *pdev)
sdhci_get_of_property(pdev);
+ if (of_property_read_bool(np, "mmc-hs200-1_8v") ||
+ of_property_read_bool(np, "sd-uhs-sdr104")) {
+ aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP1_1_8V,
+ true, slot);
+ }
+
+ if (of_property_read_bool(np, "sd-uhs-sdr104")) {
+ aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP2_SDR104,
+ true, slot);
+ }
+
pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pltfm_host->clk))
return PTR_ERR(pltfm_host->clk);
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 7893fd3599b6..8f4d1f003f65 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -1173,10 +1173,9 @@ static int sdhci_omap_probe(struct platform_device *pdev)
* as part of pm_runtime_get_sync.
*/
pm_runtime_enable(dev);
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret) {
dev_err(dev, "pm_runtime_get_sync failed\n");
- pm_runtime_put_noidle(dev);
goto err_rpm_disable;
}
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index 061618aa247f..4fd99c1e82ba 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -94,7 +94,7 @@
#define PCIE_GLI_9763E_CFG2 0x8A4
#define GLI_9763E_CFG2_L1DLY GENMASK(28, 19)
-#define GLI_9763E_CFG2_L1DLY_MID 0x50
+#define GLI_9763E_CFG2_L1DLY_MID 0x54
#define PCIE_GLI_9763E_MMC_CTRL 0x960
#define GLI_9763E_HS400_SLOW BIT(3)
@@ -847,7 +847,7 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value);
value &= ~GLI_9763E_CFG2_L1DLY;
- /* set ASPM L1 entry delay to 20us */
+ /* set ASPM L1 entry delay to 21us */
value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID);
pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value);
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index 5dc36efff47f..11e375579cfb 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -393,6 +393,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host,
static struct sdhci_ops sdhci_sprd_ops = {
.read_l = sdhci_sprd_readl,
.write_l = sdhci_sprd_writel,
+ .write_w = sdhci_sprd_writew,
.write_b = sdhci_sprd_writeb,
.set_clock = sdhci_sprd_set_clock,
.get_max_clock = sdhci_sprd_get_max_clock,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index bf238ade1602..aba6e10b8605 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1812,6 +1812,10 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
u16 preset = 0;
switch (host->timing) {
+ case MMC_TIMING_MMC_HS:
+ case MMC_TIMING_SD_HS:
+ preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED);
+ break;
case MMC_TIMING_UHS_SDR12:
preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
break;
@@ -2680,7 +2684,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
sdhci_end_tuning(host);
- mmc_abort_tuning(host->mmc, opcode);
+ mmc_send_abort_tuning(host->mmc, opcode);
}
EXPORT_SYMBOL_GPL(sdhci_abort_tuning);
@@ -4072,9 +4076,13 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
bounce_size,
DMA_BIDIRECTIONAL);
ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr);
- if (ret)
+ if (ret) {
+ devm_kfree(mmc_dev(mmc), host->bounce_buffer);
+ host->bounce_buffer = NULL;
/* Again fall back to max_segs == 1 */
return;
+ }
+
host->bounce_buffer_size = bounce_size;
/* Lie about this since we're bouncing */
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 0770c036e2ff..074dc182b184 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -201,8 +201,10 @@
#define SDHCI_CAPABILITIES 0x40
#define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0)
+#define SDHCI_TIMEOUT_CLK_SHIFT 0
#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
#define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8)
+#define SDHCI_CLOCK_BASE_SHIFT 8
#define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8)
#define SDHCI_MAX_BLOCK_MASK 0x00030000
#define SDHCI_MAX_BLOCK_SHIFT 16
@@ -253,6 +255,7 @@
/* 60-FB reserved */
+#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64
#define SDHCI_PRESET_FOR_SDR12 0x66
#define SDHCI_PRESET_FOR_SDR25 0x68
#define SDHCI_PRESET_FOR_SDR50 0x6A
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index 1fad6e442688..f654afbe8e83 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -809,11 +809,9 @@ static int sdhci_am654_probe(struct platform_device *pdev)
/* Clocks are enabled using pm_runtime */
pm_runtime_enable(dev);
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- pm_runtime_put_noidle(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
goto pm_runtime_disable;
- }
base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(base)) {
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index 615f3d008af1..b9b79b1089a0 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1801,6 +1801,7 @@ static int usdhi6_probe(struct platform_device *pdev)
version = usdhi6_read(host, USDHI6_VERSION);
if ((version & 0xfff) != 0xa0d) {
+ ret = -EPERM;
dev_err(dev, "Version not recognized %x\n", version);
goto e_clk_off;
}
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index a1d098560099..c32df5530b94 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -857,6 +857,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask)
{
BUG_ON(intmask == 0);
+ if (!host->data)
+ return;
+
if (intmask & VIA_CRDR_SDSTS_DT)
host->data->error = -ETIMEDOUT;
else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC))
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index 739cf63ef6e2..4950d10d3a19 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface,
if (retval < 0)
goto error5;
retval =
- usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
+ usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_ROM_WAIT_STATES,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
firmware_rom_wait_states, 0x0000, NULL, 0, HZ);