sdhci: Split card-detection IRQs management from sdhci_init()
[safe/jmp/linux-2.6] / drivers / mmc / host / sdhci.c
index f52f305..bd5acfb 100644 (file)
@@ -48,35 +48,35 @@ static void sdhci_dumpregs(struct sdhci_host *host)
        printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
 
        printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
-               readl(host->ioaddr + SDHCI_DMA_ADDRESS),
-               readw(host->ioaddr + SDHCI_HOST_VERSION));
+               sdhci_readl(host, SDHCI_DMA_ADDRESS),
+               sdhci_readw(host, SDHCI_HOST_VERSION));
        printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
-               readw(host->ioaddr + SDHCI_BLOCK_SIZE),
-               readw(host->ioaddr + SDHCI_BLOCK_COUNT));
+               sdhci_readw(host, SDHCI_BLOCK_SIZE),
+               sdhci_readw(host, SDHCI_BLOCK_COUNT));
        printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_ARGUMENT),
-               readw(host->ioaddr + SDHCI_TRANSFER_MODE));
+               sdhci_readl(host, SDHCI_ARGUMENT),
+               sdhci_readw(host, SDHCI_TRANSFER_MODE));
        printk(KERN_DEBUG DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_PRESENT_STATE),
-               readb(host->ioaddr + SDHCI_HOST_CONTROL));
+               sdhci_readl(host, SDHCI_PRESENT_STATE),
+               sdhci_readb(host, SDHCI_HOST_CONTROL));
        printk(KERN_DEBUG DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
-               readb(host->ioaddr + SDHCI_POWER_CONTROL),
-               readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
+               sdhci_readb(host, SDHCI_POWER_CONTROL),
+               sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
        printk(KERN_DEBUG DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
-               readb(host->ioaddr + SDHCI_WAKE_UP_CONTROL),
-               readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
+               sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
+               sdhci_readw(host, SDHCI_CLOCK_CONTROL));
        printk(KERN_DEBUG DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
-               readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
-               readl(host->ioaddr + SDHCI_INT_STATUS));
+               sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
+               sdhci_readl(host, SDHCI_INT_STATUS));
        printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_INT_ENABLE),
-               readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
+               sdhci_readl(host, SDHCI_INT_ENABLE),
+               sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
        printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
-               readw(host->ioaddr + SDHCI_ACMD12_ERR),
-               readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
+               sdhci_readw(host, SDHCI_ACMD12_ERR),
+               sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
        printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Max curr: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_CAPABILITIES),
-               readl(host->ioaddr + SDHCI_MAX_CURRENT));
+               sdhci_readl(host, SDHCI_CAPABILITIES),
+               sdhci_readl(host, SDHCI_MAX_CURRENT));
 
        printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
 }
@@ -87,17 +87,58 @@ static void sdhci_dumpregs(struct sdhci_host *host)
  *                                                                           *
 \*****************************************************************************/
 
+static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
+{
+       u32 ier;
+
+       ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+       ier &= ~clear;
+       ier |= set;
+       sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+       sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
+{
+       sdhci_clear_set_irqs(host, 0, irqs);
+}
+
+static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
+{
+       sdhci_clear_set_irqs(host, irqs, 0);
+}
+
+static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
+{
+       u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
+
+       if (enable)
+               sdhci_unmask_irqs(host, irqs);
+       else
+               sdhci_mask_irqs(host, irqs);
+}
+
+static void sdhci_enable_card_detection(struct sdhci_host *host)
+{
+       sdhci_set_card_detection(host, true);
+}
+
+static void sdhci_disable_card_detection(struct sdhci_host *host)
+{
+       sdhci_set_card_detection(host, false);
+}
+
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
        unsigned long timeout;
 
        if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
-               if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+               if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
                        SDHCI_CARD_PRESENT))
                        return;
        }
 
-       writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
+       sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
 
        if (mask & SDHCI_RESET_ALL)
                host->clock = 0;
@@ -106,7 +147,7 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
        timeout = 100;
 
        /* hw clears the bit when it's done */
-       while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
+       while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
                if (timeout == 0) {
                        printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
                                mmc_hostname(host->mmc), (int)mask);
@@ -120,38 +161,39 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
 
 static void sdhci_init(struct sdhci_host *host)
 {
-       u32 intmask;
-
        sdhci_reset(host, SDHCI_RESET_ALL);
 
-       intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+       sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
+               SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
                SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
                SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
-               SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
                SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
                SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
-               SDHCI_INT_ADMA_ERROR;
+               SDHCI_INT_ADMA_ERROR);
+}
 
