diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/mmc/core | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/mmc/core')
-rw-r--r-- | kernel/drivers/mmc/core/Kconfig | 10 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/core.c | 415 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/core.h | 7 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/debugfs.c | 30 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/host.c | 323 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/host.h | 6 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/mmc.c | 233 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/mmc_ops.c | 53 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/mmc_ops.h | 4 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/pwrseq_emmc.c | 8 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/pwrseq_simple.c | 45 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/quirks.c | 18 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/sd.c | 136 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/sdio.c | 121 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/sdio_bus.c | 12 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/sdio_irq.c | 14 | ||||
-rw-r--r-- | kernel/drivers/mmc/core/sdio_ops.h | 7 |
17 files changed, 764 insertions, 678 deletions
diff --git a/kernel/drivers/mmc/core/Kconfig b/kernel/drivers/mmc/core/Kconfig index 9ebee72d9..4c33d7690 100644 --- a/kernel/drivers/mmc/core/Kconfig +++ b/kernel/drivers/mmc/core/Kconfig @@ -1,13 +1,3 @@ # # MMC core configuration # - -config MMC_CLKGATE - bool "MMC host clock gating" - help - This will attempt to aggressively gate the clock to the MMC card. - This is done to save power due to gating off the logic and bus - noise when the MMC card is not in use. Your host driver has to - support handling this in order for it to be of any use. - - If unsure, say N. diff --git a/kernel/drivers/mmc/core/core.c b/kernel/drivers/mmc/core/core.c index 588fb7908..5ae89e48f 100644 --- a/kernel/drivers/mmc/core/core.c +++ b/kernel/drivers/mmc/core/core.c @@ -133,6 +133,14 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) struct mmc_command *cmd = mrq->cmd; int err = cmd->error; + /* Flag re-tuning needed on CRC errors */ + if ((cmd->opcode != MMC_SEND_TUNING_BLOCK && + cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) && + (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || + (mrq->data && mrq->data->error == -EILSEQ) || + (mrq->stop && mrq->stop->error == -EILSEQ))) + mmc_retune_needed(host); + if (err && cmd->retries && mmc_host_is_spi(host)) { if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) cmd->retries = 0; @@ -179,19 +187,51 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) if (mrq->done) mrq->done(mrq); - - mmc_host_clk_release(host); } } EXPORT_SYMBOL(mmc_request_done); +static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) +{ + int err; + + /* Assumes host controller has been runtime resumed by mmc_claim_host */ + err = mmc_retune(host); + if (err) { + mrq->cmd->error = err; + mmc_request_done(host, mrq); + return; + } + + /* + * For sdio rw commands we must wait for card busy otherwise some + * sdio devices won't work properly. + */ + if (mmc_is_io_op(mrq->cmd->opcode) && host->ops->card_busy) { + int tries = 500; /* Wait aprox 500ms at maximum */ + + while (host->ops->card_busy(host) && --tries) + mmc_delay(1); + + if (tries == 0) { + mrq->cmd->error = -EBUSY; + mmc_request_done(host, mrq); + return; + } + } + + host->ops->request(host, mrq); +} + static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { #ifdef CONFIG_MMC_DEBUG unsigned int i, sz; struct scatterlist *sg; #endif + mmc_retune_hold(host); + if (mmc_card_removed(host->card)) return -ENOMEDIUM; @@ -250,9 +290,8 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->stop->mrq = mrq; } } - mmc_host_clk_hold(host); led_trigger_event(host->led, LED_FULL); - host->ops->request(host, mrq); + __mmc_start_request(host, mrq); return 0; } @@ -301,12 +340,15 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) use_busy_signal = false; } + mmc_retune_hold(card->host); + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true, false); if (err) { pr_warn("%s: Error %d starting bkops\n", mmc_hostname(card->host), err); + mmc_retune_release(card->host); goto out; } @@ -317,6 +359,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) */ if (!use_busy_signal) mmc_card_set_doing_bkops(card); + else + mmc_retune_release(card->host); out: mmc_release_host(card->host); } @@ -419,22 +463,22 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, host->areq); break; /* return err */ } else { + mmc_retune_recheck(host); pr_info("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; - host->ops->request(host, mrq); + __mmc_start_request(host, mrq); continue; /* wait for done/new event again */ } } else if (context_info->is_new_req) { context_info->is_new_req = false; - if (!next_req) { - err = MMC_BLK_NEW_REQUEST; - break; /* return err */ - } + if (!next_req) + return MMC_BLK_NEW_REQUEST; } } + mmc_retune_release(host); return err; } @@ -469,12 +513,16 @@ static void mmc_wait_for_req_done(struct mmc_host *host, mmc_card_removed(host->card)) break; + mmc_retune_recheck(host); + pr_debug("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; - host->ops->request(host, mrq); + __mmc_start_request(host, mrq); } + + mmc_retune_release(host); } /** @@ -491,11 +539,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host, static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, bool is_first_req) { - if (host->ops->pre_req) { - mmc_host_clk_hold(host); + if (host->ops->pre_req) host->ops->pre_req(host, mrq, is_first_req); - mmc_host_clk_release(host); - } } /** @@ -510,11 +555,8 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, int err) { - if (host->ops->post_req) { - mmc_host_clk_hold(host); + if (host->ops->post_req) host->ops->post_req(host, mrq, err); - mmc_host_clk_release(host); - } } /** @@ -730,6 +772,7 @@ int mmc_stop_bkops(struct mmc_card *card) */ if (!err || (err == -EINVAL)) { mmc_card_clr_doing_bkops(card); + mmc_retune_release(card->host); err = 0; } @@ -798,9 +841,9 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) unsigned int timeout_us, limit_us; timeout_us = data->timeout_ns / 1000; - if (mmc_host_clk_rate(card->host)) + if (card->host->ios.clock) timeout_us += data->timeout_clks * 1000 / - (mmc_host_clk_rate(card->host) / 1000); + (card->host->ios.clock / 1000); if (data->flags & MMC_DATA_WRITE) /* @@ -998,8 +1041,6 @@ static inline void mmc_set_ios(struct mmc_host *host) ios->power_mode, ios->chip_select, ios->vdd, ios->bus_width, ios->timing); - if (ios->clock > 0) - mmc_set_ungated(host); host->ops->set_ios(host, ios); } @@ -1008,17 +1049,15 @@ static inline void mmc_set_ios(struct mmc_host *host) */ void mmc_set_chip_select(struct mmc_host *host, int mode) { - mmc_host_clk_hold(host); host->ios.chip_select = mode; mmc_set_ios(host); - mmc_host_clk_release(host); } /* * Sets the host clock to the highest possible frequency that * is below "hz". */ -static void __mmc_set_clock(struct mmc_host *host, unsigned int hz) +void mmc_set_clock(struct mmc_host *host, unsigned int hz) { WARN_ON(hz && hz < host->f_min); @@ -1029,68 +1068,6 @@ static void __mmc_set_clock(struct mmc_host *host, unsigned int hz) mmc_set_ios(host); } -void mmc_set_clock(struct mmc_host *host, unsigned int hz) -{ - mmc_host_clk_hold(host); - __mmc_set_clock(host, hz); - mmc_host_clk_release(host); -} - -#ifdef CONFIG_MMC_CLKGATE -/* - * This gates the clock by setting it to 0 Hz. - */ -void mmc_gate_clock(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->clk_lock, flags); - host->clk_old = host->ios.clock; - host->ios.clock = 0; - host->clk_gated = true; - spin_unlock_irqrestore(&host->clk_lock, flags); - mmc_set_ios(host); -} - -/* - * This restores the clock from gating by using the cached - * clock value. - */ -void mmc_ungate_clock(struct mmc_host *host) -{ - /* - * We should previously have gated the clock, so the clock shall - * be 0 here! The clock may however be 0 during initialization, - * when some request operations are performed before setting - * the frequency. When ungate is requested in that situation - * we just ignore the call. - */ - if (host->clk_old) { - BUG_ON(host->ios.clock); - /* This call will also set host->clk_gated to false */ - __mmc_set_clock(host, host->clk_old); - } -} - -void mmc_set_ungated(struct mmc_host *host) -{ - unsigned long flags; - - /* - * We've been given a new frequency while the clock is gated, - * so make sure we regard this as ungating it. - */ - spin_lock_irqsave(&host->clk_lock, flags); - host->clk_gated = false; - spin_unlock_irqrestore(&host->clk_lock, flags); -} - -#else -void mmc_set_ungated(struct mmc_host *host) -{ -} -#endif - int mmc_execute_tuning(struct mmc_card *card) { struct mmc_host *host = card->host; @@ -1105,12 +1082,12 @@ int mmc_execute_tuning(struct mmc_card *card) else opcode = MMC_SEND_TUNING_BLOCK; - mmc_host_clk_hold(host); err = host->ops->execute_tuning(host, opcode); - mmc_host_clk_release(host); if (err) pr_err("%s: tuning execution failed\n", mmc_hostname(host)); + else + mmc_retune_enable(host); return err; } @@ -1120,10 +1097,8 @@ int mmc_execute_tuning(struct mmc_card *card) */ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) { - mmc_host_clk_hold(host); host->ios.bus_mode = mode; mmc_set_ios(host); - mmc_host_clk_release(host); } /* @@ -1131,10 +1106,8 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) */ void mmc_set_bus_width(struct mmc_host *host, unsigned int width) { - mmc_host_clk_hold(host); host->ios.bus_width = width; mmc_set_ios(host); - mmc_host_clk_release(host); } /* @@ -1142,6 +1115,8 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width) */ void mmc_set_initial_state(struct mmc_host *host) { + mmc_retune_disable(host); + if (mmc_host_is_spi(host)) host->ios.chip_select = MMC_CS_HIGH; else @@ -1149,6 +1124,7 @@ void mmc_set_initial_state(struct mmc_host *host) host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; host->ios.bus_width = MMC_BUS_WIDTH_1; host->ios.timing = MMC_TIMING_LEGACY; + host->ios.drv_type = 0; mmc_set_ios(host); } @@ -1301,6 +1277,40 @@ struct device_node *mmc_of_find_child_device(struct mmc_host *host, #ifdef CONFIG_REGULATOR /** + * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage + * @vdd_bit: OCR bit number + * @min_uV: minimum voltage value (mV) + * @max_uV: maximum voltage value (mV) + * + * This function returns the voltage range according to the provided OCR + * bit number. If conversion is not possible a negative errno value returned. + */ +static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV) +{ + int tmp; + + if (!vdd_bit) + return -EINVAL; + + /* + * REVISIT mmc_vddrange_to_ocrmask() may have set some + * bits this regulator doesn't quite support ... don't + * be too picky, most cards and regulators are OK with + * a 0.1V range goof (it's a small error percentage). + */ + tmp = vdd_bit - ilog2(MMC_VDD_165_195); + if (tmp == 0) { + *min_uV = 1650 * 1000; + *max_uV = 1950 * 1000; + } else { + *min_uV = 1900 * 1000 + tmp * 100 * 1000; + *max_uV = *min_uV + 100 * 1000; + } + + return 0; +} + +/** * mmc_regulator_get_ocrmask - return mask of supported voltages * @supply: regulator to use * @@ -1363,22 +1373,7 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, int min_uV, max_uV; if (vdd_bit) { - int tmp; - - /* - * REVISIT mmc_vddrange_to_ocrmask() may have set some - * bits this regulator doesn't quite support ... don't - * be too picky, most cards and regulators are OK with - * a 0.1V range goof (it's a small error percentage). - */ - tmp = vdd_bit - ilog2(MMC_VDD_165_195); - if (tmp == 0) { - min_uV = 1650 * 1000; - max_uV = 1950 * 1000; - } else { - min_uV = 1900 * 1000 + tmp * 100 * 1000; - max_uV = min_uV + 100 * 1000; - } + mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV); result = regulator_set_voltage(supply, min_uV, max_uV); if (result == 0 && !mmc->regulator_enabled) { @@ -1399,6 +1394,84 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, } EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); +static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator, + int min_uV, int target_uV, + int max_uV) +{ + /* + * Check if supported first to avoid errors since we may try several + * signal levels during power up and don't want to show errors. + */ + if (!regulator_is_supported_voltage(regulator, min_uV, max_uV)) + return -EINVAL; + + return regulator_set_voltage_triplet(regulator, min_uV, target_uV, + max_uV); +} + +/** + * mmc_regulator_set_vqmmc - Set VQMMC as per the ios + * + * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible. + * That will match the behavior of old boards where VQMMC and VMMC were supplied + * by the same supply. The Bus Operating conditions for 3.3V signaling in the + * SD card spec also define VQMMC in terms of VMMC. + * If this is not possible we'll try the full 2.7-3.6V of the spec. + * + * For 1.2V and 1.8V signaling we'll try to get as close as possible to the + * requested voltage. This is definitely a good idea for UHS where there's a + * separate regulator on the card that's trying to make 1.8V and it's best if + * we match. + * + * This function is expected to be used by a controller's + * start_signal_voltage_switch() function. + */ +int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct device *dev = mmc_dev(mmc); + int ret, volt, min_uV, max_uV; + + /* If no vqmmc supply then we can't change the voltage */ + if (IS_ERR(mmc->supply.vqmmc)) + return -EINVAL; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_120: + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 1100000, 1200000, 1300000); + case MMC_SIGNAL_VOLTAGE_180: + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 1700000, 1800000, 1950000); + case MMC_SIGNAL_VOLTAGE_330: + ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV); + if (ret < 0) + return ret; + + dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n", + __func__, volt, max_uV); + + min_uV = max(volt - 300000, 2700000); + max_uV = min(max_uV + 200000, 3600000); + + /* + * Due to a limitation in the current implementation of + * regulator_set_voltage_triplet() which is taking the lowest + * voltage possible if below the target, search for a suitable + * voltage in two steps and try to stay close to vmmc + * with a 0.3V tolerance at first. + */ + if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + min_uV, volt, max_uV)) + return 0; + + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 2700000, volt, 3600000); + default: + return -EINVAL; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); + #endif /* CONFIG_REGULATOR */ int mmc_regulator_get_supply(struct mmc_host *mmc) @@ -1475,11 +1548,8 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) int old_signal_voltage = host->ios.signal_voltage; host->ios.signal_voltage = signal_voltage; - if (host->ops->start_signal_voltage_switch) { - mmc_host_clk_hold(host); + if (host->ops->start_signal_voltage_switch) err = host->ops->start_signal_voltage_switch(host, &host->ios); - mmc_host_clk_release(host); - } if (err) host->ios.signal_voltage = old_signal_voltage; @@ -1513,20 +1583,17 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) 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; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(host, &cmd, 0); if (err) - goto err_command; + return err; + + if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) + return -EIO; - 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 @@ -1553,8 +1620,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) goto power_cycle; } - /* Keep clock gated for at least 5 ms */ - mmc_delay(5); + /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ + mmc_delay(10); host->ios.clock = clock; mmc_set_ios(host); @@ -1575,9 +1642,6 @@ power_cycle: mmc_power_cycle(host, ocr); } -err_command: - mmc_host_clk_release(host); - return err; } @@ -1586,10 +1650,8 @@ err_command: */ void mmc_set_timing(struct mmc_host *host, unsigned int timing) { - mmc_host_clk_hold(host); host->ios.timing = timing; mmc_set_ios(host); - mmc_host_clk_release(host); } /* @@ -1597,10 +1659,41 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) */ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) { - mmc_host_clk_hold(host); host->ios.drv_type = drv_type; mmc_set_ios(host); - mmc_host_clk_release(host); +} + +int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, + int card_drv_type, int *drv_type) +{ + struct mmc_host *host = card->host; + int host_drv_type = SD_DRIVER_TYPE_B; + + *drv_type = 0; + + if (!host->ops->select_drive_strength) + return 0; + + /* Use SD definition of driver strength for hosts */ + if (host->caps & MMC_CAP_DRIVER_TYPE_A) + host_drv_type |= SD_DRIVER_TYPE_A; + + if (host->caps & MMC_CAP_DRIVER_TYPE_C) + host_drv_type |= SD_DRIVER_TYPE_C; + + if (host->caps & MMC_CAP_DRIVER_TYPE_D) + host_drv_type |= SD_DRIVER_TYPE_D; + + /* + * The drive strength that the hardware can support + * depends on the board design. Pass the appropriate + * information and let the hardware specific code + * return what is possible given the options + */ + return host->ops->select_drive_strength(card, max_dtr, + host_drv_type, + card_drv_type, + drv_type); } /* @@ -1619,8 +1712,6 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) if (host->ios.power_mode == MMC_POWER_ON) return; - mmc_host_clk_hold(host); - mmc_pwrseq_pre_power_on(host); host->ios.vdd = fls(ocr) - 1; @@ -1654,8 +1745,6 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) * time required to reach a stable voltage. */ mmc_delay(10); - - mmc_host_clk_release(host); } void mmc_power_off(struct mmc_host *host) @@ -1663,8 +1752,6 @@ void mmc_power_off(struct mmc_host *host) if (host->ios.power_mode == MMC_POWER_OFF) return; - mmc_host_clk_hold(host); - mmc_pwrseq_power_off(host); host->ios.clock = 0; @@ -1680,8 +1767,6 @@ void mmc_power_off(struct mmc_host *host) * can be successfully turned on again. */ mmc_delay(1); - - mmc_host_clk_release(host); } void mmc_power_cycle(struct mmc_host *host, u32 ocr) @@ -1897,7 +1982,7 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, */ timeout_clks <<= 1; timeout_us += (timeout_clks * 1000) / - (mmc_host_clk_rate(card->host) / 1000); + (card->host->ios.clock / 1000); erase_timeout = timeout_us / 1000; @@ -1972,6 +2057,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, unsigned long timeout; int err; + mmc_retune_hold(card->host); + /* * qty is used to calculate the erase timeout which depends on how many * erase groups (or allocation units in SD terminology) are affected. @@ -2075,6 +2162,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG)); out: + mmc_retune_release(card->host); return err; } @@ -2091,6 +2179,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, unsigned int arg) { unsigned int rem, to = from + nr; + int err; if (!(card->host->caps & MMC_CAP_ERASE) || !(card->csd.cmdclass & CCC_ERASE)) @@ -2141,6 +2230,22 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, /* 'from' and 'to' are inclusive */ to -= 1; + /* + * Special case where only one erase-group fits in the timeout budget: + * If the region crosses an erase-group boundary on this particular + * case, we will be trimming more than one erase-group which, does not + * fit in the timeout budget of the controller, so we need to split it + * and call mmc_do_erase() twice if necessary. This special case is + * identified by the card->eg_boundary flag. + */ + rem = card->erase_size - (from % card->erase_size); + if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) { + err = mmc_do_erase(card, from, from + rem - 1, arg); + from += rem; + if ((err) || (to <= from)) + return err; + } + return mmc_do_erase(card, from, to, arg); } EXPORT_SYMBOL(mmc_erase); @@ -2156,7 +2261,8 @@ EXPORT_SYMBOL(mmc_can_erase); int mmc_can_trim(struct mmc_card *card) { - if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) + if ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) && + (!(card->quirks & MMC_QUIRK_TRIM_BROKEN))) return 1; return 0; } @@ -2236,16 +2342,28 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; + /* + * When specifying a sector range to trim, chances are we might cross + * an erase-group boundary even if the amount of sectors is less than + * one erase-group. + * If we can only fit one erase-group in the controller timeout budget, + * we have to care that erase-group boundaries are not crossed by a + * single trim operation. We flag that special case with "eg_boundary". + * In all other cases we can just decrement qty and pretend that we + * always touch (qty + 1) erase-groups as a simple optimization. + */ if (qty == 1) - return 1; + card->eg_boundary = 1; + else + qty--; /* Convert qty to sectors */ if (card->erase_shift) - max_discard = --qty << card->erase_shift; + max_discard = qty << card->erase_shift; else if (mmc_card_sd(card)) - max_discard = qty; + max_discard = qty + 1; else - max_discard = --qty * card->erase_size; + max_discard = qty * card->erase_size; return max_discard; } @@ -2312,9 +2430,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) { if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) return; - mmc_host_clk_hold(host); host->ops->hw_reset(host); - mmc_host_clk_release(host); } int mmc_hw_reset(struct mmc_host *host) @@ -2333,7 +2449,8 @@ int mmc_hw_reset(struct mmc_host *host) ret = host->bus_ops->reset(host); mmc_bus_put(host); - pr_warn("%s: tried to reset card\n", mmc_hostname(host)); + if (ret != -EOPNOTSUPP) + pr_warn("%s: tried to reset card\n", mmc_hostname(host)); return ret; } @@ -2521,10 +2638,14 @@ 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; + + mmc_claim_host(host); if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) mmc_power_off(host); else mmc_power_up(host, host->ocr_avail); + mmc_release_host(host); + mmc_gpiod_request_cd_irq(host); _mmc_detect_change(host, 0, false); } @@ -2562,7 +2683,9 @@ void mmc_stop_host(struct mmc_host *host) BUG_ON(host->card); + mmc_claim_host(host); mmc_power_off(host); + mmc_release_host(host); } int mmc_power_save_host(struct mmc_host *host) diff --git a/kernel/drivers/mmc/core/core.h b/kernel/drivers/mmc/core/core.h index cfba3c05a..09241e56d 100644 --- a/kernel/drivers/mmc/core/core.h +++ b/kernel/drivers/mmc/core/core.h @@ -40,9 +40,6 @@ void mmc_init_erase(struct mmc_card *card); void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); -void mmc_gate_clock(struct mmc_host *host); -void mmc_ungate_clock(struct mmc_host *host); -void mmc_set_ungated(struct mmc_host *host); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); @@ -50,6 +47,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr); int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); +int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, + int card_drv_type, int *drv_type); void mmc_power_up(struct mmc_host *host, u32 ocr); void mmc_power_off(struct mmc_host *host); void mmc_power_cycle(struct mmc_host *host, u32 ocr); @@ -88,6 +87,8 @@ void mmc_remove_card_debugfs(struct mmc_card *card); void mmc_init_context_info(struct mmc_host *host); int mmc_execute_tuning(struct mmc_card *card); +int mmc_hs200_to_hs400(struct mmc_card *card); +int mmc_hs400_to_hs200(struct mmc_card *card); #endif diff --git a/kernel/drivers/mmc/core/debugfs.c b/kernel/drivers/mmc/core/debugfs.c index e9142108a..154aced0b 100644 --- a/kernel/drivers/mmc/core/debugfs.c +++ b/kernel/drivers/mmc/core/debugfs.c @@ -126,6 +126,12 @@ static int mmc_ios_show(struct seq_file *s, void *data) case MMC_TIMING_SD_HS: str = "sd high-speed"; break; + case MMC_TIMING_UHS_SDR12: + str = "sd uhs SDR12"; + break; + case MMC_TIMING_UHS_SDR25: + str = "sd uhs SDR25"; + break; case MMC_TIMING_UHS_SDR50: str = "sd uhs SDR50"; break; @@ -166,6 +172,25 @@ static int mmc_ios_show(struct seq_file *s, void *data) } seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str); + switch (ios->drv_type) { + case MMC_SET_DRIVER_TYPE_A: + str = "driver type A"; + break; + case MMC_SET_DRIVER_TYPE_B: + str = "driver type B"; + break; + case MMC_SET_DRIVER_TYPE_C: + str = "driver type C"; + break; + case MMC_SET_DRIVER_TYPE_D: + str = "driver type D"; + break; + default: + str = "invalid"; + break; + } + seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str); + return 0; } @@ -230,11 +255,6 @@ void mmc_add_host_debugfs(struct mmc_host *host) &mmc_clock_fops)) goto err_node; -#ifdef CONFIG_MMC_CLKGATE - if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), - root, &host->clk_delay)) - goto err_node; -#endif #ifdef CONFIG_FAIL_MMC_REQUEST if (fail_request) setup_fault_attr(&fail_default_attr, fail_request); diff --git a/kernel/drivers/mmc/core/host.c b/kernel/drivers/mmc/core/host.c index 8be0df758..da950c442 100644 --- a/kernel/drivers/mmc/core/host.c +++ b/kernel/drivers/mmc/core/host.c @@ -61,245 +61,89 @@ void mmc_unregister_host_class(void) class_unregister(&mmc_host_class); } -#ifdef CONFIG_MMC_CLKGATE -static ssize_t clkgate_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) +void mmc_retune_enable(struct mmc_host *host) { - struct mmc_host *host = cls_dev_to_mmc_host(dev); - return snprintf(buf, PAGE_SIZE, "%lu\n", host->clkgate_delay); + host->can_retune = 1; + if (host->retune_period) + mod_timer(&host->retune_timer, + jiffies + host->retune_period * HZ); } -static ssize_t clkgate_delay_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +void mmc_retune_disable(struct mmc_host *host) { - struct mmc_host *host = cls_dev_to_mmc_host(dev); - unsigned long flags, value; - - if (kstrtoul(buf, 0, &value)) - return -EINVAL; - - spin_lock_irqsave(&host->clk_lock, flags); - host->clkgate_delay = value; - spin_unlock_irqrestore(&host->clk_lock, flags); - return count; + host->can_retune = 0; + del_timer_sync(&host->retune_timer); + host->retune_now = 0; + host->need_retune = 0; } -/* - * Enabling clock gating will make the core call out to the host - * once up and once down when it performs a request or card operation - * intermingled in any fashion. The driver will see this through - * set_ios() operations with ios.clock field set to 0 to gate (disable) - * the block clock, and to the old frequency to enable it again. - */ -static void mmc_host_clk_gate_delayed(struct mmc_host *host) +void mmc_retune_timer_stop(struct mmc_host *host) { - unsigned long tick_ns; - unsigned long freq = host->ios.clock; - unsigned long flags; - - if (!freq) { - pr_debug("%s: frequency set to 0 in disable function, " - "this means the clock is already disabled.\n", - mmc_hostname(host)); - return; - } - /* - * New requests may have appeared while we were scheduling, - * then there is no reason to delay the check before - * clk_disable(). - */ - spin_lock_irqsave(&host->clk_lock, flags); - - /* - * Delay n bus cycles (at least 8 from MMC spec) before attempting - * to disable the MCI block clock. The reference count may have - * gone up again after this delay due to rescheduling! - */ - if (!host->clk_requests) { - spin_unlock_irqrestore(&host->clk_lock, flags); - tick_ns = DIV_ROUND_UP(1000000000, freq); - ndelay(host->clk_delay * tick_ns); - } else { - /* New users appeared while waiting for this work */ - spin_unlock_irqrestore(&host->clk_lock, flags); - return; - } - mutex_lock(&host->clk_gate_mutex); - spin_lock_irqsave(&host->clk_lock, flags); - if (!host->clk_requests) { - spin_unlock_irqrestore(&host->clk_lock, flags); - /* This will set host->ios.clock to 0 */ - mmc_gate_clock(host); - spin_lock_irqsave(&host->clk_lock, flags); - pr_debug("%s: gated MCI clock\n", mmc_hostname(host)); - } - spin_unlock_irqrestore(&host->clk_lock, flags); - mutex_unlock(&host->clk_gate_mutex); + del_timer_sync(&host->retune_timer); } +EXPORT_SYMBOL(mmc_retune_timer_stop); -/* - * Internal work. Work to disable the clock at some later point. - */ -static void mmc_host_clk_gate_work(struct work_struct *work) +void mmc_retune_hold(struct mmc_host *host) { - struct mmc_host *host = container_of(work, struct mmc_host, - clk_gate_work.work); - - mmc_host_clk_gate_delayed(host); + if (!host->hold_retune) + host->retune_now = 1; + host->hold_retune += 1; } -/** - * mmc_host_clk_hold - ungate hardware MCI clocks - * @host: host to ungate. - * - * Makes sure the host ios.clock is restored to a non-zero value - * past this call. Increase clock reference count and ungate clock - * if we're the first user. - */ -void mmc_host_clk_hold(struct mmc_host *host) +void mmc_retune_release(struct mmc_host *host) { - unsigned long flags; - - /* cancel any clock gating work scheduled by mmc_host_clk_release() */ - cancel_delayed_work_sync(&host->clk_gate_work); - mutex_lock(&host->clk_gate_mutex); - spin_lock_irqsave(&host->clk_lock, flags); - if (host->clk_gated) { - spin_unlock_irqrestore(&host->clk_lock, flags); - mmc_ungate_clock(host); - spin_lock_irqsave(&host->clk_lock, flags); - pr_debug("%s: ungated MCI clock\n", mmc_hostname(host)); - } - host->clk_requests++; - spin_unlock_irqrestore(&host->clk_lock, flags); - mutex_unlock(&host->clk_gate_mutex); + if (host->hold_retune) + host->hold_retune -= 1; + else + WARN_ON(1); } -/** - * mmc_host_may_gate_card - check if this card may be gated - * @card: card to check. - */ -static bool mmc_host_may_gate_card(struct mmc_card *card) +int mmc_retune(struct mmc_host *host) { - /* If there is no card we may gate it */ - if (!card) - return true; - /* - * Don't gate SDIO cards! These need to be clocked at all times - * since they may be independent systems generating interrupts - * and other events. The clock requests counter from the core will - * go down to zero since the core does not need it, but we will not - * gate the clock, because there is somebody out there that may still - * be using it. - */ - return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING); -} + bool return_to_hs400 = false; + int err; -/** - * mmc_host_clk_release - gate off hardware MCI clocks - * @host: host to gate. - * - * Calls the host driver with ios.clock set to zero as often as possible - * in order to gate off hardware MCI clocks. Decrease clock reference - * count and schedule disabling of clock. - */ -void mmc_host_clk_release(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->clk_lock, flags); - host->clk_requests--; - if (mmc_host_may_gate_card(host->card) && - !host->clk_requests) - schedule_delayed_work(&host->clk_gate_work, - msecs_to_jiffies(host->clkgate_delay)); - spin_unlock_irqrestore(&host->clk_lock, flags); -} + if (host->retune_now) + host->retune_now = 0; + else + return 0; -/** - * mmc_host_clk_rate - get current clock frequency setting - * @host: host to get the clock frequency for. - * - * Returns current clock frequency regardless of gating. - */ -unsigned int mmc_host_clk_rate(struct mmc_host *host) -{ - unsigned long freq; - unsigned long flags; + if (!host->need_retune || host->doing_retune || !host->card) + return 0; - spin_lock_irqsave(&host->clk_lock, flags); - if (host->clk_gated) - freq = host->clk_old; - else - freq = host->ios.clock; - spin_unlock_irqrestore(&host->clk_lock, flags); - return freq; -} + host->need_retune = 0; -/** - * mmc_host_clk_init - set up clock gating code - * @host: host with potential clock to control - */ -static inline void mmc_host_clk_init(struct mmc_host *host) -{ - host->clk_requests = 0; - /* Hold MCI clock for 8 cycles by default */ - host->clk_delay = 8; - /* - * Default clock gating delay is 0ms to avoid wasting power. - * This value can be tuned by writing into sysfs entry. - */ - host->clkgate_delay = 0; - host->clk_gated = false; - INIT_DELAYED_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); - spin_lock_init(&host->clk_lock); - mutex_init(&host->clk_gate_mutex); -} + host->doing_retune = 1; -/** - * mmc_host_clk_exit - shut down clock gating code - * @host: host with potential clock to control - */ -static inline void mmc_host_clk_exit(struct mmc_host *host) -{ - /* - * Wait for any outstanding gate and then make sure we're - * ungated before exiting. - */ - if (cancel_delayed_work_sync(&host->clk_gate_work)) - mmc_host_clk_gate_delayed(host); - if (host->clk_gated) - mmc_host_clk_hold(host); - /* There should be only one user now */ - WARN_ON(host->clk_requests > 1); -} + if (host->ios.timing == MMC_TIMING_MMC_HS400) { + err = mmc_hs400_to_hs200(host->card); + if (err) + goto out; -static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) -{ - host->clkgate_delay_attr.show = clkgate_delay_show; - host->clkgate_delay_attr.store = clkgate_delay_store; - sysfs_attr_init(&host->clkgate_delay_attr.attr); - host->clkgate_delay_attr.attr.name = "clkgate_delay"; - host->clkgate_delay_attr.attr.mode = S_IRUGO | S_IWUSR; - if (device_create_file(&host->class_dev, &host->clkgate_delay_attr)) - pr_err("%s: Failed to create clkgate_delay sysfs entry\n", - mmc_hostname(host)); -} -#else + return_to_hs400 = true; -static inline void mmc_host_clk_init(struct mmc_host *host) -{ -} + if (host->ops->prepare_hs400_tuning) + host->ops->prepare_hs400_tuning(host, &host->ios); + } -static inline void mmc_host_clk_exit(struct mmc_host *host) -{ + err = mmc_execute_tuning(host->card); + if (err) + goto out; + + if (return_to_hs400) + err = mmc_hs200_to_hs400(host->card); +out: + host->doing_retune = 0; + + return err; } -static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) +static void mmc_retune_timer(unsigned long data) { -} + struct mmc_host *host = (struct mmc_host *)data; -#endif + mmc_retune_needed(host); +} /** * mmc_of_parse() - parse host's device-tree node @@ -314,7 +158,7 @@ int mmc_of_parse(struct mmc_host *host) { struct device_node *np; u32 bus_width; - int len, ret; + int ret; bool cd_cap_invert, cd_gpio_invert = false; bool ro_cap_invert, ro_gpio_invert = false; @@ -361,19 +205,19 @@ int mmc_of_parse(struct mmc_host *host) */ /* Parse Card Detection */ - if (of_find_property(np, "non-removable", &len)) { + if (of_property_read_bool(np, "non-removable")) { host->caps |= MMC_CAP_NONREMOVABLE; } else { cd_cap_invert = of_property_read_bool(np, "cd-inverted"); - if (of_find_property(np, "broken-cd", &len)) + if (of_property_read_bool(np, "broken-cd")) host->caps |= MMC_CAP_NEEDS_POLL; ret = mmc_gpiod_request_cd(host, "cd", 0, true, 0, &cd_gpio_invert); if (!ret) dev_info(host->parent, "Got CD GPIO\n"); - else if (ret != -ENOENT) + else if (ret != -ENOENT && ret != -ENOSYS) return ret; /* @@ -397,48 +241,53 @@ int mmc_of_parse(struct mmc_host *host) ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); if (!ret) dev_info(host->parent, "Got WP GPIO\n"); - else if (ret != -ENOENT) + else if (ret != -ENOENT && ret != -ENOSYS) return ret; + if (of_property_read_bool(np, "disable-wp")) + host->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; + /* See the comment on CD inversion above */ if (ro_cap_invert ^ ro_gpio_invert) host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - if (of_find_property(np, "cap-sd-highspeed", &len)) + if (of_property_read_bool(np, "cap-sd-highspeed")) host->caps |= MMC_CAP_SD_HIGHSPEED; - if (of_find_property(np, "cap-mmc-highspeed", &len)) + if (of_property_read_bool(np, "cap-mmc-highspeed")) host->caps |= MMC_CAP_MMC_HIGHSPEED; - if (of_find_property(np, "sd-uhs-sdr12", &len)) + if (of_property_read_bool(np, "sd-uhs-sdr12")) host->caps |= MMC_CAP_UHS_SDR12; - if (of_find_property(np, "sd-uhs-sdr25", &len)) + if (of_property_read_bool(np, "sd-uhs-sdr25")) host->caps |= MMC_CAP_UHS_SDR25; - if (of_find_property(np, "sd-uhs-sdr50", &len)) + if (of_property_read_bool(np, "sd-uhs-sdr50")) host->caps |= MMC_CAP_UHS_SDR50; - if (of_find_property(np, "sd-uhs-sdr104", &len)) + if (of_property_read_bool(np, "sd-uhs-sdr104")) host->caps |= MMC_CAP_UHS_SDR104; - if (of_find_property(np, "sd-uhs-ddr50", &len)) + if (of_property_read_bool(np, "sd-uhs-ddr50")) host->caps |= MMC_CAP_UHS_DDR50; - if (of_find_property(np, "cap-power-off-card", &len)) + if (of_property_read_bool(np, "cap-power-off-card")) host->caps |= MMC_CAP_POWER_OFF_CARD; - if (of_find_property(np, "cap-sdio-irq", &len)) + if (of_property_read_bool(np, "cap-mmc-hw-reset")) + host->caps |= MMC_CAP_HW_RESET; + if (of_property_read_bool(np, "cap-sdio-irq")) host->caps |= MMC_CAP_SDIO_IRQ; - if (of_find_property(np, "full-pwr-cycle", &len)) + if (of_property_read_bool(np, "full-pwr-cycle")) host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; - if (of_find_property(np, "keep-power-in-suspend", &len)) + if (of_property_read_bool(np, "keep-power-in-suspend")) host->pm_caps |= MMC_PM_KEEP_POWER; - if (of_find_property(np, "enable-sdio-wakeup", &len)) + if (of_property_read_bool(np, "enable-sdio-wakeup")) host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; - if (of_find_property(np, "mmc-ddr-1_8v", &len)) + if (of_property_read_bool(np, "mmc-ddr-1_8v")) host->caps |= MMC_CAP_1_8V_DDR; - if (of_find_property(np, "mmc-ddr-1_2v", &len)) + if (of_property_read_bool(np, "mmc-ddr-1_2v")) host->caps |= MMC_CAP_1_2V_DDR; - if (of_find_property(np, "mmc-hs200-1_8v", &len)) + if (of_property_read_bool(np, "mmc-hs200-1_8v")) host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; - if (of_find_property(np, "mmc-hs200-1_2v", &len)) + if (of_property_read_bool(np, "mmc-hs200-1_2v")) host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; - if (of_find_property(np, "mmc-hs400-1_8v", &len)) + if (of_property_read_bool(np, "mmc-hs400-1_8v")) host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; - if (of_find_property(np, "mmc-hs400-1_2v", &len)) + if (of_property_read_bool(np, "mmc-hs400-1_2v")) host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR; host->dsr_req = !of_property_read_u32(np, "dsr", &host->dsr); @@ -496,14 +345,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) return NULL; } - mmc_host_clk_init(host); - spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); #ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; #endif + setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host); /* * By default, hosts do not support SGIO or large requests. @@ -545,7 +393,6 @@ int mmc_add_host(struct mmc_host *host) #ifdef CONFIG_DEBUG_FS mmc_add_host_debugfs(host); #endif - mmc_host_clk_sysfs_init(host); mmc_start_host(host); register_pm_notifier(&host->pm_notify); @@ -575,8 +422,6 @@ void mmc_remove_host(struct mmc_host *host) device_del(&host->class_dev); led_trigger_unregister_simple(host->led); - - mmc_host_clk_exit(host); } EXPORT_SYMBOL(mmc_remove_host); diff --git a/kernel/drivers/mmc/core/host.h b/kernel/drivers/mmc/core/host.h index f2ab9e578..992bf5397 100644 --- a/kernel/drivers/mmc/core/host.h +++ b/kernel/drivers/mmc/core/host.h @@ -15,5 +15,11 @@ int mmc_register_host_class(void); void mmc_unregister_host_class(void); +void mmc_retune_enable(struct mmc_host *host); +void mmc_retune_disable(struct mmc_host *host); +void mmc_retune_hold(struct mmc_host *host); +void mmc_retune_release(struct mmc_host *host); +int mmc_retune(struct mmc_host *host); + #endif diff --git a/kernel/drivers/mmc/core/mmc.c b/kernel/drivers/mmc/core/mmc.c index f36c76f8b..3d5087b03 100644 --- a/kernel/drivers/mmc/core/mmc.c +++ b/kernel/drivers/mmc/core/mmc.c @@ -21,6 +21,7 @@ #include <linux/mmc/mmc.h> #include "core.h" +#include "host.h" #include "bus.h" #include "mmc_ops.h" #include "sd_ops.h" @@ -266,8 +267,10 @@ static void mmc_manage_enhanced_area(struct mmc_card *card, u8 *ext_csd) * calculate the enhanced data area offset, in bytes */ card->ext_csd.enhanced_area_offset = - (ext_csd[139] << 24) + (ext_csd[138] << 16) + - (ext_csd[137] << 8) + ext_csd[136]; + (((unsigned long long)ext_csd[139]) << 24) + + (((unsigned long long)ext_csd[138]) << 16) + + (((unsigned long long)ext_csd[137]) << 8) + + (((unsigned long long)ext_csd[136])); if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; /* @@ -434,6 +437,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; + card->ext_csd.raw_driver_strength = ext_csd[EXT_CSD_DRIVER_STRENGTH]; if (card->ext_csd.rev >= 4) { if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED] & EXT_CSD_PART_SETTING_COMPLETED) @@ -1036,10 +1040,26 @@ static int mmc_select_hs_ddr(struct mmc_card *card) return err; } +/* Caller must hold re-tuning */ +static int mmc_switch_status(struct mmc_card *card) +{ + u32 status; + int err; + + err = mmc_send_status(card, &status); + if (err) + return err; + + return mmc_switch_status_error(card->host, status); +} + static int mmc_select_hs400(struct mmc_card *card) { struct mmc_host *host = card->host; + bool send_status = true; + unsigned int max_dtr; int err = 0; + u8 val; /* * HS400 mode requires 8-bit bus width @@ -1048,23 +1068,35 @@ static int mmc_select_hs400(struct mmc_card *card) host->ios.bus_width == MMC_BUS_WIDTH_8)) return 0; - /* - * Before switching to dual data rate operation for HS400, - * it is required to convert from HS200 mode to HS mode. - */ - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - mmc_set_bus_speed(card); + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) + send_status = false; + + /* Reduce frequency to HS frequency */ + max_dtr = card->ext_csd.hs_max_dtr; + mmc_set_clock(host, max_dtr); + /* Switch card to HS mode */ + val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, + EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, - true, true, true); + true, send_status, true); if (err) { pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", mmc_hostname(host), err); return err; } + /* Set host controller to HS timing */ + mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + + if (!send_status) { + err = mmc_switch_status(card); + if (err) + goto out_err; + } + + /* Switch card to DDR */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8, @@ -1075,20 +1107,130 @@ static int mmc_select_hs400(struct mmc_card *card) return err; } + /* Switch card to HS400 */ + val = EXT_CSD_TIMING_HS400 | + card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400, + EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, - true, true, true); + true, send_status, true); if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); return err; } + /* Set host controller to HS400 timing and frequency */ mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); + if (!send_status) { + err = mmc_switch_status(card); + if (err) + goto out_err; + } + return 0; + +out_err: + pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), + __func__, err); + return err; +} + +int mmc_hs200_to_hs400(struct mmc_card *card) +{ + return mmc_select_hs400(card); +} + +int mmc_hs400_to_hs200(struct mmc_card *card) +{ + struct mmc_host *host = card->host; + bool send_status = true; + unsigned int max_dtr; + int err; + u8 val; + + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) + send_status = false; + + /* Reduce frequency to HS */ + max_dtr = card->ext_csd.hs_max_dtr; + mmc_set_clock(host, max_dtr); + + /* Switch HS400 to HS DDR */ + val = EXT_CSD_TIMING_HS; + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, + val, card->ext_csd.generic_cmd6_time, + true, send_status, true); + if (err) + goto out_err; + + mmc_set_timing(host, MMC_TIMING_MMC_DDR52); + + if (!send_status) { + err = mmc_switch_status(card); + if (err) + goto out_err; + } + + /* Switch HS DDR to HS */ + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, + EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time, + true, send_status, true); + if (err) + goto out_err; + + mmc_set_timing(host, MMC_TIMING_MMC_HS); + + if (!send_status) { + err = mmc_switch_status(card); + if (err) + goto out_err; + } + + /* Switch HS to HS200 */ + val = EXT_CSD_TIMING_HS200 | + card->drive_strength << EXT_CSD_DRV_STR_SHIFT; + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, + val, card->ext_csd.generic_cmd6_time, true, + send_status, true); + if (err) + goto out_err; + + mmc_set_timing(host, MMC_TIMING_MMC_HS200); + + if (!send_status) { + err = mmc_switch_status(card); + if (err) + goto out_err; + } + + mmc_set_bus_speed(card); + + return 0; + +out_err: + pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), + __func__, err); + return err; +} + +static void mmc_select_driver_type(struct mmc_card *card) +{ + int card_drv_type, drive_strength, drv_type; + + card_drv_type = card->ext_csd.raw_driver_strength | + mmc_driver_type_mask(0); + + drive_strength = mmc_select_drive_strength(card, + card->ext_csd.hs200_max_dtr, + card_drv_type, &drv_type); + + card->drive_strength = drive_strength; + + if (drv_type) + mmc_set_driver_type(card->host, drv_type); } /* @@ -1101,7 +1243,10 @@ static int mmc_select_hs400(struct mmc_card *card) static int mmc_select_hs200(struct mmc_card *card) { struct mmc_host *host = card->host; + bool send_status = true; + unsigned int old_timing; int err = -EINVAL; + u8 val; if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); @@ -1113,20 +1258,41 @@ static int mmc_select_hs200(struct mmc_card *card) if (err) goto err; + mmc_select_driver_type(card); + + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) + send_status = false; + /* * Set the bus width(4 or 8) with host's support and * switch to HS200 mode if bus width is set successfully. */ err = mmc_select_bus_width(card); if (!IS_ERR_VALUE(err)) { + val = EXT_CSD_TIMING_HS200 | + card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200, + EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, - true, true, true); - if (!err) - mmc_set_timing(host, MMC_TIMING_MMC_HS200); + true, send_status, true); + if (err) + goto err; + old_timing = host->ios.timing; + mmc_set_timing(host, MMC_TIMING_MMC_HS200); + if (!send_status) { + err = mmc_switch_status(card); + /* + * mmc_select_timing() assumes timing has not changed if + * it is a switch error. + */ + if (err == -EBADMSG) + mmc_set_timing(host, old_timing); + } } err: + if (err) + pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), + __func__, err); return err; } @@ -1511,9 +1677,12 @@ static int mmc_sleep(struct mmc_host *host) unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000); int err; + /* Re-tuning can't be done once the card is deselected */ + mmc_retune_hold(host); + err = mmc_deselect_cards(host); if (err) - return err; + goto out_release; cmd.opcode = MMC_SLEEP_AWAKE; cmd.arg = card->rca << 16; @@ -1534,7 +1703,7 @@ static int mmc_sleep(struct mmc_host *host) err = mmc_wait_for_cmd(host, &cmd, 0); if (err) - return err; + goto out_release; /* * If the host does not wait while the card signals busy, then we will @@ -1545,6 +1714,8 @@ static int mmc_sleep(struct mmc_host *host) if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) mmc_delay(timeout_ms); +out_release: + mmc_retune_release(host); return err; } @@ -1782,17 +1953,6 @@ static int mmc_runtime_resume(struct mmc_host *host) return 0; } -static int mmc_power_restore(struct mmc_host *host) -{ - int ret; - - mmc_claim_host(host); - ret = mmc_init_card(host, host->card->ocr, host->card); - mmc_release_host(host); - - return ret; -} - int mmc_can_reset(struct mmc_card *card) { u8 rst_n_function; @@ -1807,7 +1967,6 @@ EXPORT_SYMBOL(mmc_can_reset); static int mmc_reset(struct mmc_host *host) { struct mmc_card *card = host->card; - u32 status; if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) return -EOPNOTSUPP; @@ -1815,22 +1974,14 @@ static int mmc_reset(struct mmc_host *host) if (!mmc_can_reset(card)) return -EOPNOTSUPP; - mmc_host_clk_hold(host); mmc_set_clock(host, host->f_init); host->ops->hw_reset(host); - /* If the reset has happened, then a status command will fail */ - if (!mmc_send_status(card, &status)) { - mmc_host_clk_release(host); - return -ENOSYS; - } - /* Set initial state and call mmc_set_ios */ mmc_set_initial_state(host); - mmc_host_clk_release(host); - return mmc_power_restore(host); + return mmc_init_card(host, card->ocr, card); } static const struct mmc_bus_ops mmc_ops = { @@ -1840,7 +1991,6 @@ static const struct mmc_bus_ops mmc_ops = { .resume = mmc_resume, .runtime_suspend = mmc_runtime_suspend, .runtime_resume = mmc_runtime_resume, - .power_restore = mmc_power_restore, .alive = mmc_alive, .shutdown = mmc_shutdown, .reset = mmc_reset, @@ -1897,14 +2047,13 @@ int mmc_attach_mmc(struct mmc_host *host) mmc_release_host(host); err = mmc_add_card(host->card); - mmc_claim_host(host); if (err) goto remove_card; + mmc_claim_host(host); return 0; remove_card: - mmc_release_host(host); mmc_remove_card(host->card); mmc_claim_host(host); host->card = NULL; diff --git a/kernel/drivers/mmc/core/mmc_ops.c b/kernel/drivers/mmc/core/mmc_ops.c index 0ea042dc7..1f444269e 100644 --- a/kernel/drivers/mmc/core/mmc_ops.c +++ b/kernel/drivers/mmc/core/mmc_ops.c @@ -19,6 +19,7 @@ #include <linux/mmc/mmc.h> #include "core.h" +#include "host.h" #include "mmc_ops.h" #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ @@ -449,6 +450,21 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc) return err; } +int mmc_switch_status_error(struct mmc_host *host, u32 status) +{ + if (mmc_host_is_spi(host)) { + if (status & R1_SPI_ILLEGAL_COMMAND) + return -EBADMSG; + } else { + if (status & 0xFDFFA000) + pr_warn("%s: unexpected status %#x after switch\n", + mmc_hostname(host), status); + if (status & R1_SWITCH_ERROR) + return -EBADMSG; + } + return 0; +} + /** * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer @@ -474,6 +490,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, u32 status = 0; bool use_r1b_resp = use_busy_signal; + mmc_retune_hold(host); + /* * If the cmd timeout and the max_busy_timeout of the host are both * specified, let's validate them. A failure means we need to prevent @@ -506,11 +524,11 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); if (err) - return err; + goto out; /* No need to check card status in case of unblocking command */ if (!use_busy_signal) - return 0; + goto out; /* * CRC errors shall only be ignored in cases were CMD13 is used to poll @@ -529,7 +547,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, if (send_status) { err = __mmc_send_status(card, &status, ignore_crc); if (err) - return err; + goto out; } if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) break; @@ -543,31 +561,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, */ if (!send_status) { mmc_delay(timeout_ms); - return 0; + goto out; } /* Timeout if the device never leaves the program state. */ if (time_after(jiffies, timeout)) { pr_err("%s: Card stuck in programming state! %s\n", mmc_hostname(host), __func__); - return -ETIMEDOUT; + err = -ETIMEDOUT; + goto out; } } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); - if (mmc_host_is_spi(host)) { - if (status & R1_SPI_ILLEGAL_COMMAND) - return -EBADMSG; - } else { - if (status & 0xFDFFA000) - pr_warn("%s: unexpected status %#x after switch\n", - mmc_hostname(host), status); - if (status & R1_SWITCH_ERROR) - return -EBADMSG; - } + err = mmc_switch_status_error(host, status); +out: + mmc_retune_release(host); - return 0; + return err; } -EXPORT_SYMBOL_GPL(__mmc_switch); int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms) @@ -577,7 +588,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, } EXPORT_SYMBOL_GPL(mmc_switch); -int mmc_send_tuning(struct mmc_host *host) +int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error) { struct mmc_request mrq = {NULL}; struct mmc_command cmd = {0}; @@ -587,16 +598,13 @@ int mmc_send_tuning(struct mmc_host *host) const u8 *tuning_block_pattern; int size, err = 0; u8 *data_buf; - u32 opcode; if (ios->bus_width == MMC_BUS_WIDTH_8) { tuning_block_pattern = tuning_blk_pattern_8bit; size = sizeof(tuning_blk_pattern_8bit); - opcode = MMC_SEND_TUNING_BLOCK_HS200; } else if (ios->bus_width == MMC_BUS_WIDTH_4) { tuning_block_pattern = tuning_blk_pattern_4bit; size = sizeof(tuning_blk_pattern_4bit); - opcode = MMC_SEND_TUNING_BLOCK; } else return -EINVAL; @@ -627,6 +635,9 @@ int mmc_send_tuning(struct mmc_host *host) mmc_wait_for_req(host, &mrq); + if (cmd_error) + *cmd_error = cmd.error; + if (cmd.error) { err = cmd.error; goto out; diff --git a/kernel/drivers/mmc/core/mmc_ops.h b/kernel/drivers/mmc/core/mmc_ops.h index 6f4b00ed9..f1b8e81aa 100644 --- a/kernel/drivers/mmc/core/mmc_ops.h +++ b/kernel/drivers/mmc/core/mmc_ops.h @@ -27,6 +27,10 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc); int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); int mmc_can_ext_csd(struct mmc_card *card); +int mmc_switch_status_error(struct mmc_host *host, u32 status); +int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, + unsigned int timeout_ms, bool use_busy_signal, bool send_status, + bool ignore_crc); #endif diff --git a/kernel/drivers/mmc/core/pwrseq_emmc.c b/kernel/drivers/mmc/core/pwrseq_emmc.c index 9d6d2fb21..ad4f94ec7 100644 --- a/kernel/drivers/mmc/core/pwrseq_emmc.c +++ b/kernel/drivers/mmc/core/pwrseq_emmc.c @@ -76,7 +76,7 @@ struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, if (!pwrseq) return ERR_PTR(-ENOMEM); - pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_LOW); + pwrseq->reset_gpio = gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(pwrseq->reset_gpio)) { ret = PTR_ERR(pwrseq->reset_gpio); goto free; @@ -84,11 +84,11 @@ struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, /* * register reset handler to ensure emmc reset also from - * emergency_reboot(), priority 129 schedules it just before - * system reboot + * emergency_reboot(), priority 255 is the highest priority + * so it will be executed before any system reboot handler. */ pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; - pwrseq->reset_nb.priority = 129; + pwrseq->reset_nb.priority = 255; register_restart_handler(&pwrseq->reset_nb); pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; diff --git a/kernel/drivers/mmc/core/pwrseq_simple.c b/kernel/drivers/mmc/core/pwrseq_simple.c index 0b14b83a5..d10538bb5 100644 --- a/kernel/drivers/mmc/core/pwrseq_simple.c +++ b/kernel/drivers/mmc/core/pwrseq_simple.c @@ -23,18 +23,21 @@ struct mmc_pwrseq_simple { struct mmc_pwrseq pwrseq; bool clk_enabled; struct clk *ext_clk; - int nr_gpios; - struct gpio_desc *reset_gpios[0]; + struct gpio_descs *reset_gpios; }; static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, int value) { int i; + struct gpio_descs *reset_gpios = pwrseq->reset_gpios; + int values[reset_gpios->ndescs]; - for (i = 0; i < pwrseq->nr_gpios; i++) - if (!IS_ERR(pwrseq->reset_gpios[i])) - gpiod_set_value_cansleep(pwrseq->reset_gpios[i], value); + for (i = 0; i < reset_gpios->ndescs; i++) + values[i] = value; + + gpiod_set_array_value_cansleep(reset_gpios->ndescs, reset_gpios->desc, + values); } static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) @@ -75,11 +78,8 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host) { struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, struct mmc_pwrseq_simple, pwrseq); - int i; - for (i = 0; i < pwrseq->nr_gpios; i++) - if (!IS_ERR(pwrseq->reset_gpios[i])) - gpiod_put(pwrseq->reset_gpios[i]); + gpiod_put_array(pwrseq->reset_gpios); if (!IS_ERR(pwrseq->ext_clk)) clk_put(pwrseq->ext_clk); @@ -98,14 +98,9 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) { struct mmc_pwrseq_simple *pwrseq; - int i, nr_gpios, ret = 0; - - nr_gpios = of_gpio_named_count(dev->of_node, "reset-gpios"); - if (nr_gpios < 0) - nr_gpios = 0; + int ret = 0; - pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple) + nr_gpios * - sizeof(struct gpio_desc *), GFP_KERNEL); + pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL); if (!pwrseq) return ERR_PTR(-ENOMEM); @@ -116,22 +111,12 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, goto free; } - for (i = 0; i < nr_gpios; i++) { - pwrseq->reset_gpios[i] = gpiod_get_index(dev, "reset", i, - GPIOD_OUT_HIGH); - if (IS_ERR(pwrseq->reset_gpios[i]) && - PTR_ERR(pwrseq->reset_gpios[i]) != -ENOENT && - PTR_ERR(pwrseq->reset_gpios[i]) != -ENOSYS) { - ret = PTR_ERR(pwrseq->reset_gpios[i]); - - while (i--) - gpiod_put(pwrseq->reset_gpios[i]); - - goto clk_put; - } + pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(pwrseq->reset_gpios)) { + ret = PTR_ERR(pwrseq->reset_gpios); + goto clk_put; } - pwrseq->nr_gpios = nr_gpios; pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; return &pwrseq->pwrseq; diff --git a/kernel/drivers/mmc/core/quirks.c b/kernel/drivers/mmc/core/quirks.c index dd1d1e0fe..fad660b95 100644 --- a/kernel/drivers/mmc/core/quirks.c +++ b/kernel/drivers/mmc/core/quirks.c @@ -35,25 +35,7 @@ #define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128 #endif -/* - * This hook just adds a quirk for all sdio devices - */ -static void add_quirk_for_sdio_devices(struct mmc_card *card, int data) -{ - if (mmc_card_sdio(card)) - card->quirks |= data; -} - static const struct mmc_fixup mmc_fixup_methods[] = { - /* by default sdio devices are considered CLK_GATING broken */ - /* good cards will be whitelisted as they are tested */ - SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID, - add_quirk_for_sdio_devices, - MMC_QUIRK_BROKEN_CLK_GATING), - - SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, - remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING), - SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, add_quirk, MMC_QUIRK_NONSTD_FUNC_IF), diff --git a/kernel/drivers/mmc/core/sd.c b/kernel/drivers/mmc/core/sd.c index 31a9ef256..967535d76 100644 --- a/kernel/drivers/mmc/core/sd.c +++ b/kernel/drivers/mmc/core/sd.c @@ -357,8 +357,6 @@ int mmc_sd_switch_hs(struct mmc_card *card) if (card->sw_caps.hs_max_dtr == 0) return 0; - err = -EIO; - status = kmalloc(64, GFP_KERNEL); if (!status) { pr_err("%s: could not allocate a buffer for " @@ -386,64 +384,31 @@ out: static int sd_select_driver_type(struct mmc_card *card, u8 *status) { - int host_drv_type = SD_DRIVER_TYPE_B; - int card_drv_type = SD_DRIVER_TYPE_B; - int drive_strength; + int card_drv_type, drive_strength, drv_type; int err; - /* - * If the host doesn't support any of the Driver Types A,C or D, - * or there is no board specific handler then default Driver - * Type B is used. - */ - if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C - | MMC_CAP_DRIVER_TYPE_D))) - return 0; - - if (!card->host->ops->select_drive_strength) - return 0; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) - host_drv_type |= SD_DRIVER_TYPE_A; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) - host_drv_type |= SD_DRIVER_TYPE_C; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_D) - host_drv_type |= SD_DRIVER_TYPE_D; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) - card_drv_type |= SD_DRIVER_TYPE_A; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) - card_drv_type |= SD_DRIVER_TYPE_C; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D) - card_drv_type |= SD_DRIVER_TYPE_D; + card->drive_strength = 0; - /* - * The drive strength that the hardware can support - * depends on the board design. Pass the appropriate - * information and let the hardware specific code - * return what is possible given the options - */ - mmc_host_clk_hold(card->host); - drive_strength = card->host->ops->select_drive_strength( - card->sw_caps.uhs_max_dtr, - host_drv_type, card_drv_type); - mmc_host_clk_release(card->host); + card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B; - err = mmc_sd_switch(card, 1, 2, drive_strength, status); - if (err) - return err; + drive_strength = mmc_select_drive_strength(card, + card->sw_caps.uhs_max_dtr, + card_drv_type, &drv_type); - if ((status[15] & 0xF) != drive_strength) { - pr_warn("%s: Problem setting drive strength!\n", - mmc_hostname(card->host)); - return 0; + if (drive_strength) { + err = mmc_sd_switch(card, 1, 2, drive_strength, status); + if (err) + return err; + if ((status[15] & 0xF) != drive_strength) { + pr_warn("%s: Problem setting drive strength!\n", + mmc_hostname(card->host)); + return 0; + } + card->drive_strength = drive_strength; } - mmc_set_driver_type(card->host, drive_strength); + if (drv_type) + mmc_set_driver_type(card->host, drv_type); return 0; } @@ -661,9 +626,25 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. */ if (!mmc_host_is_spi(card->host) && - (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || - card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) + (card->host->ios.timing == MMC_TIMING_UHS_SDR50 || + card->host->ios.timing == MMC_TIMING_UHS_DDR50 || + card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { err = mmc_execute_tuning(card); + + /* + * As SD Specifications Part1 Physical Layer Specification + * Version 3.01 says, CMD19 tuning is available for unlocked + * cards in transfer state of 1.8V signaling mode. The small + * difference between v3.00 and 3.01 spec means that CMD19 + * tuning is also available for DDR50 mode. + */ + if (err && card->host->ios.timing == MMC_TIMING_UHS_DDR50) { + pr_warn("%s: ddr50 tuning failed\n", + mmc_hostname(card->host)); + err = 0; + } + } + out: kfree(status); @@ -804,6 +785,26 @@ int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card) return 0; } +static int mmc_sd_get_ro(struct mmc_host *host) +{ + int ro; + + /* + * Some systems don't feature a write-protect pin and don't need one. + * E.g. because they only have micro-SD card slot. For those systems + * assume that the SD card is always read-write. + */ + if (host->caps2 & MMC_CAP2_NO_WRITE_PROTECT) + return 0; + + if (!host->ops->get_ro) + return -1; + + ro = host->ops->get_ro(host); + + return ro; +} + int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, bool reinit) { @@ -855,13 +856,7 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, * Check if read-only switch is active. */ if (!reinit) { - int ro = -1; - - if (host->ops->get_ro) { - mmc_host_clk_hold(card->host); - ro = host->ops->get_ro(host); - mmc_host_clk_release(card->host); - } + int ro = mmc_sd_get_ro(host); if (ro < 0) { pr_warn("%s: host does not support reading read-only switch, assuming write-enable\n", @@ -1181,21 +1176,10 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) return 0; } -static int mmc_sd_power_restore(struct mmc_host *host) -{ - int ret; - - mmc_claim_host(host); - ret = mmc_sd_init_card(host, host->card->ocr, host->card); - mmc_release_host(host); - - return ret; -} - static int mmc_sd_reset(struct mmc_host *host) { mmc_power_cycle(host, host->card->ocr); - return mmc_sd_power_restore(host); + return mmc_sd_init_card(host, host->card->ocr, host->card); } static const struct mmc_bus_ops mmc_sd_ops = { @@ -1205,7 +1189,6 @@ static const struct mmc_bus_ops mmc_sd_ops = { .runtime_resume = mmc_sd_runtime_resume, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, - .power_restore = mmc_sd_power_restore, .alive = mmc_sd_alive, .shutdown = mmc_sd_suspend, .reset = mmc_sd_reset, @@ -1260,14 +1243,13 @@ int mmc_attach_sd(struct mmc_host *host) mmc_release_host(host); err = mmc_add_card(host->card); - mmc_claim_host(host); if (err) goto remove_card; + mmc_claim_host(host); return 0; remove_card: - mmc_release_host(host); mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host); diff --git a/kernel/drivers/mmc/core/sdio.c b/kernel/drivers/mmc/core/sdio.c index 5bc6c7dbb..467b3cf80 100644 --- a/kernel/drivers/mmc/core/sdio.c +++ b/kernel/drivers/mmc/core/sdio.c @@ -402,69 +402,38 @@ static unsigned char host_drive_to_sdio_drive(int host_strength) static void sdio_select_driver_type(struct mmc_card *card) { - int host_drv_type = SD_DRIVER_TYPE_B; - int card_drv_type = SD_DRIVER_TYPE_B; - int drive_strength; + int card_drv_type, drive_strength, drv_type; unsigned char card_strength; int err; - /* - * If the host doesn't support any of the Driver Types A,C or D, - * or there is no board specific handler then default Driver - * Type B is used. - */ - if (!(card->host->caps & - (MMC_CAP_DRIVER_TYPE_A | - MMC_CAP_DRIVER_TYPE_C | - MMC_CAP_DRIVER_TYPE_D))) - return; - - if (!card->host->ops->select_drive_strength) - return; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) - host_drv_type |= SD_DRIVER_TYPE_A; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) - host_drv_type |= SD_DRIVER_TYPE_C; + card->drive_strength = 0; - if (card->host->caps & MMC_CAP_DRIVER_TYPE_D) - host_drv_type |= SD_DRIVER_TYPE_D; + card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B; - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) - card_drv_type |= SD_DRIVER_TYPE_A; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) - card_drv_type |= SD_DRIVER_TYPE_C; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D) - card_drv_type |= SD_DRIVER_TYPE_D; - - /* - * The drive strength that the hardware can support - * depends on the board design. Pass the appropriate - * information and let the hardware specific code - * return what is possible given the options - */ - drive_strength = card->host->ops->select_drive_strength( - card->sw_caps.uhs_max_dtr, - host_drv_type, card_drv_type); + drive_strength = mmc_select_drive_strength(card, + card->sw_caps.uhs_max_dtr, + card_drv_type, &drv_type); - /* if error just use default for drive strength B */ - err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0, - &card_strength); - if (err) - return; + if (drive_strength) { + /* if error just use default for drive strength B */ + err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0, + &card_strength); + if (err) + return; - card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT); - card_strength |= host_drive_to_sdio_drive(drive_strength); + card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT); + card_strength |= host_drive_to_sdio_drive(drive_strength); - err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH, - card_strength, NULL); + /* if error default to drive strength B */ + err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH, + card_strength, NULL); + if (err) + return; + card->drive_strength = drive_strength; + } - /* if error default to drive strength B */ - if (!err) - mmc_set_driver_type(card->host, drive_strength); + if (drv_type) + mmc_set_driver_type(card->host, drv_type); } @@ -566,8 +535,8 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. */ if (!mmc_host_is_spi(card->host) && - ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || - (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) + ((card->host->ios.timing == MMC_TIMING_UHS_SDR50) || + (card->host->ios.timing == MMC_TIMING_UHS_SDR104))) err = mmc_execute_tuning(card); out: return err; @@ -661,7 +630,7 @@ try_again: */ if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - ocr); + ocr_card); if (err == -EAGAIN) { sdio_reset(host); mmc_go_idle(host); @@ -928,14 +897,19 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host) */ static int mmc_sdio_suspend(struct mmc_host *host) { - if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { - mmc_claim_host(host); + mmc_claim_host(host); + + if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) sdio_disable_wide(host->card); - mmc_release_host(host); - } - if (!mmc_card_keep_power(host)) + if (!mmc_card_keep_power(host)) { mmc_power_off(host); + } else if (host->retune_period) { + mmc_retune_timer_stop(host); + mmc_retune_needed(host); + } + + mmc_release_host(host); return 0; } @@ -982,13 +956,10 @@ static int mmc_sdio_resume(struct mmc_host *host) } if (!err && host->sdio_irqs) { - if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { + if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) wake_up_process(host->sdio_irq_thread); - } else if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + else if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 1); - mmc_host_clk_release(host); - } } mmc_release_host(host); @@ -1045,14 +1016,29 @@ out: static int mmc_sdio_runtime_suspend(struct mmc_host *host) { /* No references to the card, cut the power to it. */ + mmc_claim_host(host); mmc_power_off(host); + mmc_release_host(host); + return 0; } static int mmc_sdio_runtime_resume(struct mmc_host *host) { + int ret; + /* Restore power and re-initialize. */ + mmc_claim_host(host); mmc_power_up(host, host->card->ocr); + ret = mmc_sdio_power_restore(host); + mmc_release_host(host); + + return ret; +} + +static int mmc_sdio_reset(struct mmc_host *host) +{ + mmc_power_cycle(host, host->card->ocr); return mmc_sdio_power_restore(host); } @@ -1066,6 +1052,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { .runtime_resume = mmc_sdio_runtime_resume, .power_restore = mmc_sdio_power_restore, .alive = mmc_sdio_alive, + .reset = mmc_sdio_reset, }; diff --git a/kernel/drivers/mmc/core/sdio_bus.c b/kernel/drivers/mmc/core/sdio_bus.c index bee02e644..7e327a6dd 100644 --- a/kernel/drivers/mmc/core/sdio_bus.c +++ b/kernel/drivers/mmc/core/sdio_bus.c @@ -137,6 +137,10 @@ static int sdio_bus_probe(struct device *dev) if (!id) return -ENODEV; + ret = dev_pm_domain_attach(dev, false); + if (ret == -EPROBE_DEFER) + return ret; + /* Unbound SDIO functions are always suspended. * During probe, the function is set active and the usage count * is incremented. If the driver supports runtime PM, @@ -166,6 +170,7 @@ static int sdio_bus_probe(struct device *dev) disable_runtimepm: if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) pm_runtime_put_noidle(dev); + dev_pm_domain_detach(dev, false); return ret; } @@ -197,6 +202,8 @@ static int sdio_bus_remove(struct device *dev) if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) pm_runtime_put_sync(dev); + dev_pm_domain_detach(dev, false); + return ret; } @@ -316,10 +323,8 @@ int sdio_add_func(struct sdio_func *func) sdio_set_of_node(func); sdio_acpi_set_handle(func); ret = device_add(&func->dev); - if (ret == 0) { + if (ret == 0) sdio_func_set_present(func); - dev_pm_domain_attach(&func->dev, false); - } return ret; } @@ -335,7 +340,6 @@ void sdio_remove_func(struct sdio_func *func) if (!sdio_func_present(func)) return; - dev_pm_domain_detach(&func->dev, false); device_del(&func->dev); of_node_put(func->dev.of_node); put_device(&func->dev); diff --git a/kernel/drivers/mmc/core/sdio_irq.c b/kernel/drivers/mmc/core/sdio_irq.c index 09cc67d02..91bbbfb29 100644 --- a/kernel/drivers/mmc/core/sdio_irq.c +++ b/kernel/drivers/mmc/core/sdio_irq.c @@ -168,21 +168,15 @@ static int sdio_irq_thread(void *_host) } set_current_state(TASK_INTERRUPTIBLE); - if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 1); - mmc_host_clk_release(host); - } if (!kthread_should_stop()) schedule_timeout(period); set_current_state(TASK_RUNNING); } while (!kthread_should_stop()); - if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 0); - mmc_host_clk_release(host); - } pr_debug("%s: IRQ thread exiting with code %d\n", mmc_hostname(host), ret); @@ -208,9 +202,7 @@ static int sdio_card_irq_get(struct mmc_card *card) return err; } } else if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); host->ops->enable_sdio_irq(host, 1); - mmc_host_clk_release(host); } } @@ -229,9 +221,7 @@ static int sdio_card_irq_put(struct mmc_card *card) atomic_set(&host->sdio_irq_thread_abort, 1); kthread_stop(host->sdio_irq_thread); } else if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); host->ops->enable_sdio_irq(host, 0); - mmc_host_clk_release(host); } } diff --git a/kernel/drivers/mmc/core/sdio_ops.h b/kernel/drivers/mmc/core/sdio_ops.h index 12a4d3ab1..5660c7f45 100644 --- a/kernel/drivers/mmc/core/sdio_ops.h +++ b/kernel/drivers/mmc/core/sdio_ops.h @@ -12,6 +12,8 @@ #ifndef _MMC_SDIO_OPS_H #define _MMC_SDIO_OPS_H +#include <linux/mmc/sdio.h> + int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, unsigned addr, u8 in, u8* out); @@ -19,5 +21,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); int sdio_reset(struct mmc_host *host); +static inline bool mmc_is_io_op(u32 opcode) +{ + return opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED; +} + #endif |