* *
\*****************************************************************************/
+/*
+ * 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
*/
{
struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr;
- int change = 0;
spin_lock(&host->lock);
{
DBG("Card inserted\n");
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)
{
DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT;
- change = 1;
if (host->mrq)
{
host->mrq->cmd->error = MMC_ERR_FAILED;
tasklet_schedule(&host->finish_tasklet);
}
- }
-
- /*
- * Unlock first since we might get a call back.
- */
- spin_unlock(&host->lock);
+
+ /*
+ * Unlock first since we might get a call back.
+ */
+ spin_unlock(&host->lock);
- if (change)
mmc_detect_change(host->mmc);
+ }
}
static void wbsd_tasklet_fifo(unsigned long param)
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
* so this will be 64kB/512.
static void __devexit wbsd_free_mmc(struct device* dev)
{
struct mmc_host* mmc;
+ struct wbsd_host* host;
mmc = dev_get_drvdata(dev);
if (!mmc)
return;
+ host = mmc_priv(mmc);
+ BUG_ON(host == NULL);
+
+ del_timer_sync(&host->timer);
+
mmc_free_host(mmc);
dev_set_drvdata(dev, NULL);