-       writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
-       writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
+static void sdhci_reinit(struct sdhci_host *host)
+{
+       sdhci_init(host);
+       sdhci_enable_card_detection(host);
 }
 
 static void sdhci_activate_led(struct sdhci_host *host)
 {
        u8 ctrl;
 
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
        ctrl |= SDHCI_CTRL_LED;
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 }
 
 static void sdhci_deactivate_led(struct sdhci_host *host)
 {
        u8 ctrl;
 
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
        ctrl &= ~SDHCI_CTRL_LED;
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 }
 
 #ifdef SDHCI_USE_LEDS_CLASS
@@ -205,7 +247,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
 
                while (len) {
                        if (chunk == 0) {
-                               scratch = readl(host->ioaddr + SDHCI_BUFFER);
+                               scratch = sdhci_readl(host, SDHCI_BUFFER);
                                chunk = 4;
                        }
 
@@ -257,7 +299,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
                        len--;
 
                        if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
-                               writel(scratch, host->ioaddr + SDHCI_BUFFER);
+                               sdhci_writel(host, scratch, SDHCI_BUFFER);
                                chunk = 0;
                                scratch = 0;
                        }
@@ -292,7 +334,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
                (host->data->blocks == 1))
                mask = ~0;
 
-       while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
+       while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
                if (host->data->flags & MMC_DATA_READ)
                        sdhci_read_block_pio(host);
                else
@@ -581,7 +623,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
        host->data_early = 0;
 
        count = sdhci_calc_timeout(host, data);
-       writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
+       sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
 
        if (host->flags & SDHCI_USE_DMA)
                host->flags |= SDHCI_REQ_USE_DMA;
@@ -661,8 +703,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
                                WARN_ON(1);
                                host->flags &= ~SDHCI_REQ_USE_DMA;
                        } else {
-                               writel(host->adma_addr,
-                                       host->ioaddr + SDHCI_ADMA_ADDRESS);
+                               sdhci_writel(host, host->adma_addr,
+                                       SDHCI_ADMA_ADDRESS);
                        }
                } else {
                        int sg_cnt;
@@ -681,8 +723,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
                                host->flags &= ~SDHCI_REQ_USE_DMA;
                        } else {
                                WARN_ON(sg_cnt != 1);
-                               writel(sg_dma_address(data->sg),
-                                       host->ioaddr + SDHCI_DMA_ADDRESS);
+                               sdhci_writel(host, sg_dma_address(data->sg),
+                                       SDHCI_DMA_ADDRESS);
                        }
                }
        }
@@ -693,14 +735,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
         * is ADMA.
         */
        if (host->version >= SDHCI_SPEC_200) {
-               ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+               ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
                ctrl &= ~SDHCI_CTRL_DMA_MASK;
                if ((host->flags & SDHCI_REQ_USE_DMA) &&
                        (host->flags & SDHCI_USE_ADMA))
                        ctrl |= SDHCI_CTRL_ADMA32;
                else
                        ctrl |= SDHCI_CTRL_SDMA;
-               writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+               sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
        }
 
        if (!(host->flags & SDHCI_REQ_USE_DMA)) {
@@ -710,9 +752,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
        }
 
        /* We do not handle DMA boundaries, so set it to max (512 KiB) */
-       writew(SDHCI_MAKE_BLKSZ(7, data->blksz),
-               host->ioaddr + SDHCI_BLOCK_SIZE);
-       writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
+       sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE);
+       sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
 }
 
 static void sdhci_set_transfer_mode(struct sdhci_host *host,
@@ -733,7 +774,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
        if (host->flags & SDHCI_REQ_USE_DMA)
                mode |= SDHCI_TRNS_DMA;
 
-       writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
+       sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
 }
 
 static void sdhci_finish_data(struct sdhci_host *host)
@@ -802,7 +843,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
        if (host->mrq->data && (cmd == host->mrq->data->stop))
                mask &= ~SDHCI_DATA_INHIBIT;
 
-       while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
+       while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
                if (timeout == 0) {
                        printk(KERN_ERR "%s: Controller never released "
                                "inhibit bit(s).\n", mmc_hostname(host->mmc));
@@ -821,7 +862,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 
        sdhci_prepare_data(host, cmd->data);
 
-       writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
+       sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
 
        sdhci_set_transfer_mode(host, cmd->data);
 
@@ -849,8 +890,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
        if (cmd->data)
                flags |= SDHCI_CMD_DATA;
 
-       writew(SDHCI_MAKE_CMD(cmd->opcode, flags),
-               host->ioaddr + SDHCI_COMMAND);
+       sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
 }
 
 static void sdhci_finish_command(struct sdhci_host *host)
