summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-05-20 21:26:12 -0700
committerGary King <gking@nvidia.com>2010-05-21 19:35:05 -0700
commit3d1dfcea86ee15753498e8cf8134cde52574b45f (patch)
tree3d4f38832adb7e5aa0af08fa956e822aad3ee4e1
parent7d4f9215bde5cb2f607d5fda035c677b64c8c997 (diff)
sdhci: add callback for non-polled, broken card detection
some platforms support alternative means of detecting card presence (e.g., GPIOs). add a callback function for these hosts to allow card detection without polling and without relying on the PRESENT_STATE register Change-Id: Ic024d7c2f39b7089a4f4683ffe36ed367756941d
-rw-r--r--drivers/mmc/host/sdhci.c25
-rw-r--r--drivers/mmc/host/sdhci.h1
2 files changed, 20 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 296ff92bd8b6..466a64683d5f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1129,9 +1129,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->mrq = mrq;
/* If polling, assume that the card is always present. */
- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
- present = true;
- else
+ if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) {
+ if (host->ops->card_detect)
+ present = host->ops->card_detect(host);
+ else
+ present = true;
+ } else
present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_PRESENT;
@@ -1833,8 +1836,10 @@ int sdhci_add_host(struct sdhci_host *host)
if (caps & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
- mmc->caps |= MMC_CAP_NEEDS_POLL;
+ if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) {
+ if (!host->ops->card_detect)
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+ }
if (host->data_width >= 8)
mmc->caps |= MMC_CAP_8_BIT_DATA;
@@ -2024,10 +2029,18 @@ EXPORT_SYMBOL_GPL(sdhci_free_host);
void sdhci_card_detect_callback(struct sdhci_host *host)
{
unsigned long flags;
+ int present;
spin_lock_irqsave(&host->lock, flags);
- if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+ if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
+ host->ops->card_detect)
+ present = host->ops->card_detect(host);
+ else
+ present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+ SDHCI_CARD_PRESENT;
+
+ if (!present) {
if (host->mrq) {
printk(KERN_ERR "%s: Card removed during transfer!\n",
mmc_hostname(host->mmc));
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 7539c17ce12a..b72cf351cb45 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -327,6 +327,7 @@ struct sdhci_ops {
/* returns card read-only status in a host-specific way if
* SDHCI_QUIRK_BROKEN_WRITE_PROTECT is set */
int (*get_ro)(struct sdhci_host *host);
+ bool (*card_detect)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS