diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 11:35:36 -0800 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 11:35:36 -0800 |
commit | 4ba24fef3eb3b142197135223b90ced2f319cd53 (patch) | |
tree | a20c125b27740ec7b4c761b11d801108e1b316b2 /drivers/mmc/core/core.c | |
parent | 47c1ffb2b6b630894e9a16442611c056ab21c057 (diff) | |
parent | 98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff) |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 159 |
1 files changed, 79 insertions, 80 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d03a080fb9c..9584bffa8b2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -149,6 +149,14 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) led_trigger_event(host->led, LED_OFF); + if (mrq->sbc) { + pr_debug("%s: req done <CMD%u>: %d: %08x %08x %08x %08x\n", + mmc_hostname(host), mrq->sbc->opcode, + mrq->sbc->error, + mrq->sbc->resp[0], mrq->sbc->resp[1], + mrq->sbc->resp[2], mrq->sbc->resp[3]); + } + pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n", mmc_hostname(host), cmd->opcode, err, cmd->resp[0], cmd->resp[1], @@ -214,6 +222,10 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->cmd->error = 0; mrq->cmd->mrq = mrq; + if (mrq->sbc) { + mrq->sbc->error = 0; + mrq->sbc->mrq = mrq; + } if (mrq->data) { BUG_ON(mrq->data->blksz > host->max_blk_size); BUG_ON(mrq->data->blocks > host->max_blk_count); @@ -433,8 +445,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host, */ if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) { if (!mmc_interrupt_hpi(host->card)) { - pr_warning("%s: %s: Interrupted sanitize\n", - mmc_hostname(host), __func__); + pr_warn("%s: %s: Interrupted sanitize\n", + mmc_hostname(host), __func__); cmd->error = 0; break; } else { @@ -538,8 +550,18 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, if (host->card && mmc_card_mmc(host->card) && ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) || (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) && - (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) + (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) { + + /* Cancel the prepared request */ + if (areq) + mmc_post_req(host, areq->mrq, -EINVAL); + mmc_start_bkops(host->card, true); + + /* prepare the request again */ + if (areq) + mmc_pre_req(host, areq->mrq, !host->areq); + } } if (!err && areq) @@ -709,27 +731,16 @@ int mmc_read_bkops_status(struct mmc_card *card) int err; u8 *ext_csd; - /* - * In future work, we should consider storing the entire ext_csd. - */ - ext_csd = kmalloc(512, GFP_KERNEL); - if (!ext_csd) { - pr_err("%s: could not allocate buffer to receive the ext_csd.\n", - mmc_hostname(card->host)); - return -ENOMEM; - } - mmc_claim_host(card->host); - err = mmc_send_ext_csd(card, ext_csd); + err = mmc_get_ext_csd(card, &ext_csd); mmc_release_host(card->host); if (err) - goto out; + return err; card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS]; -out: kfree(ext_csd); - return err; + return 0; } EXPORT_SYMBOL(mmc_read_bkops_status); @@ -995,7 +1006,7 @@ void mmc_set_chip_select(struct mmc_host *host, int mode) */ static void __mmc_set_clock(struct mmc_host *host, unsigned int hz) { - WARN_ON(hz < host->f_min); + WARN_ON(hz && hz < host->f_min); if (hz > host->f_max) hz = host->f_max; @@ -1088,6 +1099,22 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width) mmc_host_clk_release(host); } +/* + * Set initial state after a power cycle or a hw_reset. + */ +void mmc_set_initial_state(struct mmc_host *host) +{ + if (mmc_host_is_spi(host)) + host->ios.chip_select = MMC_CS_HIGH; + else + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + + mmc_set_ios(host); +} + /** * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number * @vdd: voltage (mV) @@ -1221,15 +1248,14 @@ int mmc_regulator_get_ocrmask(struct regulator *supply) int result = 0; int count; int i; + int vdd_uV; + int vdd_mV; count = regulator_count_voltages(supply); if (count < 0) return count; for (i = 0; i < count; i++) { - int vdd_uV; - int vdd_mV; - vdd_uV = regulator_list_voltage(supply, i); if (vdd_uV <= 0) continue; @@ -1238,6 +1264,15 @@ int mmc_regulator_get_ocrmask(struct regulator *supply) result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); } + if (!result) { + vdd_uV = regulator_get_voltage(supply); + if (vdd_uV <= 0) + return vdd_uV; + + vdd_mV = vdd_uV / 1000; + result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); + } + return result; } EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask); @@ -1263,7 +1298,6 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, if (vdd_bit) { int tmp; - int voltage; /* * REVISIT mmc_vddrange_to_ocrmask() may have set some @@ -1280,22 +1314,7 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, max_uV = min_uV + 100 * 1000; } - /* - * If we're using a fixed/static regulator, don't call - * regulator_set_voltage; it would fail. - */ - voltage = regulator_get_voltage(supply); - - if (!regulator_can_change_voltage(supply)) - min_uV = max_uV = voltage; - - if (voltage < 0) - result = voltage; - else if (voltage < min_uV || voltage > max_uV) - result = regulator_set_voltage(supply, min_uV, max_uV); - else - result = 0; - + result = regulator_set_voltage(supply, min_uV, max_uV); if (result == 0 && !mmc->regulator_enabled) { result = regulator_enable(supply); if (!result) @@ -1425,8 +1444,10 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) if (!host->ops->start_signal_voltage_switch) return -EPERM; if (!host->ops->card_busy) - pr_warning("%s: cannot verify signal voltage switch\n", - mmc_hostname(host)); + pr_warn("%s: cannot verify signal voltage switch\n", + mmc_hostname(host)); + + mmc_host_clk_hold(host); cmd.opcode = SD_SWITCH_VOLTAGE; cmd.arg = 0; @@ -1434,12 +1455,12 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) err = mmc_wait_for_cmd(host, &cmd, 0); if (err) - return err; - - if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) - return -EIO; + goto err_command; - mmc_host_clk_hold(host); + if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) { + err = -EIO; + goto err_command; + } /* * The card should drive cmd and dat[0:3] low immediately * after the response of cmd11, but wait 1 ms to be sure @@ -1488,6 +1509,7 @@ power_cycle: mmc_power_cycle(host, ocr); } +err_command: mmc_host_clk_release(host); return err; @@ -1534,15 +1556,9 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) mmc_host_clk_hold(host); host->ios.vdd = fls(ocr) - 1; - if (mmc_host_is_spi(host)) - host->ios.chip_select = MMC_CS_HIGH; - else - host->ios.chip_select = MMC_CS_DONTCARE; - host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; host->ios.power_mode = MMC_POWER_UP; - host->ios.bus_width = MMC_BUS_WIDTH_1; - host->ios.timing = MMC_TIMING_LEGACY; - mmc_set_ios(host); + /* Set initial state and call mmc_set_ios */ + mmc_set_initial_state(host); /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0) @@ -1582,14 +1598,9 @@ void mmc_power_off(struct mmc_host *host) host->ios.clock = 0; host->ios.vdd = 0; - if (!mmc_host_is_spi(host)) { - host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; - host->ios.chip_select = MMC_CS_DONTCARE; - } host->ios.power_mode = MMC_POWER_OFF; - host->ios.bus_width = MMC_BUS_WIDTH_1; - host->ios.timing = MMC_TIMING_LEGACY; - mmc_set_ios(host); + /* Set initial state and call mmc_set_ios */ + mmc_set_initial_state(host); /* * Some configurations, such as the 802.11 SDIO card in the OLPC @@ -1761,7 +1772,7 @@ void mmc_init_erase(struct mmc_card *card) card->erase_shift = ffs(card->ssr.au) - 1; } else if (card->ext_csd.hc_erase_size) { card->pref_erase = card->ext_csd.hc_erase_size; - } else { + } else if (card->erase_size) { sz = (card->csd.capacity << (card->csd.read_blkbits - 9)) >> 11; if (sz < 128) card->pref_erase = 512 * 1024 / 512; @@ -1778,7 +1789,8 @@ void mmc_init_erase(struct mmc_card *card) if (sz) card->pref_erase += card->erase_size - sz; } - } + } else + card->pref_erase = 0; } static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, @@ -2266,30 +2278,16 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) /* If the reset has happened, then a status command will fail */ if (check) { - struct mmc_command cmd = {0}; - int err; + u32 status; - cmd.opcode = MMC_SEND_STATUS; - if (!mmc_host_is_spi(card->host)) - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; - err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (!err) { + if (!mmc_send_status(card, &status)) { mmc_host_clk_release(host); return -ENOSYS; } } - if (mmc_host_is_spi(host)) { - host->ios.chip_select = MMC_CS_HIGH; - host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; - } else { - host->ios.chip_select = MMC_CS_DONTCARE; - host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; - } - host->ios.bus_width = MMC_BUS_WIDTH_1; - host->ios.timing = MMC_TIMING_LEGACY; - mmc_set_ios(host); + /* Set initial state and call mmc_set_ios */ + mmc_set_initial_state(host); mmc_host_clk_release(host); @@ -2489,6 +2487,7 @@ void mmc_start_host(struct mmc_host *host) { host->f_init = max(freqs[0], host->f_min); host->rescan_disable = 0; + host->ios.power_mode = MMC_POWER_UNDEFINED; if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) mmc_power_off(host); else |