@@ -863,15 +903,15 @@ static void sdhci_finish_command(struct sdhci_host *host)
                if (host->cmd->flags & MMC_RSP_136) {
                        /* CRC is stripped so we need to do some shifting. */
                        for (i = 0;i < 4;i++) {
-                               host->cmd->resp[i] = readl(host->ioaddr +
+                               host->cmd->resp[i] = sdhci_readl(host,
                                        SDHCI_RESPONSE + (3-i)*4) << 8;
                                if (i != 3)
                                        host->cmd->resp[i] |=
-                                               readb(host->ioaddr +
+                                               sdhci_readb(host,
                                                SDHCI_RESPONSE + (3-i)*4-1);
                        }
                } else {
-                       host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
+                       host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE);
                }
        }
 
@@ -895,7 +935,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        if (clock == host->clock)
                return;
 
-       writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
+       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
        if (clock == 0)
                goto out;
@@ -908,11 +948,11 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 
        clk = div << SDHCI_DIVIDER_SHIFT;
        clk |= SDHCI_CLOCK_INT_EN;
-       writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
        /* Wait max 10 ms */
        timeout = 10;
-       while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
+       while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
                & SDHCI_CLOCK_INT_STABLE)) {
                if (timeout == 0) {
                        printk(KERN_ERR "%s: Internal clock never "
@@ -925,7 +965,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        }
 
        clk |= SDHCI_CLOCK_CARD_EN;
-       writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
 out:
        host->clock = clock;
@@ -939,7 +979,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
                return;
 
        if (power == (unsigned short)-1) {
-               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
+               sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
                goto out;
        }
 
@@ -948,7 +988,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
         * a new value. Some controllers don't seem to like this though.
         */
        if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
-               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
+               sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 
        pwr = SDHCI_POWER_ON;
 
@@ -973,10 +1013,9 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
         * and set turn on power at the same time, so set the voltage first.
         */
        if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
-               writeb(pwr & ~SDHCI_POWER_ON,
-                               host->ioaddr + SDHCI_POWER_CONTROL);
+               sdhci_writeb(host, pwr & ~SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
 
-       writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
+       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
 out:
        host->power = power;
@@ -1005,7 +1044,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        host->mrq = mrq;
 
-       if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
+       if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
                || (host->flags & SDHCI_DEVICE_DEAD)) {
                host->mrq->cmd->error = -ENOMEDIUM;
                tasklet_schedule(&host->finish_tasklet);
@@ -1034,8 +1073,8 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
         * Should clear out any weird states.
         */
        if (ios->power_mode == MMC_POWER_OFF) {
-               writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
-               sdhci_init(host);
+               sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+               sdhci_reinit(host);
        }
 
        sdhci_set_clock(host, ios->clock);
@@ -1045,7 +1084,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        else
                sdhci_set_power(host, ios->vdd);
 
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 
        if (ios->bus_width == MMC_BUS_WIDTH_4)
                ctrl |= SDHCI_CTRL_4BITBUS;
@@ -1057,7 +1096,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        else
                ctrl &= ~SDHCI_CTRL_HISPD;
 
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
        /*
         * Some (ENE) controllers go apeshit on some ios operation,
@@ -1085,7 +1124,7 @@ static int sdhci_get_ro(struct mmc_host *mmc)
        if (host->flags & SDHCI_DEVICE_DEAD)
                present = 0;
        else
-               present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
+               present = sdhci_readl(host, SDHCI_PRESENT_STATE);
 
        spin_unlock_irqrestore(&host->lock, flags);
 
@@ -1096,7 +1135,6 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
        struct sdhci_host *host;
        unsigned long flags;
-       u32 ier;
 
        host = mmc_priv(mmc);
 
@@ -1105,15 +1143,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
        if (host->flags & SDHCI_DEVICE_DEAD)
                goto out;
 
-       ier = readl(host->ioaddr + SDHCI_INT_ENABLE);
-
-       ier &= ~SDHCI_INT_CARD_INT;
        if (enable)
-               ier |= SDHCI_INT_CARD_INT;
-
-       writel(ier, host->ioaddr + SDHCI_INT_ENABLE);
-       writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
-
+               sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
+       else
+               sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
 out:
        mmiowb();
 
@@ -1142,7 +1175,7 @@ static void sdhci_tasklet_card(unsigned long param)
 
        spin_lock_irqsave(&host->lock, flags);
 
-       if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+       if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
                if (host->mrq) {
                        printk(KERN_ERR "%s: Card removed during transfer!\n",
                                mmc_hostname(host->mmc));
@@ -1291,8 +1324,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
                if (host->cmd->data)
                        DBG("Cannot wait for busy signal when also "
                                "doing a data transfer");
-               else
+               else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ))
                        return;
+
+               /* The controller does not support the end-of-busy IRQ,
+                * fall through and take the SDHCI_INT_RESPONSE */
        }
 
        if (intmask & SDHCI_INT_RESPONSE)
@@ -1343,8 +1379,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                 * we need to at least restart the transfer.
                 */
                if (intmask & SDHCI_INT_DMA_END)
-                       writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
-                               host->ioaddr + SDHCI_DMA_ADDRESS);
+                       sdhci_writel(host, sdhci_readl(host, SDHCI_DMA_ADDRESS),
+                               SDHCI_DMA_ADDRESS);
 
                if (intmask & SDHCI_INT_DATA_END) {
                        if (host->cmd) {
@@ -1370,7 +1406,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 
        spin_lock(&host->lock);
 
-       intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
+       intmask = sdhci_readl(host, SDHCI_INT_STATUS);
 
        if (!intmask || intmask == 0xffffffff) {
                result = IRQ_NONE;
@@ -1381,22 +1417,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                mmc_hostname(host->mmc), intmask);
 
        if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-               writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
-                       host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
+                       SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
                tasklet_schedule(&host->card_tasklet);
        }
 
        intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
 
        if (intmask & SDHCI_INT_CMD_MASK) {
-               writel(intmask & SDHCI_INT_CMD_MASK,
-                       host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
+                       SDHCI_INT_STATUS);
                sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
        }
 
        if (intmask & SDHCI_INT_DATA_MASK) {
-               writel(intmask & SDHCI_INT_DATA_MASK,
-                       host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
+                       SDHCI_INT_STATUS);
                sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
        }
 
@@ -1407,7 +1443,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
        if (intmask & SDHCI_INT_BUS_POWER) {
                printk(KERN_ERR "%s: Card is consuming too much power!\n",
                        mmc_hostname(host->mmc));
-               writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
        }
 
        intmask &= ~SDHCI_INT_BUS_POWER;
@@ -1422,7 +1458,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                        mmc_hostname(host->mmc), intmask);
                sdhci_dumpregs(host);
 
-               writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_writel(host, intmask, SDHCI_INT_STATUS);
        }
 
        result = IRQ_HANDLED;
