diff options
author | Gary King <gking@nvidia.com> | 2010-05-20 21:26:12 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-21 19:35:05 -0700 |
commit | 3d1dfcea86ee15753498e8cf8134cde52574b45f (patch) | |
tree | 3d4f38832adb7e5aa0af08fa956e822aad3ee4e1 | |
parent | 7d4f9215bde5cb2f607d5fda035c677b64c8c997 (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.c | 25 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 1 |
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 |