diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 111 |
1 files changed, 71 insertions, 40 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 1f453acc8682..68091dda3f31 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -236,12 +236,10 @@ EXPORT_SYMBOL(mmc_wait_for_req); */ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries) { - struct mmc_request mrq; + struct mmc_request mrq = {0}; WARN_ON(!host->claimed); - memset(&mrq, 0, sizeof(struct mmc_request)); - memset(cmd->resp, 0, sizeof(cmd->resp)); cmd->retries = retries; @@ -720,22 +718,12 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) } /* - * Change data bus width and DDR mode of a host. - */ -void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, - unsigned int ddr) -{ - host->ios.bus_width = width; - host->ios.ddr = ddr; - mmc_set_ios(host); -} - -/* * Change data bus width of a host. */ void mmc_set_bus_width(struct mmc_host *host, unsigned int width) { - mmc_set_bus_width_ddr(host, width, MMC_SDR_MODE); + host->ios.bus_width = width; + mmc_set_ios(host); } /** @@ -944,6 +932,38 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) return ocr; } +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11) +{ + struct mmc_command cmd = {0}; + int err = 0; + + BUG_ON(!host); + + /* + * Send CMD11 only if the request is to switch the card to + * 1.8V signalling. + */ + if ((signal_voltage != MMC_SIGNAL_VOLTAGE_330) && cmd11) { + cmd.opcode = SD_SWITCH_VOLTAGE; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + + 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; + } + + host->ios.signal_voltage = signal_voltage; + + if (host->ops->start_signal_voltage_switch) + err = host->ops->start_signal_voltage_switch(host, &host->ios); + + return err; +} + /* * Select timing parameters for host. */ @@ -954,6 +974,15 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) } /* + * Select appropriate driver type for host. + */ +void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) +{ + host->ios.drv_type = drv_type; + mmc_set_ios(host); +} + +/* * Apply power to the MMC stack. This is a two-stage process. * First, we enable power to the card without the clock running. * We then wait a bit for the power to stabilise. Finally, @@ -1187,9 +1216,8 @@ void mmc_init_erase(struct mmc_card *card) } } -static void mmc_set_mmc_erase_timeout(struct mmc_card *card, - struct mmc_command *cmd, - unsigned int arg, unsigned int qty) +static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, + unsigned int arg, unsigned int qty) { unsigned int erase_timeout; @@ -1246,44 +1274,48 @@ static void mmc_set_mmc_erase_timeout(struct mmc_card *card, if (mmc_host_is_spi(card->host) && erase_timeout < 1000) erase_timeout = 1000; - cmd->erase_timeout = erase_timeout; + return erase_timeout; } -static void mmc_set_sd_erase_timeout(struct mmc_card *card, - struct mmc_command *cmd, unsigned int arg, - unsigned int qty) +static unsigned int mmc_sd_erase_timeout(struct mmc_card *card, + unsigned int arg, + unsigned int qty) { + unsigned int erase_timeout; + if (card->ssr.erase_timeout) { /* Erase timeout specified in SD Status Register (SSR) */ - cmd->erase_timeout = card->ssr.erase_timeout * qty + - card->ssr.erase_offset; + erase_timeout = card->ssr.erase_timeout * qty + + card->ssr.erase_offset; } else { /* * Erase timeout not specified in SD Status Register (SSR) so * use 250ms per write block. */ - cmd->erase_timeout = 250 * qty; + erase_timeout = 250 * qty; } /* Must not be less than 1 second */ - if (cmd->erase_timeout < 1000) - cmd->erase_timeout = 1000; + if (erase_timeout < 1000) + erase_timeout = 1000; + + return erase_timeout; } -static void mmc_set_erase_timeout(struct mmc_card *card, - struct mmc_command *cmd, unsigned int arg, - unsigned int qty) +static unsigned int mmc_erase_timeout(struct mmc_card *card, + unsigned int arg, + unsigned int qty) { if (mmc_card_sd(card)) - mmc_set_sd_erase_timeout(card, cmd, arg, qty); + return mmc_sd_erase_timeout(card, arg, qty); else - mmc_set_mmc_erase_timeout(card, cmd, arg, qty); + return mmc_mmc_erase_timeout(card, arg, qty); } static int mmc_do_erase(struct mmc_card *card, unsigned int from, unsigned int to, unsigned int arg) { - struct mmc_command cmd; + struct mmc_command cmd = {0}; unsigned int qty = 0; int err; @@ -1317,7 +1349,6 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, to <<= 9; } - memset(&cmd, 0, sizeof(struct mmc_command)); if (mmc_card_sd(card)) cmd.opcode = SD_ERASE_WR_BLK_START; else @@ -1351,7 +1382,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.opcode = MMC_ERASE; cmd.arg = arg; cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - mmc_set_erase_timeout(card, &cmd, arg, qty); + cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty); err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n", @@ -1487,12 +1518,11 @@ EXPORT_SYMBOL(mmc_erase_group_aligned); int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) { - struct mmc_command cmd; + struct mmc_command cmd = {0}; if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) return 0; - memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = MMC_SET_BLOCKLEN; cmd.arg = blocklen; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; @@ -1578,7 +1608,7 @@ void mmc_rescan(struct work_struct *work) for (i = 0; i < ARRAY_SIZE(freqs); i++) { if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) break; - if (freqs[i] < host->f_min) + if (freqs[i] <= host->f_min) break; } mmc_release_host(host); @@ -1746,7 +1776,7 @@ int mmc_suspend_host(struct mmc_host *host) } mmc_bus_put(host); - if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) + if (!err && !mmc_card_keep_power(host)) mmc_power_off(host); return err; @@ -1764,7 +1794,7 @@ int mmc_resume_host(struct mmc_host *host) mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { - if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { + if (!mmc_card_keep_power(host)) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); /* @@ -1789,6 +1819,7 @@ int mmc_resume_host(struct mmc_host *host) err = 0; } } + host->pm_flags &= ~MMC_PM_KEEP_POWER; mmc_bus_put(host); return err; |