sdhci: Add support for card-detection polling
This patch adds SDHCI_QUIRK_BROKEN_CARD_DETECTION quirk. When specified, sdhci driver will set MMC_CAP_NEEDS_POLL MMC host capability, and won't enable card insert/remove interrupts. This is needed for hosts with unreliable card detection, such as FSL eSDHC. The original eSDHC driver was tring to "debounce" card-detection IRQs by reading present state and disabling particular interrupts. But with this debouncing scheme I noticed that sometimes we miss card insertion/removal events. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
This commit is contained in:
Родитель
6aa943ab89
Коммит
68d1fb7e22
|
@ -112,6 +112,9 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
|
|||
{
|
||||
u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
|
||||
|
||||
if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
|
||||
return;
|
||||
|
||||
if (enable)
|
||||
sdhci_unmask_irqs(host, irqs);
|
||||
else
|
||||
|
@ -1041,6 +1044,7 @@ out:
|
|||
static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
{
|
||||
struct sdhci_host *host;
|
||||
bool present;
|
||||
unsigned long flags;
|
||||
|
||||
host = mmc_priv(mmc);
|
||||
|
@ -1055,8 +1059,14 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
|||
|
||||
host->mrq = mrq;
|
||||
|
||||
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
|
||||
|| (host->flags & SDHCI_DEVICE_DEAD)) {
|
||||
/* If polling, assume that the card is always present. */
|
||||
if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
|
||||
present = true;
|
||||
else
|
||||
present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
|
||||
SDHCI_CARD_PRESENT;
|
||||
|
||||
if (!present || host->flags & SDHCI_DEVICE_DEAD) {
|
||||
host->mrq->cmd->error = -ENOMEDIUM;
|
||||
tasklet_schedule(&host->finish_tasklet);
|
||||
} else
|
||||
|
@ -1690,6 +1700,9 @@ 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;
|
||||
|
||||
mmc->ocr_avail = 0;
|
||||
if (caps & SDHCI_CAN_VDD_330)
|
||||
mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
|
||||
|
|
|
@ -214,6 +214,8 @@ struct sdhci_host {
|
|||
#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
|
||||
/* Controller does not provide transfer-complete interrupt when not busy */
|
||||
#define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14)
|
||||
/* Controller has unreliable card detection */
|
||||
#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15)
|
||||
|
||||
int irq; /* Device IRQ */
|
||||
void __iomem * ioaddr; /* Mapped address */
|
||||
|
|
Загрузка…
Ссылка в новой задаче