--- a/drivers/mmc/host/atmel-mci.c 2011-02-02 08:09:41.938080192 +0100 +++ b/drivers/mmc/host/atmel-mci.c 2011-02-02 08:11:17.461455343 +0100 @@ -191,6 +191,7 @@ struct atmel_mci *host; u32 sdc_reg; + u32 sdio_irq; struct mmc_request *mrq; struct list_head queue_node; @@ -790,11 +791,19 @@ } mci_writel(host, SDCR, slot->sdc_reg); + /* The DMA engine will leave some MCI interrupts enabled after a + * data transfer, so we can't be sure that all interrupts are disabled + * at this point. Also note that the SDIO interrupt is controlled + * through enable_sdio_irq(), so we can't be sure about that one + * either. + */ +#ifndef CONFIG_MMC_ATMELMCI_DMA iflags = mci_readl(host, IMR); - if (iflags) + if (iflags & ~slot->sdio_irq) dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", iflags); - +#endif + if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { /* Send init sequence (74 clock cycles) */ mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT); @@ -1064,11 +1073,23 @@ return present; } +static void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct atmel_mci_slot *slot = mmc_priv(mmc); + struct atmel_mci *host = slot->host; + + if (enable) + mci_writel(host, IER, slot->sdio_irq); + else + mci_writel(host, IDR, slot->sdio_irq); +} + static const struct mmc_host_ops atmci_ops = { .request = atmci_request, .set_ios = atmci_set_ios, .get_ro = atmci_get_ro, .get_cd = atmci_get_cd, + .enable_sdio_irq = atmci_enable_sdio_irq, }; /* Called with host->lock held */ @@ -1523,6 +1544,7 @@ struct atmel_mci *host = dev_id; u32 status, mask, pending; unsigned int pass_count = 0; + unsigned int i; do { status = mci_readl(host, SR); @@ -1557,6 +1579,14 @@ if (pending & MCI_CMDRDY) atmci_cmd_interrupt(host, status); + + for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + struct atmel_mci_slot *slot = host->slot[i]; + if (slot && (pending & slot->sdio_irq)) + mmc_signal_sdio_irq(slot->mmc); + } + + } while (pass_count++ < 5); return pass_count ? IRQ_HANDLED : IRQ_NONE; @@ -1579,7 +1609,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, struct mci_slot_pdata *slot_data, unsigned int id, - u32 sdc_reg) + u32 sdc_reg, u32 sdio_irq) { struct mmc_host *mmc; struct atmel_mci_slot *slot; @@ -1594,11 +1624,14 @@ slot->detect_pin = slot_data->detect_pin; slot->wp_pin = slot_data->wp_pin; slot->sdc_reg = sdc_reg; + slot->sdio_irq = sdio_irq; mmc->ops = &atmci_ops; mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); mmc->f_max = host->bus_hz / 2; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + if (sdio_irq) + mmc->caps |= MMC_CAP_SDIO_IRQ; #if defined(AT91_HSMODE) if (atmci_is_mci2()) mmc->caps |= MMC_CAP_SD_HIGHSPEED; @@ -1816,13 +1849,13 @@ ret = -ENODEV; if (pdata->slot[0].bus_width) { ret = atmci_init_slot(host, &pdata->slot[0], - MCI_SDCSEL_SLOT_A, 0); + 0, MCI_SDCSEL_SLOT_A, MCI_SDIOIRQA); if (!ret) nr_slots++; } if (pdata->slot[1].bus_width) { ret = atmci_init_slot(host, &pdata->slot[1], - MCI_SDCSEL_SLOT_B, 1); + 1, MCI_SDCSEL_SLOT_B, MCI_SDIOIRQB); if (!ret) nr_slots++; }