aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/Kconfig18
-rw-r--r--drivers/mmc/core/Makefile2
-rw-r--r--drivers/mmc/core/bus.c114
-rw-r--r--drivers/mmc/core/cd-gpio.c74
-rw-r--r--drivers/mmc/core/core.c1330
-rw-r--r--drivers/mmc/core/core.h13
-rw-r--r--drivers/mmc/core/debugfs.c34
-rw-r--r--drivers/mmc/core/host.c189
-rw-r--r--drivers/mmc/core/host.h1
-rw-r--r--drivers/mmc/core/mmc.c1195
-rw-r--r--drivers/mmc/core/mmc_ops.c270
-rw-r--r--drivers/mmc/core/mmc_ops.h1
-rw-r--r--drivers/mmc/core/quirks.c8
-rw-r--r--drivers/mmc/core/sd.c454
-rw-r--r--drivers/mmc/core/sd.h1
-rw-r--r--drivers/mmc/core/sdio.c234
-rw-r--r--drivers/mmc/core/sdio_bus.c55
-rw-r--r--drivers/mmc/core/sdio_cis.c2
-rw-r--r--drivers/mmc/core/sdio_io.c10
-rw-r--r--drivers/mmc/core/sdio_irq.c63
-rw-r--r--drivers/mmc/core/sdio_ops.c32
-rw-r--r--drivers/mmc/core/slot-gpio.c355
22 files changed, 2811 insertions, 1644 deletions
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index ef103871517..9ebee72d9c3 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -2,24 +2,8 @@
# MMC core configuration
#
-config MMC_UNSAFE_RESUME
- bool "Assume MMC/SD cards are non-removable (DANGEROUS)"
- help
- If you say Y here, the MMC layer will assume that all cards
- stayed in their respective slots during the suspend. The
- normal behaviour is to remove them at suspend and
- redetecting them at resume. Breaking this assumption will
- in most cases result in data corruption.
-
- This option is usually just for embedded systems which use
- a MMC/SD card for rootfs. Most people should say N here.
-
- This option sets a default which can be overridden by the
- module parameter "removable=0" or "removable=1".
-
config MMC_CLKGATE
- bool "MMC host clock gating (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "MMC host clock gating"
help
This will attempt to aggressively gate the clock to the MMC card.
This is done to save power due to gating off the logic and bus
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index dca4428380f..38ed210ce2f 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,6 +7,6 @@ mmc_core-y := core.o bus.o host.o \
mmc.o mmc_ops.o sd.o sd_ops.o \
sdio.o sdio_ops.o sdio_bus.o \
sdio_cis.o sdio_io.o sdio_irq.o \
- quirks.o cd-gpio.o
+ quirks.o slot-gpio.o
mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 5d011a39dff..d2dbf02022b 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -27,7 +27,7 @@
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
-static ssize_t mmc_type_show(struct device *dev,
+static ssize_t type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mmc_card *card = mmc_dev_to_card(dev);
@@ -45,11 +45,13 @@ static ssize_t mmc_type_show(struct device *dev,
return -EFAULT;
}
}
+static DEVICE_ATTR_RO(type);
-static struct device_attribute mmc_dev_attrs[] = {
- __ATTR(type, S_IRUGO, mmc_type_show, NULL),
- __ATTR_NULL,
+static struct attribute *mmc_dev_attrs[] = {
+ &dev_attr_type.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(mmc_dev);
/*
* This currently matches any MMC driver to any MMC card - drivers
@@ -122,14 +124,39 @@ static int mmc_bus_remove(struct device *dev)
return 0;
}
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+static void mmc_bus_shutdown(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
- int ret = 0;
+ struct mmc_host *host = card->host;
+ int ret;
+
+ if (dev->driver && drv->shutdown)
+ drv->shutdown(card);
+
+ if (host->bus_ops->shutdown) {
+ ret = host->bus_ops->shutdown(host);
+ if (ret)
+ pr_warn("%s: error %d during shutdown\n",
+ mmc_hostname(host), ret);
+ }
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mmc_bus_suspend(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = mmc_dev_to_card(dev);
+ struct mmc_host *host = card->host;
+ int ret;
- if (dev->driver && drv->suspend)
- ret = drv->suspend(card, state);
+ if (dev->driver && drv->suspend) {
+ ret = drv->suspend(card);
+ if (ret)
+ return ret;
+ }
+
+ ret = host->bus_ops->suspend(host);
return ret;
}
@@ -137,58 +164,61 @@ static int mmc_bus_resume(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
- int ret = 0;
+ struct mmc_host *host = card->host;
+ int ret;
+
+ ret = host->bus_ops->resume(host);
+ if (ret)
+ pr_warn("%s: error %d during resume (card was removed?)\n",
+ mmc_hostname(host), ret);
if (dev->driver && drv->resume)
ret = drv->resume(card);
+
return ret;
}
+#endif
#ifdef CONFIG_PM_RUNTIME
static int mmc_runtime_suspend(struct device *dev)
{
struct mmc_card *card = mmc_dev_to_card(dev);
+ struct mmc_host *host = card->host;
- return mmc_power_save_host(card->host);
+ return host->bus_ops->runtime_suspend(host);
}
static int mmc_runtime_resume(struct device *dev)
{
struct mmc_card *card = mmc_dev_to_card(dev);
+ struct mmc_host *host = card->host;
- return mmc_power_restore_host(card->host);
+ return host->bus_ops->runtime_resume(host);
}
static int mmc_runtime_idle(struct device *dev)
{
- return pm_runtime_suspend(dev);
+ return 0;
}
+#endif /* !CONFIG_PM_RUNTIME */
+
static const struct dev_pm_ops mmc_bus_pm_ops = {
- .runtime_suspend = mmc_runtime_suspend,
- .runtime_resume = mmc_runtime_resume,
- .runtime_idle = mmc_runtime_idle,
+ SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
+ mmc_runtime_idle)
+ SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
};
-#define MMC_PM_OPS_PTR (&mmc_bus_pm_ops)
-
-#else /* !CONFIG_PM_RUNTIME */
-
-#define MMC_PM_OPS_PTR NULL
-
-#endif /* !CONFIG_PM_RUNTIME */
-
static struct bus_type mmc_bus_type = {
.name = "mmc",
- .dev_attrs = mmc_dev_attrs,
+ .dev_groups = mmc_dev_groups,
.match = mmc_bus_match,
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
.remove = mmc_bus_remove,
- .suspend = mmc_bus_suspend,
- .resume = mmc_bus_resume,
- .pm = MMC_PM_OPS_PTR,
+ .shutdown = mmc_bus_shutdown,
+ .pm = &mmc_bus_pm_ops,
};
int mmc_register_bus(void)
@@ -231,8 +261,7 @@ static void mmc_release_card(struct device *dev)
sdio_free_common_cis(card);
- if (card->info)
- kfree(card->info);
+ kfree(card->info);
kfree(card);
}
@@ -267,6 +296,15 @@ int mmc_add_card(struct mmc_card *card)
{
int ret;
const char *type;
+ const char *uhs_bus_speed_mode = "";
+ static const char *const uhs_speeds[] = {
+ [UHS_SDR12_BUS_SPEED] = "SDR12 ",
+ [UHS_SDR25_BUS_SPEED] = "SDR25 ",
+ [UHS_SDR50_BUS_SPEED] = "SDR50 ",
+ [UHS_SDR104_BUS_SPEED] = "SDR104 ",
+ [UHS_DDR50_BUS_SPEED] = "DDR50 ",
+ };
+
dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
@@ -296,25 +334,31 @@ int mmc_add_card(struct mmc_card *card)
break;
}
+ if (mmc_card_uhs(card) &&
+ (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
+ uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];
+
if (mmc_host_is_spi(card->host)) {
pr_info("%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host),
- mmc_card_highspeed(card) ? "high speed " : "",
- mmc_card_ddr_mode(card) ? "DDR " : "",
+ mmc_card_hs(card) ? "high speed " : "",
+ mmc_card_ddr52(card) ? "DDR " : "",
type);
} else {
- pr_info("%s: new %s%s%s%s card at address %04x\n",
+ pr_info("%s: new %s%s%s%s%s card at address %04x\n",
mmc_hostname(card->host),
mmc_card_uhs(card) ? "ultra high speed " :
- (mmc_card_highspeed(card) ? "high speed " : ""),
+ (mmc_card_hs(card) ? "high speed " : ""),
+ mmc_card_hs400(card) ? "HS400 " :
(mmc_card_hs200(card) ? "HS200 " : ""),
- mmc_card_ddr_mode(card) ? "DDR " : "",
- type, card->rca);
+ mmc_card_ddr52(card) ? "DDR " : "",
+ uhs_bus_speed_mode, type, card->rca);
}
#ifdef CONFIG_DEBUG_FS
mmc_add_card_debugfs(card);
#endif
+ mmc_init_context_info(card->host);
ret = device_add(&card->dev);
if (ret)
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
deleted file mode 100644
index 082202ae4a0..00000000000
--- a/drivers/mmc/core/cd-gpio.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Generic GPIO card-detect helper
- *
- * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-#include <linux/mmc/host.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-struct mmc_cd_gpio {
- unsigned int gpio;
- char label[0];
-};
-
-static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
-{
- /* Schedule a card detection after a debounce timeout */
- mmc_detect_change(dev_id, msecs_to_jiffies(100));
- return IRQ_HANDLED;
-}
-
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
- unsigned int irq, unsigned long flags)
-{
- size_t len = strlen(dev_name(host->parent)) + 4;
- struct mmc_cd_gpio *cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
- int ret;
-
- if (!cd)
- return -ENOMEM;
-
- snprintf(cd->label, len, "%s cd", dev_name(host->parent));
-
- ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
- if (ret < 0)
- goto egpioreq;
-
- ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
- flags, cd->label, host);
- if (ret < 0)
- goto eirqreq;
-
- cd->gpio = gpio;
- host->hotplug.irq = irq;
- host->hotplug.handler_priv = cd;
-
- return 0;
-
-eirqreq:
- gpio_free(gpio);
-egpioreq:
- kfree(cd);
- return ret;
-}
-EXPORT_SYMBOL(mmc_cd_gpio_request);
-
-void mmc_cd_gpio_free(struct mmc_host *host)
-{
- struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
-
- free_irq(host->hotplug.irq, host);
- gpio_free(cd->gpio);
- kfree(cd);
-}
-EXPORT_SYMBOL(mmc_cd_gpio_free);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 132378b89d7..7dc0c85fdb6 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -23,14 +23,18 @@
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_wakeup.h>
#include <linux/suspend.h>
#include <linux/fault-inject.h>
#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/of.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
+#include <linux/mmc/slot-gpio.h>
#include "core.h"
#include "bus.h"
@@ -41,7 +45,17 @@
#include "sd_ops.h"
#include "sdio_ops.h"
+/* If the device is not responding */
+#define MMC_CORE_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+
+/*
+ * Background operations can take a long time, depending on the housekeeping
+ * operations the card has to perform.
+ */
+#define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */
+
static struct workqueue_struct *workqueue;
+static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
/*
* Enabling software CRCs on the data blocks can be a significant (30%)
@@ -52,23 +66,6 @@ bool use_spi_crc = 1;
module_param(use_spi_crc, bool, 0);
/*
- * We normally treat cards as removed during suspend if they are not
- * known to be on a non-removable bus, to avoid the risk of writing
- * back data to a different card after resume. Allow this to be
- * overridden if necessary.
- */
-#ifdef CONFIG_MMC_UNSAFE_RESUME
-bool mmc_assume_removable;
-#else
-bool mmc_assume_removable = 1;
-#endif
-EXPORT_SYMBOL(mmc_assume_removable);
-module_param_named(removable, mmc_assume_removable, bool, 0644);
-MODULE_PARM_DESC(
- removable,
- "MMC/SD cards are removable and may be removed during suspend");
-
-/*
* Internal function. Schedule delayed work in the MMC work queue.
*/
static int mmc_schedule_delayed_work(struct delayed_work *work,
@@ -109,8 +106,8 @@ static void mmc_should_fail_request(struct mmc_host *host,
!should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
return;
- data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
- data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
+ data->error = data_errors[prandom_u32() % ARRAY_SIZE(data_errors)];
+ data->bytes_xfered = (prandom_u32() % (data->bytes_xfered >> 9)) << 9;
}
#else /* CONFIG_FAIL_MMC_REQUEST */
@@ -188,6 +185,12 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
struct scatterlist *sg;
#endif
+ if (mrq->sbc) {
+ pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n",
+ mmc_hostname(host), mrq->sbc->opcode,
+ mrq->sbc->arg, mrq->sbc->flags);
+ }
+
pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
mmc_hostname(host), mrq->cmd->opcode,
mrq->cmd->arg, mrq->cmd->flags);
@@ -238,21 +241,178 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
host->ops->request(host, mrq);
}
+/**
+ * mmc_start_bkops - start BKOPS for supported cards
+ * @card: MMC card to start BKOPS
+ * @form_exception: A flag to indicate if this function was
+ * called due to an exception raised by the card
+ *
+ * Start background operations whenever requested.
+ * When the urgent BKOPS bit is set in a R1 command response
+ * then background operations should be started immediately.
+*/
+void mmc_start_bkops(struct mmc_card *card, bool from_exception)
+{
+ int err;
+ int timeout;
+ bool use_busy_signal;
+
+ BUG_ON(!card);
+
+ if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
+ return;
+
+ err = mmc_read_bkops_status(card);
+ if (err) {
+ pr_err("%s: Failed to read bkops status: %d\n",
+ mmc_hostname(card->host), err);
+ return;
+ }
+
+ if (!card->ext_csd.raw_bkops_status)
+ return;
+
+ if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
+ from_exception)
+ return;
+
+ mmc_claim_host(card->host);
+ if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
+ timeout = MMC_BKOPS_MAX_TIMEOUT;
+ use_busy_signal = true;
+ } else {
+ timeout = 0;
+ use_busy_signal = false;
+ }
+
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BKOPS_START, 1, timeout,
+ use_busy_signal, true, false);
+ if (err) {
+ pr_warn("%s: Error %d starting bkops\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ /*
+ * For urgent bkops status (LEVEL_2 and more)
+ * bkops executed synchronously, otherwise
+ * the operation is in progress
+ */
+ if (!use_busy_signal)
+ mmc_card_set_doing_bkops(card);
+out:
+ mmc_release_host(card->host);
+}
+EXPORT_SYMBOL(mmc_start_bkops);
+
+/*
+ * mmc_wait_data_done() - done callback for data request
+ * @mrq: done data request
+ *
+ * Wakes up mmc context, passed as a callback to host controller driver
+ */
+static void mmc_wait_data_done(struct mmc_request *mrq)
+{
+ mrq->host->context_info.is_done_rcv = true;
+ wake_up_interruptible(&mrq->host->context_info.wait);
+}
+
static void mmc_wait_done(struct mmc_request *mrq)
{
complete(&mrq->completion);
}
-static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+/*
+ *__mmc_start_data_req() - starts data request
+ * @host: MMC host to start the request
+ * @mrq: data request to start
+ *
+ * Sets the done callback to be called when request is completed by the card.
+ * Starts data mmc request execution
+ */
+static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+ mrq->done = mmc_wait_data_done;
+ mrq->host = host;
+ if (mmc_card_removed(host->card)) {
+ mrq->cmd->error = -ENOMEDIUM;
+ mmc_wait_data_done(mrq);
+ return -ENOMEDIUM;
+ }
+ mmc_start_request(host, mrq);
+
+ return 0;
+}
+
+static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
init_completion(&mrq->completion);
mrq->done = mmc_wait_done;
if (mmc_card_removed(host->card)) {
mrq->cmd->error = -ENOMEDIUM;
complete(&mrq->completion);
- return;
+ return -ENOMEDIUM;
}
mmc_start_request(host, mrq);
+ return 0;
+}
+
+/*
+ * mmc_wait_for_data_req_done() - wait for request completed
+ * @host: MMC host to prepare the command.
+ * @mrq: MMC request to wait for
+ *
+ * Blocks MMC context till host controller will ack end of data request
+ * execution or new request notification arrives from the block layer.
+ * Handles command retries.
+ *
+ * Returns enum mmc_blk_status after checking errors.
+ */
+static int mmc_wait_for_data_req_done(struct mmc_host *host,
+ struct mmc_request *mrq,
+ struct mmc_async_req *next_req)
+{
+ struct mmc_command *cmd;
+ struct mmc_context_info *context_info = &host->context_info;
+ int err;
+ unsigned long flags;
+
+ while (1) {
+ wait_event_interruptible(context_info->wait,
+ (context_info->is_done_rcv ||
+ context_info->is_new_req));
+ spin_lock_irqsave(&context_info->lock, flags);
+ context_info->is_waiting_last_req = false;
+ spin_unlock_irqrestore(&context_info->lock, flags);
+ if (context_info->is_done_rcv) {
+ context_info->is_done_rcv = false;
+ context_info->is_new_req = false;
+ cmd = mrq->cmd;
+
+ if (!cmd->error || !cmd->retries ||
+ mmc_card_removed(host->card)) {
+ err = host->areq->err_check(host->card,
+ host->areq);
+ break; /* return err */
+ } else {
+ pr_info("%s: req failed (CMD%u): %d, retrying...\n",
+ mmc_hostname(host),
+ cmd->opcode, cmd->error);
+ cmd->retries--;
+ cmd->error = 0;
+ host->ops->request(host, mrq);
+ continue; /* wait for done/new event again */
+ }
+ } else if (context_info->is_new_req) {
+ context_info->is_new_req = false;
+ if (!next_req) {
+ err = MMC_BLK_NEW_REQUEST;
+ break; /* return err */
+ }
+ }
+ }
+ return err;
}
static void mmc_wait_for_req_done(struct mmc_host *host,
@@ -264,6 +424,24 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
wait_for_completion(&mrq->completion);
cmd = mrq->cmd;
+
+ /*
+ * If host has timed out waiting for the sanitize
+ * to complete, card might be still in programming state
+ * so let's try to bring the card out of programming
+ * state.
+ */
+ if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) {
+ if (!mmc_interrupt_hpi(host->card)) {
+ pr_warning("%s: %s: Interrupted sanitize\n",
+ mmc_hostname(host), __func__);
+ cmd->error = 0;
+ break;
+ } else {
+ pr_err("%s: %s: Failed to interrupt sanitize\n",
+ mmc_hostname(host), __func__);
+ }
+ }
if (!cmd->error || !cmd->retries ||
mmc_card_removed(host->card))
break;
@@ -336,6 +514,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
struct mmc_async_req *areq, int *error)
{
int err = 0;
+ int start_err = 0;
struct mmc_async_req *data = host->areq;
/* Prepare a new request */
@@ -343,32 +522,41 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
mmc_pre_req(host, areq->mrq, !host->areq);
if (host->areq) {
- mmc_wait_for_req_done(host, host->areq->mrq);
- err = host->areq->err_check(host->card, host->areq);
- if (err) {
- /* post process the completed failed request */
- mmc_post_req(host, host->areq->mrq, 0);
- if (areq)
- /*
- * Cancel the new prepared request, because
- * it can't run until the failed
- * request has been properly handled.
- */
- mmc_post_req(host, areq->mrq, -EINVAL);
-
- host->areq = NULL;
- goto out;
+ err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq);
+ if (err == MMC_BLK_NEW_REQUEST) {
+ if (error)
+ *error = err;
+ /*
+ * The previous request was not completed,
+ * nothing to return
+ */
+ return NULL;
}
+ /*
+ * Check BKOPS urgency for each R1 response
+ */
+ if (host->card && mmc_card_mmc(host->card) &&
+ ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) ||
+ (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) &&
+ (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT))
+ mmc_start_bkops(host->card, true);
}
- if (areq)
- __mmc_start_req(host, areq->mrq);
+ if (!err && areq)
+ start_err = __mmc_start_data_req(host, areq->mrq);
if (host->areq)
mmc_post_req(host, host->areq->mrq, 0);
- host->areq = areq;
- out:
+ /* Cancel a prepared request if it was not started. */
+ if ((err || start_err) && areq)
+ mmc_post_req(host, areq->mrq, -EINVAL);
+
+ if (err)
+ host->areq = NULL;
+ else
+ host->areq = areq;
+
if (error)
*error = err;
return data;
@@ -396,12 +584,13 @@ EXPORT_SYMBOL(mmc_wait_for_req);
* @card: the MMC card associated with the HPI transfer
*
* Issued High Priority Interrupt, and check for card status
- * util out-of prg-state.
+ * until out-of prg-state.
*/
int mmc_interrupt_hpi(struct mmc_card *card)
{
int err;
u32 status;
+ unsigned long prg_wait;
BUG_ON(!card);
@@ -417,30 +606,39 @@ int mmc_interrupt_hpi(struct mmc_card *card)
goto out;
}
- /*
- * If the card status is in PRG-state, we can send the HPI command.
- */
- if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
- do {
- /*
- * We don't know when the HPI command will finish
- * processing, so we need to resend HPI until out
- * of prg-state, and keep checking the card status
- * with SEND_STATUS. If a timeout error occurs when
- * sending the HPI command, we are already out of
- * prg-state.
- */
- err = mmc_send_hpi_cmd(card, &status);
- if (err)
- pr_debug("%s: abort HPI (%d error)\n",
- mmc_hostname(card->host), err);
+ switch (R1_CURRENT_STATE(status)) {
+ case R1_STATE_IDLE:
+ case R1_STATE_READY:
+ case R1_STATE_STBY:
+ case R1_STATE_TRAN:
+ /*
+ * In idle and transfer states, HPI is not needed and the caller
+ * can issue the next intended command immediately
+ */
+ goto out;
+ case R1_STATE_PRG:
+ break;
+ default:
+ /* In all other states, it's illegal to issue HPI */
+ pr_debug("%s: HPI cannot be sent. Card state=%d\n",
+ mmc_hostname(card->host), R1_CURRENT_STATE(status));
+ err = -EINVAL;
+ goto out;
+ }
- err = mmc_send_status(card, &status);
- if (err)
- break;
- } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
- } else
- pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
+ err = mmc_send_hpi_cmd(card, &status);
+ if (err)
+ goto out;
+
+ prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
+ do {
+ err = mmc_send_status(card, &status);
+
+ if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
+ break;
+ if (time_after(jiffies, prg_wait))
+ err = -ETIMEDOUT;
+ } while (!err);
out:
mmc_release_host(card->host);
@@ -478,6 +676,64 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
EXPORT_SYMBOL(mmc_wait_for_cmd);
/**
+ * mmc_stop_bkops - stop ongoing BKOPS
+ * @card: MMC card to check BKOPS
+ *
+ * Send HPI command to stop ongoing background operations to
+ * allow rapid servicing of foreground operations, e.g. read/
+ * writes. Wait until the card comes out of the programming state
+ * to avoid errors in servicing read/write requests.
+ */
+int mmc_stop_bkops(struct mmc_card *card)
+{
+ int err = 0;
+
+ BUG_ON(!card);
+ err = mmc_interrupt_hpi(card);
+
+ /*
+ * If err is EINVAL, we can't issue an HPI.
+ * It should complete the BKOPS.
+ */
+ if (!err || (err == -EINVAL)) {
+ mmc_card_clr_doing_bkops(card);
+ err = 0;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(mmc_stop_bkops);
+
+int mmc_read_bkops_status(struct mmc_card *card)
+{
+ int err;
+ u8 *ext_csd;
+
+ /*
+ * In future work, we should consider storing the entire ext_csd.
+ */
+ ext_csd = kmalloc(512, GFP_KERNEL);
+ if (!ext_csd) {
+ pr_err("%s: could not allocate buffer to receive the ext_csd.\n",
+ mmc_hostname(card->host));
+ return -ENOMEM;
+ }
+
+ mmc_claim_host(card->host);
+ err = mmc_send_ext_csd(card, ext_csd);
+ mmc_release_host(card->host);
+ if (err)
+ goto out;
+
+ card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
+ card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
+out:
+ kfree(ext_csd);
+ return err;
+}
+EXPORT_SYMBOL(mmc_read_bkops_status);
+
+/**
* mmc_set_data_timeout - set the timeout for a data command
* @data: data phase for command
* @card: the MMC card associated with the data transfer
@@ -526,10 +782,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
if (data->flags & MMC_DATA_WRITE)
/*
- * The limit is really 250 ms, but that is
- * insufficient for some crappy cards.
+ * The MMC spec "It is strongly recommended
+ * for hosts to implement more than 500ms
+ * timeout value even if the card indicates
+ * the 250ms maximum busy length." Even the
+ * previous value of 300ms is known to be
+ * insufficient for some cards.
*/
- limit_us = 300000;
+ limit_us = 3000000;
else
limit_us = 100000;
@@ -540,6 +800,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
data->timeout_ns = limit_us * 1000;
data->timeout_clks = 0;
}
+
+ /* assign limit value if invalid */
+ if (timeout_us == 0)
+ data->timeout_ns = limit_us * 1000;
}
/*
@@ -599,105 +863,6 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
EXPORT_SYMBOL(mmc_align_data_size);
/**
- * mmc_host_enable - enable a host.
- * @host: mmc host to enable
- *
- * Hosts that support power saving can use the 'enable' and 'disable'
- * methods to exit and enter power saving states. For more information
- * see comments for struct mmc_host_ops.
- */
-int mmc_host_enable(struct mmc_host *host)
-{
- if (!(host->caps & MMC_CAP_DISABLE))
- return 0;
-
- if (host->en_dis_recurs)
- return 0;
-
- if (host->nesting_cnt++)
- return 0;
-
- cancel_delayed_work_sync(&host->disable);
-
- if (host->enabled)
- return 0;
-
- if (host->ops->enable) {
- int err;
-
- host->en_dis_recurs = 1;
- mmc_host_clk_hold(host);
- err = host->ops->enable(host);
- mmc_host_clk_release(host);
- host->en_dis_recurs = 0;
-
- if (err) {
- pr_debug("%s: enable error %d\n",
- mmc_hostname(host), err);
- return err;
- }
- }
- host->enabled = 1;
- return 0;
-}
-EXPORT_SYMBOL(mmc_host_enable);
-
-static int mmc_host_do_disable(struct mmc_host *host, int lazy)
-{
- if (host->ops->disable) {
- int err;
-
- host->en_dis_recurs = 1;
- mmc_host_clk_hold(host);
- err = host->ops->disable(host, lazy);
- mmc_host_clk_release(host);
- host->en_dis_recurs = 0;
-
- if (err < 0) {
- pr_debug("%s: disable error %d\n",
- mmc_hostname(host), err);
- return err;
- }
- if (err > 0) {
- unsigned long delay = msecs_to_jiffies(err);
-
- mmc_schedule_delayed_work(&host->disable, delay);
- }
- }
- host->enabled = 0;
- return 0;
-}
-
-/**
- * mmc_host_disable - disable a host.
- * @host: mmc host to disable
- *
- * Hosts that support power saving can use the 'enable' and 'disable'
- * methods to exit and enter power saving states. For more information
- * see comments for struct mmc_host_ops.
- */
-int mmc_host_disable(struct mmc_host *host)
-{
- int err;
-
- if (!(host->caps & MMC_CAP_DISABLE))
- return 0;
-
- if (host->en_dis_recurs)
- return 0;
-
- if (--host->nesting_cnt)
- return 0;
-
- if (!host->enabled)
- return 0;
-
- err = mmc_host_do_disable(host, 0);
- return err;
-}
-EXPORT_SYMBOL(mmc_host_disable);
-
-/**
* __mmc_claim_host - exclusively claim a host
* @host: mmc host to claim
* @abort: whether or not the operation should be aborted
@@ -735,46 +900,28 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
wake_up(&host->wq);
spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait);
- if (!stop)
- mmc_host_enable(host);
+ if (host->ops->enable && !stop && host->claim_cnt == 1)
+ host->ops->enable(host);
return stop;
}
EXPORT_SYMBOL(__mmc_claim_host);
/**
- * mmc_try_claim_host - try exclusively to claim a host
- * @host: mmc host to claim
+ * mmc_release_host - release a host
+ * @host: mmc host to release
*
- * Returns %1 if the host is claimed, %0 otherwise.
+ * Release a MMC host, allowing others to claim the host
+ * for their operations.
*/
-int mmc_try_claim_host(struct mmc_host *host)
+void mmc_release_host(struct mmc_host *host)
{
- int claimed_host = 0;
unsigned long flags;
- spin_lock_irqsave(&host->lock, flags);
- if (!host->claimed || host->claimer == current) {
- host->claimed = 1;
- host->claimer = current;
- host->claim_cnt += 1;
- claimed_host = 1;
- }
- spin_unlock_irqrestore(&host->lock, flags);
- return claimed_host;
-}
-EXPORT_SYMBOL(mmc_try_claim_host);
+ WARN_ON(!host->claimed);
-/**
- * mmc_do_release_host - release a claimed host
- * @host: mmc host to release
- *
- * If you successfully claimed a host, this function will
- * release it again.
- */
-void mmc_do_release_host(struct mmc_host *host)
-{
- unsigned long flags;
+ if (host->ops->disable && host->claim_cnt == 1)
+ host->ops->disable(host);
spin_lock_irqsave(&host->lock, flags);
if (--host->claim_cnt) {
@@ -787,68 +934,30 @@ void mmc_do_release_host(struct mmc_host *host)
wake_up(&host->wq);
}
}
-EXPORT_SYMBOL(mmc_do_release_host);
-
-void mmc_host_deeper_disable(struct work_struct *work)
-{
- struct mmc_host *host =
- container_of(work, struct mmc_host, disable.work);
-
- /* If the host is claimed then we do not want to disable it anymore */
- if (!mmc_try_claim_host(host))
- return;
- mmc_host_do_disable(host, 1);
- mmc_do_release_host(host);
-}
+EXPORT_SYMBOL(mmc_release_host);
-/**
- * mmc_host_lazy_disable - lazily disable a host.
- * @host: mmc host to disable
- *
- * Hosts that support power saving can use the 'enable' and 'disable'
- * methods to exit and enter power saving states. For more information
- * see comments for struct mmc_host_ops.
+/*
+ * This is a helper function, which fetches a runtime pm reference for the
+ * card device and also claims the host.
*/
-int mmc_host_lazy_disable(struct mmc_host *host)
+void mmc_get_card(struct mmc_card *card)
{
- if (!(host->caps & MMC_CAP_DISABLE))
- return 0;
-
- if (host->en_dis_recurs)
- return 0;
-
- if (--host->nesting_cnt)
- return 0;
-
- if (!host->enabled)
- return 0;
-
- if (host->disable_delay) {
- mmc_schedule_delayed_work(&host->disable,
- msecs_to_jiffies(host->disable_delay));
- return 0;
- } else
- return mmc_host_do_disable(host, 1);
+ pm_runtime_get_sync(&card->dev);
+ mmc_claim_host(card->host);
}
-EXPORT_SYMBOL(mmc_host_lazy_disable);
+EXPORT_SYMBOL(mmc_get_card);
-/**
- * mmc_release_host - release a host
- * @host: mmc host to release
- *
- * Release a MMC host, allowing others to claim the host
- * for their operations.
+/*
+ * This is a helper function, which releases the host and drops the runtime
+ * pm reference for the card device.
*/
-void mmc_release_host(struct mmc_host *host)
+void mmc_put_card(struct mmc_card *card)
{
- WARN_ON(!host->claimed);
-
- mmc_host_lazy_disable(host);
-
- mmc_do_release_host(host);
+ mmc_release_host(card->host);
+ pm_runtime_mark_last_busy(&card->dev);
+ pm_runtime_put_autosuspend(&card->dev);
}
-
-EXPORT_SYMBOL(mmc_release_host);
+EXPORT_SYMBOL(mmc_put_card);
/*
* Internal function that does the actual ios call to the host driver,
@@ -1053,6 +1162,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
}
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+#ifdef CONFIG_OF
+
+/**
+ * mmc_of_parse_voltage - return mask of supported voltages
+ * @np: The device node need to be parsed.
+ * @mask: mask of voltages available for MMC/SD/SDIO
+ *
+ * 1. Return zero on success.
+ * 2. Return negative errno: voltage-range is invalid.
+ */
+int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
+{
+ const u32 *voltage_ranges;
+ int num_ranges, i;
+
+ voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
+ num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
+ if (!voltage_ranges || !num_ranges) {
+ pr_info("%s: voltage-ranges unspecified\n", np->full_name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_ranges; i++) {
+ const int j = i * 2;
+ u32 ocr_mask;
+
+ ocr_mask = mmc_vddrange_to_ocrmask(
+ be32_to_cpu(voltage_ranges[j]),
+ be32_to_cpu(voltage_ranges[j + 1]));
+ if (!ocr_mask) {
+ pr_err("%s: voltage-range #%d is invalid\n",
+ np->full_name, i);
+ return -EINVAL;
+ }
+ *mask |= ocr_mask;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mmc_of_parse_voltage);
+
+#endif /* CONFIG_OF */
+
#ifdef CONFIG_REGULATOR
/**
@@ -1088,7 +1240,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply)
return result;
}
-EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
+EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask);
/**
* mmc_regulator_set_ocr - set regulator to match host->ios voltage
@@ -1113,7 +1265,8 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
int tmp;
int voltage;
- /* REVISIT mmc_vddrange_to_ocrmask() may have set some
+ /*
+ * REVISIT mmc_vddrange_to_ocrmask() may have set some
* bits this regulator doesn't quite support ... don't
* be too picky, most cards and regulators are OK with
* a 0.1V range goof (it's a small error percentage).
@@ -1127,12 +1280,13 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
max_uV = min_uV + 100 * 1000;
}
- /* avoid needless changes to this voltage; the regulator
- * might not allow this operation
+ /*
+ * If we're using a fixed/static regulator, don't call
+ * regulator_set_voltage; it would fail.
*/
voltage = regulator_get_voltage(supply);
- if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE)
+ if (!regulator_can_change_voltage(supply))
min_uV = max_uV = voltage;
if (voltage < 0)
@@ -1158,10 +1312,40 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
"could not set regulator OCR (%d)\n", result);
return result;
}
-EXPORT_SYMBOL(mmc_regulator_set_ocr);
+EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
#endif /* CONFIG_REGULATOR */
+int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+ struct device *dev = mmc_dev(mmc);
+ int ret;
+
+ mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
+ mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
+
+ if (IS_ERR(mmc->supply.vmmc)) {
+ if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_info(dev, "No vmmc regulator found\n");
+ } else {
+ ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
+ if (ret > 0)
+ mmc->ocr_avail = ret;
+ else
+ dev_warn(dev, "Failed getting OCR mask: %d\n", ret);
+ }
+
+ if (IS_ERR(mmc->supply.vqmmc)) {
+ if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_info(dev, "No vqmmc regulator found\n");
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
+
/*
* Mask off any voltages we don't support and select
* the lowest voltage
@@ -1170,31 +1354,60 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
{
int bit;
- ocr &= host->ocr_avail;
+ /*
+ * Sanity check the voltages that the card claims to
+ * support.
+ */
+ if (ocr & 0x7F) {
+ dev_warn(mmc_dev(host),
+ "card claims to support voltages below defined range\n");
+ ocr &= ~0x7F;
+ }
- bit = ffs(ocr);
- if (bit) {
- bit -= 1;
+ ocr &= host->ocr_avail;
+ if (!ocr) {
+ dev_warn(mmc_dev(host), "no support for card's volts\n");
+ return 0;
+ }
+ if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
+ bit = ffs(ocr) - 1;
ocr &= 3 << bit;
+ mmc_power_cycle(host, ocr);
+ } else {
+ bit = fls(ocr) - 1;
+ ocr &= 3 << bit;
+ if (bit != host->ios.vdd)
+ dev_warn(mmc_dev(host), "exceeding card's volts\n");
+ }
+
+ return ocr;
+}
+
+int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
+{
+ int err = 0;
+ int old_signal_voltage = host->ios.signal_voltage;
+ host->ios.signal_voltage = signal_voltage;
+ if (host->ops->start_signal_voltage_switch) {
mmc_host_clk_hold(host);
- host->ios.vdd = bit;
- mmc_set_ios(host);
+ err = host->ops->start_signal_voltage_switch(host, &host->ios);
mmc_host_clk_release(host);
- } else {
- pr_warning("%s: host doesn't support card's voltages\n",
- mmc_hostname(host));
- ocr = 0;
}
- return ocr;
+ if (err)
+ host->ios.signal_voltage = old_signal_voltage;
+
+ return err;
+
}
-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11)
+int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
{
struct mmc_command cmd = {0};
int err = 0;
+ u32 clock;
BUG_ON(!host);
@@ -1202,27 +1415,81 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11
* Send CMD11 only if the request is to switch the card to
* 1.8V signalling.
*/
- if ((signal_voltage != MMC_SIGNAL_VOLTAGE_330) && cmd11) {
- cmd.opcode = SD_SWITCH_VOLTAGE;
- cmd.arg = 0;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+ if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+ return __mmc_set_signal_voltage(host, signal_voltage);
- err = mmc_wait_for_cmd(host, &cmd, 0);
- if (err)
- return err;
+ /*
+ * If we cannot switch voltages, return failure so the caller
+ * can continue without UHS mode
+ */
+ if (!host->ops->start_signal_voltage_switch)
+ return -EPERM;
+ if (!host->ops->card_busy)
+ pr_warning("%s: cannot verify signal voltage switch\n",
+ mmc_hostname(host));
+
+ cmd.opcode = SD_SWITCH_VOLTAGE;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
- return -EIO;
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err)
+ return err;
+
+ if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
+ return -EIO;
+
+ mmc_host_clk_hold(host);
+ /*
+ * The card should drive cmd and dat[0:3] low immediately
+ * after the response of cmd11, but wait 1 ms to be sure
+ */
+ mmc_delay(1);
+ if (host->ops->card_busy && !host->ops->card_busy(host)) {
+ err = -EAGAIN;
+ goto power_cycle;
}
+ /*
+ * During a signal voltage level switch, the clock must be gated
+ * for 5 ms according to the SD spec
+ */
+ clock = host->ios.clock;
+ host->ios.clock = 0;
+ mmc_set_ios(host);
- host->ios.signal_voltage = signal_voltage;
+ if (__mmc_set_signal_voltage(host, signal_voltage)) {
+ /*
+ * Voltages may not have been switched, but we've already
+ * sent CMD11, so a power cycle is required anyway
+ */
+ err = -EAGAIN;
+ goto power_cycle;
+ }
- if (host->ops->start_signal_voltage_switch) {
- mmc_host_clk_hold(host);
- err = host->ops->start_signal_voltage_switch(host, &host->ios);
- mmc_host_clk_release(host);
+ /* Keep clock gated for at least 5 ms */
+ mmc_delay(5);
+ host->ios.clock = clock;
+ mmc_set_ios(host);
+
+ /* Wait for at least 1 ms according to spec */
+ mmc_delay(1);
+
+ /*
+ * Failure to switch is indicated by the card holding
+ * dat[0:3] low
+ */
+ if (host->ops->card_busy && host->ops->card_busy(host))
+ err = -EAGAIN;
+
+power_cycle:
+ if (err) {
+ pr_debug("%s: Signal voltage switch failed, "
+ "power cycling card\n", mmc_hostname(host));
+ mmc_power_cycle(host, ocr);
}
+ mmc_host_clk_release(host);
+
return err;
}
@@ -1248,48 +1515,6 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
mmc_host_clk_release(host);
}
-static void mmc_poweroff_notify(struct mmc_host *host)
-{
- struct mmc_card *card;
- unsigned int timeout;
- unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
- int err = 0;
-
- card = host->card;
- mmc_claim_host(host);
-
- /*
- * Send power notify command only if card
- * is mmc and notify state is powered ON
- */
- if (card && mmc_card_mmc(card) &&
- (card->poweroff_notify_state == MMC_POWERED_ON)) {
-
- if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
- notify_type = EXT_CSD_POWER_OFF_SHORT;
- timeout = card->ext_csd.generic_cmd6_time;
- card->poweroff_notify_state = MMC_POWEROFF_SHORT;
- } else {
- notify_type = EXT_CSD_POWER_OFF_LONG;
- timeout = card->ext_csd.power_off_longtime;
- card->poweroff_notify_state = MMC_POWEROFF_LONG;
- }
-
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_POWER_OFF_NOTIFICATION,
- notify_type, timeout);
-
- if (err && err != -EBADMSG)
- pr_err("Device failed to respond within %d poweroff "
- "time. Forcefully powering down the device\n",
- timeout);
-
- /* Set the card state to no notification after the poweroff */
- card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
- }
- mmc_release_host(host);
-}
-
/*
* Apply power to the MMC stack. This is a two-stage process.
* First, we enable power to the card without the clock running.
@@ -1301,19 +1526,14 @@ static void mmc_poweroff_notify(struct mmc_host *host)
* If a host does all the power sequencing itself, ignore the
* initial MMC_POWER_UP stage.
*/
-static void mmc_power_up(struct mmc_host *host)
+void mmc_power_up(struct mmc_host *host, u32 ocr)
{
- int bit;
+ if (host->ios.power_mode == MMC_POWER_ON)
+ return;
mmc_host_clk_hold(host);
- /* If ocr is set, we use it */
- if (host->ocr)
- bit = ffs(host->ocr) - 1;
- else
- bit = fls(host->ocr_avail) - 1;
-
- host->ios.vdd = bit;
+ host->ios.vdd = fls(ocr) - 1;
if (mmc_host_is_spi(host))
host->ios.chip_select = MMC_CS_HIGH;
else
@@ -1324,6 +1544,14 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host);
+ /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */
+ if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0)
+ dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n");
+ else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0)
+ dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n");
+ else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0)
+ dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n");
+
/*
* This delay should be sufficient to allow the power supply
* to reach the minimum voltage.
@@ -1346,35 +1574,14 @@ static void mmc_power_up(struct mmc_host *host)
void mmc_power_off(struct mmc_host *host)
{
- int err = 0;
+ if (host->ios.power_mode == MMC_POWER_OFF)
+ return;
+
mmc_host_clk_hold(host);
host->ios.clock = 0;
host->ios.vdd = 0;
- /*
- * For eMMC 4.5 device send AWAKE command before
- * POWER_OFF_NOTIFY command, because in sleep state
- * eMMC 4.5 devices respond to only RESET and AWAKE cmd
- */
- if (host->card && mmc_card_is_sleep(host->card) &&
- host->bus_ops->resume) {
- err = host->bus_ops->resume(host);
-
- if (!err)
- mmc_poweroff_notify(host);
- else
- pr_warning("%s: error %d during resume "
- "(continue with poweroff sequence)\n",
- mmc_hostname(host), err);
- }
-
- /*
- * Reset ocr mask to be the highest possible voltage supported for
- * this mmc host. This value will be used at next power up.
- */
- host->ocr = 1 << (fls(host->ocr_avail) - 1);
-
if (!mmc_host_is_spi(host)) {
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
host->ios.chip_select = MMC_CS_DONTCARE;
@@ -1394,6 +1601,14 @@ void mmc_power_off(struct mmc_host *host)
mmc_host_clk_release(host);
}
+void mmc_power_cycle(struct mmc_host *host, u32 ocr)
+{
+ mmc_power_off(host);
+ /* Wait at least 1 ms according to SD spec */
+ mmc_delay(1);
+ mmc_power_up(host, ocr);
+}
+
/*
* Cleanup when the last reference to the bus operator is dropped.
*/
@@ -1479,6 +1694,28 @@ void mmc_detach_bus(struct mmc_host *host)
mmc_bus_put(host);
}
+static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
+ bool cd_irq)
+{
+#ifdef CONFIG_MMC_DEBUG
+ unsigned long flags;
+ spin_lock_irqsave(&host->lock, flags);
+ WARN_ON(host->removed);
+ spin_unlock_irqrestore(&host->lock, flags);
+#endif
+
+ /*
+ * If the device is configured as wakeup, we prevent a new sleep for
+ * 5 s to give provision for user space to consume the event.
+ */
+ if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&
+ device_can_wakeup(mmc_dev(host)))
+ pm_wakeup_event(mmc_dev(host), 5000);
+
+ host->detect_change = 1;
+ mmc_schedule_delayed_work(&host->detect, delay);
+}
+
/**
* mmc_detect_change - process change of state on a MMC socket
* @host: host which changed state.
@@ -1491,16 +1728,8 @@ void mmc_detach_bus(struct mmc_host *host)
*/
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
-#ifdef CONFIG_MMC_DEBUG
- unsigned long flags;
- spin_lock_irqsave(&host->lock, flags);
- WARN_ON(host->removed);
- spin_unlock_irqrestore(&host->lock, flags);
-#endif
- host->detect_change = 1;
- mmc_schedule_delayed_work(&host->detect, delay);
+ _mmc_detect_change(host, delay, true);
}
-
EXPORT_SYMBOL(mmc_detect_change);
void mmc_init_erase(struct mmc_card *card)
@@ -1557,7 +1786,10 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
{
unsigned int erase_timeout;
- if (card->ext_csd.erase_group_def & 1) {
+ if (arg == MMC_DISCARD_ARG ||
+ (arg == MMC_TRIM_ARG && card->ext_csd.rev >= 6)) {
+ erase_timeout = card->ext_csd.trim_timeout;
+ } else if (card->ext_csd.erase_group_def & 1) {
/* High Capacity Erase Group Size uses HC timeouts */
if (arg == MMC_TRIM_ARG)
erase_timeout = card->ext_csd.trim_timeout;
@@ -1653,6 +1885,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
{
struct mmc_command cmd = {0};
unsigned int qty = 0;
+ unsigned long timeout;
int err;
/*
@@ -1718,7 +1951,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.opcode = MMC_ERASE;
cmd.arg = arg;
cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty);
+ cmd.busy_timeout = mmc_erase_timeout(card, arg, qty);
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
pr_err("mmc_erase: erase error %d, status %#x\n",
@@ -1730,6 +1963,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
if (mmc_host_is_spi(card->host))
goto out;
+ timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS);
do {
memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = MMC_SEND_STATUS;
@@ -1743,8 +1977,19 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
err = -EIO;
goto out;
}
+
+ /* Timeout if the device never becomes ready for data and
+ * never leaves the program state.
+ */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state! %s\n",
+ mmc_hostname(card->host), __func__);
+ err = -EIO;
+ goto out;
+ }
+
} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
- R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG);
+ (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
out:
return err;
}
@@ -1829,8 +2074,6 @@ int mmc_can_trim(struct mmc_card *card)
{
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
return 1;
- if (mmc_can_discard(card))
- return 1;
return 0;
}
EXPORT_SYMBOL(mmc_can_trim);
@@ -1849,6 +2092,8 @@ EXPORT_SYMBOL(mmc_can_discard);
int mmc_can_sanitize(struct mmc_card *card)
{
+ if (!mmc_can_trim(card) && !mmc_can_erase(card))
+ return 0;
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
return 1;
return 0;
@@ -1893,7 +2138,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
y = 0;
for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
timeout = mmc_erase_timeout(card, arg, qty + x);
- if (timeout > host->max_discard_to)
+ if (timeout > host->max_busy_timeout)
break;
if (timeout < last_timeout)
break;
@@ -1925,7 +2170,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
struct mmc_host *host = card->host;
unsigned int max_discard, max_trim;
- if (!host->max_discard_to)
+ if (!host->max_busy_timeout)
return UINT_MAX;
/*
@@ -1945,7 +2190,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
max_discard = 0;
}
pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
- mmc_hostname(host), max_discard, host->max_discard_to);
+ mmc_hostname(host), max_discard, host->max_busy_timeout);
return max_discard;
}
EXPORT_SYMBOL(mmc_calc_max_discard);
@@ -1954,7 +2199,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
{
struct mmc_command cmd = {0};
- if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+ if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
return 0;
cmd.opcode = MMC_SET_BLOCKLEN;
@@ -1964,6 +2209,20 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
}
EXPORT_SYMBOL(mmc_set_blocklen);
+int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+ bool is_rel_write)
+{
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_SET_BLOCK_COUNT;
+ cmd.arg = blockcount & 0x0000FFFF;
+ if (is_rel_write)
+ cmd.arg |= 1 << 31;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+ return mmc_wait_for_cmd(card->host, &cmd, 5);
+}
+EXPORT_SYMBOL(mmc_set_blockcount);
+
static void mmc_hw_reset_for_init(struct mmc_host *host)
{
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
@@ -1990,9 +2249,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
{
struct mmc_card *card = host->card;
- if (!host->bus_ops->power_restore)
- return -EOPNOTSUPP;
-
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
return -EOPNOTSUPP;
@@ -2023,7 +2279,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
}
}
- host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
if (mmc_host_is_spi(host)) {
host->ios.chip_select = MMC_CS_HIGH;
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
@@ -2060,7 +2315,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
pr_info("%s: %s: trying to init card at %u Hz\n",
mmc_hostname(host), __func__, host->f_init);
#endif
- mmc_power_up(host);
+ mmc_power_up(host, host->ocr_avail);
/*
* Some eMMCs (with VCCQ always on) may not be reset after power up, so
@@ -2068,9 +2323,6 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
*/
mmc_hw_reset_for_init(host);
- /* Initialization should be done at 3.3 V I/O voltage. */
- mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
/*
* sdio_reset sends CMD52 to reset card. Since we do not know
* if the card is being re-initialized, just send it. CMD52
@@ -2097,13 +2349,26 @@ int _mmc_detect_card_removed(struct mmc_host *host)
{
int ret;
- if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
+ if (host->caps & MMC_CAP_NONREMOVABLE)
return 0;
if (!host->card || mmc_card_removed(host->card))
return 1;
ret = host->bus_ops->alive(host);
+
+ /*
+ * Card detect status and alive check may be out of sync if card is
+ * removed slowly, when card detect switch changes while card/slot
+ * pads are still contacted in hardware (refer to "SD Card Mechanical
+ * Addendum, Appendix C: Card Detection Switch"). So reschedule a
+ * detect work 200ms later for this case.
+ */
+ if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) {
+ mmc_detect_change(host, msecs_to_jiffies(200));
+ pr_debug("%s: card removed too slowly\n", mmc_hostname(host));
+ }
+
if (ret) {
mmc_card_set_removed(host->card);
pr_debug("%s: card remove detected\n", mmc_hostname(host));
@@ -2115,38 +2380,64 @@ int _mmc_detect_card_removed(struct mmc_host *host)
int mmc_detect_card_removed(struct mmc_host *host)
{
struct mmc_card *card = host->card;
+ int ret;
WARN_ON(!host->claimed);
+
+ if (!card)
+ return 1;
+
+ ret = mmc_card_removed(card);
/*
* The card will be considered unchanged unless we have been asked to
* detect a change or host requires polling to provide card detection.
*/
- if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL))
- return mmc_card_removed(card);
+ if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL))
+ return ret;
host->detect_change = 0;
+ if (!ret) {
+ ret = _mmc_detect_card_removed(host);
+ if (ret && (host->caps & MMC_CAP_NEEDS_POLL)) {
+ /*
+ * Schedule a detect work as soon as possible to let a
+ * rescan handle the card removal.
+ */
+ cancel_delayed_work(&host->detect);
+ _mmc_detect_change(host, 0, false);
+ }
+ }
- return _mmc_detect_card_removed(host);
+ return ret;
}
EXPORT_SYMBOL(mmc_detect_card_removed);
void mmc_rescan(struct work_struct *work)
{
- static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
struct mmc_host *host =
container_of(work, struct mmc_host, detect.work);
int i;
+ if (host->trigger_card_event && host->ops->card_event) {
+ host->ops->card_event(host);
+ host->trigger_card_event = false;
+ }
+
if (host->rescan_disable)
return;
+ /* If there is a non-removable card registered, only scan once */
+ if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered)
+ return;
+ host->rescan_entered = 1;
+
mmc_bus_get(host);
/*
* if there is a _removable_ card registered, check whether it is
* still present
*/
- if (host->bus_ops && host->bus_ops->detect && !host->bus_dead
+ if (host->bus_ops && !host->bus_dead
&& !(host->caps & MMC_CAP_NONREMOVABLE))
host->bus_ops->detect(host);
@@ -2171,8 +2462,13 @@ void mmc_rescan(struct work_struct *work)
*/
mmc_bus_put(host);
- if (host->ops->get_cd && host->ops->get_cd(host) == 0)
+ if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd &&
+ host->ops->get_cd(host) == 0) {
+ mmc_claim_host(host);
+ mmc_power_off(host);
+ mmc_release_host(host);
goto out;
+ }
mmc_claim_host(host);
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
@@ -2190,8 +2486,14 @@ void mmc_rescan(struct work_struct *work)
void mmc_start_host(struct mmc_host *host)
{
- mmc_power_off(host);
- mmc_detect_change(host, 0);
+ host->f_init = max(freqs[0], host->f_min);
+ host->rescan_disable = 0;
+ if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
+ mmc_power_off(host);
+ else
+ mmc_power_up(host, host->ocr_avail);
+ mmc_gpiod_request_cd_irq(host);
+ _mmc_detect_change(host, 0, false);
}
void mmc_stop_host(struct mmc_host *host)
@@ -2202,9 +2504,10 @@ void mmc_stop_host(struct mmc_host *host)
host->removed = 1;
spin_unlock_irqrestore(&host->lock, flags);
#endif
+ if (host->slot.cd_irq >= 0)
+ disable_irq(host->slot.cd_irq);
- if (host->caps & MMC_CAP_DISABLE)
- cancel_delayed_work(&host->disable);
+ host->rescan_disable = 1;
cancel_delayed_work_sync(&host->detect);
mmc_flush_scheduled_work();
@@ -2214,9 +2517,7 @@ void mmc_stop_host(struct mmc_host *host)
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
/* Calling bus_ops->remove() with a claimed host can deadlock */
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
-
+ host->bus_ops->remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_power_off(host);
@@ -2241,7 +2542,7 @@ int mmc_power_save_host(struct mmc_host *host)
mmc_bus_get(host);
- if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
+ if (!host->bus_ops || host->bus_dead) {
mmc_bus_put(host);
return -EINVAL;
}
@@ -2267,12 +2568,12 @@ int mmc_power_restore_host(struct mmc_host *host)
mmc_bus_get(host);
- if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
+ if (!host->bus_ops || host->bus_dead) {
mmc_bus_put(host);
return -EINVAL;
}
- mmc_power_up(host);
+ mmc_power_up(host, host->card->ocr);
ret = host->bus_ops->power_restore(host);
mmc_bus_put(host);
@@ -2281,63 +2582,13 @@ int mmc_power_restore_host(struct mmc_host *host)
}
EXPORT_SYMBOL(mmc_power_restore_host);
-int mmc_card_awake(struct mmc_host *host)
-{
- int err = -ENOSYS;
-
- if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
- return 0;
-
- mmc_bus_get(host);
-
- if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
- err = host->bus_ops->awake(host);
-
- mmc_bus_put(host);
-
- return err;
-}
-EXPORT_SYMBOL(mmc_card_awake);
-
-int mmc_card_sleep(struct mmc_host *host)
-{
- int err = -ENOSYS;
-
- if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
- return 0;
-
- mmc_bus_get(host);
-
- if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep)
- err = host->bus_ops->sleep(host);
-
- mmc_bus_put(host);
-
- return err;
-}
-EXPORT_SYMBOL(mmc_card_sleep);
-
-int mmc_card_can_sleep(struct mmc_host *host)
-{
- struct mmc_card *card = host->card;
-
- if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3)
- return 1;
- return 0;
-}
-EXPORT_SYMBOL(mmc_card_can_sleep);
-
/*
* Flush the cache to the non-volatile storage.
*/
int mmc_flush_cache(struct mmc_card *card)
{
- struct mmc_host *host = card->host;
int err = 0;
- if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
- return err;
-
if (mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0) &&
(card->ext_csd.cache_ctrl & 1)) {
@@ -2352,155 +2603,8 @@ int mmc_flush_cache(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_flush_cache);
-/*
- * Turn the cache ON/OFF.
- * Turning the cache OFF shall trigger flushing of the data
- * to the non-volatile storage.
- */
-int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
-{
- struct mmc_card *card = host->card;
- unsigned int timeout;
- int err = 0;
-
- if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
- mmc_card_is_removable(host))
- return err;
-
- if (card && mmc_card_mmc(card) &&
- (card->ext_csd.cache_size > 0)) {
- enable = !!enable;
-
- if (card->ext_csd.cache_ctrl ^ enable) {
- timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_CACHE_CTRL, enable, timeout);
- if (err)
- pr_err("%s: cache %s error %d\n",
- mmc_hostname(card->host),
- enable ? "on" : "off",
- err);
- else
- card->ext_csd.cache_ctrl = enable;
- }
- }
-
- return err;
-}
-EXPORT_SYMBOL(mmc_cache_ctrl);
-
#ifdef CONFIG_PM
-/**
- * mmc_suspend_host - suspend a host
- * @host: mmc host
- */
-int mmc_suspend_host(struct mmc_host *host)
-{
- int err = 0;
-
- if (host->caps & MMC_CAP_DISABLE)
- cancel_delayed_work(&host->disable);
- cancel_delayed_work(&host->detect);
- mmc_flush_scheduled_work();
- if (mmc_try_claim_host(host)) {
- err = mmc_cache_ctrl(host, 0);
- mmc_do_release_host(host);
- } else {
- err = -EBUSY;
- }
-
- if (err)
- goto out;
-
- mmc_bus_get(host);
- if (host->bus_ops && !host->bus_dead) {
-
- /*
- * A long response time is not acceptable for device drivers
- * when doing suspend. Prevent mmc_claim_host in the suspend
- * sequence, to potentially wait "forever" by trying to
- * pre-claim the host.
- */
- if (mmc_try_claim_host(host)) {
- if (host->bus_ops->suspend) {
- err = host->bus_ops->suspend(host);
- }
- mmc_do_release_host(host);
-
- if (err == -ENOSYS || !host->bus_ops->resume) {
- /*
- * We simply "remove" the card in this case.
- * It will be redetected on resume. (Calling
- * bus_ops->remove() with a claimed host can
- * deadlock.)
- */
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
- mmc_claim_host(host);
- mmc_detach_bus(host);
- mmc_power_off(host);
- mmc_release_host(host);
- host->pm_flags = 0;
- err = 0;
- }
- } else {
- err = -EBUSY;
- }
- }
- mmc_bus_put(host);
-
- if (!err && !mmc_card_keep_power(host))
- mmc_power_off(host);
-
-out:
- return err;
-}
-
-EXPORT_SYMBOL(mmc_suspend_host);
-
-/**
- * mmc_resume_host - resume a previously suspended host
- * @host: mmc host
- */
-int mmc_resume_host(struct mmc_host *host)
-{
- int err = 0;
-
- mmc_bus_get(host);
- if (host->bus_ops && !host->bus_dead) {
- if (!mmc_card_keep_power(host)) {
- mmc_power_up(host);
- mmc_select_voltage(host, host->ocr);
- /*
- * Tell runtime PM core we just powered up the card,
- * since it still believes the card is powered off.
- * Note that currently runtime PM is only enabled
- * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
- */
- if (mmc_card_sdio(host->card) &&
- (host->caps & MMC_CAP_POWER_OFF_CARD)) {
- pm_runtime_disable(&host->card->dev);
- pm_runtime_set_active(&host->card->dev);
- pm_runtime_enable(&host->card->dev);
- }
- }
- BUG_ON(!host->bus_ops->resume);
- err = host->bus_ops->resume(host);
- if (err) {
- pr_warning("%s: error %d during resume "
- "(card was removed?)\n",
- mmc_hostname(host), err);
- err = 0;
- }
- }
- host->pm_flags &= ~MMC_PM_KEEP_POWER;
- mmc_bus_put(host);
-
- return err;
-}
-EXPORT_SYMBOL(mmc_resume_host);
-
/* Do the card removal on suspend if card is assumed removeable
* Do that in pm notifier while userspace isn't yet frozen, so we will be able
to sync the card.
@@ -2511,25 +2615,27 @@ int mmc_pm_notify(struct notifier_block *notify_block,
struct mmc_host *host = container_of(
notify_block, struct mmc_host, pm_notify);
unsigned long flags;
-
+ int err = 0;
switch (mode) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
-
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 1;
- host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
spin_unlock_irqrestore(&host->lock, flags);
cancel_delayed_work_sync(&host->detect);
- if (!host->bus_ops || host->bus_ops->suspend)
+ if (!host->bus_ops)
break;
- /* Calling bus_ops->remove() with a claimed host can deadlock */
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
+ /* Validate prerequisites for suspend */
+ if (host->bus_ops->pre_suspend)
+ err = host->bus_ops->pre_suspend(host);
+ if (!err)
+ break;
+ /* Calling bus_ops->remove() with a claimed host can deadlock */
+ host->bus_ops->remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_power_off(host);
@@ -2543,9 +2649,8 @@ int mmc_pm_notify(struct notifier_block *notify_block,
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 0;
- host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
spin_unlock_irqrestore(&host->lock, flags);
- mmc_detect_change(host, 0);
+ _mmc_detect_change(host, 0, false);
}
@@ -2553,6 +2658,23 @@ int mmc_pm_notify(struct notifier_block *notify_block,
}
#endif
+/**
+ * mmc_init_context_info() - init synchronization context
+ * @host: mmc host
+ *
+ * Init struct context_info needed to implement asynchronous
+ * request mechanism, used by mmc core, host driver and mmc requests
+ * supplier.
+ */
+void mmc_init_context_info(struct mmc_host *host)
+{
+ spin_lock_init(&host->context_info.lock);
+ host->context_info.is_new_req = false;
+ host->context_info.is_done_rcv = false;
+ host->context_info.is_waiting_last_req = false;
+ init_waitqueue_head(&host->context_info.wait);
+}
+
static int __init mmc_init(void)
{
int ret;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 3bdafbca354..443a584660f 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -16,15 +16,17 @@
#define MMC_CMD_RETRIES 3
struct mmc_bus_ops {
- int (*awake)(struct mmc_host *);
- int (*sleep)(struct mmc_host *);
void (*remove)(struct mmc_host *);
void (*detect)(struct mmc_host *);
+ int (*pre_suspend)(struct mmc_host *);
int (*suspend)(struct mmc_host *);
int (*resume)(struct mmc_host *);
+ int (*runtime_suspend)(struct mmc_host *);
+ int (*runtime_resume)(struct mmc_host *);
int (*power_save)(struct mmc_host *);
int (*power_restore)(struct mmc_host *);
int (*alive)(struct mmc_host *);
+ int (*shutdown)(struct mmc_host *);
};
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
@@ -40,11 +42,13 @@ void mmc_set_ungated(struct mmc_host *host);
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage,
- bool cmd11);
+int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr);
+int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
+void mmc_power_up(struct mmc_host *host, u32 ocr);
void mmc_power_off(struct mmc_host *host);
+void mmc_power_cycle(struct mmc_host *host, u32 ocr);
static inline void mmc_delay(unsigned int ms)
{
@@ -76,5 +80,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host);
void mmc_add_card_debugfs(struct mmc_card *card);
void mmc_remove_card_debugfs(struct mmc_card *card);
+void mmc_init_context_info(struct mmc_host *host);
#endif
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 9ab5b17d488..91eb1622324 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -135,8 +135,14 @@ static int mmc_ios_show(struct seq_file *s, void *data)
case MMC_TIMING_UHS_DDR50:
str = "sd uhs DDR50";
break;
+ case MMC_TIMING_MMC_DDR52:
+ str = "mmc DDR52";
+ break;
case MMC_TIMING_MMC_HS200:
- str = "mmc high-speed SDR200";
+ str = "mmc HS200";
+ break;
+ case MMC_TIMING_MMC_HS400:
+ str = "mmc HS400";
break;
default:
str = "invalid";
@@ -144,6 +150,22 @@ static int mmc_ios_show(struct seq_file *s, void *data)
}
seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ str = "3.30 V";
+ break;
+ case MMC_SIGNAL_VOLTAGE_180:
+ str = "1.80 V";
+ break;
+ case MMC_SIGNAL_VOLTAGE_120:
+ str = "1.20 V";
+ break;
+ default:
+ str = "invalid";
+ break;
+ }
+ seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str);
+
return 0;
}
@@ -242,13 +264,13 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
u32 status;
int ret;
- mmc_claim_host(card->host);
+ mmc_get_card(card);
ret = mmc_send_status(data, &status);
if (!ret)
*val = status;
- mmc_release_host(card->host);
+ mmc_put_card(card);
return ret;
}
@@ -275,13 +297,13 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
goto out_free;
}
- mmc_claim_host(card->host);
+ mmc_get_card(card);
err = mmc_send_ext_csd(card, ext_csd);
- mmc_release_host(card->host);
+ mmc_put_card(card);
if (err)
goto out_free;
- for (i = 511; i >= 0; i--)
+ for (i = 0; i < 512; i++)
n += sprintf(buf + n, "%02x", ext_csd[i]);
n += sprintf(buf + n, "\n");
BUG_ON(n != EXT_CSD_STR_LEN);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index c3704e293a7..95cceae9694 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -15,6 +15,8 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/idr.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/pagemap.h>
#include <linux/export.h>
#include <linux/leds.h>
@@ -23,6 +25,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/slot-gpio.h>
#include "core.h"
#include "host.h"
@@ -32,6 +35,7 @@
static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ mutex_destroy(&host->slot.lock);
kfree(host);
}
@@ -203,8 +207,8 @@ void mmc_host_clk_release(struct mmc_host *host)
host->clk_requests--;
if (mmc_host_may_gate_card(host->card) &&
!host->clk_requests)
- queue_delayed_work(system_nrt_wq, &host->clk_gate_work,
- msecs_to_jiffies(host->clkgate_delay));
+ schedule_delayed_work(&host->clk_gate_work,
+ msecs_to_jiffies(host->clkgate_delay));
spin_unlock_irqrestore(&host->clk_lock, flags);
}
@@ -294,6 +298,170 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)
#endif
/**
+ * mmc_of_parse() - parse host's device-tree node
+ * @host: host whose node should be parsed.
+ *
+ * To keep the rest of the MMC subsystem unaware of whether DT has been
+ * used to to instantiate and configure this host instance or not, we
+ * parse the properties and set respective generic mmc-host flags and
+ * parameters.
+ */
+int mmc_of_parse(struct mmc_host *host)
+{
+ struct device_node *np;
+ u32 bus_width;
+ bool explicit_inv_wp, gpio_inv_wp = false;
+ enum of_gpio_flags flags;
+ int len, ret, gpio;
+
+ if (!host->parent || !host->parent->of_node)
+ return 0;
+
+ np = host->parent->of_node;
+
+ /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
+ if (of_property_read_u32(np, "bus-width", &bus_width) < 0) {
+ dev_dbg(host->parent,
+ "\"bus-width\" property is missing, assuming 1 bit.\n");
+ bus_width = 1;
+ }
+
+ switch (bus_width) {
+ case 8:
+ host->caps |= MMC_CAP_8_BIT_DATA;
+ /* Hosts capable of 8-bit transfers can also do 4 bits */
+ case 4:
+ host->caps |= MMC_CAP_4_BIT_DATA;
+ break;
+ case 1:
+ break;
+ default:
+ dev_err(host->parent,
+ "Invalid \"bus-width\" value %u!\n", bus_width);
+ return -EINVAL;
+ }
+
+ /* f_max is obtained from the optional "max-frequency" property */
+ of_property_read_u32(np, "max-frequency", &host->f_max);
+
+ /*
+ * Configure CD and WP pins. They are both by default active low to
+ * match the SDHCI spec. If GPIOs are provided for CD and / or WP, the
+ * mmc-gpio helpers are used to attach, configure and use them. If
+ * polarity inversion is specified in DT, one of MMC_CAP2_CD_ACTIVE_HIGH
+ * and MMC_CAP2_RO_ACTIVE_HIGH capability-2 flags is set. If the
+ * "broken-cd" property is provided, the MMC_CAP_NEEDS_POLL capability
+ * is set. If the "non-removable" property is found, the
+ * MMC_CAP_NONREMOVABLE capability is set and no card-detection
+ * configuration is performed.
+ */
+
+ /* Parse Card Detection */
+ if (of_find_property(np, "non-removable", &len)) {
+ host->caps |= MMC_CAP_NONREMOVABLE;
+ } else {
+ bool explicit_inv_cd, gpio_inv_cd = false;
+
+ explicit_inv_cd = of_property_read_bool(np, "cd-inverted");
+
+ if (of_find_property(np, "broken-cd", &len))
+ host->caps |= MMC_CAP_NEEDS_POLL;
+
+ gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags);
+ if (gpio == -EPROBE_DEFER)
+ return gpio;
+ if (gpio_is_valid(gpio)) {
+ if (!(flags & OF_GPIO_ACTIVE_LOW))
+ gpio_inv_cd = true;
+
+ ret = mmc_gpio_request_cd(host, gpio, 0);
+ if (ret < 0) {
+ dev_err(host->parent,
+ "Failed to request CD GPIO #%d: %d!\n",
+ gpio, ret);
+ return ret;
+ } else {
+ dev_info(host->parent, "Got CD GPIO #%d.\n",
+ gpio);
+ }
+ }
+
+ if (explicit_inv_cd ^ gpio_inv_cd)
+ host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+ }
+
+ /* Parse Write Protection */
+ explicit_inv_wp = of_property_read_bool(np, "wp-inverted");
+
+ gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags);
+ if (gpio == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto out;
+ }
+ if (gpio_is_valid(gpio)) {
+ if (!(flags & OF_GPIO_ACTIVE_LOW))
+ gpio_inv_wp = true;
+
+ ret = mmc_gpio_request_ro(host, gpio);
+ if (ret < 0) {
+ dev_err(host->parent,
+ "Failed to request WP GPIO: %d!\n", ret);
+ goto out;
+ } else {
+ dev_info(host->parent, "Got WP GPIO #%d.\n",
+ gpio);
+ }
+ }
+ if (explicit_inv_wp ^ gpio_inv_wp)
+ host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+
+ if (of_find_property(np, "cap-sd-highspeed", &len))
+ host->caps |= MMC_CAP_SD_HIGHSPEED;
+ if (of_find_property(np, "cap-mmc-highspeed", &len))
+ host->caps |= MMC_CAP_MMC_HIGHSPEED;
+ if (of_find_property(np, "sd-uhs-sdr12", &len))
+ host->caps |= MMC_CAP_UHS_SDR12;
+ if (of_find_property(np, "sd-uhs-sdr25", &len))
+ host->caps |= MMC_CAP_UHS_SDR25;
+ if (of_find_property(np, "sd-uhs-sdr50", &len))
+ host->caps |= MMC_CAP_UHS_SDR50;
+ if (of_find_property(np, "sd-uhs-sdr104", &len))
+ host->caps |= MMC_CAP_UHS_SDR104;
+ if (of_find_property(np, "sd-uhs-ddr50", &len))
+ host->caps |= MMC_CAP_UHS_DDR50;
+ if (of_find_property(np, "cap-power-off-card", &len))
+ host->caps |= MMC_CAP_POWER_OFF_CARD;
+ if (of_find_property(np, "cap-sdio-irq", &len))
+ host->caps |= MMC_CAP_SDIO_IRQ;
+ if (of_find_property(np, "full-pwr-cycle", &len))
+ host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
+ if (of_find_property(np, "keep-power-in-suspend", &len))
+ host->pm_caps |= MMC_PM_KEEP_POWER;
+ if (of_find_property(np, "enable-sdio-wakeup", &len))
+ host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+ if (of_find_property(np, "mmc-ddr-1_8v", &len))
+ host->caps |= MMC_CAP_1_8V_DDR;
+ if (of_find_property(np, "mmc-ddr-1_2v", &len))
+ host->caps |= MMC_CAP_1_2V_DDR;
+ if (of_find_property(np, "mmc-hs200-1_8v", &len))
+ host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
+ if (of_find_property(np, "mmc-hs200-1_2v", &len))
+ host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
+ if (of_find_property(np, "mmc-hs400-1_8v", &len))
+ host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR;
+ if (of_find_property(np, "mmc-hs400-1_2v", &len))
+ host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
+
+ return 0;
+
+out:
+ mmc_gpio_free_cd(host);
+ return ret;
+}
+
+EXPORT_SYMBOL(mmc_of_parse);
+
+/**
* mmc_alloc_host - initialise the per-host structure.
* @extra: sizeof private data structure
* @dev: pointer to host device model structure
@@ -305,17 +473,20 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
int err;
struct mmc_host *host;
- if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
- return NULL;
-
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
return NULL;
+ /* scanning will be enabled when we're ready */
+ host->rescan_disable = 1;
+ idr_preload(GFP_KERNEL);
spin_lock(&mmc_host_lock);
- err = idr_get_new(&mmc_host_idr, host, &host->index);
+ err = idr_alloc(&mmc_host_idr, host, 0, 0, GFP_NOWAIT);
+ if (err >= 0)
+ host->index = err;
spin_unlock(&mmc_host_lock);
- if (err)
+ idr_preload_end();
+ if (err < 0)
goto free;
dev_set_name(&host->class_dev, "mmc%d", host->index);
@@ -327,10 +498,12 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
mmc_host_clk_init(host);
+ mutex_init(&host->slot.lock);
+ host->slot.cd_irq = -EINVAL;
+
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
- INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
#ifdef CONFIG_PM
host->pm_notify.notifier_call = mmc_pm_notify;
#endif
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index 08a7852ade4..f2ab9e57812 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -14,7 +14,6 @@
int mmc_register_host_class(void);
void mmc_unregister_host_class(void);
-void mmc_host_deeper_disable(struct work_struct *work);
#endif
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 2b9ed1401dc..793c6f7ddb0 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -13,6 +13,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/stat.h>
+#include <linux/pm_runtime.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
@@ -96,6 +97,7 @@ static int mmc_decode_cid(struct mmc_card *card)
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
+ card->cid.prv = UNSTUFF_BITS(resp, 48, 8);
card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
@@ -235,6 +237,67 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
return err;
}
+static void mmc_select_card_type(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ u8 card_type = card->ext_csd.raw_card_type;
+ u32 caps = host->caps, caps2 = host->caps2;
+ unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
+ unsigned int avail_type = 0;
+
+ if (caps & MMC_CAP_MMC_HIGHSPEED &&
+ card_type & EXT_CSD_CARD_TYPE_HS_26) {
+ hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+ }
+
+ if (caps & MMC_CAP_MMC_HIGHSPEED &&
+ card_type & EXT_CSD_CARD_TYPE_HS_52) {
+ hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+ }
+
+ if (caps & MMC_CAP_1_8V_DDR &&
+ card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
+ hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+ }
+
+ if (caps & MMC_CAP_1_2V_DDR &&
+ card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+ hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+ }
+
+ if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+ card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
+ hs200_max_dtr = MMC_HS200_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+ }
+
+ if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+ card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+ hs200_max_dtr = MMC_HS200_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+ }
+
+ if (caps2 & MMC_CAP2_HS400_1_8V &&
+ card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) {
+ hs200_max_dtr = MMC_HS200_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V;
+ }
+
+ if (caps2 & MMC_CAP2_HS400_1_2V &&
+ card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) {
+ hs200_max_dtr = MMC_HS200_MAX_DTR;
+ avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
+ }
+
+ card->ext_csd.hs_max_dtr = hs_max_dtr;
+ card->ext_csd.hs200_max_dtr = hs200_max_dtr;
+ card->mmc_avail_type = avail_type;
+}
+
/*
* Decode extended CSD.
*/
@@ -262,7 +325,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
}
card->ext_csd.rev = ext_csd[EXT_CSD_REV];
- if (card->ext_csd.rev > 6) {
+ if (card->ext_csd.rev > 7) {
pr_err("%s: unrecognised EXT_CSD revision %d\n",
mmc_hostname(card->host), card->ext_csd.rev);
err = -EINVAL;
@@ -284,56 +347,9 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512)
mmc_card_set_blockaddr(card);
}
+
card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
- switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
- case EXT_CSD_CARD_TYPE_SDR_ALL:
- case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
- case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
- case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
- card->ext_csd.hs_max_dtr = 200000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200;
- break;
- case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
- case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
- case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
- case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
- card->ext_csd.hs_max_dtr = 200000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V;
- break;
- case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
- case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
- case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
- case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
- card->ext_csd.hs_max_dtr = 200000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V;
- break;
- case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 |
- EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52;
- break;
- case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 |
- EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V;
- break;
- case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 |
- EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V;
- break;
- case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- break;
- case EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 26000000;
- break;
- default:
- /* MMC v4 spec says this cannot happen */
- pr_warning("%s: card is mmc v4 but doesn't "
- "support any high-speed modes.\n",
- mmc_hostname(card->host));
- }
+ mmc_select_card_type(card);
card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT];
card->ext_csd.raw_erase_timeout_mult =
@@ -385,13 +401,13 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
card->ext_csd.raw_trim_mult =
ext_csd[EXT_CSD_TRIM_MULT];
+ card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if (card->ext_csd.rev >= 4) {
/*
* Enhanced area feature support -- check whether the eMMC
* card has the Enhanced area enabled. If so, export enhanced
* area offset and size to user by adding sysfs interface.
*/
- card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
hc_erase_grp_sz =
@@ -477,9 +493,44 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
*/
card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP];
card->ext_csd.boot_ro_lockable = true;
+
+ /* Save power class values */
+ card->ext_csd.raw_pwr_cl_52_195 =
+ ext_csd[EXT_CSD_PWR_CL_52_195];
+ card->ext_csd.raw_pwr_cl_26_195 =
+ ext_csd[EXT_CSD_PWR_CL_26_195];
+ card->ext_csd.raw_pwr_cl_52_360 =
+ ext_csd[EXT_CSD_PWR_CL_52_360];
+ card->ext_csd.raw_pwr_cl_26_360 =
+ ext_csd[EXT_CSD_PWR_CL_26_360];
+ card->ext_csd.raw_pwr_cl_200_195 =
+ ext_csd[EXT_CSD_PWR_CL_200_195];
+ card->ext_csd.raw_pwr_cl_200_360 =
+ ext_csd[EXT_CSD_PWR_CL_200_360];
+ card->ext_csd.raw_pwr_cl_ddr_52_195 =
+ ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
+ card->ext_csd.raw_pwr_cl_ddr_52_360 =
+ ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
+ card->ext_csd.raw_pwr_cl_ddr_200_360 =
+ ext_csd[EXT_CSD_PWR_CL_DDR_200_360];
}
if (card->ext_csd.rev >= 5) {
+ /* Adjust production date as per JEDEC JESD84-B451 */
+ if (card->cid.year < 2010)
+ card->cid.year += 16;
+
+ /* check whether the eMMC card supports BKOPS */
+ if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
+ card->ext_csd.bkops = 1;
+ card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN];
+ card->ext_csd.raw_bkops_status =
+ ext_csd[EXT_CSD_BKOPS_STATUS];
+ if (!card->ext_csd.bkops_en)
+ pr_info("%s: BKOPS_EN bit is not set\n",
+ mmc_hostname(card->host));
+ }
+
/* check whether the eMMC card supports HPI */
if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
card->ext_csd.hpi = 1;
@@ -497,6 +548,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+
+ /*
+ * RPMB regions are defined in multiples of 128K.
+ */
+ card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
+ if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) {
+ mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
+ EXT_CSD_PART_CONFIG_ACC_RPMB,
+ "rpmb", 0, false,
+ MMC_BLK_DATA_AREA_RPMB);
+ }
}
card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
@@ -519,6 +581,27 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+
+ if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1)
+ card->ext_csd.data_sector_size = 4096;
+ else
+ card->ext_csd.data_sector_size = 512;
+
+ if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) &&
+ (ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) {
+ card->ext_csd.data_tag_unit_size =
+ ((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) *
+ (card->ext_csd.data_sector_size);
+ } else {
+ card->ext_csd.data_tag_unit_size = 0;
+ }
+
+ card->ext_csd.max_packed_writes =
+ ext_csd[EXT_CSD_MAX_PACKED_WRITES];
+ card->ext_csd.max_packed_reads =
+ ext_csd[EXT_CSD_MAX_PACKED_READS];
+ } else {
+ card->ext_csd.data_sector_size = 512;
}
out:
@@ -542,14 +625,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
err = mmc_get_ext_csd(card, &bw_ext_csd);
if (err || bw_ext_csd == NULL) {
- if (bus_width != MMC_BUS_WIDTH_1)
- err = -EINVAL;
+ err = -EINVAL;
goto out;
}
- if (bus_width == MMC_BUS_WIDTH_1)
- goto out;
-
/* only compare read only fields */
err = !((card->ext_csd.raw_partition_support ==
bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) &&
@@ -584,7 +663,26 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
(card->ext_csd.raw_sectors[2] ==
bw_ext_csd[EXT_CSD_SEC_CNT + 2]) &&
(card->ext_csd.raw_sectors[3] ==
- bw_ext_csd[EXT_CSD_SEC_CNT + 3]));
+ bw_ext_csd[EXT_CSD_SEC_CNT + 3]) &&
+ (card->ext_csd.raw_pwr_cl_52_195 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_52_195]) &&
+ (card->ext_csd.raw_pwr_cl_26_195 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_26_195]) &&
+ (card->ext_csd.raw_pwr_cl_52_360 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_52_360]) &&
+ (card->ext_csd.raw_pwr_cl_26_360 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_26_360]) &&
+ (card->ext_csd.raw_pwr_cl_200_195 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_200_195]) &&
+ (card->ext_csd.raw_pwr_cl_200_360 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_200_360]) &&
+ (card->ext_csd.raw_pwr_cl_ddr_52_195 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
+ (card->ext_csd.raw_pwr_cl_ddr_52_360 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) &&
+ (card->ext_csd.raw_pwr_cl_ddr_200_360 ==
+ bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360]));
+
if (err)
err = -EINVAL;
@@ -605,10 +703,13 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
card->ext_csd.enhanced_area_offset);
MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
+MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
+MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
static struct attribute *mmc_std_attrs[] = {
&dev_attr_cid.attr,
@@ -621,23 +722,18 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_manfid.attr,
&dev_attr_name.attr,
&dev_attr_oemid.attr,
+ &dev_attr_prv.attr,
&dev_attr_serial.attr,
&dev_attr_enhanced_area_offset.attr,
&dev_attr_enhanced_area_size.attr,
+ &dev_attr_raw_rpmb_size_mult.attr,
+ &dev_attr_rel_sectors.attr,
NULL,
};
-
-static struct attribute_group mmc_std_attr_group = {
- .attrs = mmc_std_attrs,
-};
-
-static const struct attribute_group *mmc_attr_groups[] = {
- &mmc_std_attr_group,
- NULL,
-};
+ATTRIBUTE_GROUPS(mmc_std);
static struct device_type mmc_type = {
- .groups = mmc_attr_groups,
+ .groups = mmc_std_groups,
};
/*
@@ -646,21 +742,13 @@ static struct device_type mmc_type = {
* extended CSD register, select it by executing the
* mmc_switch command.
*/
-static int mmc_select_powerclass(struct mmc_card *card,
- unsigned int bus_width, u8 *ext_csd)
+static int __mmc_select_powerclass(struct mmc_card *card,
+ unsigned int bus_width)
{
+ struct mmc_host *host = card->host;
+ struct mmc_ext_csd *ext_csd = &card->ext_csd;
+ unsigned int pwrclass_val = 0;
int err = 0;
- unsigned int pwrclass_val;
- unsigned int index = 0;
- struct mmc_host *host;
-
- BUG_ON(!card);
-
- host = card->host;
- BUG_ON(!host);
-
- if (ext_csd == NULL)
- return 0;
/* Power class selection is supported for versions >= 4.0 */
if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
@@ -672,27 +760,34 @@ static int mmc_select_powerclass(struct mmc_card *card,
switch (1 << host->ios.vdd) {
case MMC_VDD_165_195:
- if (host->ios.clock <= 26000000)
- index = EXT_CSD_PWR_CL_26_195;
- else if (host->ios.clock <= 52000000)
- index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
- EXT_CSD_PWR_CL_52_195 :
- EXT_CSD_PWR_CL_DDR_52_195;
- else if (host->ios.clock <= 200000000)
- index = EXT_CSD_PWR_CL_200_195;
+ if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
+ pwrclass_val = ext_csd->raw_pwr_cl_26_195;
+ else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR)
+ pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+ ext_csd->raw_pwr_cl_52_195 :
+ ext_csd->raw_pwr_cl_ddr_52_195;
+ else if (host->ios.clock <= MMC_HS200_MAX_DTR)
+ pwrclass_val = ext_csd->raw_pwr_cl_200_195;
break;
+ case MMC_VDD_27_28:
+ case MMC_VDD_28_29:
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ case MMC_VDD_31_32:
case MMC_VDD_32_33:
case MMC_VDD_33_34:
case MMC_VDD_34_35:
case MMC_VDD_35_36:
- if (host->ios.clock <= 26000000)
- index = EXT_CSD_PWR_CL_26_360;
- else if (host->ios.clock <= 52000000)
- index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
- EXT_CSD_PWR_CL_52_360 :
- EXT_CSD_PWR_CL_DDR_52_360;
- else if (host->ios.clock <= 200000000)
- index = EXT_CSD_PWR_CL_200_360;
+ if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
+ pwrclass_val = ext_csd->raw_pwr_cl_26_360;
+ else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR)
+ pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+ ext_csd->raw_pwr_cl_52_360 :
+ ext_csd->raw_pwr_cl_ddr_52_360;
+ else if (host->ios.clock <= MMC_HS200_MAX_DTR)
+ pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ?
+ ext_csd->raw_pwr_cl_ddr_200_360 :
+ ext_csd->raw_pwr_cl_200_360;
break;
default:
pr_warning("%s: Voltage range not supported "
@@ -700,8 +795,6 @@ static int mmc_select_powerclass(struct mmc_card *card,
return -EINVAL;
}
- pwrclass_val = ext_csd[index];
-
if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8))
pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >>
EXT_CSD_PWR_CL_8BIT_SHIFT;
@@ -720,38 +813,79 @@ static int mmc_select_powerclass(struct mmc_card *card,
return err;
}
+static int mmc_select_powerclass(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ u32 bus_width, ext_csd_bits;
+ int err, ddr;
+
+ /* Power class selection is supported for versions >= 4.0 */
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ return 0;
+
+ bus_width = host->ios.bus_width;
+ /* Power class values are defined only for 4/8 bit bus */
+ if (bus_width == MMC_BUS_WIDTH_1)
+ return 0;
+
+ ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+ if (ddr)
+ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
+ EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
+ else
+ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
+ EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
+
+ err = __mmc_select_powerclass(card, ext_csd_bits);
+ if (err)
+ pr_warn("%s: power class selection to bus width %d ddr %d failed\n",
+ mmc_hostname(host), 1 << bus_width, ddr);
+
+ return err;
+}
+
/*
- * Selects the desired buswidth and switch to the HS200 mode
- * if bus width set without error
+ * Set the bus speed for the selected speed mode.
*/
-static int mmc_select_hs200(struct mmc_card *card)
+static void mmc_set_bus_speed(struct mmc_card *card)
+{
+ unsigned int max_dtr = (unsigned int)-1;
+
+ if ((mmc_card_hs200(card) || mmc_card_hs400(card)) &&
+ max_dtr > card->ext_csd.hs200_max_dtr)
+ max_dtr = card->ext_csd.hs200_max_dtr;
+ else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
+ max_dtr = card->ext_csd.hs_max_dtr;
+ else if (max_dtr > card->csd.max_dtr)
+ max_dtr = card->csd.max_dtr;
+
+ mmc_set_clock(card->host, max_dtr);
+}
+
+/*
+ * Select the bus width amoung 4-bit and 8-bit(SDR).
+ * If the bus width is changed successfully, return the selected width value.
+ * Zero is returned instead of error value if the wide width is not supported.
+ */
+static int mmc_select_bus_width(struct mmc_card *card)
{
- int idx, err = 0;
- struct mmc_host *host;
static unsigned ext_csd_bits[] = {
- EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8,
+ EXT_CSD_BUS_WIDTH_4,
};
static unsigned bus_widths[] = {
- MMC_BUS_WIDTH_4,
MMC_BUS_WIDTH_8,
+ MMC_BUS_WIDTH_4,
};
+ struct mmc_host *host = card->host;
+ unsigned idx, bus_width = 0;
+ int err = 0;
- BUG_ON(!card);
-
- host = card->host;
-
- if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
- host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
- if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0))
- err = mmc_set_signal_voltage(host,
- MMC_SIGNAL_VOLTAGE_180, 0);
-
- /* If fails try again during next card power cycle */
- if (err)
- goto err;
+ if ((card->csd.mmca_vsn < CSD_SPEC_VER_4) &&
+ !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
+ return 0;
- idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0;
+ idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 0 : 1;
/*
* Unlike SD, MMC cards dont have a configuration register to notify
@@ -759,8 +893,7 @@ static int mmc_select_hs200(struct mmc_card *card)
* the supported bus width or compare the ext csd values of current
* bus width and ext csd values of 1 bit mode read earlier.
*/
- for (; idx >= 0; idx--) {
-
+ for (; idx < ARRAY_SIZE(bus_widths); idx++) {
/*
* Host is capable of 8bit transfer, then switch
* the device to work in 8bit transfer mode. If the
@@ -775,25 +908,266 @@ static int mmc_select_hs200(struct mmc_card *card)
if (err)
continue;
- mmc_set_bus_width(card->host, bus_widths[idx]);
+ bus_width = bus_widths[idx];
+ mmc_set_bus_width(host, bus_width);
+ /*
+ * If controller can't handle bus width test,
+ * compare ext_csd previously read in 1 bit mode
+ * against ext_csd at new bus width
+ */
if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
- err = mmc_compare_ext_csds(card, bus_widths[idx]);
+ err = mmc_compare_ext_csds(card, bus_width);
else
- err = mmc_bus_test(card, bus_widths[idx]);
- if (!err)
+ err = mmc_bus_test(card, bus_width);
+
+ if (!err) {
+ err = bus_width;
break;
+ } else {
+ pr_warn("%s: switch to bus width %d failed\n",
+ mmc_hostname(host), ext_csd_bits[idx]);
+ }
}
- /* switch to HS200 mode if bus width set successfully */
+ return err;
+}
+
+/*
+ * Switch to the high-speed mode
+ */
+static int mmc_select_hs(struct mmc_card *card)
+{
+ int err;
+
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+ card->ext_csd.generic_cmd6_time,
+ true, true, true);
if (!err)
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 2, 0);
+ mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+
+ return err;
+}
+
+/*
+ * Activate wide bus and DDR if supported.
+ */
+static int mmc_select_hs_ddr(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ u32 bus_width, ext_csd_bits;
+ int err = 0;
+
+ if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52))
+ return 0;
+
+ bus_width = host->ios.bus_width;
+ if (bus_width == MMC_BUS_WIDTH_1)
+ return 0;
+
+ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
+ EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
+
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ ext_csd_bits,
+ card->ext_csd.generic_cmd6_time);
+ if (err) {
+ pr_warn("%s: switch to bus width %d ddr failed\n",
+ mmc_hostname(host), 1 << bus_width);
+ return err;
+ }
+
+ /*
+ * eMMC cards can support 3.3V to 1.2V i/o (vccq)
+ * signaling.
+ *
+ * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
+ *
+ * 1.8V vccq at 3.3V core voltage (vcc) is not required
+ * in the JEDEC spec for DDR.
+ *
+ * Do not force change in vccq since we are obviously
+ * working and no change to vccq is needed.
+ *
+ * WARNING: eMMC rules are NOT the same as SD DDR
+ */
+ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+ err = __mmc_set_signal_voltage(host,
+ MMC_SIGNAL_VOLTAGE_120);
+ if (err)
+ return err;
+ }
+
+ mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
+
+ return err;
+}
+
+static int mmc_select_hs400(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ int err = 0;
+
+ /*
+ * HS400 mode requires 8-bit bus width
+ */
+ if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 &&
+ host->ios.bus_width == MMC_BUS_WIDTH_8))
+ return 0;
+
+ /*
+ * Before switching to dual data rate operation for HS400,
+ * it is required to convert from HS200 mode to HS mode.
+ */
+ mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+ mmc_set_bus_speed(card);
+
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+ card->ext_csd.generic_cmd6_time,
+ true, true, true);
+ if (err) {
+ pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+ mmc_hostname(host), err);
+ return err;
+ }
+
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ EXT_CSD_DDR_BUS_WIDTH_8,
+ card->ext_csd.generic_cmd6_time);
+ if (err) {
+ pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+ mmc_hostname(host), err);
+ return err;
+ }
+
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+ card->ext_csd.generic_cmd6_time,
+ true, true, true);
+ if (err) {
+ pr_warn("%s: switch to hs400 failed, err:%d\n",
+ mmc_hostname(host), err);
+ return err;
+ }
+
+ mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+ mmc_set_bus_speed(card);
+
+ return 0;
+}
+
+/*
+ * For device supporting HS200 mode, the following sequence
+ * should be done before executing the tuning process.
+ * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported)
+ * 2. switch to HS200 mode
+ * 3. set the clock to > 52Mhz and <=200MHz
+ */
+static int mmc_select_hs200(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ int err = -EINVAL;
+
+ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
+ err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
+
+ if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
+ err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
+
+ /* If fails try again during next card power cycle */
+ if (err)
+ goto err;
+
+ /*
+ * Set the bus width(4 or 8) with host's support and
+ * switch to HS200 mode if bus width is set successfully.
+ */
+ err = mmc_select_bus_width(card);
+ if (!IS_ERR_VALUE(err)) {
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
+ card->ext_csd.generic_cmd6_time,
+ true, true, true);
+ if (!err)
+ mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+ }
err:
return err;
}
/*
+ * Activate High Speed or HS200 mode if supported.
+ */
+static int mmc_select_timing(struct mmc_card *card)
+{
+ int err = 0;
+
+ if ((card->csd.mmca_vsn < CSD_SPEC_VER_4 &&
+ card->ext_csd.hs_max_dtr == 0))
+ goto bus_speed;
+
+ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
+ err = mmc_select_hs200(card);
+ else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
+ err = mmc_select_hs(card);
+
+ if (err && err != -EBADMSG)
+ return err;
+
+ if (err) {
+ pr_warn("%s: switch to %s failed\n",
+ mmc_card_hs(card) ? "high-speed" :
+ (mmc_card_hs200(card) ? "hs200" : ""),
+ mmc_hostname(card->host));
+ err = 0;
+ }
+
+bus_speed:
+ /*
+ * Set the bus speed to the selected bus timing.
+ * If timing is not selected, backward compatible is the default.
+ */
+ mmc_set_bus_speed(card);
+ return err;
+}
+
+/*
+ * Execute tuning sequence to seek the proper bus operating
+ * conditions for HS200 and HS400, which sends CMD21 to the device.
+ */
+static int mmc_hs200_tuning(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ int err = 0;
+
+ /*
+ * Timing should be adjusted to the HS400 target
+ * operation frequency for tuning process
+ */
+ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 &&
+ host->ios.bus_width == MMC_BUS_WIDTH_8)
+ if (host->ops->prepare_hs400_tuning)
+ host->ops->prepare_hs400_tuning(host, &host->ios);
+
+ if (host->ops->execute_tuning) {
+ mmc_host_clk_hold(host);
+ err = host->ops->execute_tuning(host,
+ MMC_SEND_TUNING_BLOCK_HS200);
+ mmc_host_clk_release(host);
+
+ if (err)
+ pr_warn("%s: tuning execution failed\n",
+ mmc_hostname(host));
+ }
+
+ return err;
+}
+
+/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
@@ -803,9 +1177,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
struct mmc_card *card;
- int err, ddr = 0;
+ int err;
u32 cid[4];
- unsigned int max_dtr;
u32 rocr;
u8 *ext_csd = NULL;
@@ -816,9 +1189,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host))
mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
- /* Initialization should be done at 3.3 V I/O voltage. */
- mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
/*
* Since we're changing the OCR value, we seem to
* need to tell some cards to go back to the idle
@@ -869,6 +1239,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
goto err;
}
+ card->ocr = ocr;
card->type = MMC_TYPE_MMC;
card->rca = 1;
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
@@ -938,7 +1309,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
* If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
* bit. This bit will be lost every time after a reset or power off.
*/
- if (card->ext_csd.enhanced_area_en) {
+ if (card->ext_csd.enhanced_area_en ||
+ (card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_ERASE_GROUP_DEF, 1,
card->ext_csd.generic_cmd6_time);
@@ -979,11 +1351,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
- * If the host supports the power_off_notify capability then
- * set the notification byte in the ext_csd register of device
+ * Enable power_off_notification byte in the ext_csd register
*/
- if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
- (card->ext_csd.rev >= 6)) {
+ if (card->ext_csd.rev >= 6) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_POWER_OFF_NOTIFICATION,
EXT_CSD_POWER_ON,
@@ -996,48 +1366,46 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
* so check for success and update the flag
*/
if (!err)
- card->poweroff_notify_state = MMC_POWERED_ON;
+ card->ext_csd.power_off_notification = EXT_CSD_POWER_ON;
}
/*
- * Activate high speed (if supported)
+ * Select timing interface
*/
- if (card->ext_csd.hs_max_dtr != 0) {
- err = 0;
- if (card->ext_csd.hs_max_dtr > 52000000 &&
- host->caps2 & MMC_CAP2_HS200)
- err = mmc_select_hs200(card);
- else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 1,
- card->ext_csd.generic_cmd6_time);
+ err = mmc_select_timing(card);
+ if (err)
+ goto free_card;
- if (err && err != -EBADMSG)
- goto free_card;
+ if (mmc_card_hs200(card)) {
+ err = mmc_hs200_tuning(card);
+ if (err)
+ goto err;
- if (err) {
- pr_warning("%s: switch to highspeed failed\n",
- mmc_hostname(card->host));
- err = 0;
- } else {
- if (card->ext_csd.hs_max_dtr > 52000000 &&
- host->caps2 & MMC_CAP2_HS200) {
- mmc_card_set_hs200(card);
- mmc_set_timing(card->host,
- MMC_TIMING_MMC_HS200);
- } else {
- mmc_card_set_highspeed(card);
- mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- }
+ err = mmc_select_hs400(card);
+ if (err)
+ goto err;
+ } else if (mmc_card_hs(card)) {
+ /* Select the desired bus width optionally */
+ err = mmc_select_bus_width(card);
+ if (!IS_ERR_VALUE(err)) {
+ err = mmc_select_hs_ddr(card);
+ if (err)
+ goto err;
}
}
/*
+ * Choose the power class with selected bus interface
+ */
+ mmc_select_powerclass(card);
+
+ /*
* Enable HPI feature (if supported)
*/
if (card->ext_csd.hpi) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HPI_MGMT, 1, 0);
+ EXT_CSD_HPI_MGMT, 1,
+ card->ext_csd.generic_cmd6_time);
if (err && err != -EBADMSG)
goto free_card;
if (err) {
@@ -1049,181 +1417,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
- * Compute bus speed.
- */
- max_dtr = (unsigned int)-1;
-
- if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
- if (max_dtr > card->ext_csd.hs_max_dtr)
- max_dtr = card->ext_csd.hs_max_dtr;
- } else if (max_dtr > card->csd.max_dtr) {
- max_dtr = card->csd.max_dtr;
- }
-
- mmc_set_clock(host, max_dtr);
-
- /*
- * Indicate DDR mode (if supported).
- */
- if (mmc_card_highspeed(card)) {
- if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
- && ((host->caps & (MMC_CAP_1_8V_DDR |
- MMC_CAP_UHS_DDR50))
- == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
- ddr = MMC_1_8V_DDR_MODE;
- else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
- && ((host->caps & (MMC_CAP_1_2V_DDR |
- MMC_CAP_UHS_DDR50))
- == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
- ddr = MMC_1_2V_DDR_MODE;
- }
-
- /*
- * Indicate HS200 SDR mode (if supported).
- */
- if (mmc_card_hs200(card)) {
- u32 ext_csd_bits;
- u32 bus_width = card->host->ios.bus_width;
-
- /*
- * For devices supporting HS200 mode, the bus width has
- * to be set before executing the tuning function. If
- * set before tuning, then device will respond with CRC
- * errors for responses on CMD line. So for HS200 the
- * sequence will be
- * 1. set bus width 4bit / 8 bit (1 bit not supported)
- * 2. switch to HS200 mode
- * 3. set the clock to > 52Mhz <=200MHz and
- * 4. execute tuning for HS200
- */
- if ((host->caps2 & MMC_CAP2_HS200) &&
- card->host->ops->execute_tuning)
- err = card->host->ops->execute_tuning(card->host,
- MMC_SEND_TUNING_BLOCK_HS200);
- if (err) {
- pr_warning("%s: tuning execution failed\n",
- mmc_hostname(card->host));
- goto err;
- }
-
- ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
- EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
- err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
- if (err) {
- pr_err("%s: power class selection to bus width %d failed\n",
- mmc_hostname(card->host), 1 << bus_width);
- goto err;
- }
- }
-
- /*
- * Activate wide bus and DDR (if supported).
- */
- if (!mmc_card_hs200(card) &&
- (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
- (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
- static unsigned ext_csd_bits[][2] = {
- { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
- { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
- { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
- };
- static unsigned bus_widths[] = {
- MMC_BUS_WIDTH_8,
- MMC_BUS_WIDTH_4,
- MMC_BUS_WIDTH_1
- };
- unsigned idx, bus_width = 0;
-
- if (host->caps & MMC_CAP_8_BIT_DATA)
- idx = 0;
- else
- idx = 1;
- for (; idx < ARRAY_SIZE(bus_widths); idx++) {
- bus_width = bus_widths[idx];
- if (bus_width == MMC_BUS_WIDTH_1)
- ddr = 0; /* no DDR for 1-bit width */
- err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
- ext_csd);
- if (err)
- pr_err("%s: power class selection to "
- "bus width %d failed\n",
- mmc_hostname(card->host),
- 1 << bus_width);
-
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits[idx][0],
- card->ext_csd.generic_cmd6_time);
- if (!err) {
- mmc_set_bus_width(card->host, bus_width);
-
- /*
- * If controller can't handle bus width test,
- * compare ext_csd previously read in 1 bit mode
- * against ext_csd at new bus width
- */
- if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
- err = mmc_compare_ext_csds(card,
- bus_width);
- else
- err = mmc_bus_test(card, bus_width);
- if (!err)
- break;
- }
- }
-
- if (!err && ddr) {
- err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
- ext_csd);
- if (err)
- pr_err("%s: power class selection to "
- "bus width %d ddr %d failed\n",
- mmc_hostname(card->host),
- 1 << bus_width, ddr);
-
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits[idx][1],
- card->ext_csd.generic_cmd6_time);
- }
- if (err) {
- pr_warning("%s: switch to bus width %d ddr %d "
- "failed\n", mmc_hostname(card->host),
- 1 << bus_width, ddr);
- goto free_card;
- } else if (ddr) {
- /*
- * eMMC cards can support 3.3V to 1.2V i/o (vccq)
- * signaling.
- *
- * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
- *
- * 1.8V vccq at 3.3V core voltage (vcc) is not required
- * in the JEDEC spec for DDR.
- *
- * Do not force change in vccq since we are obviously
- * working and no change to vccq is needed.
- *
- * WARNING: eMMC rules are NOT the same as SD DDR
- */
- if (ddr == MMC_1_2V_DDR_MODE) {
- err = mmc_set_signal_voltage(host,
- MMC_SIGNAL_VOLTAGE_120, 0);
- if (err)
- goto err;
- }
- mmc_card_set_ddr_mode(card);
- mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
- mmc_set_bus_width(card->host, bus_width);
- }
- }
-
- /*
* If cache size is higher than 0, this indicates
* the existence of cache and it can be turned on.
*/
- if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
- card->ext_csd.cache_size > 0) {
+ if (card->ext_csd.cache_size > 0) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, 1,
card->ext_csd.generic_cmd6_time);
@@ -1244,6 +1441,29 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
}
+ /*
+ * The mandatory minimum values are defined for packed command.
+ * read: 5, write: 3
+ */
+ if (card->ext_csd.max_packed_writes >= 3 &&
+ card->ext_csd.max_packed_reads >= 5 &&
+ host->caps2 & MMC_CAP2_PACKED_CMD) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_EXP_EVENTS_CTRL,
+ EXT_CSD_PACKED_EVENT_EN,
+ card->ext_csd.generic_cmd6_time);
+ if (err && err != -EBADMSG)
+ goto free_card;
+ if (err) {
+ pr_warn("%s: Enabling packed event failed\n",
+ mmc_hostname(card->host));
+ card->ext_csd.packed_event_en = 0;
+ err = 0;
+ } else {
+ card->ext_csd.packed_event_en = 1;
+ }
+ }
+
if (!oldcard)
host->card = card;
@@ -1259,6 +1479,84 @@ err:
return err;
}
+static int mmc_can_sleep(struct mmc_card *card)
+{
+ return (card && card->ext_csd.rev >= 3);
+}
+
+static int mmc_sleep(struct mmc_host *host)
+{
+ struct mmc_command cmd = {0};
+ struct mmc_card *card = host->card;
+ unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
+ int err;
+
+ err = mmc_deselect_cards(host);
+ if (err)
+ return err;
+
+ 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.
+ */
+ if (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;
+ }
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err)
+ return err;
+
+ /*
+ * 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 (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+ mmc_delay(timeout_ms);
+
+ return err;
+}
+
+static int mmc_can_poweroff_notify(const struct mmc_card *card)
+{
+ return card &&
+ mmc_card_mmc(card) &&
+ (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON);
+}
+
+static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
+{
+ unsigned int timeout = card->ext_csd.generic_cmd6_time;
+ int err;
+
+ /* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */
+ if (notify_type == EXT_CSD_POWER_OFF_LONG)
+ timeout = card->ext_csd.power_off_longtime;
+
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_POWER_OFF_NOTIFICATION,
+ notify_type, timeout, true, false, false);
+ if (err)
+ pr_err("%s: Power Off Notification timed out, %u\n",
+ mmc_hostname(card->host), timeout);
+
+ /* Disable the power off notification after the switch operation. */
+ card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION;
+
+ return err;
+}
+
/*
* Host is being removed. Free up the current card.
*/
@@ -1289,14 +1587,14 @@ static void mmc_detect(struct mmc_host *host)
BUG_ON(!host);
BUG_ON(!host->card);
- mmc_claim_host(host);
+ mmc_get_card(host->card);
/*
* Just check if our card has been removed.
*/
err = _mmc_detect_card_removed(host);
- mmc_release_host(host);
+ mmc_put_card(host->card);
if (err) {
mmc_remove(host);
@@ -1308,136 +1606,192 @@ static void mmc_detect(struct mmc_host *host)
}
}
-/*
- * Suspend callback from host.
- */
-static int mmc_suspend(struct mmc_host *host)
+static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
{
int err = 0;
+ unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT :
+ EXT_CSD_POWER_OFF_LONG;
BUG_ON(!host);
BUG_ON(!host->card);
mmc_claim_host(host);
- if (mmc_card_can_sleep(host)) {
- err = mmc_card_sleep(host);
- if (!err)
- mmc_card_set_sleep(host->card);
- } else if (!mmc_host_is_spi(host))
- mmc_deselect_cards(host);
- host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+
+ if (mmc_card_suspended(host->card))
+ goto out;
+
+ if (mmc_card_doing_bkops(host->card)) {
+ err = mmc_stop_bkops(host->card);
+ if (err)
+ goto out;
+ }
+
+ err = mmc_flush_cache(host->card);
+ if (err)
+ goto out;
+
+ if (mmc_can_poweroff_notify(host->card) &&
+ ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend))
+ err = mmc_poweroff_notify(host->card, notify_type);
+ else if (mmc_can_sleep(host->card))
+ err = mmc_sleep(host);
+ else if (!mmc_host_is_spi(host))
+ err = mmc_deselect_cards(host);
+
+ if (!err) {
+ mmc_power_off(host);
+ mmc_card_set_suspended(host->card);
+ }
+out:
mmc_release_host(host);
+ return err;
+}
+
+/*
+ * Suspend callback
+ */
+static int mmc_suspend(struct mmc_host *host)
+{
+ int err;
+
+ err = _mmc_suspend(host, true);
+ if (!err) {
+ pm_runtime_disable(&host->card->dev);
+ pm_runtime_set_suspended(&host->card->dev);
+ }
return err;
}
/*
- * Resume callback from host.
- *
* This function tries to determine if the same card is still present
* and, if so, restore all state to it.
*/
-static int mmc_resume(struct mmc_host *host)
+static int _mmc_resume(struct mmc_host *host)
{
- int err;
+ int err = 0;
BUG_ON(!host);
BUG_ON(!host->card);
mmc_claim_host(host);
- if (mmc_card_is_sleep(host->card)) {
- err = mmc_card_awake(host);
- mmc_card_clr_sleep(host->card);
- } else
- err = mmc_init_card(host, host->ocr, host->card);
- mmc_release_host(host);
+ if (!mmc_card_suspended(host->card))
+ goto out;
+
+ mmc_power_up(host, host->card->ocr);
+ err = mmc_init_card(host, host->card->ocr, host->card);
+ mmc_card_clr_suspended(host->card);
+
+out:
+ mmc_release_host(host);
return err;
}
-static int mmc_power_restore(struct mmc_host *host)
+/*
+ * Shutdown callback
+ */
+static int mmc_shutdown(struct mmc_host *host)
{
- int ret;
+ int err = 0;
- host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
- mmc_card_clr_sleep(host->card);
- mmc_claim_host(host);
- ret = mmc_init_card(host, host->ocr, host->card);
- mmc_release_host(host);
+ /*
+ * In a specific case for poweroff notify, we need to resume the card
+ * before we can shutdown it properly.
+ */
+ if (mmc_can_poweroff_notify(host->card) &&
+ !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE))
+ err = _mmc_resume(host);
- return ret;
+ if (!err)
+ err = _mmc_suspend(host, false);
+
+ return err;
}
-static int mmc_sleep(struct mmc_host *host)
+/*
+ * Callback for resume.
+ */
+static int mmc_resume(struct mmc_host *host)
{
- struct mmc_card *card = host->card;
- int err = -ENOSYS;
+ int err = 0;
- if (card && card->ext_csd.rev >= 3) {
- err = mmc_card_sleepawake(host, 1);
- if (err < 0)
- pr_debug("%s: Error %d while putting card into sleep",
- mmc_hostname(host), err);
+ if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
+ err = _mmc_resume(host);
+ pm_runtime_set_active(&host->card->dev);
+ pm_runtime_mark_last_busy(&host->card->dev);
}
+ pm_runtime_enable(&host->card->dev);
return err;
}
-static int mmc_awake(struct mmc_host *host)
+/*
+ * Callback for runtime_suspend.
+ */
+static int mmc_runtime_suspend(struct mmc_host *host)
{
- struct mmc_card *card = host->card;
- int err = -ENOSYS;
+ int err;
- if (card && card->ext_csd.rev >= 3) {
- err = mmc_card_sleepawake(host, 0);
- if (err < 0)
- pr_debug("%s: Error %d while awaking sleeping card",
- mmc_hostname(host), err);
- }
+ if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
+ return 0;
+
+ err = _mmc_suspend(host, true);
+ if (err)
+ pr_err("%s: error %d doing aggessive suspend\n",
+ mmc_hostname(host), err);
return err;
}
-static const struct mmc_bus_ops mmc_ops = {
- .awake = mmc_awake,
- .sleep = mmc_sleep,
- .remove = mmc_remove,
- .detect = mmc_detect,
- .suspend = NULL,
- .resume = NULL,
- .power_restore = mmc_power_restore,
- .alive = mmc_alive,
-};
+/*
+ * Callback for runtime_resume.
+ */
+static int mmc_runtime_resume(struct mmc_host *host)
+{
+ int err;
-static const struct mmc_bus_ops mmc_ops_unsafe = {
- .awake = mmc_awake,
- .sleep = mmc_sleep,
+ if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
+ return 0;
+
+ err = _mmc_resume(host);
+ if (err)
+ pr_err("%s: error %d doing aggessive resume\n",
+ mmc_hostname(host), err);
+
+ return 0;
+}
+
+static int mmc_power_restore(struct mmc_host *host)
+{
+ int ret;
+
+ mmc_claim_host(host);
+ ret = mmc_init_card(host, host->card->ocr, host->card);
+ mmc_release_host(host);
+
+ return ret;
+}
+
+static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
.suspend = mmc_suspend,
.resume = mmc_resume,
+ .runtime_suspend = mmc_runtime_suspend,
+ .runtime_resume = mmc_runtime_resume,
.power_restore = mmc_power_restore,
.alive = mmc_alive,
+ .shutdown = mmc_shutdown,
};
-static void mmc_attach_bus_ops(struct mmc_host *host)
-{
- const struct mmc_bus_ops *bus_ops;
-
- if (!mmc_card_is_removable(host))
- bus_ops = &mmc_ops_unsafe;
- else
- bus_ops = &mmc_ops;
- mmc_attach_bus(host, bus_ops);
-}
-
/*
* Starting point for MMC card init.
*/
int mmc_attach_mmc(struct mmc_host *host)
{
int err;
- u32 ocr;
+ u32 ocr, rocr;
BUG_ON(!host);
WARN_ON(!host->claimed);
@@ -1450,7 +1804,7 @@ int mmc_attach_mmc(struct mmc_host *host)
if (err)
return err;
- mmc_attach_bus_ops(host);
+ mmc_attach_bus(host, &mmc_ops);
if (host->ocr_avail_mmc)
host->ocr_avail = host->ocr_avail_mmc;
@@ -1463,23 +1817,12 @@ int mmc_attach_mmc(struct mmc_host *host)
goto err;
}
- /*
- * Sanity check the voltages that the card claims to
- * support.
- */
- if (ocr & 0x7F) {
- pr_warning("%s: card claims to support voltages "
- "below the defined range. These will be ignored.\n",
- mmc_hostname(host));
- ocr &= ~0x7F;
- }
-
- host->ocr = mmc_select_voltage(host, ocr);
+ rocr = mmc_select_voltage(host, ocr);
/*
* Can we support the voltage of the card?
*/
- if (!host->ocr) {
+ if (!rocr) {
err = -EINVAL;
goto err;
}
@@ -1487,7 +1830,7 @@ int mmc_attach_mmc(struct mmc_host *host)
/*
* Detect and init the card.
*/
- err = mmc_init_card(host, host->ocr, NULL);
+ err = mmc_init_card(host, rocr, NULL);
if (err)
goto err;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 4d41fa984c9..f51b5ba3bbe 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -21,6 +21,42 @@
#include "core.h"
#include "mmc_ops.h"
+#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+
+static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
+ bool ignore_crc)
+{
+ int err;
+ struct mmc_command cmd = {0};
+
+ BUG_ON(!card);
+ BUG_ON(!card->host);
+
+ cmd.opcode = MMC_SEND_STATUS;
+ if (!mmc_host_is_spi(card->host))
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+ if (ignore_crc)
+ cmd.flags &= ~MMC_RSP_CRC;
+
+ err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+ if (err)
+ return err;
+
+ /* NOTE: callers are required to understand the difference
+ * between "native" and SPI format status words!
+ */
+ if (status)
+ *status = cmd.resp[0];
+
+ return 0;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+ return __mmc_send_status(card, status, false);
+}
+
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
int err;
@@ -57,40 +93,6 @@ int mmc_deselect_cards(struct mmc_host *host)
return _mmc_select_card(host, NULL);
}
-int mmc_card_sleepawake(struct mmc_host *host, int sleep)
-{
- struct mmc_command cmd = {0};
- struct mmc_card *card = host->card;
- int err;
-
- if (sleep)
- mmc_deselect_cards(host);
-
- cmd.opcode = MMC_SLEEP_AWAKE;
- cmd.arg = card->rca << 16;
- if (sleep)
- cmd.arg |= 1 << 15;
-
- cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
- err = mmc_wait_for_cmd(host, &cmd, 0);
- if (err)
- return err;
-
- /*
- * 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 (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
- mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
-
- if (!sleep)
- err = mmc_select_card(card);
-
- return err;
-}
-
int mmc_go_idle(struct mmc_host *host)
{
int err;
@@ -230,6 +232,10 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
return 0;
}
+/*
+ * 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)
@@ -239,13 +245,19 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
struct mmc_data data = {0};
struct scatterlist sg;
void *data_buf;
+ int is_on_stack;
- /* dma onto stack is unsafe/nonportable, but callers to this
- * routine normally provide temporary on-stack buffers ...
- */
- data_buf = kmalloc(len, GFP_KERNEL);
- if (data_buf == NULL)
- return -ENOMEM;
+ is_on_stack = object_is_on_stack(buf);
+ if (is_on_stack) {
+ /*
+ * dma onto stack is unsafe/nonportable, but callers to this
+ * routine normally provide temporary on-stack buffers ...
+ */
+ data_buf = kmalloc(len, GFP_KERNEL);
+ if (!data_buf)
+ return -ENOMEM;
+ } else
+ data_buf = buf;
mrq.cmd = &cmd;
mrq.data = &data;
@@ -280,8 +292,10 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
mmc_wait_for_req(host, &mrq);
- memcpy(buf, data_buf, len);
- kfree(data_buf);
+ if (is_on_stack) {
+ memcpy(buf, data_buf, len);
+ kfree(data_buf);
+ }
if (cmd.error)
return cmd.error;
@@ -294,24 +308,32 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
int mmc_send_csd(struct mmc_card *card, u32 *csd)
{
int ret, i;
+ u32 *csd_tmp;
if (!mmc_host_is_spi(card->host))
return mmc_send_cxd_native(card->host, card->rca << 16,
csd, MMC_SEND_CSD);
- ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
+ csd_tmp = kmalloc(16, GFP_KERNEL);
+ if (!csd_tmp)
+ return -ENOMEM;
+
+ ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16);
if (ret)
- return ret;
+ goto err;
for (i = 0;i < 4;i++)
- csd[i] = be32_to_cpu(csd[i]);
+ csd[i] = be32_to_cpu(csd_tmp[i]);
- return 0;
+err:
+ kfree(csd_tmp);
+ return ret;
}
int mmc_send_cid(struct mmc_host *host, u32 *cid)
{
int ret, i;
+ u32 *cid_tmp;
if (!mmc_host_is_spi(host)) {
if (!host->card)
@@ -320,14 +342,20 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid)
cid, MMC_SEND_CID);
}
- ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
+ cid_tmp = kmalloc(16, GFP_KERNEL);
+ if (!cid_tmp)
+ return -ENOMEM;
+
+ ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16);
if (ret)
- return ret;
+ goto err;
for (i = 0;i < 4;i++)
- cid[i] = be32_to_cpu(cid[i]);
+ cid[i] = be32_to_cpu(cid_tmp[i]);
- return 0;
+err:
+ kfree(cid_tmp);
+ return ret;
}
int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
@@ -335,6 +363,7 @@ int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD,
ext_csd, 512);
}
+EXPORT_SYMBOL_GPL(mmc_send_ext_csd);
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp)
{
@@ -367,89 +396,132 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
}
/**
- * mmc_switch - modify EXT_CSD register
+ * __mmc_switch - modify EXT_CSD register
* @card: the MMC card associated with the data transfer
* @set: cmd set values
* @index: EXT_CSD register index
* @value: value to program into EXT_CSD register
* @timeout_ms: timeout (ms) for operation performed by register write,
* timeout of zero implies maximum possible timeout
+ * @use_busy_signal: use the busy signal as response type
+ * @send_status: send status cmd to poll for busy
+ * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy
*
* Modifies the EXT_CSD register for selected card.
*/
-int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
- unsigned int timeout_ms)
+int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+ unsigned int timeout_ms, bool use_busy_signal, bool send_status,
+ bool ignore_crc)
{
+ struct mmc_host *host = card->host;
int err;
struct mmc_command cmd = {0};
- u32 status;
+ unsigned long timeout;
+ u32 status = 0;
+ bool use_r1b_resp = use_busy_signal;
- BUG_ON(!card);
- BUG_ON(!card->host);
+ /*
+ * If the cmd timeout and the max_busy_timeout of the host are both
+ * specified, let's validate them. 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.
+ */
+ if (timeout_ms && 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_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- cmd.cmd_timeout_ms = timeout_ms;
+ cmd.flags = MMC_CMD_AC;
+ if (use_r1b_resp) {
+ cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
+ /*
+ * A busy_timeout of zero means the host can decide to use
+ * whatever value it finds suitable.
+ */
+ cmd.busy_timeout = timeout_ms;
+ } else {
+ cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
+ }
- err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+ if (index == EXT_CSD_SANITIZE_START)
+ cmd.sanitize_busy = true;
+
+ err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
if (err)
return err;
- /* Must check status to be sure of no errors */
+ /* No need to check card status in case of unblocking command */
+ if (!use_busy_signal)
+ return 0;
+
+ /*
+ * CRC errors shall only be ignored in cases were CMD13 is used to poll
+ * to detect busy completion.
+ */
+ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
+ ignore_crc = false;
+
+ /* We have an unspecified cmd timeout, use the fallback value. */
+ if (!timeout_ms)
+ timeout_ms = MMC_OPS_TIMEOUT_MS;
+
+ /* Must check status to be sure of no errors. */
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
do {
- err = mmc_send_status(card, &status);
- if (err)
- return err;
- if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ if (send_status) {
+ err = __mmc_send_status(card, &status, ignore_crc);
+ if (err)
+ return err;
+ }
+ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
break;
- if (mmc_host_is_spi(card->host))
+ if (mmc_host_is_spi(host))
break;
+
+ /*
+ * We are not allowed to issue a status command and the host
+ * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
+ * rely on waiting for the stated timeout to be sufficient.
+ */
+ if (!send_status) {
+ mmc_delay(timeout_ms);
+ return 0;
+ }
+
+ /* Timeout if the device never leaves the program state. */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state! %s\n",
+ mmc_hostname(host), __func__);
+ return -ETIMEDOUT;
+ }
} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
- if (mmc_host_is_spi(card->host)) {
+ if (mmc_host_is_spi(host)) {
if (status & R1_SPI_ILLEGAL_COMMAND)
return -EBADMSG;
} else {
if (status & 0xFDFFA000)
- pr_warning("%s: unexpected status %#x after "
- "switch", mmc_hostname(card->host), status);
+ pr_warn("%s: unexpected status %#x after switch\n",
+ mmc_hostname(host), status);
if (status & R1_SWITCH_ERROR)
return -EBADMSG;
}
return 0;
}
-EXPORT_SYMBOL_GPL(mmc_switch);
+EXPORT_SYMBOL_GPL(__mmc_switch);
-int mmc_send_status(struct mmc_card *card, u32 *status)
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+ unsigned int timeout_ms)
{
- int err;
- struct mmc_command cmd = {0};
-
- BUG_ON(!card);
- BUG_ON(!card->host);
-
- cmd.opcode = MMC_SEND_STATUS;
- if (!mmc_host_is_spi(card->host))
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-
- err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
- if (err)
- return err;
-
- /* NOTE: callers are required to understand the difference
- * between "native" and SPI format status words!
- */
- if (status)
- *status = cmd.resp[0];
-
- return 0;
+ return __mmc_switch(card, set, index, value, timeout_ms, true, true,
+ false);
}
+EXPORT_SYMBOL_GPL(mmc_switch);
static int
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
@@ -507,6 +579,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
data.sg = &sg;
data.sg_len = 1;
+ mmc_set_data_timeout(&data, card);
sg_init_one(&sg, data_buf, len);
mmc_wait_for_req(host, &mrq);
err = 0;
@@ -553,19 +626,22 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
{
struct mmc_command cmd = {0};
unsigned int opcode;
- unsigned int flags;
int err;
+ if (!card->ext_csd.hpi) {
+ pr_warning("%s: Card didn't support HPI command\n",
+ mmc_hostname(card->host));
+ return -EINVAL;
+ }
+
opcode = card->ext_csd.hpi_cmd;
if (opcode == MMC_STOP_TRANSMISSION)
- flags = MMC_RSP_R1 | MMC_CMD_AC;
+ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
else if (opcode == MMC_SEND_STATUS)
- flags = MMC_RSP_R1 | MMC_CMD_AC;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
cmd.opcode = opcode;
cmd.arg = card->rca << 16 | 1;
- cmd.flags = flags;
- cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 3dd8941c298..80ae9f4e029 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -24,7 +24,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status);
int mmc_send_cid(struct mmc_host *host, u32 *cid);
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
-int mmc_card_sleepawake(struct mmc_host *host, int sleep);
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index 06ee1aeaace..6c36fccaa1e 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_ids.h>
#ifndef SDIO_VENDOR_ID_TI
#define SDIO_VENDOR_ID_TI 0x0097
@@ -30,6 +31,10 @@
#define SDIO_DEVICE_ID_STE_CW1200 0x2280
#endif
+#ifndef SDIO_DEVICE_ID_MARVELL_8797_F0
+#define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128
+#endif
+
/*
* This hook just adds a quirk for all sdio devices
*/
@@ -58,6 +63,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = {
SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200,
add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512),
+ SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0,
+ add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING),
+
END_FIXUP
};
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index c272c6868ec..0c44510bf71 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -11,8 +11,10 @@
*/
#include <linux/err.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/stat.h>
+#include <linux/pm_runtime.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
@@ -44,6 +46,13 @@ static const unsigned int tacc_mant[] = {
35, 40, 45, 50, 55, 60, 70, 80,
};
+static const unsigned int sd_au_size[] = {
+ 0, SZ_16K / 512, SZ_32K / 512, SZ_64K / 512,
+ SZ_128K / 512, SZ_256K / 512, SZ_512K / 512, SZ_1M / 512,
+ SZ_2M / 512, SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512,
+ SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512,
+};
+
#define UNSTUFF_BITS(resp,start,size) \
({ \
const int __size = size; \
@@ -244,18 +253,20 @@ static int mmc_read_ssr(struct mmc_card *card)
* bitfield positions accordingly.
*/
au = UNSTUFF_BITS(ssr, 428 - 384, 4);
- if (au > 0 || au <= 9) {
- card->ssr.au = 1 << (au + 4);
- es = UNSTUFF_BITS(ssr, 408 - 384, 16);
- et = UNSTUFF_BITS(ssr, 402 - 384, 6);
- eo = UNSTUFF_BITS(ssr, 400 - 384, 2);
- if (es && et) {
- card->ssr.erase_timeout = (et * 1000) / es;
- card->ssr.erase_offset = eo * 1000;
+ if (au) {
+ if (au <= 9 || card->scr.sda_spec3) {
+ card->ssr.au = sd_au_size[au];
+ es = UNSTUFF_BITS(ssr, 408 - 384, 16);
+ et = UNSTUFF_BITS(ssr, 402 - 384, 6);
+ if (es && et) {
+ eo = UNSTUFF_BITS(ssr, 400 - 384, 2);
+ card->ssr.erase_timeout = (et * 1000) / es;
+ card->ssr.erase_offset = eo * 1000;
+ }
+ } else {
+ pr_warning("%s: SD Status: Invalid Allocation Unit size.\n",
+ mmc_hostname(card->host));
}
- } else {
- pr_warning("%s: SD Status: Invalid Allocation Unit "
- "size.\n", mmc_hostname(card->host));
}
out:
kfree(ssr);
@@ -290,8 +301,12 @@ static int mmc_read_switch(struct mmc_card *card)
return -ENOMEM;
}
- /* Find out the supported Bus Speed Modes. */
- err = mmc_sd_switch(card, 0, 0, 1, status);
+ /*
+ * Find out the card's support bits with a mode 0 operation.
+ * The argument does not matter, as the support bits do not
+ * change with the arguments.
+ */
+ err = mmc_sd_switch(card, 0, 0, 0, status);
if (err) {
/*
* If the host or the card can't do the switch,
@@ -312,46 +327,8 @@ static int mmc_read_switch(struct mmc_card *card)
if (card->scr.sda_spec3) {
card->sw_caps.sd3_bus_mode = status[13];
-
- /* Find out Driver Strengths supported by the card */
- err = mmc_sd_switch(card, 0, 2, 1, status);
- if (err) {
- /*
- * If the host or the card can't do the switch,
- * fail more gracefully.
- */
- if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
- goto out;
-
- pr_warning("%s: problem reading "
- "Driver Strength.\n",
- mmc_hostname(card->host));
- err = 0;
-
- goto out;
- }
-
+ /* Driver Strengths supported by the card */
card->sw_caps.sd3_drv_type = status[9];
-
- /* Find out Current Limits supported by the card */
- err = mmc_sd_switch(card, 0, 3, 1, status);
- if (err) {
- /*
- * If the host or the card can't do the switch,
- * fail more gracefully.
- */
- if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
- goto out;
-
- pr_warning("%s: problem reading "
- "Current Limit.\n",
- mmc_hostname(card->host));
- err = 0;
-
- goto out;
- }
-
- card->sw_caps.sd3_curr_limit = status[7];
}
out:
@@ -478,8 +455,7 @@ static void sd_update_bus_speed_mode(struct mmc_card *card)
* If the host doesn't support any of the UHS-I modes, fallback on
* default speed.
*/
- if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) {
+ if (!mmc_host_uhs(card->host)) {
card->sd_bus_speed = 0;
return;
}
@@ -551,60 +527,80 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
return 0;
}
+/* Get host's max current setting at its current voltage */
+static u32 sd_get_host_max_current(struct mmc_host *host)
+{
+ u32 voltage, max_current;
+
+ voltage = 1 << host->ios.vdd;
+ switch (voltage) {
+ case MMC_VDD_165_195:
+ max_current = host->max_current_180;
+ break;
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ max_current = host->max_current_300;
+ break;
+ case MMC_VDD_32_33:
+ case MMC_VDD_33_34:
+ max_current = host->max_current_330;
+ break;
+ default:
+ max_current = 0;
+ }
+
+ return max_current;
+}
+
static int sd_set_current_limit(struct mmc_card *card, u8 *status)
{
- int current_limit = 0;
+ int current_limit = SD_SET_CURRENT_NO_CHANGE;
int err;
+ u32 max_current;
/*
* Current limit switch is only defined for SDR50, SDR104, and DDR50
- * bus speed modes. For other bus speed modes, we set the default
- * current limit of 200mA.
+ * bus speed modes. For other bus speed modes, we do not change the
+ * current limit.
*/
- if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
- (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
- (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
- if (card->host->caps & MMC_CAP_MAX_CURRENT_800) {
- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800)
- current_limit = SD_SET_CURRENT_LIMIT_800;
- else if (card->sw_caps.sd3_curr_limit &
- SD_MAX_CURRENT_600)
- current_limit = SD_SET_CURRENT_LIMIT_600;
- else if (card->sw_caps.sd3_curr_limit &
- SD_MAX_CURRENT_400)
- current_limit = SD_SET_CURRENT_LIMIT_400;
- else if (card->sw_caps.sd3_curr_limit &
- SD_MAX_CURRENT_200)
- current_limit = SD_SET_CURRENT_LIMIT_200;
- } else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) {
- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600)
- current_limit = SD_SET_CURRENT_LIMIT_600;
- else if (card->sw_caps.sd3_curr_limit &
- SD_MAX_CURRENT_400)
- current_limit = SD_SET_CURRENT_LIMIT_400;
- else if (card->sw_caps.sd3_curr_limit &
- SD_MAX_CURRENT_200)
- current_limit = SD_SET_CURRENT_LIMIT_200;
- } else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) {
- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400)
- current_limit = SD_SET_CURRENT_LIMIT_400;
- else if (card->sw_caps.sd3_curr_limit &
- SD_MAX_CURRENT_200)
- current_limit = SD_SET_CURRENT_LIMIT_200;
- } else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) {
- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200)
- current_limit = SD_SET_CURRENT_LIMIT_200;
- }
- } else
+ if ((card->sd_bus_speed != UHS_SDR50_BUS_SPEED) &&
+ (card->sd_bus_speed != UHS_SDR104_BUS_SPEED) &&
+ (card->sd_bus_speed != UHS_DDR50_BUS_SPEED))
+ return 0;
+
+ /*
+ * Host has different current capabilities when operating at
+ * different voltages, so find out its max current first.
+ */
+ max_current = sd_get_host_max_current(card->host);
+
+ /*
+ * We only check host's capability here, if we set a limit that is
+ * higher than the card's maximum current, the card will be using its
+ * maximum current, e.g. if the card's maximum current is 300ma, and
+ * when we set current limit to 200ma, the card will draw 200ma, and
+ * when we set current limit to 400/600/800ma, the card will draw its
+ * maximum 300ma from the host.
+ */
+ if (max_current >= 800)
+ current_limit = SD_SET_CURRENT_LIMIT_800;
+ else if (max_current >= 600)
+ current_limit = SD_SET_CURRENT_LIMIT_600;
+ else if (max_current >= 400)
+ current_limit = SD_SET_CURRENT_LIMIT_400;
+ else if (max_current >= 200)
current_limit = SD_SET_CURRENT_LIMIT_200;
- err = mmc_sd_switch(card, 1, 3, current_limit, status);
- if (err)
- return err;
+ if (current_limit != SD_SET_CURRENT_NO_CHANGE) {
+ err = mmc_sd_switch(card, 1, 3, current_limit, status);
+ if (err)
+ return err;
- if (((status[15] >> 4) & 0x0F) != current_limit)
- pr_warning("%s: Problem setting current limit!\n",
- mmc_hostname(card->host));
+ if (((status[15] >> 4) & 0x0F) != current_limit)
+ pr_warning("%s: Problem setting current limit!\n",
+ mmc_hostname(card->host));
+
+ }
return 0;
}
@@ -661,8 +657,13 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
if (err)
goto out;
- /* SPI mode doesn't define CMD19 */
- if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) {
+ /*
+ * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and
+ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
+ */
+ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning &&
+ (card->sd_bus_speed == UHS_SDR50_BUS_SPEED ||
+ card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) {
mmc_host_clk_hold(card->host);
err = card->host->ops->execute_tuning(card->host,
MMC_SEND_TUNING_BLOCK);
@@ -706,18 +707,10 @@ static struct attribute *sd_std_attrs[] = {
&dev_attr_serial.attr,
NULL,
};
-
-static struct attribute_group sd_std_attr_group = {
- .attrs = sd_std_attrs,
-};
-
-static const struct attribute_group *sd_attr_groups[] = {
- &sd_std_attr_group,
- NULL,
-};
+ATTRIBUTE_GROUPS(sd_std);
struct device_type sd_type = {
- .groups = sd_attr_groups,
+ .groups = sd_std_groups,
};
/*
@@ -726,6 +719,16 @@ struct device_type sd_type = {
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
{
int err;
+ u32 max_current;
+ int retries = 10;
+ u32 pocr = ocr;
+
+try_again:
+ if (!retries) {
+ ocr &= ~SD_OCR_S18R;
+ pr_warning("%s: Skipping voltage switch\n",
+ mmc_hostname(host));
+ }
/*
* Since we're changing the OCR value, we seem to
@@ -747,18 +750,20 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
/*
* If the host supports one of UHS-I modes, request the card
- * to switch to 1.8V signaling level.
+ * to switch to 1.8V signaling level. If the card has failed
+ * repeatedly to switch however, skip this.
*/
- if (host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))
+ if (retries && mmc_host_uhs(host))
ocr |= SD_OCR_S18R;
- /* If the host can supply more than 150mA, XPC should be set to 1. */
- if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
- MMC_CAP_SET_XPC_180))
+ /*
+ * If the host can supply more than 150mA at current voltage,
+ * XPC should be set to 1.
+ */
+ max_current = sd_get_host_max_current(host);
+ if (max_current > 150)
ocr |= SD_OCR_XPC;
-try_again:
err = mmc_send_app_op_cond(host, ocr, rocr);
if (err)
return err;
@@ -769,9 +774,13 @@ try_again:
*/
if (!mmc_host_is_spi(host) && rocr &&
((*rocr & 0x41000000) == 0x41000000)) {
- err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, true);
- if (err) {
- ocr &= ~SD_OCR_S18R;
+ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
+ pocr);
+ if (err == -EAGAIN) {
+ retries--;
+ goto try_again;
+ } else if (err) {
+ retries = 0;
goto try_again;
}
}
@@ -878,7 +887,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
{
unsigned max_dtr = (unsigned int)-1;
- if (mmc_card_highspeed(card)) {
+ if (mmc_card_hs(card)) {
if (max_dtr > card->sw_caps.hs_max_dtr)
max_dtr = card->sw_caps.hs_max_dtr;
} else if (max_dtr > card->csd.max_dtr) {
@@ -888,12 +897,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
return max_dtr;
}
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
- mmc_card_set_highspeed(card);
- mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
/*
* Handle the detection and initialisation of a card.
*
@@ -911,9 +914,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
BUG_ON(!host);
WARN_ON(!host->claimed);
- /* The initialization should be done at 3.3 V I/O voltage. */
- mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
err = mmc_sd_get_cid(host, ocr, cid, &rocr);
if (err)
return err;
@@ -931,6 +931,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (IS_ERR(card))
return PTR_ERR(card);
+ card->ocr = ocr;
card->type = MMC_TYPE_SD;
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
}
@@ -941,13 +942,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host)) {
err = mmc_send_relative_addr(host, &card->rca);
if (err)
- return err;
+ goto free_card;
}
if (!oldcard) {
err = mmc_sd_get_csd(host, card);
if (err)
- return err;
+ goto free_card;
mmc_decode_cid(card);
}
@@ -958,7 +959,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host)) {
err = mmc_select_card(card);
if (err)
- return err;
+ goto free_card;
}
err = mmc_sd_setup_card(host, card, oldcard != NULL);
@@ -970,26 +971,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
err = mmc_sd_init_uhs_card(card);
if (err)
goto free_card;
-
- /* Card is an ultra-high-speed card */
- mmc_card_set_uhs(card);
-
- /*
- * Since initialization is now complete, enable preset
- * value registers for UHS-I cards.
- */
- if (host->ops->enable_preset_value) {
- mmc_host_clk_hold(card->host);
- host->ops->enable_preset_value(host, true);
- mmc_host_clk_release(card->host);
- }
} else {
/*
* Attempt to change to high-speed (if supported)
*/
err = mmc_sd_switch_hs(card);
if (err > 0)
- mmc_sd_go_highspeed(card);
+ mmc_set_timing(card->host, MMC_TIMING_SD_HS);
else if (err)
goto free_card;
@@ -1051,14 +1039,14 @@ static void mmc_sd_detect(struct mmc_host *host)
BUG_ON(!host);
BUG_ON(!host->card);
- mmc_claim_host(host);
+ mmc_get_card(host->card);
/*
* Just check if our card has been removed.
*/
err = _mmc_detect_card_removed(host);
- mmc_release_host(host);
+ mmc_put_card(host->card);
if (err) {
mmc_sd_remove(host);
@@ -1070,50 +1058,131 @@ static void mmc_sd_detect(struct mmc_host *host)
}
}
-/*
- * Suspend callback from host.
- */
-static int mmc_sd_suspend(struct mmc_host *host)
+static int _mmc_sd_suspend(struct mmc_host *host)
{
+ int err = 0;
+
BUG_ON(!host);
BUG_ON(!host->card);
mmc_claim_host(host);
+
+ if (mmc_card_suspended(host->card))
+ goto out;
+
if (!mmc_host_is_spi(host))
- mmc_deselect_cards(host);
- host->card->state &= ~MMC_STATE_HIGHSPEED;
+ err = mmc_deselect_cards(host);
+
+ if (!err) {
+ mmc_power_off(host);
+ mmc_card_set_suspended(host->card);
+ }
+
+out:
mmc_release_host(host);
+ return err;
+}
- return 0;
+/*
+ * Callback for suspend
+ */
+static int mmc_sd_suspend(struct mmc_host *host)
+{
+ int err;
+
+ err = _mmc_sd_suspend(host);
+ if (!err) {
+ pm_runtime_disable(&host->card->dev);
+ pm_runtime_set_suspended(&host->card->dev);
+ }
+
+ return err;
}
/*
- * Resume callback from host.
- *
* This function tries to determine if the same card is still present
* and, if so, restore all state to it.
*/
-static int mmc_sd_resume(struct mmc_host *host)
+static int _mmc_sd_resume(struct mmc_host *host)
{
- int err;
+ int err = 0;
BUG_ON(!host);
BUG_ON(!host->card);
mmc_claim_host(host);
- err = mmc_sd_init_card(host, host->ocr, host->card);
+
+ if (!mmc_card_suspended(host->card))
+ goto out;
+
+ mmc_power_up(host, host->card->ocr);
+ err = mmc_sd_init_card(host, host->card->ocr, host->card);
+ mmc_card_clr_suspended(host->card);
+
+out:
mmc_release_host(host);
+ return err;
+}
+
+/*
+ * Callback for resume
+ */
+static int mmc_sd_resume(struct mmc_host *host)
+{
+ int err = 0;
+
+ if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
+ err = _mmc_sd_resume(host);
+ pm_runtime_set_active(&host->card->dev);
+ pm_runtime_mark_last_busy(&host->card->dev);
+ }
+ pm_runtime_enable(&host->card->dev);
+
+ return err;
+}
+
+/*
+ * Callback for runtime_suspend.
+ */
+static int mmc_sd_runtime_suspend(struct mmc_host *host)
+{
+ int err;
+
+ if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
+ return 0;
+
+ err = _mmc_sd_suspend(host);
+ if (err)
+ pr_err("%s: error %d doing aggessive suspend\n",
+ mmc_hostname(host), err);
return err;
}
+/*
+ * Callback for runtime_resume.
+ */
+static int mmc_sd_runtime_resume(struct mmc_host *host)
+{
+ int err;
+
+ if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
+ return 0;
+
+ err = _mmc_sd_resume(host);
+ if (err)
+ pr_err("%s: error %d doing aggessive resume\n",
+ mmc_hostname(host), err);
+
+ return 0;
+}
+
static int mmc_sd_power_restore(struct mmc_host *host)
{
int ret;
- host->card->state &= ~MMC_STATE_HIGHSPEED;
mmc_claim_host(host);
- ret = mmc_sd_init_card(host, host->ocr, host->card);
+ ret = mmc_sd_init_card(host, host->card->ocr, host->card);
mmc_release_host(host);
return ret;
@@ -1122,55 +1191,31 @@ static int mmc_sd_power_restore(struct mmc_host *host)
static const struct mmc_bus_ops mmc_sd_ops = {
.remove = mmc_sd_remove,
.detect = mmc_sd_detect,
- .suspend = NULL,
- .resume = NULL,
- .power_restore = mmc_sd_power_restore,
- .alive = mmc_sd_alive,
-};
-
-static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
- .remove = mmc_sd_remove,
- .detect = mmc_sd_detect,
+ .runtime_suspend = mmc_sd_runtime_suspend,
+ .runtime_resume = mmc_sd_runtime_resume,
.suspend = mmc_sd_suspend,
.resume = mmc_sd_resume,
.power_restore = mmc_sd_power_restore,
.alive = mmc_sd_alive,
+ .shutdown = mmc_sd_suspend,
};
-static void mmc_sd_attach_bus_ops(struct mmc_host *host)
-{
- const struct mmc_bus_ops *bus_ops;
-
- if (!mmc_card_is_removable(host))
- bus_ops = &mmc_sd_ops_unsafe;
- else
- bus_ops = &mmc_sd_ops;
- mmc_attach_bus(host, bus_ops);
-}
-
/*
* Starting point for SD card init.
*/
int mmc_attach_sd(struct mmc_host *host)
{
int err;
- u32 ocr;
+ u32 ocr, rocr;
BUG_ON(!host);
WARN_ON(!host->claimed);
- /* Disable preset value enable if already set since last time */
- if (host->ops->enable_preset_value) {
- mmc_host_clk_hold(host);
- host->ops->enable_preset_value(host, false);
- mmc_host_clk_release(host);
- }
-
err = mmc_send_app_op_cond(host, 0, &ocr);
if (err)
return err;
- mmc_sd_attach_bus_ops(host);
+ mmc_attach_bus(host, &mmc_sd_ops);
if (host->ocr_avail_sd)
host->ocr_avail = host->ocr_avail_sd;
@@ -1185,31 +1230,12 @@ int mmc_attach_sd(struct mmc_host *host)
goto err;
}
- /*
- * Sanity check the voltages that the card claims to
- * support.
- */
- if (ocr & 0x7F) {
- pr_warning("%s: card claims to support voltages "
- "below the defined range. These will be ignored.\n",
- mmc_hostname(host));
- ocr &= ~0x7F;
- }
-
- if ((ocr & MMC_VDD_165_195) &&
- !(host->ocr_avail_sd & MMC_VDD_165_195)) {
- pr_warning("%s: SD card claims to support the "
- "incompletely defined 'low voltage range'. This "
- "will be ignored.\n", mmc_hostname(host));
- ocr &= ~MMC_VDD_165_195;
- }
-
- host->ocr = mmc_select_voltage(host, ocr);
+ rocr = mmc_select_voltage(host, ocr);
/*
* Can we support the voltage(s) of the card(s)?
*/
- if (!host->ocr) {
+ if (!rocr) {
err = -EINVAL;
goto err;
}
@@ -1217,7 +1243,7 @@ int mmc_attach_sd(struct mmc_host *host)
/*
* Detect and init the card.
*/
- err = mmc_sd_init_card(host, host->ocr, NULL);
+ err = mmc_sd_init_card(host, rocr, NULL);
if (err)
goto err;
diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h
index 4b34b24f3f7..aab824a9a7f 100644
--- a/drivers/mmc/core/sd.h
+++ b/drivers/mmc/core/sd.h
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
bool reinit);
unsigned mmc_sd_get_max_clock(struct mmc_card *card);
int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
#endif
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 2c7c83f832d..e636d9e99e4 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -157,10 +157,7 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr)
if (ret)
goto out;
- if (card->host->caps &
- (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
- MMC_CAP_UHS_DDR50)) {
+ if (mmc_host_uhs(card->host)) {
if (data & SDIO_UHS_DDR50)
card->sw_caps.sd3_bus_mode
|= SD_MODE_UHS_DDR50;
@@ -218,6 +215,12 @@ static int sdio_enable_wide(struct mmc_card *card)
if (ret)
return ret;
+ if ((ctrl & SDIO_BUS_WIDTH_MASK) == SDIO_BUS_WIDTH_RESERVED)
+ pr_warning("%s: SDIO_CCCR_IF is invalid: 0x%02x\n",
+ mmc_hostname(card->host), ctrl);
+
+ /* set as 4-bit bus width */
+ ctrl &= ~SDIO_BUS_WIDTH_MASK;
ctrl |= SDIO_BUS_WIDTH_4BIT;
ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
@@ -360,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
{
unsigned max_dtr;
- if (mmc_card_highspeed(card)) {
+ if (mmc_card_hs(card)) {
/*
* The SDIO specification doesn't mention how
* the CIS transfer speed register relates to
@@ -472,8 +475,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)
* If the host doesn't support any of the UHS-I modes, fallback on
* default speed.
*/
- if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)))
+ if (!mmc_host_uhs(card->host))
return 0;
bus_speed = SDIO_SPEED_SDR12;
@@ -483,23 +485,27 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)
bus_speed = SDIO_SPEED_SDR104;
timing = MMC_TIMING_UHS_SDR104;
card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
+ card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
} else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
(card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
bus_speed = SDIO_SPEED_DDR50;
timing = MMC_TIMING_UHS_DDR50;
card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
+ card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
SD_MODE_UHS_SDR50)) {
bus_speed = SDIO_SPEED_SDR50;
timing = MMC_TIMING_UHS_SDR50;
card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
+ card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
(card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
bus_speed = SDIO_SPEED_SDR25;
timing = MMC_TIMING_UHS_SDR25;
card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
+ card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
@@ -507,6 +513,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)
bus_speed = SDIO_SPEED_SDR12;
timing = MMC_TIMING_UHS_SDR12;
card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
+ card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
}
err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
@@ -556,10 +563,18 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card)
if (err)
goto out;
- /* Initialize and start re-tuning timer */
- if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
+ /*
+ * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and
+ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
+ */
+ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning &&
+ ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) ||
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) {
+ mmc_host_clk_hold(card->host);
err = card->host->ops->execute_tuning(card->host,
MMC_SEND_TUNING_BLOCK);
+ mmc_host_clk_release(card->host);
+ }
out:
@@ -577,18 +592,29 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
{
struct mmc_card *card;
int err;
+ int retries = 10;
+ u32 rocr = 0;
+ u32 ocr_card = ocr;
BUG_ON(!host);
WARN_ON(!host->claimed);
+ /* to query card if 1.8V signalling is supported */
+ if (mmc_host_uhs(host))
+ ocr |= R4_18V_PRESENT;
+
+try_again:
+ if (!retries) {
+ pr_warning("%s: Skipping voltage switch\n",
+ mmc_hostname(host));
+ ocr &= ~R4_18V_PRESENT;
+ }
+
/*
* Inform the card of the voltage
*/
if (!powered_resume) {
- /* The initialization should be done at 3.3 V I/O voltage. */
- mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
- err = mmc_send_io_op_cond(host, host->ocr, &ocr);
+ err = mmc_send_io_op_cond(host, ocr, &rocr);
if (err)
goto err;
}
@@ -611,8 +637,8 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
goto err;
}
- if ((ocr & R4_MEMORY_PRESENT) &&
- mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid, NULL) == 0) {
+ if ((rocr & R4_MEMORY_PRESENT) &&
+ mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {
card->type = MMC_TYPE_SD_COMBO;
if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
@@ -638,25 +664,26 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
/*
* If the host and card support UHS-I mode request the card
* to switch to 1.8V signaling level. No 1.8v signalling if
- * UHS mode is not enabled to maintain compatibilty and some
+ * UHS mode is not enabled to maintain compatibility and some
* systems that claim 1.8v signalling in fact do not support
* it.
*/
- if ((ocr & R4_18V_PRESENT) &&
- (host->caps &
- (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
- MMC_CAP_UHS_DDR50))) {
+ if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
- true);
- if (err) {
+ ocr);
+ if (err == -EAGAIN) {
+ sdio_reset(host);
+ mmc_go_idle(host);
+ mmc_send_if_cond(host, host->ocr_avail);
+ mmc_remove_card(card);
+ retries--;
+ goto try_again;
+ } else if (err) {
ocr &= ~R4_18V_PRESENT;
- host->ocr &= ~R4_18V_PRESENT;
}
err = 0;
} else {
ocr &= ~R4_18V_PRESENT;
- host->ocr &= ~R4_18V_PRESENT;
}
/*
@@ -706,7 +733,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
mmc_set_clock(host, card->cis.max_dtr);
if (card->cccr.high_speed) {
- mmc_card_set_highspeed(card);
mmc_set_timing(card->host, MMC_TIMING_SD_HS);
}
@@ -736,6 +762,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
card = oldcard;
}
+ card->ocr = ocr_card;
mmc_fixup_device(card, NULL);
if (card->type == MMC_TYPE_SD_COMBO) {
@@ -764,16 +791,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
err = mmc_sdio_init_uhs_card(card);
if (err)
goto remove;
-
- /* Card is an ultra-high-speed card */
- mmc_card_set_uhs(card);
} else {
/*
* Switch to high-speed (if supported).
*/
err = sdio_enable_hs(card);
if (err > 0)
- mmc_sd_go_highspeed(card);
+ mmc_set_timing(card->host, MMC_TIMING_SD_HS);
else if (err)
goto remove;
@@ -846,8 +870,10 @@ 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)
+ if (err < 0) {
+ pm_runtime_put_noidle(&host->card->dev);
goto out;
+ }
}
mmc_claim_host(host);
@@ -885,11 +911,11 @@ out:
}
/*
- * SDIO suspend. We need to suspend all functions separately.
+ * SDIO pre_suspend. We need to suspend all functions separately.
* Therefore all registered functions must have drivers with suspend
* and resume methods. Failing that we simply remove the whole card.
*/
-static int mmc_sdio_suspend(struct mmc_host *host)
+static int mmc_sdio_pre_suspend(struct mmc_host *host)
{
int i, err = 0;
@@ -900,32 +926,34 @@ static int mmc_sdio_suspend(struct mmc_host *host)
if (!pmops || !pmops->suspend || !pmops->resume) {
/* force removal of entire card in that case */
err = -ENOSYS;
- } else
- err = pmops->suspend(&func->dev);
- if (err)
break;
+ }
}
}
- while (err && --i >= 0) {
- struct sdio_func *func = host->card->sdio_func[i];
- if (func && sdio_func_present(func) && func->dev.driver) {
- const struct dev_pm_ops *pmops = func->dev.driver->pm;
- pmops->resume(&func->dev);
- }
- }
- if (!err && mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
+ return err;
+}
+
+/*
+ * SDIO suspend. Suspend all functions separately.
+ */
+static int mmc_sdio_suspend(struct mmc_host *host)
+{
+ if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
mmc_claim_host(host);
sdio_disable_wide(host->card);
mmc_release_host(host);
}
- return err;
+ if (!mmc_card_keep_power(host))
+ mmc_power_off(host);
+
+ return 0;
}
static int mmc_sdio_resume(struct mmc_host *host)
{
- int i, err = 0;
+ int err = 0;
BUG_ON(!host);
BUG_ON(!host->card);
@@ -933,11 +961,29 @@ static int mmc_sdio_resume(struct mmc_host *host)
/* Basic card reinitialization. */
mmc_claim_host(host);
+ /* Restore power if needed */
+ if (!mmc_card_keep_power(host)) {
+ mmc_power_up(host, host->card->ocr);
+ /*
+ * Tell runtime PM core we just powered up the card,
+ * since it still believes the card is powered off.
+ * Note that currently runtime PM is only enabled
+ * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
+ */
+ if (host->caps & MMC_CAP_POWER_OFF_CARD) {
+ pm_runtime_disable(&host->card->dev);
+ pm_runtime_set_active(&host->card->dev);
+ pm_runtime_enable(&host->card->dev);
+ }
+ }
+
/* No need to reinitialize powered-resumed nonremovable cards */
- if (mmc_card_is_removable(host) || !mmc_card_keep_power(host))
- err = mmc_sdio_init_card(host, host->ocr, host->card,
+ if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) {
+ sdio_reset(host);
+ mmc_go_idle(host);
+ err = mmc_sdio_init_card(host, host->card->ocr, host->card,
mmc_card_keep_power(host));
- else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
+ } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
/* We may have switched to 1-bit mode during suspend */
err = sdio_enable_4bit_bus(host->card);
if (err > 0) {
@@ -947,34 +993,16 @@ static int mmc_sdio_resume(struct mmc_host *host)
}
if (!err && host->sdio_irqs)
- mmc_signal_sdio_irq(host);
+ wake_up_process(host->sdio_irq_thread);
mmc_release_host(host);
- /*
- * If the card looked to be the same as before suspending, then
- * we proceed to resume all card functions. If one of them returns
- * an error then we simply return that error to the core and the
- * card will be redetected as new. It is the responsibility of
- * the function driver to perform further tests with the extra
- * knowledge it has of the card to confirm the card is indeed the
- * same as before suspending (same MAC address for network cards,
- * etc.) and return an error otherwise.
- */
- for (i = 0; !err && i < host->card->sdio_funcs; i++) {
- struct sdio_func *func = host->card->sdio_func[i];
- if (func && sdio_func_present(func) && func->dev.driver) {
- const struct dev_pm_ops *pmops = func->dev.driver->pm;
- err = pmops->resume(&func->dev);
- }
- }
-
+ host->pm_flags &= ~MMC_PM_KEEP_POWER;
return err;
}
static int mmc_sdio_power_restore(struct mmc_host *host)
{
int ret;
- u32 ocr;
BUG_ON(!host);
BUG_ON(!host->card);
@@ -996,32 +1024,17 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
* for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
* harmless in other situations.
*
- * With these steps taken, mmc_select_voltage() is also required to
- * restore the correct voltage setting of the card.
*/
- /* The initialization should be done at 3.3 V I/O voltage. */
- if (!mmc_card_keep_power(host))
- mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
sdio_reset(host);
mmc_go_idle(host);
mmc_send_if_cond(host, host->ocr_avail);
- ret = mmc_send_io_op_cond(host, 0, &ocr);
+ ret = mmc_send_io_op_cond(host, 0, NULL);
if (ret)
goto out;
- if (host->ocr_avail_sdio)
- host->ocr_avail = host->ocr_avail_sdio;
-
- host->ocr = mmc_select_voltage(host, ocr & ~0x7F);
- if (!host->ocr) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = mmc_sdio_init_card(host, host->ocr, host->card,
+ ret = mmc_sdio_init_card(host, host->card->ocr, host->card,
mmc_card_keep_power(host));
if (!ret && host->sdio_irqs)
mmc_signal_sdio_irq(host);
@@ -1032,11 +1045,28 @@ out:
return ret;
}
+static int mmc_sdio_runtime_suspend(struct mmc_host *host)
+{
+ /* No references to the card, cut the power to it. */
+ mmc_power_off(host);
+ return 0;
+}
+
+static int mmc_sdio_runtime_resume(struct mmc_host *host)
+{
+ /* Restore power and re-initialize. */
+ mmc_power_up(host, host->card->ocr);
+ return mmc_sdio_power_restore(host);
+}
+
static const struct mmc_bus_ops mmc_sdio_ops = {
.remove = mmc_sdio_remove,
.detect = mmc_sdio_detect,
+ .pre_suspend = mmc_sdio_pre_suspend,
.suspend = mmc_sdio_suspend,
.resume = mmc_sdio_resume,
+ .runtime_suspend = mmc_sdio_runtime_suspend,
+ .runtime_resume = mmc_sdio_runtime_resume,
.power_restore = mmc_sdio_power_restore,
.alive = mmc_sdio_alive,
};
@@ -1048,7 +1078,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = {
int mmc_attach_sdio(struct mmc_host *host)
{
int err, i, funcs;
- u32 ocr;
+ u32 ocr, rocr;
struct mmc_card *card;
BUG_ON(!host);
@@ -1062,23 +1092,13 @@ int mmc_attach_sdio(struct mmc_host *host)
if (host->ocr_avail_sdio)
host->ocr_avail = host->ocr_avail_sdio;
- /*
- * Sanity check the voltages that the card claims to
- * support.
- */
- if (ocr & 0x7F) {
- pr_warning("%s: card claims to support voltages "
- "below the defined range. These will be ignored.\n",
- mmc_hostname(host));
- ocr &= ~0x7F;
- }
- host->ocr = mmc_select_voltage(host, ocr);
+ rocr = mmc_select_voltage(host, ocr);
/*
* Can we support the voltage(s) of the card(s)?
*/
- if (!host->ocr) {
+ if (!rocr) {
err = -EINVAL;
goto err;
}
@@ -1086,18 +1106,10 @@ int mmc_attach_sdio(struct mmc_host *host)
/*
* Detect and init the card.
*/
- err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
- if (err) {
- if (err == -EAGAIN) {
- /*
- * Retry initialization with S18R set to 0.
- */
- host->ocr &= ~R4_18V_PRESENT;
- err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
- }
- if (err)
- goto err;
- }
+ err = mmc_sdio_init_card(host, rocr, NULL, 0);
+ if (err)
+ goto err;
+
card = host->card;
/*
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 40989e6bb53..4fa8fef9147 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
+#include <linux/acpi.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -33,7 +34,8 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
\
func = dev_to_sdio_func (dev); \
return sprintf (buf, format_string, func->field); \
-}
+} \
+static DEVICE_ATTR_RO(field)
sdio_config_attr(class, "0x%02x\n");
sdio_config_attr(vendor, "0x%04x\n");
@@ -46,14 +48,16 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
func->class, func->vendor, func->device);
}
-
-static struct device_attribute sdio_dev_attrs[] = {
- __ATTR_RO(class),
- __ATTR_RO(vendor),
- __ATTR_RO(device),
- __ATTR_RO(modalias),
- __ATTR_NULL,
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *sdio_dev_attrs[] = {
+ &dev_attr_class.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_device.attr,
+ &dev_attr_modalias.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(sdio_dev);
static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
const struct sdio_device_id *id)
@@ -137,7 +141,7 @@ static int sdio_bus_probe(struct device *dev)
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
ret = pm_runtime_get_sync(dev);
if (ret < 0)
- goto out;
+ goto disable_runtimepm;
}
/* Set the default block size so the driver is sure it's something
@@ -157,7 +161,6 @@ static int sdio_bus_probe(struct device *dev)
disable_runtimepm:
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_noidle(dev);
-out:
return ret;
}
@@ -192,27 +195,28 @@ static int sdio_bus_remove(struct device *dev)
return ret;
}
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static const struct dev_pm_ops sdio_bus_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
- pm_generic_runtime_idle
+ NULL
)
};
#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)
-#else /* !CONFIG_PM_RUNTIME */
+#else /* !CONFIG_PM */
#define SDIO_PM_OPS_PTR NULL
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* !CONFIG_PM */
static struct bus_type sdio_bus_type = {
.name = "sdio",
- .dev_attrs = sdio_dev_attrs,
+ .dev_groups = sdio_dev_groups,
.match = sdio_bus_match,
.uevent = sdio_bus_uevent,
.probe = sdio_bus_probe,
@@ -259,8 +263,7 @@ static void sdio_release_func(struct device *dev)
sdio_free_func_cis(func);
- if (func->info)
- kfree(func->info);
+ kfree(func->info);
kfree(func);
}
@@ -287,6 +290,18 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
return func;
}
+#ifdef CONFIG_ACPI
+static void sdio_acpi_set_handle(struct sdio_func *func)
+{
+ struct mmc_host *host = func->card->host;
+ u64 addr = (host->slotno << 16) | func->num;
+
+ acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);
+}
+#else
+static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
+#endif
+
/*
* Register a new SDIO function with the driver model.
*/
@@ -296,9 +311,12 @@ int sdio_add_func(struct sdio_func *func)
dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
+ sdio_acpi_set_handle(func);
ret = device_add(&func->dev);
- if (ret == 0)
+ if (ret == 0) {
sdio_func_set_present(func);
+ acpi_dev_pm_attach(&func->dev, false);
+ }
return ret;
}
@@ -314,6 +332,7 @@ void sdio_remove_func(struct sdio_func *func)
if (!sdio_func_present(func))
return;
+ acpi_dev_pm_detach(&func->dev, false);
device_del(&func->dev);
put_device(&func->dev);
}
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index f1c7ed8f4d8..8e94e555b78 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -313,7 +313,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
if (ret == -ENOENT) {
/* warn about unknown tuples */
- pr_warning("%s: queuing unknown"
+ pr_warn_ratelimited("%s: queuing unknown"
" CIS tuple 0x%02x (%u bytes)\n",
mmc_hostname(card->host),
tpl_code, tpl_link);
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 8f6f5ac131f..78cb4d5d9d5 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -188,8 +188,7 @@ EXPORT_SYMBOL_GPL(sdio_set_block_size);
*/
static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
{
- unsigned mval = min(func->card->host->max_seg_size,
- func->card->host->max_blk_size);
+ unsigned mval = func->card->host->max_blk_size;
if (mmc_blksz_for_byte_mode(func->card))
mval = min(mval, func->cur_blksize);
@@ -311,11 +310,8 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
/* Do the bulk of the transfer using block mode (if supported). */
if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
/* Blocks per command is limited by host count, host transfer
- * size (we only use a single sg entry) and the maximum for
- * IO_RW_EXTENDED of 511 blocks. */
- max_blocks = min(func->card->host->max_blk_count,
- func->card->host->max_seg_size / func->cur_blksize);
- max_blocks = min(max_blocks, 511u);
+ * size and the maximum for IO_RW_EXTENDED of 511 blocks. */
+ max_blocks = min(func->card->host->max_blk_count, 511u);
while (remainder >= func->cur_blksize) {
unsigned blocks;
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index f573e7f9f74..5cc13c8d35b 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -28,18 +28,20 @@
#include "sdio_ops.h"
-static int process_sdio_pending_irqs(struct mmc_card *card)
+static int process_sdio_pending_irqs(struct mmc_host *host)
{
+ struct mmc_card *card = host->card;
int i, ret, count;
unsigned char pending;
struct sdio_func *func;
/*
* Optimization, if there is only 1 function interrupt registered
- * call irq handler directly
+ * and we know an IRQ was signaled then call irq handler directly.
+ * Otherwise do the full probe.
*/
func = card->sdio_single_irq;
- if (func) {
+ if (func && host->sdio_irq_pending) {
func->irq_handler(func);
return 1;
}
@@ -51,6 +53,17 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
return ret;
}
+ if (pending && mmc_card_broken_irq_polling(card) &&
+ !(host->caps & MMC_CAP_SDIO_IRQ)) {
+ unsigned char dummy;
+
+ /* A fake interrupt could be created when we poll SDIO_CCCR_INTx
+ * register with a Marvell SD8797 card. A dummy CMD52 read to
+ * function 0 register 0xff can avoid this.
+ */
+ mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy);
+ }
+
count = 0;
for (i = 1; i <= 7; i++) {
if (pending & (1 << i)) {
@@ -77,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
return ret;
}
+void sdio_run_irqs(struct mmc_host *host)
+{
+ mmc_claim_host(host);
+ host->sdio_irq_pending = true;
+ process_sdio_pending_irqs(host);
+ mmc_release_host(host);
+}
+EXPORT_SYMBOL_GPL(sdio_run_irqs);
+
static int sdio_irq_thread(void *_host)
{
struct mmc_host *host = _host;
@@ -116,7 +138,8 @@ static int sdio_irq_thread(void *_host)
ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
if (ret)
break;
- ret = process_sdio_pending_irqs(host->card);
+ ret = process_sdio_pending_irqs(host);
+ host->sdio_irq_pending = false;
mmc_release_host(host);
/*
@@ -175,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
WARN_ON(!host->claimed);
if (!host->sdio_irqs++) {
- atomic_set(&host->sdio_irq_thread_abort, 0);
- host->sdio_irq_thread =
- kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
- mmc_hostname(host));
- if (IS_ERR(host->sdio_irq_thread)) {
- int err = PTR_ERR(host->sdio_irq_thread);
- host->sdio_irqs--;
- return err;
+ if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
+ atomic_set(&host->sdio_irq_thread_abort, 0);
+ host->sdio_irq_thread =
+ kthread_run(sdio_irq_thread, host,
+ "ksdioirqd/%s", mmc_hostname(host));
+ if (IS_ERR(host->sdio_irq_thread)) {
+ int err = PTR_ERR(host->sdio_irq_thread);
+ host->sdio_irqs--;
+ return err;
+ }
+ } else {
+ mmc_host_clk_hold(host);
+ host->ops->enable_sdio_irq(host, 1);
+ mmc_host_clk_release(host);
}
}
@@ -197,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
BUG_ON(host->sdio_irqs < 1);
if (!--host->sdio_irqs) {
- atomic_set(&host->sdio_irq_thread_abort, 1);
- kthread_stop(host->sdio_irq_thread);
+ if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
+ atomic_set(&host->sdio_irq_thread_abort, 1);
+ kthread_stop(host->sdio_irq_thread);
+ } else {
+ mmc_host_clk_hold(host);
+ host->ops->enable_sdio_irq(host, 0);
+ mmc_host_clk_release(host);
+ }
}
return 0;
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index d29e20630ee..62508b457c4 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -124,7 +124,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
- struct scatterlist sg;
+ struct scatterlist sg, *sg_ptr;
+ struct sg_table sgtable;
+ unsigned int nents, left_size, i;
+ unsigned int seg_size = card->host->max_seg_size;
BUG_ON(!card);
BUG_ON(fn > 7);
@@ -152,15 +155,36 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
/* Code in host drivers/fwk assumes that "blocks" always is >=1 */
data.blocks = blocks ? blocks : 1;
data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
- data.sg = &sg;
- data.sg_len = 1;
- sg_init_one(&sg, buf, data.blksz * data.blocks);
+ left_size = data.blksz * data.blocks;
+ nents = (left_size - 1) / seg_size + 1;
+ if (nents > 1) {
+ if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
+ return -ENOMEM;
+
+ data.sg = sgtable.sgl;
+ data.sg_len = nents;
+
+ for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
+ sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
+ min(seg_size, left_size),
+ offset_in_page(buf + (i * seg_size)));
+ left_size = left_size - seg_size;
+ }
+ } else {
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ sg_init_one(&sg, buf, left_size);
+ }
mmc_set_data_timeout(&data, card);
mmc_wait_for_req(card->host, &mrq);
+ if (nents > 1)
+ sg_free_table(&sgtable);
+
if (cmd.error)
return cmd.error;
if (data.error)
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
new file mode 100644
index 00000000000..5f89cb83d5f
--- /dev/null
+++ b/drivers/mmc/core/slot-gpio.c
@@ -0,0 +1,355 @@
+/*
+ * Generic GPIO card-detect helper
+ *
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct mmc_gpio {
+ struct gpio_desc *ro_gpio;
+ struct gpio_desc *cd_gpio;
+ bool override_ro_active_level;
+ bool override_cd_active_level;
+ char *ro_label;
+ char cd_label[0];
+};
+
+static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
+{
+ /* Schedule a card detection after a debounce timeout */
+ struct mmc_host *host = dev_id;
+
+ host->trigger_card_event = true;
+ mmc_detect_change(host, msecs_to_jiffies(200));
+
+ return IRQ_HANDLED;
+}
+
+static int mmc_gpio_alloc(struct mmc_host *host)
+{
+ size_t len = strlen(dev_name(host->parent)) + 4;
+ struct mmc_gpio *ctx;
+
+ mutex_lock(&host->slot.lock);
+
+ ctx = host->slot.handler_priv;
+ if (!ctx) {
+ /*
+ * devm_kzalloc() can be called after device_initialize(), even
+ * before device_add(), i.e., between mmc_alloc_host() and
+ * mmc_add_host()
+ */
+ ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
+ GFP_KERNEL);
+ if (ctx) {
+ ctx->ro_label = ctx->cd_label + len;
+ snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
+ snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
+ host->slot.handler_priv = ctx;
+ }
+ }
+
+ mutex_unlock(&host->slot.lock);
+
+ return ctx ? 0 : -ENOMEM;
+}
+
+int mmc_gpio_get_ro(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+
+ if (!ctx || !ctx->ro_gpio)
+ return -ENOSYS;
+
+ if (ctx->override_ro_active_level)
+ return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^
+ !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
+
+ return gpiod_get_value_cansleep(ctx->ro_gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_get_ro);
+
+int mmc_gpio_get_cd(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+
+ if (!ctx || !ctx->cd_gpio)
+ return -ENOSYS;
+
+ if (ctx->override_cd_active_level)
+ return !gpiod_get_raw_value_cansleep(ctx->cd_gpio) ^
+ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
+
+ return gpiod_get_value_cansleep(ctx->cd_gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_get_cd);
+
+/**
+ * mmc_gpio_request_ro - request a gpio for write-protection
+ * @host: mmc host
+ * @gpio: gpio number requested
+ *
+ * As devm_* managed functions are used in mmc_gpio_request_ro(), client
+ * drivers do not need to explicitly call mmc_gpio_free_ro() for freeing up,
+ * if the requesting and freeing are only needed at probing and unbinding time
+ * for once. However, if client drivers do something special like runtime
+ * switching for write-protection, they are responsible for calling
+ * mmc_gpio_request_ro() and mmc_gpio_free_ro() as a pair on their own.
+ *
+ * Returns zero on success, else an error.
+ */
+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
+{
+ struct mmc_gpio *ctx;
+ int ret;
+
+ if (!gpio_is_valid(gpio))
+ return -EINVAL;
+
+ ret = mmc_gpio_alloc(host);
+ if (ret < 0)
+ return ret;
+
+ ctx = host->slot.handler_priv;
+
+ ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN,
+ ctx->ro_label);
+ if (ret < 0)
+ return ret;
+
+ ctx->override_ro_active_level = true;
+ ctx->ro_gpio = gpio_to_desc(gpio);
+
+ return 0;
+}
+EXPORT_SYMBOL(mmc_gpio_request_ro);
+
+void mmc_gpiod_request_cd_irq(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+ int ret, irq;
+
+ if (host->slot.cd_irq >= 0 || !ctx || !ctx->cd_gpio)
+ return;
+
+ irq = gpiod_to_irq(ctx->cd_gpio);
+
+ /*
+ * Even if gpiod_to_irq() returns a valid IRQ number, the platform might
+ * still prefer to poll, e.g., because that IRQ number is already used
+ * by another unit and cannot be shared.
+ */
+ if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
+ irq = -EINVAL;
+
+ if (irq >= 0) {
+ ret = devm_request_threaded_irq(&host->class_dev, irq,
+ NULL, mmc_gpio_cd_irqt,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ ctx->cd_label, host);
+ if (ret < 0)
+ irq = ret;
+ }
+
+ host->slot.cd_irq = irq;
+
+ if (irq < 0)
+ host->caps |= MMC_CAP_NEEDS_POLL;
+}
+EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
+
+/**
+ * mmc_gpio_request_cd - request a gpio for card-detection
+ * @host: mmc host
+ * @gpio: gpio number requested
+ * @debounce: debounce time in microseconds
+ *
+ * As devm_* managed functions are used in mmc_gpio_request_cd(), client
+ * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up,
+ * if the requesting and freeing are only needed at probing and unbinding time
+ * for once. However, if client drivers do something special like runtime
+ * switching for card-detection, they are responsible for calling
+ * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own.
+ *
+ * If GPIO debouncing is desired, set the debounce parameter to a non-zero
+ * value. The caller is responsible for ensuring that the GPIO driver associated
+ * with the GPIO supports debouncing, otherwise an error will be returned.
+ *
+ * Returns zero on success, else an error.
+ */
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
+ unsigned int debounce)
+{
+ struct mmc_gpio *ctx;
+ int ret;
+
+ ret = mmc_gpio_alloc(host);
+ if (ret < 0)
+ return ret;
+
+ ctx = host->slot.handler_priv;
+
+ ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN,
+ ctx->cd_label);
+ if (ret < 0)
+ /*
+ * don't bother freeing memory. It might still get used by other
+ * slot functions, in any case it will be freed, when the device
+ * is destroyed.
+ */
+ return ret;
+
+ if (debounce) {
+ ret = gpio_set_debounce(gpio, debounce);
+ if (ret < 0)
+ return ret;
+ }
+
+ ctx->override_cd_active_level = true;
+ ctx->cd_gpio = gpio_to_desc(gpio);
+
+ mmc_gpiod_request_cd_irq(host);
+
+ return 0;
+}
+EXPORT_SYMBOL(mmc_gpio_request_cd);
+
+/**
+ * mmc_gpio_free_ro - free the write-protection gpio
+ * @host: mmc host
+ *
+ * It's provided only for cases that client drivers need to manually free
+ * up the write-protection gpio requested by mmc_gpio_request_ro().
+ */
+void mmc_gpio_free_ro(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+ int gpio;
+
+ if (!ctx || !ctx->ro_gpio)
+ return;
+
+ gpio = desc_to_gpio(ctx->ro_gpio);
+ ctx->ro_gpio = NULL;
+
+ devm_gpio_free(&host->class_dev, gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_free_ro);
+
+/**
+ * mmc_gpio_free_cd - free the card-detection gpio
+ * @host: mmc host
+ *
+ * It's provided only for cases that client drivers need to manually free
+ * up the card-detection gpio requested by mmc_gpio_request_cd().
+ */
+void mmc_gpio_free_cd(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+ int gpio;
+
+ if (!ctx || !ctx->cd_gpio)
+ return;
+
+ if (host->slot.cd_irq >= 0) {
+ devm_free_irq(&host->class_dev, host->slot.cd_irq, host);
+ host->slot.cd_irq = -EINVAL;
+ }
+
+ gpio = desc_to_gpio(ctx->cd_gpio);
+ ctx->cd_gpio = NULL;
+
+ devm_gpio_free(&host->class_dev, gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_free_cd);
+
+/**
+ * mmc_gpiod_request_cd - request a gpio descriptor for card-detection
+ * @host: mmc host
+ * @con_id: function within the GPIO consumer
+ * @idx: index of the GPIO to obtain in the consumer
+ * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
+ * @debounce: debounce time in microseconds
+ *
+ * Use this function in place of mmc_gpio_request_cd() to use the GPIO
+ * descriptor API. Note that it is paired with mmc_gpiod_free_cd() not
+ * mmc_gpio_free_cd(). Note also that it must be called prior to mmc_add_host()
+ * otherwise the caller must also call mmc_gpiod_request_cd_irq().
+ *
+ * Returns zero on success, else an error.
+ */
+int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
+ unsigned int idx, bool override_active_level,
+ unsigned int debounce)
+{
+ struct mmc_gpio *ctx;
+ struct gpio_desc *desc;
+ int ret;
+
+ ret = mmc_gpio_alloc(host);
+ if (ret < 0)
+ return ret;
+
+ ctx = host->slot.handler_priv;
+
+ if (!con_id)
+ con_id = ctx->cd_label;
+
+ desc = devm_gpiod_get_index(host->parent, con_id, idx);
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ ret = gpiod_direction_input(desc);
+ if (ret < 0)
+ return ret;
+
+ if (debounce) {
+ ret = gpiod_set_debounce(desc, debounce);
+ if (ret < 0)
+ return ret;
+ }
+
+ ctx->override_cd_active_level = override_active_level;
+ ctx->cd_gpio = desc;
+
+ return 0;
+}
+EXPORT_SYMBOL(mmc_gpiod_request_cd);
+
+/**
+ * mmc_gpiod_free_cd - free the card-detection gpio descriptor
+ * @host: mmc host
+ *
+ * It's provided only for cases that client drivers need to manually free
+ * up the card-detection gpio requested by mmc_gpiod_request_cd().
+ */
+void mmc_gpiod_free_cd(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+
+ if (!ctx || !ctx->cd_gpio)
+ return;
+
+ if (host->slot.cd_irq >= 0) {
+ devm_free_irq(&host->class_dev, host->slot.cd_irq, host);
+ host->slot.cd_irq = -EINVAL;
+ }
+
+ devm_gpiod_put(&host->class_dev, ctx->cd_gpio);
+
+ ctx->cd_gpio = NULL;
+}
+EXPORT_SYMBOL(mmc_gpiod_free_cd);