@@ -1452,6 +1488,8 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
 {
        int ret;
 
+       sdhci_disable_card_detection(host);
+
        ret = mmc_suspend_host(host->mmc, state);
        if (ret)
                return ret;
@@ -1484,6 +1522,8 @@ int sdhci_resume_host(struct sdhci_host *host)
        if (ret)
                return ret;
 
+       sdhci_enable_card_detection(host);
+
        return 0;
 }
 
@@ -1534,7 +1574,7 @@ int sdhci_add_host(struct sdhci_host *host)
 
        sdhci_reset(host, SDHCI_RESET_ALL);
 
-       host->version = readw(host->ioaddr + SDHCI_HOST_VERSION);
+       host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
        host->version = (host->version & SDHCI_SPEC_VER_MASK)
                                >> SDHCI_SPEC_VER_SHIFT;
        if (host->version > SDHCI_SPEC_200) {
@@ -1543,7 +1583,7 @@ int sdhci_add_host(struct sdhci_host *host)
                        host->version);
        }
 
-       caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+       caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_DMA;
@@ -1743,6 +1783,8 @@ int sdhci_add_host(struct sdhci_host *host)
                (host->flags & SDHCI_USE_ADMA)?"A":"",
                (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
 
+       sdhci_enable_card_detection(host);
+
        return 0;
 
 #ifdef SDHCI_USE_LEDS_CLASS
@@ -1779,6 +1821,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
                spin_unlock_irqrestore(&host->lock, flags);
        }
 
+       sdhci_disable_card_detection(host);
+
        mmc_remove_host(host->mmc);
 
 #ifdef SDHCI_USE_LEDS_CLASS