diff options
author | Xie Xiaobo <X.Xie@freescale.com> | 2014-05-26 09:37:34 (GMT) |
---|---|---|
committer | Jose Rivera <German.Rivera@freescale.com> | 2014-05-27 14:00:56 (GMT) |
commit | 538ad2a3f8d0c3536ad4e84f5ffe4c3185347584 (patch) | |
tree | 9ca99d6d524e08099e9a83fa578d60bb5ba4cce0 /drivers | |
parent | 06c79bcebaf34cba4ee98cfbce8e6a1e670ab6ab (diff) | |
download | linux-fsl-qoriq-538ad2a3f8d0c3536ad4e84f5ffe4c3185347584.tar.xz |
MMC/SD: Add callback function to detect card
In order to check whether the card has been removed, the function
mmc_send_status() will send command CMD13 to card and ask the card
to send its status register to sdhc driver, which will generate
many interrupts repeatedly and make the system performance bad.
From the performance test on Freescale's board (such as Iozone for SD),
the performance will degrade about 4~6%.
There is one another way to get this information,
which is to read the register PRSSTAT and check the bit CDPL or CINS.
If the card is present, these two bit will set to one.
Therefore, add callback function get_cd() to check whether
the card has been inserted/removed when the driver supports this feature.
If the card is present, 0 will return, if the card is absent, 1 will return.
If the controller will not support this feature, -ENOSYS will return.
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Xie Xiaobo <X.Xie@freescale.com>
Change-Id: I5ef39890637727c0120bea7497421b5ccd99f346
Reviewed-on: http://git.am.freescale.net:8181/12879
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Yang Li <LeoLi@freescale.com>
Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/core.c | 13 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 18 |
2 files changed, 26 insertions, 5 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9785bd1..4147391 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2386,7 +2386,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) int _mmc_detect_card_removed(struct mmc_host *host) { - int ret; + int ret = -ENOSYS; if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive) return 0; @@ -2394,7 +2394,16 @@ int _mmc_detect_card_removed(struct mmc_host *host) if (!host->card || mmc_card_removed(host->card)) return 1; - ret = host->bus_ops->alive(host); + /* First, try host-controller's card detect callback */ + if (host->ops->get_cd) { + ret = host->ops->get_cd(host); + if (ret >= 0) + ret = !ret; + } + + /* If failed, back to the bus_ops alive() callback */ + if (ret < 0) + ret = host->bus_ops->alive(host); /* * Card detect status and alive check may be out of sync if card is diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 596a662..637c52f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1616,15 +1616,27 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) static int sdhci_do_get_cd(struct sdhci_host *host) { int gpio_cd = mmc_gpio_get_cd(host->mmc); + unsigned long flags; + int present = -ENOSYS; if (host->flags & SDHCI_DEVICE_DEAD) return 0; - /* If polling/nonremovable, assume that the card is always present. */ - if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || - (host->mmc->caps & MMC_CAP_NONREMOVABLE)) + /* If nonremovable, assume that the card is always present. */ + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) return 1; + /* If polling, We firstly poll the CD pin state. */ + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) { + if (host->ops->get_cd) { + spin_lock_irqsave(&host->lock, flags); + present = host->ops->get_cd(host); + spin_unlock_irqrestore(&host->lock, flags); + return present; + } else + return 1; + } + /* Try slot gpio detect */ if (!IS_ERR_VALUE(gpio_cd)) return !!gpio_cd; |