Commit 6e6293dd authored by Pierre Ossman's avatar Pierre Ossman Committed by Russell King

[PATCH] MMC: wbsd delayed insertion

Wait 0.5 seconds before scanning for cards after an insertion interrupt.
The electrical connection needs this time to stabilise for some cards.
Signed-off-by: default avatarPierre Ossman <drzeus@drzeus.cx>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 7b09cdac
...@@ -1050,6 +1050,20 @@ static struct mmc_host_ops wbsd_ops = { ...@@ -1050,6 +1050,20 @@ static struct mmc_host_ops wbsd_ops = {
* * * *
\*****************************************************************************/ \*****************************************************************************/
/*
* Helper function for card detection
*/
static void wbsd_detect_card(unsigned long data)
{
struct wbsd_host *host = (struct wbsd_host*)data;
BUG_ON(host == NULL);
DBG("Executing card detection\n");
mmc_detect_change(host->mmc);
}
/* /*
* Tasklets * Tasklets
*/ */
...@@ -1075,7 +1089,6 @@ static void wbsd_tasklet_card(unsigned long param) ...@@ -1075,7 +1089,6 @@ static void wbsd_tasklet_card(unsigned long param)
{ {
struct wbsd_host* host = (struct wbsd_host*)param; struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr; u8 csr;
int change = 0;
spin_lock(&host->lock); spin_lock(&host->lock);
...@@ -1094,14 +1107,20 @@ static void wbsd_tasklet_card(unsigned long param) ...@@ -1094,14 +1107,20 @@ static void wbsd_tasklet_card(unsigned long param)
{ {
DBG("Card inserted\n"); DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT; host->flags |= WBSD_FCARD_PRESENT;
change = 1;
/*
* Delay card detection to allow electrical connections
* to stabilise.
*/
mod_timer(&host->timer, jiffies + HZ/2);
} }
spin_unlock(&host->lock);
} }
else if (host->flags & WBSD_FCARD_PRESENT) else if (host->flags & WBSD_FCARD_PRESENT)
{ {
DBG("Card removed\n"); DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT; host->flags &= ~WBSD_FCARD_PRESENT;
change = 1;
if (host->mrq) if (host->mrq)
{ {
...@@ -1112,15 +1131,14 @@ static void wbsd_tasklet_card(unsigned long param) ...@@ -1112,15 +1131,14 @@ static void wbsd_tasklet_card(unsigned long param)
host->mrq->cmd->error = MMC_ERR_FAILED; host->mrq->cmd->error = MMC_ERR_FAILED;
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
} }
}
/* /*
* Unlock first since we might get a call back. * Unlock first since we might get a call back.
*/ */
spin_unlock(&host->lock); spin_unlock(&host->lock);
if (change)
mmc_detect_change(host->mmc); mmc_detect_change(host->mmc);
}
} }
static void wbsd_tasklet_fifo(unsigned long param) static void wbsd_tasklet_fifo(unsigned long param)
...@@ -1324,6 +1342,13 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) ...@@ -1324,6 +1342,13 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
/*
* Set up detection timer
*/
init_timer(&host->timer);
host->timer.data = (unsigned long)host;
host->timer.function = wbsd_detect_card;
/* /*
* Maximum number of segments. Worst case is one sector per segment * Maximum number of segments. Worst case is one sector per segment
* so this will be 64kB/512. * so this will be 64kB/512.
...@@ -1351,11 +1376,17 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) ...@@ -1351,11 +1376,17 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
static void __devexit wbsd_free_mmc(struct device* dev) static void __devexit wbsd_free_mmc(struct device* dev)
{ {
struct mmc_host* mmc; struct mmc_host* mmc;
struct wbsd_host* host;
mmc = dev_get_drvdata(dev); mmc = dev_get_drvdata(dev);
if (!mmc) if (!mmc)
return; return;
host = mmc_priv(mmc);
BUG_ON(host == NULL);
del_timer_sync(&host->timer);
mmc_free_host(mmc); mmc_free_host(mmc);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
......
...@@ -187,4 +187,6 @@ struct wbsd_host ...@@ -187,4 +187,6 @@ struct wbsd_host
struct tasklet_struct timeout_tasklet; struct tasklet_struct timeout_tasklet;
struct tasklet_struct finish_tasklet; struct tasklet_struct finish_tasklet;
struct tasklet_struct block_tasklet; struct tasklet_struct block_tasklet;
struct timer_list timer; /* Card detection timer */
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment