--- /dev/null
+diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
+index eeac479..7913cd8 100644
+--- a/drivers/mmc/host/atmel-mci.c
++++ b/drivers/mmc/host/atmel-mci.c
+@@ -39,7 +39,6 @@ enum {
+ EVENT_STOP_COMPLETE,
+ EVENT_DMA_COMPLETE,
+ EVENT_DMA_ERROR,
+- EVENT_CARD_DETECT,
+ };
+
+ struct atmel_mci_dma {
+@@ -70,6 +69,9 @@ struct atmel_mci {
+ int detect_pin;
+ int wp_pin;
+
++ /* For detect pin debouncing */
++ struct timer_list detect_timer;
++
+ unsigned long bus_hz;
+ unsigned long mapbase;
+ struct clk *mck;
+@@ -108,8 +110,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+ test_bit(EVENT_DMA_COMPLETE, &host->completed_events)
+ #define mci_dma_error_is_complete(host) \
+ test_bit(EVENT_DMA_ERROR, &host->completed_events)
+-#define mci_card_detect_is_complete(host) \
+- test_bit(EVENT_CARD_DETECT, &host->completed_events)
+
+ /* Test and clear bit macros for pending events */
+ #define mci_clear_cmd_is_pending(host) \
+@@ -124,8 +124,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+ test_and_clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
+ #define mci_clear_dma_error_is_pending(host) \
+ test_and_clear_bit(EVENT_DMA_ERROR, &host->pending_events)
+-#define mci_clear_card_detect_is_pending(host) \
+- test_and_clear_bit(EVENT_CARD_DETECT, &host->pending_events)
+
+ /* Test and set bit macros for completed events */
+ #define mci_set_cmd_is_completed(host) \
+@@ -140,8 +138,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+ test_and_set_bit(EVENT_STOP_COMPLETE, &host->completed_events)
+ #define mci_set_dma_error_is_completed(host) \
+ test_and_set_bit(EVENT_DMA_ERROR, &host->completed_events)
+-#define mci_set_card_detect_is_completed(host) \
+- test_and_set_bit(EVENT_CARD_DETECT, &host->completed_events)
+
+ /* Set bit macros for completed events */
+ #define mci_set_cmd_complete(host) \
+@@ -158,8 +154,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+ set_bit(EVENT_DMA_COMPLETE, &host->completed_events)
+ #define mci_set_dma_error_complete(host) \
+ set_bit(EVENT_DMA_ERROR, &host->completed_events)
+-#define mci_set_card_detect_complete(host) \
+- set_bit(EVENT_CARD_DETECT, &host->completed_events)
+
+ /* Set bit macros for pending events */
+ #define mci_set_cmd_pending(host) \
+@@ -174,8 +168,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+ set_bit(EVENT_STOP_COMPLETE, &host->pending_events)
+ #define mci_set_dma_error_pending(host) \
+ set_bit(EVENT_DMA_ERROR, &host->pending_events)
+-#define mci_set_card_detect_pending(host) \
+- set_bit(EVENT_CARD_DETECT, &host->pending_events)
+
+ /* Clear bit macros for pending events */
+ #define mci_clear_cmd_pending(host) \
+@@ -190,8 +182,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+ clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
+ #define mci_clear_dma_error_pending(host) \
+ clear_bit(EVENT_DMA_ERROR, &host->pending_events)
+-#define mci_clear_card_detect_pending(host) \
+- clear_bit(EVENT_CARD_DETECT, &host->pending_events)
+
+
+ #ifdef CONFIG_DEBUG_FS
+@@ -560,6 +550,21 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ mci_readl(host, IMR));
+
+ WARN_ON(host->mrq != NULL);
++
++ /*
++ * We may "know" the card is gone even though there's still an
++ * electrical connection. If so, we really need to communicate
++ * this to the MMC core since there won't be any more
++ * interrupts as the card is completely removed. Otherwise,
++ * the MMC core might believe the card is still there even
++ * though the card was just removed very slowly.
++ */
++ if (!host->present) {
++ mrq->cmd->error = -ENOMEDIUM;
++ mmc_request_done(mmc, mrq);
++ return;
++ }
++
+ host->mrq = mrq;
+ host->pending_events = 0;
+ host->completed_events = 0;
+@@ -729,6 +734,61 @@ static void atmci_command_complete(struct atmel_mci *host,
+ }
+ }
+
++static void atmci_detect_change(unsigned long data)
++{
++ struct atmel_mci *host = (struct atmel_mci *)data;
++ struct mmc_request *mrq = host->mrq;
++ int present;
++
++ /*
++ * atmci_remove() sets detect_pin to -1 before freeing the
++ * interrupt. We must not re-enable the interrupt if it has
++ * been freed.
++ */
++ smp_rmb();
++ if (host->detect_pin < 0)
++ return;
++
++ enable_irq(gpio_to_irq(host->detect_pin));
++ present = !gpio_get_value(host->detect_pin);
++
++ dev_vdbg(&host->pdev->dev, "detect change: %d (was %d)\n",
++ present, host->present);
++
++ if (present != host->present) {
++ dev_dbg(&host->mmc->class_dev, "card %s\n",
++ present ? "inserted" : "removed");
++ host->present = present;
++
++ /* Reset controller if card is gone */
++ if (!present) {
++ mci_writel(host, CR, MCI_BIT(SWRST));
++ mci_writel(host, IDR, ~0UL);
++ mci_writel(host, CR, MCI_BIT(MCIEN));
++ }
++
++ /* Clean up queue if present */
++ if (mrq) {
++ if (!mci_cmd_is_complete(host))
++ mrq->cmd->error = -ENOMEDIUM;
++ if (mrq->data && !mci_data_is_complete(host)
++ && !mci_data_error_is_complete(host)) {
++ dma_stop_request(host->dma.req.req.dmac,
++ host->dma.req.req.channel);
++ host->data->error = -ENOMEDIUM;
++ atmci_data_complete(host, host->data);
++ }
++ if (mrq->stop && !mci_stop_is_complete(host))
++ mrq->stop->error = -ENOMEDIUM;
++
++ host->cmd = NULL;
++ atmci_request_end(host->mmc, mrq);
++ }
++
++ mmc_detect_change(host->mmc, 0);
++ }
++}
++
+ static void atmci_tasklet_func(unsigned long priv)
+ {
+ struct mmc_host *mmc = (struct mmc_host *)priv;
+@@ -806,33 +866,6 @@ static void atmci_tasklet_func(unsigned long priv)
+ data->bytes_xfered = data->blocks * data->blksz;
+ atmci_data_complete(host, data);
+ }
+- if (mci_clear_card_detect_is_pending(host)) {
+- /* Reset controller if card is gone */
+- if (!host->present) {
+- mci_writel(host, CR, MCI_BIT(SWRST));
+- mci_writel(host, IDR, ~0UL);
+- mci_writel(host, CR, MCI_BIT(MCIEN));
+- }
+-
+- /* Clean up queue if present */
+- if (mrq) {
+- if (!mci_cmd_is_complete(host))
+- mrq->cmd->error = -ETIMEDOUT;
+- if (mrq->data && !mci_data_is_complete(host)
+- && !mci_data_error_is_complete(host)) {
+- dma_stop_request(host->dma.req.req.dmac,
+- host->dma.req.req.channel);
+- host->data->error = -ETIMEDOUT;
+- atmci_data_complete(host, data);
+- }
+- if (mrq->stop && !mci_stop_is_complete(host))
+- mrq->stop->error = -ETIMEDOUT;
+-
+- host->cmd = NULL;
+- atmci_request_end(mmc, mrq);
+- }
+- mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+- }
+ }
+
+ static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
+@@ -957,20 +990,19 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-static irqreturn_t atmci_detect_change(int irq, void *dev_id)
++static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
+ {
+ struct mmc_host *mmc = dev_id;
+ struct atmel_mci *host = mmc_priv(mmc);
+
+- int present = !gpio_get_value(irq_to_gpio(irq));
++ /*
++ * Disable interrupts until the pin has stabilized and check
++ * the state then. Use mod_timer() since we may be in the
++ * middle of the timer routine when this interrupt triggers.
++ */
++ disable_irq_nosync(irq);
++ mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20));
+
+- if (present != host->present) {
+- dev_dbg(&mmc->class_dev, "card %s\n",
+- present ? "inserted" : "removed");
+- host->present = present;
+- mci_set_card_detect_pending(host);
+- tasklet_schedule(&host->tasklet);
+- }
+ return IRQ_HANDLED;
+ }
+
+@@ -1079,8 +1111,11 @@ static int __devinit atmci_probe(struct platform_device *pdev)
+ mmc_add_host(mmc);
+
+ if (host->detect_pin >= 0) {
++ setup_timer(&host->detect_timer, atmci_detect_change,
++ (unsigned long)host);
++
+ ret = request_irq(gpio_to_irq(host->detect_pin),
+- atmci_detect_change,
++ atmci_detect_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ DRIVER_NAME, mmc);
+ if (ret) {
+@@ -1125,9 +1160,16 @@ static int __devexit atmci_remove(struct platform_device *pdev)
+ atmci_cleanup_debugfs(host);
+
+ if (host->detect_pin >= 0) {
+- free_irq(gpio_to_irq(host->detect_pin), host->mmc);
++ int pin = host->detect_pin;
++
++ /* Make sure our timer doesn't enable the interrupt */
++ host->detect_pin = -1;
++ smp_wmb();
++
++ free_irq(gpio_to_irq(pin), host->mmc);
++ del_timer_sync(&host->detect_timer);
+ cancel_delayed_work(&host->mmc->detect);
+- gpio_free(host->detect_pin);
++ gpio_free(pin);
+ }
+
+ mmc_remove_host(host->mmc);
+++ /dev/null
-diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
-index eeac479..7913cd8 100644
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -39,7 +39,6 @@ enum {
- EVENT_STOP_COMPLETE,
- EVENT_DMA_COMPLETE,
- EVENT_DMA_ERROR,
-- EVENT_CARD_DETECT,
- };
-
- struct atmel_mci_dma {
-@@ -70,6 +69,9 @@ struct atmel_mci {
- int detect_pin;
- int wp_pin;
-
-+ /* For detect pin debouncing */
-+ struct timer_list detect_timer;
-+
- unsigned long bus_hz;
- unsigned long mapbase;
- struct clk *mck;
-@@ -108,8 +110,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
- test_bit(EVENT_DMA_COMPLETE, &host->completed_events)
- #define mci_dma_error_is_complete(host) \
- test_bit(EVENT_DMA_ERROR, &host->completed_events)
--#define mci_card_detect_is_complete(host) \
-- test_bit(EVENT_CARD_DETECT, &host->completed_events)
-
- /* Test and clear bit macros for pending events */
- #define mci_clear_cmd_is_pending(host) \
-@@ -124,8 +124,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
- test_and_clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
- #define mci_clear_dma_error_is_pending(host) \
- test_and_clear_bit(EVENT_DMA_ERROR, &host->pending_events)
--#define mci_clear_card_detect_is_pending(host) \
-- test_and_clear_bit(EVENT_CARD_DETECT, &host->pending_events)
-
- /* Test and set bit macros for completed events */
- #define mci_set_cmd_is_completed(host) \
-@@ -140,8 +138,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
- test_and_set_bit(EVENT_STOP_COMPLETE, &host->completed_events)
- #define mci_set_dma_error_is_completed(host) \
- test_and_set_bit(EVENT_DMA_ERROR, &host->completed_events)
--#define mci_set_card_detect_is_completed(host) \
-- test_and_set_bit(EVENT_CARD_DETECT, &host->completed_events)
-
- /* Set bit macros for completed events */
- #define mci_set_cmd_complete(host) \
-@@ -158,8 +154,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
- set_bit(EVENT_DMA_COMPLETE, &host->completed_events)
- #define mci_set_dma_error_complete(host) \
- set_bit(EVENT_DMA_ERROR, &host->completed_events)
--#define mci_set_card_detect_complete(host) \
-- set_bit(EVENT_CARD_DETECT, &host->completed_events)
-
- /* Set bit macros for pending events */
- #define mci_set_cmd_pending(host) \
-@@ -174,8 +168,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
- set_bit(EVENT_STOP_COMPLETE, &host->pending_events)
- #define mci_set_dma_error_pending(host) \
- set_bit(EVENT_DMA_ERROR, &host->pending_events)
--#define mci_set_card_detect_pending(host) \
-- set_bit(EVENT_CARD_DETECT, &host->pending_events)
-
- /* Clear bit macros for pending events */
- #define mci_clear_cmd_pending(host) \
-@@ -190,8 +182,6 @@ MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
- clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
- #define mci_clear_dma_error_pending(host) \
- clear_bit(EVENT_DMA_ERROR, &host->pending_events)
--#define mci_clear_card_detect_pending(host) \
-- clear_bit(EVENT_CARD_DETECT, &host->pending_events)
-
-
- #ifdef CONFIG_DEBUG_FS
-@@ -560,6 +550,21 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
- mci_readl(host, IMR));
-
- WARN_ON(host->mrq != NULL);
-+
-+ /*
-+ * We may "know" the card is gone even though there's still an
-+ * electrical connection. If so, we really need to communicate
-+ * this to the MMC core since there won't be any more
-+ * interrupts as the card is completely removed. Otherwise,
-+ * the MMC core might believe the card is still there even
-+ * though the card was just removed very slowly.
-+ */
-+ if (!host->present) {
-+ mrq->cmd->error = -ENOMEDIUM;
-+ mmc_request_done(mmc, mrq);
-+ return;
-+ }
-+
- host->mrq = mrq;
- host->pending_events = 0;
- host->completed_events = 0;
-@@ -729,6 +734,61 @@ static void atmci_command_complete(struct atmel_mci *host,
- }
- }
-
-+static void atmci_detect_change(unsigned long data)
-+{
-+ struct atmel_mci *host = (struct atmel_mci *)data;
-+ struct mmc_request *mrq = host->mrq;
-+ int present;
-+
-+ /*
-+ * atmci_remove() sets detect_pin to -1 before freeing the
-+ * interrupt. We must not re-enable the interrupt if it has
-+ * been freed.
-+ */
-+ smp_rmb();
-+ if (host->detect_pin < 0)
-+ return;
-+
-+ enable_irq(gpio_to_irq(host->detect_pin));
-+ present = !gpio_get_value(host->detect_pin);
-+
-+ dev_vdbg(&host->pdev->dev, "detect change: %d (was %d)\n",
-+ present, host->present);
-+
-+ if (present != host->present) {
-+ dev_dbg(&host->mmc->class_dev, "card %s\n",
-+ present ? "inserted" : "removed");
-+ host->present = present;
-+
-+ /* Reset controller if card is gone */
-+ if (!present) {
-+ mci_writel(host, CR, MCI_BIT(SWRST));
-+ mci_writel(host, IDR, ~0UL);
-+ mci_writel(host, CR, MCI_BIT(MCIEN));
-+ }
-+
-+ /* Clean up queue if present */
-+ if (mrq) {
-+ if (!mci_cmd_is_complete(host))
-+ mrq->cmd->error = -ENOMEDIUM;
-+ if (mrq->data && !mci_data_is_complete(host)
-+ && !mci_data_error_is_complete(host)) {
-+ dma_stop_request(host->dma.req.req.dmac,
-+ host->dma.req.req.channel);
-+ host->data->error = -ENOMEDIUM;
-+ atmci_data_complete(host, host->data);
-+ }
-+ if (mrq->stop && !mci_stop_is_complete(host))
-+ mrq->stop->error = -ENOMEDIUM;
-+
-+ host->cmd = NULL;
-+ atmci_request_end(host->mmc, mrq);
-+ }
-+
-+ mmc_detect_change(host->mmc, 0);
-+ }
-+}
-+
- static void atmci_tasklet_func(unsigned long priv)
- {
- struct mmc_host *mmc = (struct mmc_host *)priv;
-@@ -806,33 +866,6 @@ static void atmci_tasklet_func(unsigned long priv)
- data->bytes_xfered = data->blocks * data->blksz;
- atmci_data_complete(host, data);
- }
-- if (mci_clear_card_detect_is_pending(host)) {
-- /* Reset controller if card is gone */
-- if (!host->present) {
-- mci_writel(host, CR, MCI_BIT(SWRST));
-- mci_writel(host, IDR, ~0UL);
-- mci_writel(host, CR, MCI_BIT(MCIEN));
-- }
--
-- /* Clean up queue if present */
-- if (mrq) {
-- if (!mci_cmd_is_complete(host))
-- mrq->cmd->error = -ETIMEDOUT;
-- if (mrq->data && !mci_data_is_complete(host)
-- && !mci_data_error_is_complete(host)) {
-- dma_stop_request(host->dma.req.req.dmac,
-- host->dma.req.req.channel);
-- host->data->error = -ETIMEDOUT;
-- atmci_data_complete(host, data);
-- }
-- if (mrq->stop && !mci_stop_is_complete(host))
-- mrq->stop->error = -ETIMEDOUT;
--
-- host->cmd = NULL;
-- atmci_request_end(mmc, mrq);
-- }
-- mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-- }
- }
-
- static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
-@@ -957,20 +990,19 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
- return IRQ_HANDLED;
- }
-
--static irqreturn_t atmci_detect_change(int irq, void *dev_id)
-+static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
- {
- struct mmc_host *mmc = dev_id;
- struct atmel_mci *host = mmc_priv(mmc);
-
-- int present = !gpio_get_value(irq_to_gpio(irq));
-+ /*
-+ * Disable interrupts until the pin has stabilized and check
-+ * the state then. Use mod_timer() since we may be in the
-+ * middle of the timer routine when this interrupt triggers.
-+ */
-+ disable_irq_nosync(irq);
-+ mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20));
-
-- if (present != host->present) {
-- dev_dbg(&mmc->class_dev, "card %s\n",
-- present ? "inserted" : "removed");
-- host->present = present;
-- mci_set_card_detect_pending(host);
-- tasklet_schedule(&host->tasklet);
-- }
- return IRQ_HANDLED;
- }
-
-@@ -1079,8 +1111,11 @@ static int __devinit atmci_probe(struct platform_device *pdev)
- mmc_add_host(mmc);
-
- if (host->detect_pin >= 0) {
-+ setup_timer(&host->detect_timer, atmci_detect_change,
-+ (unsigned long)host);
-+
- ret = request_irq(gpio_to_irq(host->detect_pin),
-- atmci_detect_change,
-+ atmci_detect_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- DRIVER_NAME, mmc);
- if (ret) {
-@@ -1125,9 +1160,16 @@ static int __devexit atmci_remove(struct platform_device *pdev)
- atmci_cleanup_debugfs(host);
-
- if (host->detect_pin >= 0) {
-- free_irq(gpio_to_irq(host->detect_pin), host->mmc);
-+ int pin = host->detect_pin;
-+
-+ /* Make sure our timer doesn't enable the interrupt */
-+ host->detect_pin = -1;
-+ smp_wmb();
-+
-+ free_irq(gpio_to_irq(pin), host->mmc);
-+ del_timer_sync(&host->detect_timer);
- cancel_delayed_work(&host->mmc->detect);
-- gpio_free(host->detect_pin);
-+ gpio_free(pin);
- }
-
- mmc_remove_host(host->mmc);