diff options
-rw-r--r-- | drivers/mmc/card/queue.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/bus.c | 23 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 144 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 22 | ||||
-rw-r--r-- | drivers/mmc/core/host.c | 7 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 26 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 36 | ||||
-rw-r--r-- | drivers/mmc/core/sd_ops.c | 62 | ||||
-rw-r--r-- | drivers/mmc/core/sd_ops.h | 3 | ||||
-rw-r--r-- | drivers/mmc/host/at91_mci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/au1xmmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/imxmmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 2 | ||||
-rw-r--r-- | drivers/mmc/host/omap.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/pxamci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 63 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 2 | ||||
-rw-r--r-- | drivers/mmc/host/wbsd.c | 15 | ||||
-rw-r--r-- | drivers/mmc/host/wbsd.h | 2 | ||||
-rw-r--r-- | include/linux/mmc/core.h | 2 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 2 |
24 files changed, 253 insertions, 176 deletions
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index e02eac876362..c9a289c6c139 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 diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 348b566bf4fd..fe0e785ed7d2 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 b5d8a6d90cca..bfd2ae5bd669 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 ae006b30dd86..bb2774af9ea9 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 1433d95c40bb..6a7e29849603 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 66f85bfa8dbb..21d7f48e1d4e 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 7dd720fa5895..913e75f00843 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 7a481e8ca5ea..76d09a93c5d6 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 1240684083f1..1edc62b1e5c6 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 9697ce581101..342f340ebc25 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 1240fddba5e3..9742d8a30664 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 15aab374127e..62564ccde03a 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 52b63f11ddd6..34c99d4ea041 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 7ee2045acbef..54bfc9f25596 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 d11c2d23ceea..be730c0a0352 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 6d7eadc9a678..000e6a919782 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 b0824a38f425..0cf97edc5f58 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 f8985c508bb9..ff960334b337 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 4a24db028d87..f2bc87ac24f7 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 a6c870480b8a..d157776c1149 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 867ca6a69298..e0c9808fd424 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 873bda1e59b4..0877866f8d28 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. * diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 04bbe12fae8d..63a80ea61124 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -99,7 +99,7 @@ struct mmc_request { struct mmc_host; struct mmc_card; -extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *); +extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *); extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, struct mmc_command *, int); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index dc41ad4203b8..69d68117bdac 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1976,6 +1976,8 @@ #define PCI_VENDOR_ID_ENE 0x1524 #define PCI_DEVICE_ID_ENE_CB712_SD 0x0550 #define PCI_DEVICE_ID_ENE_CB712_SD_2 0x0551 +#define PCI_DEVICE_ID_ENE_CB714_SD 0x0750 +#define PCI_DEVICE_ID_ENE_CB714_SD_2 0x0751 #define PCI_DEVICE_ID_ENE_1211 0x1211 #define PCI_DEVICE_ID_ENE_1225 0x1225 #define PCI_DEVICE_ID_ENE_1410 0x1410 |