diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 745 |
1 files changed, 487 insertions, 258 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 0e3d7c0..cd65d47 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -45,65 +45,62 @@ static unsigned int debug_quirks2; static void sdhci_finish_data(struct sdhci_host *); -static void sdhci_finish_command(struct sdhci_host *); -static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); -static int sdhci_get_cd(struct mmc_host *mmc); static void sdhci_dumpregs(struct sdhci_host *host) { - pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", - mmc_hostname(host->mmc)); - - pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", - sdhci_readl(host, SDHCI_DMA_ADDRESS), - sdhci_readw(host, SDHCI_HOST_VERSION)); - pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", - sdhci_readw(host, SDHCI_BLOCK_SIZE), - sdhci_readw(host, SDHCI_BLOCK_COUNT)); - pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", - sdhci_readl(host, SDHCI_ARGUMENT), - sdhci_readw(host, SDHCI_TRANSFER_MODE)); - pr_debug(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", - sdhci_readl(host, SDHCI_PRESENT_STATE), - sdhci_readb(host, SDHCI_HOST_CONTROL)); - pr_debug(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", - sdhci_readb(host, SDHCI_POWER_CONTROL), - sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); - pr_debug(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", - sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), - sdhci_readw(host, SDHCI_CLOCK_CONTROL)); - pr_debug(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", - sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), - sdhci_readl(host, SDHCI_INT_STATUS)); - pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", - sdhci_readl(host, SDHCI_INT_ENABLE), - sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); - pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", - sdhci_readw(host, SDHCI_ACMD12_ERR), - sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); - pr_debug(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n", - sdhci_readl(host, SDHCI_CAPABILITIES), - sdhci_readl(host, SDHCI_CAPABILITIES_1)); - pr_debug(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n", - sdhci_readw(host, SDHCI_COMMAND), - sdhci_readl(host, SDHCI_MAX_CURRENT)); - pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n", - sdhci_readw(host, SDHCI_HOST_CONTROL2)); + pr_err(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", + mmc_hostname(host->mmc)); + + pr_err(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", + sdhci_readl(host, SDHCI_DMA_ADDRESS), + sdhci_readw(host, SDHCI_HOST_VERSION)); + pr_err(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", + sdhci_readw(host, SDHCI_BLOCK_SIZE), + sdhci_readw(host, SDHCI_BLOCK_COUNT)); + pr_err(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", + sdhci_readl(host, SDHCI_ARGUMENT), + sdhci_readw(host, SDHCI_TRANSFER_MODE)); + pr_err(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", + sdhci_readl(host, SDHCI_PRESENT_STATE), + sdhci_readb(host, SDHCI_HOST_CONTROL)); + pr_err(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", + sdhci_readb(host, SDHCI_POWER_CONTROL), + sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); + pr_err(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", + sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), + sdhci_readw(host, SDHCI_CLOCK_CONTROL)); + pr_err(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", + sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), + sdhci_readl(host, SDHCI_INT_STATUS)); + pr_err(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", + sdhci_readl(host, SDHCI_INT_ENABLE), + sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); + pr_err(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", + sdhci_readw(host, SDHCI_ACMD12_ERR), + sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); + pr_err(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n", + sdhci_readl(host, SDHCI_CAPABILITIES), + sdhci_readl(host, SDHCI_CAPABILITIES_1)); + pr_err(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n", + sdhci_readw(host, SDHCI_COMMAND), + sdhci_readl(host, SDHCI_MAX_CURRENT)); + pr_err(DRIVER_NAME ": Host ctl2: 0x%08x\n", + sdhci_readw(host, SDHCI_HOST_CONTROL2)); if (host->flags & SDHCI_USE_ADMA) { if (host->flags & SDHCI_USE_64_BIT_DMA) - pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n", - readl(host->ioaddr + SDHCI_ADMA_ERROR), - readl(host->ioaddr + SDHCI_ADMA_ADDRESS_HI), - readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); + pr_err(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n", + readl(host->ioaddr + SDHCI_ADMA_ERROR), + readl(host->ioaddr + SDHCI_ADMA_ADDRESS_HI), + readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); else - pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", - readl(host->ioaddr + SDHCI_ADMA_ERROR), - readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); + pr_err(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", + readl(host->ioaddr + SDHCI_ADMA_ERROR), + readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); } - pr_debug(DRIVER_NAME ": ===========================================\n"); + pr_err(DRIVER_NAME ": ===========================================\n"); } /*****************************************************************************\ @@ -112,12 +109,17 @@ static void sdhci_dumpregs(struct sdhci_host *host) * * \*****************************************************************************/ +static inline bool sdhci_data_line_cmd(struct mmc_command *cmd) +{ + return cmd->data || cmd->flags & MMC_RSP_BUSY; +} + static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) { u32 present; if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || - (host->mmc->caps & MMC_CAP_NONREMOVABLE)) + !mmc_card_is_removable(host->mmc)) return; if (enable) { @@ -193,7 +195,9 @@ EXPORT_SYMBOL_GPL(sdhci_reset); static void sdhci_do_reset(struct sdhci_host *host, u8 mask) { if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { - if (!sdhci_get_cd(host->mmc)) + struct mmc_host *mmc = host->mmc; + + if (!mmc->ops->get_cd(mmc)) return; } @@ -210,10 +214,10 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) } } -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); - static void sdhci_init(struct sdhci_host *host, int soft) { + struct mmc_host *mmc = host->mmc; + if (soft) sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); else @@ -225,13 +229,17 @@ static void sdhci_init(struct sdhci_host *host, int soft) SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE; + if (host->tuning_mode == SDHCI_TUNING_MODE_2 || + host->tuning_mode == SDHCI_TUNING_MODE_3) + host->ier |= SDHCI_INT_RETUNE; + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); if (soft) { /* force clock reconfiguration */ host->clock = 0; - sdhci_set_ios(host->mmc, &host->mmc->ios); + mmc->ops->set_ios(mmc, &mmc->ios); } } @@ -429,8 +437,6 @@ static void sdhci_transfer_pio(struct sdhci_host *host) { u32 mask; - BUG_ON(!host->data); - if (host->blocks == 0) return; @@ -747,14 +753,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) u8 ctrl; struct mmc_data *data = cmd->data; - WARN_ON(host->data); - - if (data || (cmd->flags & MMC_RSP_BUSY)) + if (sdhci_data_line_cmd(cmd)) sdhci_set_timeout(host, cmd); if (!data) return; + WARN_ON(host->data); + /* Sanity checks */ BUG_ON(data->blksz * data->blocks > 524288); BUG_ON(data->blksz > host->mmc->max_blk_size); @@ -879,6 +885,12 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); } +static inline bool sdhci_auto_cmd12(struct sdhci_host *host, + struct mmc_request *mrq) +{ + return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12); +} + static void sdhci_set_transfer_mode(struct sdhci_host *host, struct mmc_command *cmd) { @@ -909,12 +921,12 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, * If we are sending CMD23, CMD12 never gets sent * on successful completion (so no Auto-CMD12). */ - if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && + if (sdhci_auto_cmd12(host, cmd->mrq) && (cmd->opcode != SD_IO_RW_EXTENDED)) mode |= SDHCI_TRNS_AUTO_CMD12; - else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { + else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { mode |= SDHCI_TRNS_AUTO_CMD23; - sdhci_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2); + sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); } } @@ -926,14 +938,63 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); } -static void sdhci_finish_data(struct sdhci_host *host) +static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) +{ + return (!(host->flags & SDHCI_DEVICE_DEAD) && + ((mrq->cmd && mrq->cmd->error) || + (mrq->sbc && mrq->sbc->error) || + (mrq->data && ((mrq->data->error && !mrq->data->stop) || + (mrq->data->stop && mrq->data->stop->error))) || + (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); +} + +static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) +{ + int i; + + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + if (host->mrqs_done[i] == mrq) { + WARN_ON(1); + return; + } + } + + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + if (!host->mrqs_done[i]) { + host->mrqs_done[i] = mrq; + break; + } + } + + WARN_ON(i >= SDHCI_MAX_MRQS); + + tasklet_schedule(&host->finish_tasklet); +} + +static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) { - struct mmc_data *data; + if (host->cmd && host->cmd->mrq == mrq) + host->cmd = NULL; + + if (host->data_cmd && host->data_cmd->mrq == mrq) + host->data_cmd = NULL; + + if (host->data && host->data->mrq == mrq) + host->data = NULL; - BUG_ON(!host->data); + if (sdhci_needs_reset(host, mrq)) + host->pending_reset = true; + + __sdhci_finish_mrq(host, mrq); +} + +static void sdhci_finish_data(struct sdhci_host *host) +{ + struct mmc_command *data_cmd = host->data_cmd; + struct mmc_data *data = host->data; - data = host->data; host->data = NULL; + host->data_cmd = NULL; if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) @@ -958,20 +1019,41 @@ static void sdhci_finish_data(struct sdhci_host *host) */ if (data->stop && (data->error || - !host->mrq->sbc)) { + !data->mrq->sbc)) { /* * The controller needs a reset of internal state machines * upon error conditions. */ if (data->error) { - sdhci_do_reset(host, SDHCI_RESET_CMD); + if (!host->cmd || host->cmd == data_cmd) + sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); } + /* Avoid triggering warning in sdhci_send_command() */ + host->cmd = NULL; sdhci_send_command(host, data->stop); - } else - tasklet_schedule(&host->finish_tasklet); + } else { + sdhci_finish_mrq(host, data->mrq); + } +} + +static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, + unsigned long timeout) +{ + if (sdhci_data_line_cmd(mrq->cmd)) + mod_timer(&host->data_timer, timeout); + else + mod_timer(&host->timer, timeout); +} + +static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) +{ + if (sdhci_data_line_cmd(mrq->cmd)) + del_timer(&host->data_timer); + else + del_timer(&host->timer); } void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) @@ -989,12 +1071,12 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout = 10; mask = SDHCI_CMD_INHIBIT; - if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) + if (sdhci_data_line_cmd(cmd)) mask |= SDHCI_DATA_INHIBIT; /* We shouldn't wait for data inihibit for stop commands, even though they might use busy signaling */ - if (host->mrq->data && (cmd == host->mrq->data->stop)) + if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) mask &= ~SDHCI_DATA_INHIBIT; while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { @@ -1003,7 +1085,7 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) mmc_hostname(host->mmc)); sdhci_dumpregs(host); cmd->error = -EIO; - tasklet_schedule(&host->finish_tasklet); + sdhci_finish_mrq(host, cmd->mrq); return; } timeout--; @@ -1015,10 +1097,13 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; else timeout += 10 * HZ; - mod_timer(&host->timer, timeout); + sdhci_mod_timer(host, cmd->mrq, timeout); host->cmd = cmd; - host->busy_handle = 0; + if (sdhci_data_line_cmd(cmd)) { + WARN_ON(host->data_cmd); + host->data_cmd = cmd; + } sdhci_prepare_data(host, cmd); @@ -1030,7 +1115,7 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) pr_err("%s: Unsupported response type!\n", mmc_hostname(host->mmc)); cmd->error = -EINVAL; - tasklet_schedule(&host->finish_tasklet); + sdhci_finish_mrq(host, cmd->mrq); return; } @@ -1059,40 +1144,58 @@ EXPORT_SYMBOL_GPL(sdhci_send_command); static void sdhci_finish_command(struct sdhci_host *host) { + struct mmc_command *cmd = host->cmd; int i; - BUG_ON(host->cmd == NULL); + host->cmd = NULL; - if (host->cmd->flags & MMC_RSP_PRESENT) { - if (host->cmd->flags & MMC_RSP_136) { + if (cmd->flags & MMC_RSP_PRESENT) { + if (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] = sdhci_readl(host, + cmd->resp[i] = sdhci_readl(host, SDHCI_RESPONSE + (3-i)*4) << 8; if (i != 3) - host->cmd->resp[i] |= + cmd->resp[i] |= sdhci_readb(host, SDHCI_RESPONSE + (3-i)*4-1); } } else { - host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); + cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); + } + } + + /* + * The host can send and interrupt when the busy state has + * ended, allowing us to wait without wasting CPU cycles. + * The busy signal uses DAT0 so this is similar to waiting + * for data to complete. + * + * Note: The 1.0 specification is a bit ambiguous about this + * feature so there might be some problems with older + * controllers. + */ + if (cmd->flags & MMC_RSP_BUSY) { + if (cmd->data) { + DBG("Cannot wait for busy signal when also doing a data transfer"); + } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && + cmd == host->data_cmd) { + /* Command complete before busy is ended */ + return; } } /* Finished CMD23, now send actual command. */ - if (host->cmd == host->mrq->sbc) { - host->cmd = NULL; - sdhci_send_command(host, host->mrq->cmd); + if (cmd == cmd->mrq->sbc) { + sdhci_send_command(host, cmd->mrq->cmd); } else { /* Processed actual command. */ if (host->data && host->data_early) sdhci_finish_data(host); - if (!host->cmd->data) - tasklet_schedule(&host->finish_tasklet); - - host->cmd = NULL; + if (!cmd->data) + sdhci_finish_mrq(host, cmd->mrq); } } @@ -1373,26 +1476,22 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) spin_lock_irqsave(&host->lock, flags); - WARN_ON(host->mrq != NULL); - sdhci_led_activate(host); /* * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED * requests if Auto-CMD12 is enabled. */ - if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { + if (sdhci_auto_cmd12(host, mrq)) { if (mrq->stop) { mrq->data->stop = NULL; mrq->stop = NULL; } } - host->mrq = mrq; - if (!present || host->flags & SDHCI_DEVICE_DEAD) { - host->mrq->cmd->error = -ENOMEDIUM; - tasklet_schedule(&host->finish_tasklet); + mrq->cmd->error = -ENOMEDIUM; + sdhci_finish_mrq(host, mrq); } else { if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) sdhci_send_command(host, mrq->sbc); @@ -1617,7 +1716,7 @@ static int sdhci_get_cd(struct mmc_host *mmc) return 0; /* If nonremovable, assume that the card is always present. */ - if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + if (!mmc_card_is_removable(host->mmc)) return 1; /* @@ -1733,13 +1832,14 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, switch (ios->signal_voltage) { case MMC_SIGNAL_VOLTAGE_330: + if (!(host->flags & SDHCI_SIGNALING_330)) + return -EINVAL; /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ ctrl &= ~SDHCI_CTRL_VDD_180; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); if (!IS_ERR(mmc->supply.vqmmc)) { - ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000, - 3600000); + ret = mmc_regulator_set_vqmmc(mmc, ios); if (ret) { pr_warn("%s: Switching to 3.3V signalling voltage failed\n", mmc_hostname(mmc)); @@ -1759,9 +1859,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, return -EAGAIN; case MMC_SIGNAL_VOLTAGE_180: + if (!(host->flags & SDHCI_SIGNALING_180)) + return -EINVAL; if (!IS_ERR(mmc->supply.vqmmc)) { - ret = regulator_set_voltage(mmc->supply.vqmmc, - 1700000, 1950000); + ret = mmc_regulator_set_vqmmc(mmc, ios); if (ret) { pr_warn("%s: Switching to 1.8V signalling voltage failed\n", mmc_hostname(mmc)); @@ -1790,9 +1891,10 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, return -EAGAIN; case MMC_SIGNAL_VOLTAGE_120: + if (!(host->flags & SDHCI_SIGNALING_120)) + return -EINVAL; if (!IS_ERR(mmc->supply.vqmmc)) { - ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000, - 1300000); + ret = mmc_regulator_set_vqmmc(mmc, ios); if (ret) { pr_warn("%s: Switching to 1.2V signalling voltage failed\n", mmc_hostname(mmc)); @@ -1811,10 +1913,10 @@ static int sdhci_card_busy(struct mmc_host *mmc) struct sdhci_host *host = mmc_priv(mmc); u32 present_state; - /* Check whether DAT[3:0] is 0000 */ + /* Check whether DAT[0] is 0 */ present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); - return !(present_state & SDHCI_DATA_LVL_MASK); + return !(present_state & SDHCI_DATA_0_LVL_MASK); } static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) @@ -1909,7 +2011,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) /* * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number - * of loops reaches 40 times or a timeout of 150ms occurs. + * of loops reaches 40 times. */ do { struct mmc_command cmd = {0}; @@ -1920,13 +2022,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.retries = 0; cmd.data = NULL; + cmd.mrq = &mrq; cmd.error = 0; if (tuning_loop_counter-- == 0) break; mrq.cmd = &cmd; - host->mrq = &mrq; /* * In response to CMD19, the card sends 64 bytes of tuning @@ -1956,7 +2058,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) sdhci_send_command(host, &cmd); host->cmd = NULL; - host->mrq = NULL; + sdhci_del_timer(host, &mrq); spin_unlock_irqrestore(&host->lock, flags); /* Wait for Buffer Read Ready interrupt */ @@ -2086,6 +2188,24 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED); } +static inline bool sdhci_has_requests(struct sdhci_host *host) +{ + return host->cmd || host->data_cmd; +} + +static void sdhci_error_out_mrqs(struct sdhci_host *host, int err) +{ + if (host->data_cmd) { + host->data_cmd->error = err; + sdhci_finish_mrq(host, host->data_cmd->mrq); + } + + if (host->cmd) { + host->cmd->error = err; + sdhci_finish_mrq(host, host->cmd->mrq); + } +} + static void sdhci_card_event(struct mmc_host *mmc) { struct sdhci_host *host = mmc_priv(mmc); @@ -2096,12 +2216,12 @@ static void sdhci_card_event(struct mmc_host *mmc) if (host->ops->card_event) host->ops->card_event(host); - present = sdhci_get_cd(host->mmc); + present = mmc->ops->get_cd(mmc); spin_lock_irqsave(&host->lock, flags); - /* Check host->mrq first in case we are runtime suspended */ - if (host->mrq && !present) { + /* Check sdhci_has_requests() first in case we are runtime suspended */ + if (sdhci_has_requests(host) && !present) { pr_err("%s: Card removed during transfer!\n", mmc_hostname(host->mmc)); pr_err("%s: Resetting controller.\n", @@ -2110,8 +2230,7 @@ static void sdhci_card_event(struct mmc_host *mmc) sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); - host->mrq->cmd->error = -ENOMEDIUM; - tasklet_schedule(&host->finish_tasklet); + sdhci_error_out_mrqs(host, -ENOMEDIUM); } spin_unlock_irqrestore(&host->lock, flags); @@ -2140,28 +2259,28 @@ static const struct mmc_host_ops sdhci_ops = { * * \*****************************************************************************/ -static void sdhci_tasklet_finish(unsigned long param) +static bool sdhci_request_done(struct sdhci_host *host) { - struct sdhci_host *host; unsigned long flags; struct mmc_request *mrq; - - host = (struct sdhci_host*)param; + int i; spin_lock_irqsave(&host->lock, flags); - /* - * If this tasklet gets rescheduled while running, it will - * be run again afterwards but without any active request. - */ - if (!host->mrq) { - spin_unlock_irqrestore(&host->lock, flags); - return; + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + mrq = host->mrqs_done[i]; + if (mrq) { + host->mrqs_done[i] = NULL; + break; + } } - del_timer(&host->timer); + if (!mrq) { + spin_unlock_irqrestore(&host->lock, flags); + return true; + } - mrq = host->mrq; + sdhci_del_timer(host, mrq); /* * Always unmap the data buffers if they were mapped by @@ -2183,13 +2302,7 @@ static void sdhci_tasklet_finish(unsigned long param) * The controller needs a reset of internal state machines * upon error conditions. */ - if (!(host->flags & SDHCI_DEVICE_DEAD) && - ((mrq->cmd && mrq->cmd->error) || - (mrq->sbc && mrq->sbc->error) || - (mrq->data && ((mrq->data->error && !mrq->data->stop) || - (mrq->data->stop && mrq->data->stop->error))) || - (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { - + if (sdhci_needs_reset(host, mrq)) { /* Some controllers need this kick or reset won't work here */ if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) /* This is to force an update */ @@ -2197,20 +2310,31 @@ static void sdhci_tasklet_finish(unsigned long param) /* Spec says we should do both at the same time, but Ricoh controllers do not like that. */ - sdhci_do_reset(host, SDHCI_RESET_CMD); - sdhci_do_reset(host, SDHCI_RESET_DATA); - } + if (!host->cmd) + sdhci_do_reset(host, SDHCI_RESET_CMD); + if (!host->data_cmd) + sdhci_do_reset(host, SDHCI_RESET_DATA); - host->mrq = NULL; - host->cmd = NULL; - host->data = NULL; + host->pending_reset = false; + } - sdhci_led_deactivate(host); + if (!sdhci_has_requests(host)) + sdhci_led_deactivate(host); mmiowb(); spin_unlock_irqrestore(&host->lock, flags); mmc_request_done(host->mmc, mrq); + + return false; +} + +static void sdhci_tasklet_finish(unsigned long param) +{ + struct sdhci_host *host = (struct sdhci_host *)param; + + while (!sdhci_request_done(host)) + ; } static void sdhci_timeout_timer(unsigned long data) @@ -2222,7 +2346,30 @@ static void sdhci_timeout_timer(unsigned long data) spin_lock_irqsave(&host->lock, flags); - if (host->mrq) { + if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { + pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + + host->cmd->error = -ETIMEDOUT; + sdhci_finish_mrq(host, host->cmd->mrq); + } + + mmiowb(); + spin_unlock_irqrestore(&host->lock, flags); +} + +static void sdhci_timeout_data_timer(unsigned long data) +{ + struct sdhci_host *host; + unsigned long flags; + + host = (struct sdhci_host *)data; + + spin_lock_irqsave(&host->lock, flags); + + if (host->data || host->data_cmd || + (host->cmd && sdhci_data_line_cmd(host->cmd))) { pr_err("%s: Timeout waiting for hardware interrupt.\n", mmc_hostname(host->mmc)); sdhci_dumpregs(host); @@ -2230,13 +2377,12 @@ static void sdhci_timeout_timer(unsigned long data) if (host->data) { host->data->error = -ETIMEDOUT; sdhci_finish_data(host); + } else if (host->data_cmd) { + host->data_cmd->error = -ETIMEDOUT; + sdhci_finish_mrq(host, host->data_cmd->mrq); } else { - if (host->cmd) - host->cmd->error = -ETIMEDOUT; - else - host->mrq->cmd->error = -ETIMEDOUT; - - tasklet_schedule(&host->finish_tasklet); + host->cmd->error = -ETIMEDOUT; + sdhci_finish_mrq(host, host->cmd->mrq); } } @@ -2252,9 +2398,14 @@ static void sdhci_timeout_timer(unsigned long data) static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) { - BUG_ON(intmask == 0); - if (!host->cmd) { + /* + * SDHCI recovers from errors by resetting the cmd and data + * circuits. Until that is done, there very well might be more + * interrupts, so ignore them in that case. + */ + if (host->pending_reset) + return; pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); @@ -2285,37 +2436,14 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) return; } - tasklet_schedule(&host->finish_tasklet); + sdhci_finish_mrq(host, host->cmd->mrq); return; } - /* - * The host can send and interrupt when the busy state has - * ended, allowing us to wait without wasting CPU cycles. - * Unfortunately this is overloaded on the "data complete" - * interrupt, so we need to take some care when handling - * it. - * - * Note: The 1.0 specification is a bit ambiguous about this - * feature so there might be some problems with older - * controllers. - */ - if (host->cmd->flags & MMC_RSP_BUSY) { - if (host->cmd->data) - DBG("Cannot wait for busy signal when also doing a data transfer"); - else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) - && !host->busy_handle) { - /* Mark that command complete before busy is ended */ - host->busy_handle = 1; - return; - } - - /* The controller does not support the end-of-busy IRQ, - * fall through and take the SDHCI_INT_RESPONSE */ - } else if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && - host->cmd->opcode == MMC_STOP_TRANSMISSION && !host->data) { + if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && + !(host->cmd->flags & MMC_RSP_BUSY) && !host->data && + host->cmd->opcode == MMC_STOP_TRANSMISSION) *mask &= ~SDHCI_INT_DATA_END; - } if (intmask & SDHCI_INT_RESPONSE) sdhci_finish_command(host); @@ -2357,7 +2485,6 @@ static void sdhci_adma_show_error(struct sdhci_host *host) { } static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { u32 command; - BUG_ON(intmask == 0); /* CMD19 generates _only_ Buffer Read Ready interrupt */ if (intmask & SDHCI_INT_DATA_AVAIL) { @@ -2371,15 +2498,20 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } if (!host->data) { + struct mmc_command *data_cmd = host->data_cmd; + + if (data_cmd) + host->data_cmd = NULL; + /* * The "data complete" interrupt is also used to * indicate that a busy state has ended. See comment * above in sdhci_cmd_irq(). */ - if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { + if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { if (intmask & SDHCI_INT_DATA_TIMEOUT) { - host->cmd->error = -ETIMEDOUT; - tasklet_schedule(&host->finish_tasklet); + data_cmd->error = -ETIMEDOUT; + sdhci_finish_mrq(host, data_cmd->mrq); return; } if (intmask & SDHCI_INT_DATA_END) { @@ -2388,14 +2520,22 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) * before the command completed, so make * sure we do things in the proper order. */ - if (host->busy_handle) - sdhci_finish_command(host); - else - host->busy_handle = 1; + if (host->cmd == data_cmd) + return; + + sdhci_finish_mrq(host, data_cmd->mrq); return; } } + /* + * SDHCI recovers from errors by resetting the cmd and data + * circuits. Until that is done, there very well might be more + * interrupts, so ignore them in that case. + */ + if (host->pending_reset) + return; + pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); @@ -2453,7 +2593,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } if (intmask & SDHCI_INT_DATA_END) { - if (host->cmd) { + if (host->cmd == host->data_cmd) { /* * Data managed to finish before the * command completed. Make sure we do @@ -2537,6 +2677,9 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) pr_err("%s: Card is consuming too much power!\n", mmc_hostname(host->mmc)); + if (intmask & SDHCI_INT_RETUNE) + mmc_retune_needed(host->mmc); + if (intmask & SDHCI_INT_CARD_INT) { sdhci_enable_sdio_irq_nolock(host, false); host->thread_isr |= SDHCI_INT_CARD_INT; @@ -2546,7 +2689,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | - SDHCI_INT_CARD_INT); + SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); if (intmask) { unexpected |= intmask; @@ -2582,8 +2725,10 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) spin_unlock_irqrestore(&host->lock, flags); if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { - sdhci_card_event(host->mmc); - mmc_detect_change(host->mmc, msecs_to_jiffies(200)); + struct mmc_host *mmc = host->mmc; + + mmc->ops->card_event(mmc); + mmc_detect_change(mmc, msecs_to_jiffies(200)); } if (isr & SDHCI_INT_CARD_INT) { @@ -2605,18 +2750,31 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) \*****************************************************************************/ #ifdef CONFIG_PM +/* + * To enable wakeup events, the corresponding events have to be enabled in + * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal + * Table' in the SD Host Controller Standard Specification. + * It is useless to restore SDHCI_INT_ENABLE state in + * sdhci_disable_irq_wakeups() since it will be set by + * sdhci_enable_card_detection() or sdhci_init(). + */ void sdhci_enable_irq_wakeups(struct sdhci_host *host) { u8 val; u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE | SDHCI_WAKE_ON_INT; + u32 irq_val = SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | + SDHCI_INT_CARD_INT; val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); val |= mask ; /* Avoid fake wake up */ - if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) { val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE); + irq_val &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); + } sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); + sdhci_writel(host, irq_val, SDHCI_INT_ENABLE); } EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); @@ -2636,7 +2794,8 @@ int sdhci_suspend_host(struct sdhci_host *host) sdhci_disable_card_detection(host); mmc_retune_timer_stop(host->mmc); - mmc_retune_needed(host->mmc); + if (host->tuning_mode != SDHCI_TUNING_MODE_3) + mmc_retune_needed(host->mmc); if (!device_may_wakeup(mmc_dev(host->mmc))) { host->ier = 0; @@ -2654,6 +2813,7 @@ EXPORT_SYMBOL_GPL(sdhci_suspend_host); int sdhci_resume_host(struct sdhci_host *host) { + struct mmc_host *mmc = host->mmc; int ret = 0; if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { @@ -2667,7 +2827,7 @@ int sdhci_resume_host(struct sdhci_host *host) sdhci_init(host, 0); host->pwr = 0; host->clock = 0; - sdhci_set_ios(host->mmc, &host->mmc->ios); + mmc->ops->set_ios(mmc, &mmc->ios); } else { sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); mmiowb(); @@ -2696,7 +2856,8 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) unsigned long flags; mmc_retune_timer_stop(host->mmc); - mmc_retune_needed(host->mmc); + if (host->tuning_mode != SDHCI_TUNING_MODE_3) + mmc_retune_needed(host->mmc); spin_lock_irqsave(&host->lock, flags); host->ier &= SDHCI_INT_CARD_INT; @@ -2716,6 +2877,7 @@ EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); int sdhci_runtime_resume_host(struct sdhci_host *host) { + struct mmc_host *mmc = host->mmc; unsigned long flags; int host_flags = host->flags; @@ -2729,8 +2891,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) /* Force clock and power re-program */ host->pwr = 0; host->clock = 0; - sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios); - sdhci_set_ios(host->mmc, &host->mmc->ios); + mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); + mmc->ops->set_ios(mmc, &mmc->ios); if ((host_flags & SDHCI_PV_ENABLED) && !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { @@ -2781,6 +2943,8 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev, host->mmc_host_ops = sdhci_ops; mmc->ops = &host->mmc_host_ops; + host->flags = SDHCI_SIGNALING_330; + return host; } @@ -2816,10 +2980,41 @@ static int sdhci_set_dma_mask(struct sdhci_host *host) return ret; } -int sdhci_add_host(struct sdhci_host *host) +void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1) +{ + u16 v; + + if (host->read_caps) + return; + + host->read_caps = true; + + if (debug_quirks) + host->quirks = debug_quirks; + + if (debug_quirks2) + host->quirks2 = debug_quirks2; + + sdhci_do_reset(host, SDHCI_RESET_ALL); + + v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); + host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; + + if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) + return; + + host->caps = caps ? *caps : sdhci_readl(host, SDHCI_CAPABILITIES); + + if (host->version < SDHCI_SPEC_300) + return; + + host->caps1 = caps1 ? *caps1 : sdhci_readl(host, SDHCI_CAPABILITIES_1); +} +EXPORT_SYMBOL_GPL(__sdhci_read_caps); + +int sdhci_setup_host(struct sdhci_host *host) { struct mmc_host *mmc; - u32 caps[2] = {0, 0}; u32 max_current_caps; unsigned int ocr_avail; unsigned int override_timeout_clk; @@ -2832,34 +3027,28 @@ int sdhci_add_host(struct sdhci_host *host) mmc = host->mmc; - if (debug_quirks) - host->quirks = debug_quirks; - if (debug_quirks2) - host->quirks2 = debug_quirks2; + /* + * If there are external regulators, get them. Note this must be done + * early before resetting the host and reading the capabilities so that + * the host can take the appropriate action if regulators are not + * available. + */ + ret = mmc_regulator_get_supply(mmc); + if (ret == -EPROBE_DEFER) + return ret; - override_timeout_clk = host->timeout_clk; + sdhci_read_caps(host); - sdhci_do_reset(host, SDHCI_RESET_ALL); + override_timeout_clk = host->timeout_clk; - 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_300) { pr_err("%s: Unknown controller version (%d). You may experience problems.\n", mmc_hostname(mmc), host->version); } - caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps : - sdhci_readl(host, SDHCI_CAPABILITIES); - - if (host->version >= SDHCI_SPEC_300) - caps[1] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? - host->caps1 : - sdhci_readl(host, SDHCI_CAPABILITIES_1); - if (host->quirks & SDHCI_QUIRK_FORCE_DMA) host->flags |= SDHCI_USE_SDMA; - else if (!(caps[0] & SDHCI_CAN_DO_SDMA)) + else if (!(host->caps & SDHCI_CAN_DO_SDMA)) DBG("Controller doesn't have SDMA capability\n"); else host->flags |= SDHCI_USE_SDMA; @@ -2871,7 +3060,7 @@ int sdhci_add_host(struct sdhci_host *host) } if ((host->version >= SDHCI_SPEC_200) && - (caps[0] & SDHCI_CAN_DO_ADMA2)) + (host->caps & SDHCI_CAN_DO_ADMA2)) host->flags |= SDHCI_USE_ADMA; if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && @@ -2887,7 +3076,7 @@ int sdhci_add_host(struct sdhci_host *host) * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to * implement. */ - if (caps[0] & SDHCI_CAN_64BIT) + if (host->caps & SDHCI_CAN_64BIT) host->flags |= SDHCI_USE_64_BIT_DMA; if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { @@ -2963,10 +3152,10 @@ int sdhci_add_host(struct sdhci_host *host) } if (host->version >= SDHCI_SPEC_300) - host->max_clk = (caps[0] & SDHCI_CLOCK_V3_BASE_MASK) + host->max_clk = (host->caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; else - host->max_clk = (caps[0] & SDHCI_CLOCK_BASE_MASK) + host->max_clk = (host->caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; host->max_clk *= 1000000; @@ -2985,7 +3174,7 @@ int sdhci_add_host(struct sdhci_host *host) * In case of Host Controller v3.00, find out whether clock * multiplier is supported. */ - host->clk_mul = (caps[1] & SDHCI_CLOCK_MUL_MASK) >> + host->clk_mul = (host->caps1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; /* @@ -3017,7 +3206,7 @@ int sdhci_add_host(struct sdhci_host *host) mmc->f_max = max_clk; if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { - host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> + host->timeout_clk = (host->caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; if (host->timeout_clk == 0) { if (host->ops->get_timeout_clock) { @@ -3031,7 +3220,7 @@ int sdhci_add_host(struct sdhci_host *host) } } - if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) + if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; if (override_timeout_clk) @@ -3072,27 +3261,22 @@ int sdhci_add_host(struct sdhci_host *host) if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) mmc->caps &= ~MMC_CAP_CMD23; - if (caps[0] & SDHCI_CAN_DO_HISPD) + if (host->caps & SDHCI_CAN_DO_HISPD) mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && - !(mmc->caps & MMC_CAP_NONREMOVABLE) && + mmc_card_is_removable(mmc) && mmc_gpio_get_cd(host->mmc) < 0) mmc->caps |= MMC_CAP_NEEDS_POLL; - /* If there are external regulators, get them */ - ret = mmc_regulator_get_supply(mmc); - if (ret == -EPROBE_DEFER) - goto undma; - /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ if (!IS_ERR(mmc->supply.vqmmc)) { ret = regulator_enable(mmc->supply.vqmmc); if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 1950000)) - caps[1] &= ~(SDHCI_SUPPORT_SDR104 | - SDHCI_SUPPORT_SDR50 | - SDHCI_SUPPORT_DDR50); + host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | + SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50); if (ret) { pr_warn("%s: Failed to enable vqmmc regulator: %d\n", mmc_hostname(mmc), ret); @@ -3100,28 +3284,30 @@ int sdhci_add_host(struct sdhci_host *host) } } - if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) - caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | - SDHCI_SUPPORT_DDR50); + if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { + host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50); + } /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ - if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | - SDHCI_SUPPORT_DDR50)) + if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50)) mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ - if (caps[1] & SDHCI_SUPPORT_SDR104) { + if (host->caps1 & SDHCI_SUPPORT_SDR104) { mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; /* SD3.0: SDR104 is supported so (for eMMC) the caps2 * field can be promoted to support HS200. */ if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) mmc->caps2 |= MMC_CAP2_HS200; - } else if (caps[1] & SDHCI_SUPPORT_SDR50) + } else if (host->caps1 & SDHCI_SUPPORT_SDR50) { mmc->caps |= MMC_CAP_UHS_SDR50; + } if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && - (caps[1] & SDHCI_SUPPORT_HS400)) + (host->caps1 & SDHCI_SUPPORT_HS400)) mmc->caps2 |= MMC_CAP2_HS400; if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && @@ -3130,25 +3316,25 @@ int sdhci_add_host(struct sdhci_host *host) 1300000))) mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; - if ((caps[1] & SDHCI_SUPPORT_DDR50) && - !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) + if ((host->caps1 & SDHCI_SUPPORT_DDR50) && + !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) mmc->caps |= MMC_CAP_UHS_DDR50; /* Does the host need tuning for SDR50? */ - if (caps[1] & SDHCI_USE_SDR50_TUNING) + if (host->caps1 & SDHCI_USE_SDR50_TUNING) host->flags |= SDHCI_SDR50_NEEDS_TUNING; /* Driver Type(s) (A, C, D) supported by the host */ - if (caps[1] & SDHCI_DRIVER_TYPE_A) + if (host->caps1 & SDHCI_DRIVER_TYPE_A) mmc->caps |= MMC_CAP_DRIVER_TYPE_A; - if (caps[1] & SDHCI_DRIVER_TYPE_C) + if (host->caps1 & SDHCI_DRIVER_TYPE_C) mmc->caps |= MMC_CAP_DRIVER_TYPE_C; - if (caps[1] & SDHCI_DRIVER_TYPE_D) + if (host->caps1 & SDHCI_DRIVER_TYPE_D) mmc->caps |= MMC_CAP_DRIVER_TYPE_D; /* Initial value for re-tuning timer count */ - host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> - SDHCI_RETUNING_TIMER_COUNT_SHIFT; + host->tuning_count = (host->caps1 & SDHCI_RETUNING_TIMER_COUNT_MASK) >> + SDHCI_RETUNING_TIMER_COUNT_SHIFT; /* * In case Re-tuning Timer is not disabled, the actual value of @@ -3158,7 +3344,7 @@ int sdhci_add_host(struct sdhci_host *host) host->tuning_count = 1 << (host->tuning_count - 1); /* Re-tuning mode supported by the Host Controller */ - host->tuning_mode = (caps[1] & SDHCI_RETUNING_MODE_MASK) >> + host->tuning_mode = (host->caps1 & SDHCI_RETUNING_MODE_MASK) >> SDHCI_RETUNING_MODE_SHIFT; ocr_avail = 0; @@ -3187,7 +3373,7 @@ int sdhci_add_host(struct sdhci_host *host) } } - if (caps[0] & SDHCI_CAN_VDD_330) { + if (host->caps & SDHCI_CAN_VDD_330) { ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; mmc->max_current_330 = ((max_current_caps & @@ -3195,7 +3381,7 @@ int sdhci_add_host(struct sdhci_host *host) SDHCI_MAX_CURRENT_330_SHIFT) * SDHCI_MAX_CURRENT_MULTIPLIER; } - if (caps[0] & SDHCI_CAN_VDD_300) { + if (host->caps & SDHCI_CAN_VDD_300) { ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; mmc->max_current_300 = ((max_current_caps & @@ -3203,7 +3389,7 @@ int sdhci_add_host(struct sdhci_host *host) SDHCI_MAX_CURRENT_300_SHIFT) * SDHCI_MAX_CURRENT_MULTIPLIER; } - if (caps[0] & SDHCI_CAN_VDD_180) { + if (host->caps & SDHCI_CAN_VDD_180) { ocr_avail |= MMC_VDD_165_195; mmc->max_current_180 = ((max_current_caps & @@ -3240,6 +3426,15 @@ int sdhci_add_host(struct sdhci_host *host) goto unreg; } + if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || + (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) + host->flags |= SDHCI_SIGNALING_180; + + if (mmc->caps2 & MMC_CAP2_HSX00_1_2V) + host->flags |= SDHCI_SIGNALING_120; + spin_lock_init(&host->lock); /* @@ -3281,7 +3476,7 @@ int sdhci_add_host(struct sdhci_host *host) if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { mmc->max_blk_size = 2; } else { - mmc->max_blk_size = (caps[0] & SDHCI_MAX_BLOCK_MASK) >> + mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; if (mmc->max_blk_size >= 3) { pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", @@ -3297,6 +3492,28 @@ int sdhci_add_host(struct sdhci_host *host) */ mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; + return 0; + +unreg: + if (!IS_ERR(mmc->supply.vqmmc)) + regulator_disable(mmc->supply.vqmmc); +undma: + if (host->align_buffer) + dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + + host->adma_table_sz, host->align_buffer, + host->align_addr); + host->adma_table = NULL; + host->align_buffer = NULL; + + return ret; +} +EXPORT_SYMBOL_GPL(sdhci_setup_host); + +int __sdhci_add_host(struct sdhci_host *host) +{ + struct mmc_host *mmc = host->mmc; + int ret; + /* * Init tasklets. */ @@ -3304,6 +3521,8 @@ int sdhci_add_host(struct sdhci_host *host) sdhci_tasklet_finish, (unsigned long)host); setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); + setup_timer(&host->data_timer, sdhci_timeout_data_timer, + (unsigned long)host); init_waitqueue_head(&host->buf_ready_int); @@ -3353,10 +3572,10 @@ unirq: free_irq(host->irq, host); untasklet: tasklet_kill(&host->finish_tasklet); -unreg: + if (!IS_ERR(mmc->supply.vqmmc)) regulator_disable(mmc->supply.vqmmc); -undma: + if (host->align_buffer) dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + host->adma_table_sz, host->align_buffer, @@ -3366,7 +3585,18 @@ undma: return ret; } +EXPORT_SYMBOL_GPL(__sdhci_add_host); + +int sdhci_add_host(struct sdhci_host *host) +{ + int ret; + ret = sdhci_setup_host(host); + if (ret) + return ret; + + return __sdhci_add_host(host); +} EXPORT_SYMBOL_GPL(sdhci_add_host); void sdhci_remove_host(struct sdhci_host *host, int dead) @@ -3379,12 +3609,10 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) host->flags |= SDHCI_DEVICE_DEAD; - if (host->mrq) { + if (sdhci_has_requests(host)) { pr_err("%s: Controller removed during " " transfer!\n", mmc_hostname(mmc)); - - host->mrq->cmd->error = -ENOMEDIUM; - tasklet_schedule(&host->finish_tasklet); + sdhci_error_out_mrqs(host, -ENOMEDIUM); } spin_unlock_irqrestore(&host->lock, flags); @@ -3404,6 +3632,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) free_irq(host->irq, host); del_timer_sync(&host->timer); + del_timer_sync(&host->data_timer); tasklet_kill(&host->finish_tasklet); |