aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/queue.c10
-rw-r--r--drivers/mmc/core/bus.c23
-rw-r--r--drivers/mmc/core/core.c144
-rw-r--r--drivers/mmc/core/core.h22
-rw-r--r--drivers/mmc/core/host.c7
-rw-r--r--drivers/mmc/core/mmc.c26
-rw-r--r--drivers/mmc/core/mmc_ops.c2
-rw-r--r--drivers/mmc/core/mmc_ops.h2
-rw-r--r--drivers/mmc/core/sd.c36
-rw-r--r--drivers/mmc/core/sd_ops.c62
-rw-r--r--drivers/mmc/core/sd_ops.h3
-rw-r--r--drivers/mmc/host/at91_mci.c2
-rw-r--r--drivers/mmc/host/au1xmmc.c2
-rw-r--r--drivers/mmc/host/imxmmc.c2
-rw-r--r--drivers/mmc/host/mmci.c2
-rw-r--r--drivers/mmc/host/mmci.h2
-rw-r--r--drivers/mmc/host/omap.c2
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/sdhci.c63
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/mmc/host/wbsd.c15
-rw-r--r--drivers/mmc/host/wbsd.h2
22 files changed, 254 insertions, 179 deletions
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index b53dac8d1b6..c9a289c6c13 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/queue.c
+ * linux/drivers/mmc/card/queue.c
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright 2006-2007 Pierre Ossman
@@ -83,7 +83,7 @@ static int mmc_queue_thread(void *d)
* on any queue on this host, and attempt to issue it. This may
* not be the queue we were asked to process.
*/
-static void mmc_request(request_queue_t *q)
+static void mmc_request(struct request_queue *q)
{
struct mmc_queue *mq = q->queuedata;
struct request *req;
@@ -211,7 +211,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
void mmc_cleanup_queue(struct mmc_queue *mq)
{
- request_queue_t *q = mq->queue;
+ struct request_queue *q = mq->queue;
unsigned long flags;
/* Mark that we should start throwing out stragglers */
@@ -252,7 +252,7 @@ EXPORT_SYMBOL(mmc_cleanup_queue);
*/
void mmc_queue_suspend(struct mmc_queue *mq)
{
- request_queue_t *q = mq->queue;
+ struct request_queue *q = mq->queue;
unsigned long flags;
if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
@@ -272,7 +272,7 @@ void mmc_queue_suspend(struct mmc_queue *mq)
*/
void mmc_queue_resume(struct mmc_queue *mq)
{
- request_queue_t *q = mq->queue;
+ struct request_queue *q = mq->queue;
unsigned long flags;
if (mq->flags & MMC_QUEUE_SUSPENDED) {
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 348b566bf4f..fe0e785ed7d 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -209,10 +209,30 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host)
int mmc_add_card(struct mmc_card *card)
{
int ret;
+ const char *type;
snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
"%s:%04x", mmc_hostname(card->host), card->rca);
+ switch (card->type) {
+ case MMC_TYPE_MMC:
+ type = "MMC";
+ break;
+ case MMC_TYPE_SD:
+ type = "SD";
+ if (mmc_card_blockaddr(card))
+ type = "SDHC";
+ break;
+ default:
+ type = "?";
+ break;
+ }
+
+ printk(KERN_INFO "%s: new %s%s card at address %04x\n",
+ mmc_hostname(card->host),
+ mmc_card_highspeed(card) ? "high speed " : "",
+ type, card->rca);
+
card->dev.uevent_suppress = 1;
ret = device_add(&card->dev);
@@ -243,6 +263,9 @@ int mmc_add_card(struct mmc_card *card)
void mmc_remove_card(struct mmc_card *card)
{
if (mmc_card_present(card)) {
+ printk(KERN_INFO "%s: card %04x removed\n",
+ mmc_hostname(card->host), card->rca);
+
if (card->host->bus_ops->sysfs_remove)
card->host->bus_ops->sysfs_remove(card->host, card);
device_del(&card->dev);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b5d8a6d90cc..bfd2ae5bd66 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -68,32 +68,41 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
struct mmc_command *cmd = mrq->cmd;
int err = cmd->error;
- pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
- mmc_hostname(host), cmd->opcode, err,
- mrq->data ? mrq->data->error : 0,
- mrq->stop ? mrq->stop->error : 0,
- cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
if (err && cmd->retries) {
+ pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
+ mmc_hostname(host), cmd->opcode, err);
+
cmd->retries--;
cmd->error = 0;
host->ops->request(host, mrq);
- } else if (mrq->done) {
- mrq->done(mrq);
+ } else {
+ pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
+ mmc_hostname(host), cmd->opcode, err,
+ cmd->resp[0], cmd->resp[1],
+ cmd->resp[2], cmd->resp[3]);
+
+ if (mrq->data) {
+ pr_debug("%s: %d bytes transferred: %d\n",
+ mmc_hostname(host),
+ mrq->data->bytes_xfered, mrq->data->error);
+ }
+
+ if (mrq->stop) {
+ pr_debug("%s: (CMD%u): %d: %08x %08x %08x %08x\n",
+ mmc_hostname(host), mrq->stop->opcode,
+ mrq->stop->error,
+ mrq->stop->resp[0], mrq->stop->resp[1],
+ mrq->stop->resp[2], mrq->stop->resp[3]);
+ }
+
+ if (mrq->done)
+ mrq->done(mrq);
}
}
EXPORT_SYMBOL(mmc_request_done);
-/**
- * mmc_start_request - start a command on a host
- * @host: MMC host to start command on
- * @mrq: MMC request to start
- *
- * Queue a command on the specified host. We expect the
- * caller to be holding the host lock with interrupts disabled.
- */
-void
+static void
mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
#ifdef CONFIG_MMC_DEBUG
@@ -104,6 +113,21 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
mmc_hostname(host), mrq->cmd->opcode,
mrq->cmd->arg, mrq->cmd->flags);
+ if (mrq->data) {
+ pr_debug("%s: blksz %d blocks %d flags %08x "
+ "tsac %d ms nsac %d\n",
+ mmc_hostname(host), mrq->data->blksz,
+ mrq->data->blocks, mrq->data->flags,
+ mrq->data->timeout_ns / 10000000,
+ mrq->data->timeout_clks);
+ }
+
+ if (mrq->stop) {
+ pr_debug("%s: CMD%u arg %08x flags %08x\n",
+ mmc_hostname(host), mrq->stop->opcode,
+ mrq->stop->arg, mrq->stop->flags);
+ }
+
WARN_ON(!host->claimed);
mrq->cmd->error = 0;
@@ -133,14 +157,21 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
host->ops->request(host, mrq);
}
-EXPORT_SYMBOL(mmc_start_request);
-
static void mmc_wait_done(struct mmc_request *mrq)
{
complete(mrq->done_data);
}
-int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+/**
+ * mmc_wait_for_req - start a request and wait for completion
+ * @host: MMC host to start command
+ * @mrq: MMC request to start
+ *
+ * Start a new MMC custom command request for a host, and wait
+ * for the command to complete. Does not attempt to parse the
+ * response.
+ */
+void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
DECLARE_COMPLETION_ONSTACK(complete);
@@ -150,8 +181,6 @@ int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
mmc_start_request(host, mrq);
wait_for_completion(&complete);
-
- return 0;
}
EXPORT_SYMBOL(mmc_wait_for_req);
@@ -192,6 +221,9 @@ EXPORT_SYMBOL(mmc_wait_for_cmd);
* @data: data phase for command
* @card: the MMC card associated with the data transfer
* @write: flag to differentiate reads from writes
+ *
+ * Computes the data timeout parameters according to the
+ * correct algorithm given the card type.
*/
void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
int write)
@@ -240,21 +272,18 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
EXPORT_SYMBOL(mmc_set_data_timeout);
/**
- * __mmc_claim_host - exclusively claim a host
+ * mmc_claim_host - exclusively claim a host
* @host: mmc host to claim
- * @card: mmc card to claim host for
- *
- * Claim a host for a set of operations. If a valid card
- * is passed and this wasn't the last card selected, select
- * the card before returning.
*
- * Note: you should use mmc_card_claim_host or mmc_claim_host.
+ * Claim a host for a set of operations.
*/
void mmc_claim_host(struct mmc_host *host)
{
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
+ might_sleep();
+
add_wait_queue(&host->wq, &wait);
spin_lock_irqsave(&host->lock, flags);
while (1) {
@@ -433,6 +462,45 @@ static void mmc_power_off(struct mmc_host *host)
}
/*
+ * Cleanup when the last reference to the bus operator is dropped.
+ */
+void __mmc_release_bus(struct mmc_host *host)
+{
+ BUG_ON(!host);
+ BUG_ON(host->bus_refs);
+ BUG_ON(!host->bus_dead);
+
+ host->bus_ops = NULL;
+}
+
+/*
+ * Increase reference count of bus operator
+ */
+static inline void mmc_bus_get(struct mmc_host *host)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+ host->bus_refs++;
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*
+ * Decrease reference count of bus operator and free it if
+ * it is the last reference.
+ */
+static inline void mmc_bus_put(struct mmc_host *host)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+ host->bus_refs--;
+ if ((host->bus_refs == 0) && host->bus_ops)
+ __mmc_release_bus(host);
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*
* Assign a mmc bus handler to a host. Only one bus handler may control a
* host at any given time.
*/
@@ -481,25 +549,15 @@ void mmc_detach_bus(struct mmc_host *host)
mmc_bus_put(host);
}
-/*
- * Cleanup when the last reference to the bus operator is dropped.
- */
-void __mmc_release_bus(struct mmc_host *host)
-{
- BUG_ON(!host);
- BUG_ON(host->bus_refs);
- BUG_ON(!host->bus_dead);
-
- host->bus_ops = NULL;
-}
-
/**
* mmc_detect_change - process change of state on a MMC socket
* @host: host which changed state.
* @delay: optional delay to wait before detection (jiffies)
*
- * All we know is that card(s) have been inserted or removed
- * from the socket(s). We don't know which socket or cards.
+ * MMC drivers should call this when they detect a card has been
+ * inserted or removed. The MMC layer will confirm that any
+ * present card is still functional, and initialize any newly
+ * inserted.
*/
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index ae006b30dd8..bb2774af9ea 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -27,28 +27,6 @@ struct mmc_bus_ops {
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
void mmc_detach_bus(struct mmc_host *host);
-void __mmc_release_bus(struct mmc_host *host);
-
-static inline void mmc_bus_get(struct mmc_host *host)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&host->lock, flags);
- host->bus_refs++;
- spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static inline void mmc_bus_put(struct mmc_host *host)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&host->lock, flags);
- host->bus_refs--;
- if ((host->bus_refs == 0) && host->bus_ops)
- __mmc_release_bus(host);
- spin_unlock_irqrestore(&host->lock, flags);
-}
-
void mmc_set_chip_select(struct mmc_host *host, int mode);
void mmc_set_clock(struct mmc_host *host, unsigned int hz);
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 1433d95c40b..6a7e2984960 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -93,6 +93,10 @@ EXPORT_SYMBOL(mmc_alloc_host);
/**
* mmc_add_host - initialise host hardware
* @host: mmc host
+ *
+ * Register the host with the driver model. The host must be
+ * prepared to start servicing requests before this function
+ * completes.
*/
int mmc_add_host(struct mmc_host *host)
{
@@ -126,7 +130,8 @@ EXPORT_SYMBOL(mmc_add_host);
* @host: mmc host
*
* Unregister and remove all cards associated with this host,
- * and power down the MMC bus.
+ * and power down the MMC bus. No new requests will be issued
+ * after this function has returned.
*/
void mmc_remove_host(struct mmc_host *host)
{
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 66f85bfa8db..21d7f48e1d4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/mmc.c
+ * linux/drivers/mmc/core/mmc.c
*
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
@@ -100,7 +100,7 @@ static int mmc_decode_cid(struct mmc_card *card)
break;
default:
- printk("%s: card has unknown MMCA version %d\n",
+ printk(KERN_ERR "%s: card has unknown MMCA version %d\n",
mmc_hostname(card->host), card->csd.mmca_vsn);
return -EINVAL;
}
@@ -123,7 +123,7 @@ static int mmc_decode_csd(struct mmc_card *card)
*/
csd_struct = UNSTUFF_BITS(resp, 126, 2);
if (csd_struct != 1 && csd_struct != 2) {
- printk("%s: unrecognised CSD structure version %d\n",
+ printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
mmc_hostname(card->host), csd_struct);
return -EINVAL;
}
@@ -499,14 +499,17 @@ static void mmc_resume(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
-
err = mmc_init_card(host, host->ocr, host->card);
+ mmc_release_host(host);
+
if (err != MMC_ERR_NONE) {
mmc_remove(host);
+
+ mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_release_host(host);
}
- mmc_release_host(host);
}
#else
@@ -553,8 +556,10 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
/*
* Can we support the voltage of the card?
*/
- if (!host->ocr)
+ if (!host->ocr) {
+ err = -EINVAL;
goto err;
+ }
/*
* Detect and init the card.
@@ -567,18 +572,21 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
err = mmc_add_card(host->card);
if (err)
- goto reclaim_host;
+ goto remove_card;
return 0;
-reclaim_host:
- mmc_claim_host(host);
+remove_card:
mmc_remove_card(host->card);
host->card = NULL;
+ mmc_claim_host(host);
err:
mmc_detach_bus(host);
mmc_release_host(host);
+ printk(KERN_ERR "%s: error %d whilst initialising MMC card\n",
+ mmc_hostname(host), err);
+
return 0;
}
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 7dd720fa589..913e75f0084 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/mmc_ops.h
+ * linux/drivers/mmc/core/mmc_ops.h
*
* Copyright 2006-2007 Pierre Ossman
*
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 7a481e8ca5e..76d09a93c5d 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/mmc_ops.h
+ * linux/drivers/mmc/core/mmc_ops.h
*
* Copyright 2006-2007 Pierre Ossman
*
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 1240684083f..1edc62b1e5c 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/sd.c
+ * linux/drivers/mmc/core/sd.c
*
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
* SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
@@ -149,7 +149,7 @@ static int mmc_decode_csd(struct mmc_card *card)
csd->write_partial = 0;
break;
default:
- printk("%s: unrecognised CSD structure version %d\n",
+ printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
mmc_hostname(card->host), csd_struct);
return -EINVAL;
}
@@ -173,7 +173,7 @@ static int mmc_decode_scr(struct mmc_card *card)
scr_struct = UNSTUFF_BITS(resp, 60, 4);
if (scr_struct != 0) {
- printk("%s: unrecognised SCR structure version %d\n",
+ printk(KERN_ERR "%s: unrecognised SCR structure version %d\n",
mmc_hostname(card->host), scr_struct);
return -EINVAL;
}
@@ -206,9 +206,8 @@ static int mmc_read_switch(struct mmc_card *card)
status = kmalloc(64, GFP_KERNEL);
if (!status) {
- printk("%s: could not allocate a buffer for switch "
- "capabilities.\n",
- mmc_hostname(card->host));
+ printk(KERN_ERR "%s: could not allocate a buffer for "
+ "switch capabilities.\n", mmc_hostname(card->host));
return err;
}
@@ -254,9 +253,8 @@ static int mmc_switch_hs(struct mmc_card *card)
status = kmalloc(64, GFP_KERNEL);
if (!status) {
- printk("%s: could not allocate a buffer for switch "
- "capabilities.\n",
- mmc_hostname(card->host));
+ printk(KERN_ERR "%s: could not allocate a buffer for "
+ "switch capabilities.\n", mmc_hostname(card->host));
return err;
}
@@ -573,14 +571,17 @@ static void mmc_sd_resume(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
-
err = mmc_sd_init_card(host, host->ocr, host->card);
+ mmc_release_host(host);
+
if (err != MMC_ERR_NONE) {
mmc_sd_remove(host);
+
+ mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_release_host(host);
}
- mmc_release_host(host);
}
#else
@@ -634,8 +635,10 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
/*
* Can we support the voltage(s) of the card(s)?
*/
- if (!host->ocr)
+ if (!host->ocr) {
+ err = -EINVAL;
goto err;
+ }
/*
* Detect and init the card.
@@ -648,18 +651,21 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
err = mmc_add_card(host->card);
if (err)
- goto reclaim_host;
+ goto remove_card;
return 0;
-reclaim_host:
- mmc_claim_host(host);
+remove_card:
mmc_remove_card(host->card);
host->card = NULL;
+ mmc_claim_host(host);
err:
mmc_detach_bus(host);
mmc_release_host(host);
+ printk(KERN_ERR "%s: error %d whilst initialising SD card\n",
+ mmc_hostname(host), err);
+
return 0;
}
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 9697ce58110..342f340ebc2 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/sd_ops.h
+ * linux/drivers/mmc/core/sd_ops.h
*
* Copyright 2006-2007 Pierre Ossman
*
@@ -21,11 +21,40 @@
#include "core.h"
#include "sd_ops.h"
+static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
+{
+ int err;
+ struct mmc_command cmd;
+
+ BUG_ON(!host);
+ BUG_ON(card && (card->host != host));
+
+ cmd.opcode = MMC_APP_CMD;
+
+ if (card) {
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+ } else {
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
+ }
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ /* Check that card supported application commands */
+ if (!(cmd.resp[0] & R1_APP_CMD))
+ return MMC_ERR_FAILED;
+
+ return MMC_ERR_NONE;
+}
+
/**
* mmc_wait_for_app_cmd - start an application command and wait for
completion
* @host: MMC host to start command
- * @rca: RCA to send MMC_APP_CMD to
+ * @card: Card to send MMC_APP_CMD to
* @cmd: MMC command to start
* @retries: maximum number of retries
*
@@ -77,35 +106,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
EXPORT_SYMBOL(mmc_wait_for_app_cmd);
-int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
-{
- int err;
- struct mmc_command cmd;
-
- BUG_ON(!host);
- BUG_ON(card && (card->host != host));
-
- cmd.opcode = MMC_APP_CMD;
-
- if (card) {
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- } else {
- cmd.arg = 0;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
- }
-
- err = mmc_wait_for_cmd(host, &cmd, 0);
- if (err != MMC_ERR_NONE)
- return err;
-
- /* Check that card supported application commands */
- if (!(cmd.resp[0] & R1_APP_CMD))
- return MMC_ERR_FAILED;
-
- return MMC_ERR_NONE;
-}
-
int mmc_app_set_bus_width(struct mmc_card *card, int width)
{
int err;
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
index 1240fddba5e..9742d8a3066 100644
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/sd_ops.h
+ * linux/drivers/mmc/core/sd_ops.h
*
* Copyright 2006-2007 Pierre Ossman
*
@@ -12,7 +12,6 @@
#ifndef _MMC_SD_OPS_H
#define _MMC_SD_OPS_H
-int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 15aab374127..62564ccde03 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver
+ * linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
*
* Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
*
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 52b63f11ddd..34c99d4ea04 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver
+ * linux/drivers/mmc/host/au1xmmc.c - AU1XX0 MMC driver
*
* Copyright (c) 2005, Advanced Micro Devices, Inc.
*
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
index 7ee2045acbe..54bfc9f2559 100644
--- a/drivers/mmc/host/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
+ * linux/drivers/mmc/host/imxmmc.c - Motorola i.MX MMCI driver
*
* Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
* Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index d11c2d23cee..be730c0a035 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver
+ * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver
*
* Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
*
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 6d7eadc9a67..000e6a91978 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/mmci.h - ARM PrimeCell MMCI PL180/1 driver
+ * linux/drivers/mmc/host/mmci.h - ARM PrimeCell MMCI PL180/1 driver
*
* Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
*
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index b0824a38f42..0cf97edc5f5 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/media/mmc/omap.c
+ * linux/drivers/mmc/host/omap.c
*
* Copyright (C) 2004 Nokia Corporation
* Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com>
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index f8985c508bb..ff960334b33 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/pxa.c - PXA MMCI driver
+ * linux/drivers/mmc/host/pxa.c - PXA MMCI driver
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 4a24db028d8..f2bc87ac24f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
+ * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
*
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
*
@@ -34,6 +34,7 @@ static unsigned int debug_quirks = 0;
/* Controller doesn't like some resets when there is no card inserted. */
#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
+#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4)
static const struct pci_device_id pci_ids[] __devinitdata = {
{
@@ -78,6 +79,24 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE,
},
+ {
+ .vendor = PCI_VENDOR_ID_ENE,
+ .device = PCI_DEVICE_ID_ENE_CB714_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_ENE,
+ .device = PCI_DEVICE_ID_ENE_CB714_SD_2,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
+ },
+
{ /* Generic SD host controller */
PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
},
@@ -361,11 +380,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
if (data == NULL)
return;
- DBG("blksz %04x blks %04x flags %08x\n",
- data->blksz, data->blocks, data->flags);
- DBG("tsac %d ms nsac %d clk\n",
- data->timeout_ns / 1000000, data->timeout_clks);
-
/* Sanity checks */
BUG_ON(data->blksz * data->blocks > 524288);
BUG_ON(data->blksz > host->mmc->max_blk_size);
@@ -476,8 +490,6 @@ static void sdhci_finish_data(struct sdhci_host *host)
data->error = MMC_ERR_FAILED;
}
- DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-
if (data->stop) {
/*
* The controller needs a reset of internal state machines
@@ -501,8 +513,6 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
WARN_ON(host->cmd);
- DBG("Sending cmd (%x)\n", cmd->opcode);
-
/* Wait max 10 ms */
timeout = 10;
@@ -590,8 +600,6 @@ static void sdhci_finish_command(struct sdhci_host *host)
host->cmd->error = MMC_ERR_NONE;
- DBG("Ending cmd (%x)\n", host->cmd->opcode);
-
if (host->cmd->data)
host->data = host->cmd->data;
else
@@ -759,6 +767,14 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+ /*
+ * Some (ENE) controllers go apeshit on some ios operation,
+ * signalling timeout and CRC errors even on CMD0. Resetting
+ * it on each ios seems to solve the problem.
+ */
+ if(host->chip->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
}
@@ -835,8 +851,6 @@ static void sdhci_tasklet_finish(unsigned long param)
mrq = host->mrq;
- DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
/*
* The controller needs a reset of internal state machines
* upon error conditions.
@@ -922,20 +936,17 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
return;
}
- if (intmask & SDHCI_INT_RESPONSE)
- sdhci_finish_command(host);
- else {
- if (intmask & SDHCI_INT_TIMEOUT)
- host->cmd->error = MMC_ERR_TIMEOUT;
- else if (intmask & SDHCI_INT_CRC)
- host->cmd->error = MMC_ERR_BADCRC;
- else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
- host->cmd->error = MMC_ERR_FAILED;
- else
- host->cmd->error = MMC_ERR_INVALID;
+ if (intmask & SDHCI_INT_TIMEOUT)
+ host->cmd->error = MMC_ERR_TIMEOUT;
+ else if (intmask & SDHCI_INT_CRC)
+ host->cmd->error = MMC_ERR_BADCRC;
+ else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
+ host->cmd->error = MMC_ERR_FAILED;
+ if (host->cmd->error != MMC_ERR_NONE)
tasklet_schedule(&host->finish_tasklet);
- }
+ else if (intmask & SDHCI_INT_RESPONSE)
+ sdhci_finish_command(host);
}
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index a6c870480b8..d157776c114 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
+ * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
*
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
*
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 867ca6a6929..e0c9808fd42 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
+ * linux/drivers/mmc/host/wbsd.c - Winbond W83L51xD SD/MMC driver
*
* Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved.
*
@@ -207,8 +207,6 @@ static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq)
{
unsigned long dmaflags;
- DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
if (host->dma >= 0) {
/*
* Release ISA DMA controller.
@@ -360,8 +358,6 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
int i;
u8 status, isr;
- DBGF("Sending cmd (%x)\n", cmd->opcode);
-
/*
* Clear accumulated ISR. The interrupt routine
* will fill this one with events that occur during
@@ -411,8 +407,6 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
wbsd_get_short_reply(host, cmd);
}
}
-
- DBGF("Sent cmd (%x), res %d\n", cmd->opcode, cmd->error);
}
/*
@@ -550,11 +544,6 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
unsigned long dmaflags;
unsigned int size;
- DBGF("blksz %04x blks %04x flags %08x\n",
- data->blksz, data->blocks, data->flags);
- DBGF("tsac %d ms nsac %d clk\n",
- data->timeout_ns / 1000000, data->timeout_clks);
-
/*
* Calculate size.
*/
@@ -752,8 +741,6 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
}
}
- DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-
wbsd_request_end(host, host->mrq);
}
diff --git a/drivers/mmc/host/wbsd.h b/drivers/mmc/host/wbsd.h
index 873bda1e59b..0877866f8d2 100644
--- a/drivers/mmc/host/wbsd.h
+++ b/drivers/mmc/host/wbsd.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
+ * linux/drivers/mmc/host/wbsd.h - Winbond W83L51xD SD/MMC driver
*
* Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved.
*