Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: drivers/mmc/core/: make 3 functions static mmc: add missing printk levels mmc: remove redundant debug information from sdhci and wbsd mmc: proper debugging output in core mmc: be more verbose about card insertions/removal mmc: Don't hold lock when releasing an added card mmc: add a might_sleep() to mmc_claim_host() mmc: update kerneldoc mmc: update header file paths sdhci: add support to ENE-CB714 mmc: check error bits before command completion
This commit is contained in:
Коммит
d941cf5e37
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
@ -432,6 +461,45 @@ static void mmc_power_off(struct mmc_host *host)
|
|||
mmc_set_ios(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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* linux/drivers/mmc/mmc_ops.h
|
||||
* linux/drivers/mmc/core/mmc_ops.h
|
||||
*
|
||||
* Copyright 2006-2007 Pierre Ossman
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* linux/drivers/mmc/mmc_ops.h
|
||||
* linux/drivers/mmc/core/mmc_ops.h
|
||||
*
|
||||
* Copyright 2006-2007 Pierre Ossman
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче