Commit 0ccab014 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Improve API to make it clear that mmc_hw_reset() is for cards
   - Fixup support for writeback-cache for eMMC and SD
   - Check for errors after writes on SPI

  MMC host:
   - renesas_sdhi: A couple of fixes of TAP settings for eMMC HS400 mode
   - mmci_stm32: Fixup check of all elements in sg list
   - sdhci-xenon: Revert unnecessary fix for annoying 1.8V regulator warning"

* tag 'mmc-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: core: improve API to make clear mmc_hw_reset is for cards
  mmc: renesas_sdhi: don't overwrite TAP settings when HS400 tuning is complete
  mmc: renesas_sdhi: special 4tap settings only apply to HS400
  mmc: core: Fixup support for writeback-cache for eMMC and SD
  mmc: block: Check for errors after write on SPI
  mmc: mmci: stm32: correctly check all elements of sg list
  Revert "mmc: sdhci-xenon: fix annoying 1.8V regulator warning"
parents 02994fd2 b71597ed
...@@ -993,7 +993,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, ...@@ -993,7 +993,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
return -EEXIST; return -EEXIST;
md->reset_done |= type; md->reset_done |= type;
err = mmc_hw_reset(host); err = mmc_hw_reset(host->card);
/* Ensure we switch back to the correct partition */ /* Ensure we switch back to the correct partition */
if (err) { if (err) {
struct mmc_blk_data *main_md = struct mmc_blk_data *main_md =
...@@ -1880,6 +1880,31 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq) ...@@ -1880,6 +1880,31 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq)
brq->data.error || brq->cmd.resp[0] & CMD_ERRORS; brq->data.error || brq->cmd.resp[0] & CMD_ERRORS;
} }
static int mmc_spi_err_check(struct mmc_card *card)
{
u32 status = 0;
int err;
/*
* SPI does not have a TRAN state we have to wait on, instead the
* card is ready again when it no longer holds the line LOW.
* We still have to ensure two things here before we know the write
* was successful:
* 1. The card has not disconnected during busy and we actually read our
* own pull-up, thinking it was still connected, so ensure it
* still responds.
* 2. Check for any error bits, in particular R1_SPI_IDLE to catch a
* just reconnected card after being disconnected during busy.
*/
err = __mmc_send_status(card, &status, 0);
if (err)
return err;
/* All R1 and R2 bits of SPI are errors in our case */
if (status)
return -EIO;
return 0;
}
static int mmc_blk_busy_cb(void *cb_data, bool *busy) static int mmc_blk_busy_cb(void *cb_data, bool *busy)
{ {
struct mmc_blk_busy_data *data = cb_data; struct mmc_blk_busy_data *data = cb_data;
...@@ -1903,9 +1928,16 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req) ...@@ -1903,9 +1928,16 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
struct mmc_blk_busy_data cb_data; struct mmc_blk_busy_data cb_data;
int err; int err;
if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ) if (rq_data_dir(req) == READ)
return 0; return 0;
if (mmc_host_is_spi(card->host)) {
err = mmc_spi_err_check(card);
if (err)
mqrq->brq.data.bytes_xfered = 0;
return err;
}
cb_data.card = card; cb_data.card = card;
cb_data.status = 0; cb_data.status = 0;
err = __mmc_poll_for_busy(card->host, 0, MMC_BLK_TIMEOUT_MS, err = __mmc_poll_for_busy(card->host, 0, MMC_BLK_TIMEOUT_MS,
...@@ -2350,6 +2382,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, ...@@ -2350,6 +2382,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct mmc_blk_data *md; struct mmc_blk_data *md;
int devidx, ret; int devidx, ret;
char cap_str[10]; char cap_str[10];
bool cache_enabled = false;
bool fua_enabled = false;
devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL); devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL);
if (devidx < 0) { if (devidx < 0) {
...@@ -2429,13 +2463,17 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, ...@@ -2429,13 +2463,17 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
md->flags |= MMC_BLK_CMD23; md->flags |= MMC_BLK_CMD23;
} }
if (mmc_card_mmc(card) && if (md->flags & MMC_BLK_CMD23 &&
md->flags & MMC_BLK_CMD23 &&
((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
card->ext_csd.rel_sectors)) { card->ext_csd.rel_sectors)) {
md->flags |= MMC_BLK_REL_WR; md->flags |= MMC_BLK_REL_WR;
blk_queue_write_cache(md->queue.queue, true, true); fua_enabled = true;
cache_enabled = true;
} }
if (mmc_cache_enabled(card->host))
cache_enabled = true;
blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);
string_get_size((u64)size, 512, STRING_UNITS_2, string_get_size((u64)size, 512, STRING_UNITS_2,
cap_str, sizeof(cap_str)); cap_str, sizeof(cap_str));
......
...@@ -1995,7 +1995,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) ...@@ -1995,7 +1995,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
/** /**
* mmc_hw_reset - reset the card in hardware * mmc_hw_reset - reset the card in hardware
* @host: MMC host to which the card is attached * @card: card to be reset
* *
* Hard reset the card. This function is only for upper layers, like the * Hard reset the card. This function is only for upper layers, like the
* block layer or card drivers. You cannot use it in host drivers (struct * block layer or card drivers. You cannot use it in host drivers (struct
...@@ -2003,8 +2003,9 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) ...@@ -2003,8 +2003,9 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
* *
* Return: 0 on success, -errno on failure * Return: 0 on success, -errno on failure
*/ */
int mmc_hw_reset(struct mmc_host *host) int mmc_hw_reset(struct mmc_card *card)
{ {
struct mmc_host *host = card->host;
int ret; int ret;
ret = host->bus_ops->hw_reset(host); ret = host->bus_ops->hw_reset(host);
......
...@@ -2325,10 +2325,9 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test) ...@@ -2325,10 +2325,9 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
static int mmc_test_reset(struct mmc_test_card *test) static int mmc_test_reset(struct mmc_test_card *test)
{ {
struct mmc_card *card = test->card; struct mmc_card *card = test->card;
struct mmc_host *host = card->host;
int err; int err;
err = mmc_hw_reset(host); err = mmc_hw_reset(card);
if (!err) { if (!err) {
/* /*
* Reset will re-enable the card's command queue, but tests * Reset will re-enable the card's command queue, but tests
......
...@@ -62,8 +62,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host, ...@@ -62,8 +62,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
* excepted the last element which has no constraint on idmasize * excepted the last element which has no constraint on idmasize
*/ */
for_each_sg(data->sg, sg, data->sg_len - 1, i) { for_each_sg(data->sg, sg, data->sg_len - 1, i) {
if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) || if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
!IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) { !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"unaligned scatterlist: ofst:%x length:%d\n", "unaligned scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length); data->sg->offset, data->sg->length);
...@@ -71,7 +71,7 @@ static int sdmmc_idma_validate_data(struct mmci_host *host, ...@@ -71,7 +71,7 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
} }
} }
if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) { if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"unaligned last scatterlist: ofst:%x length:%d\n", "unaligned last scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length); data->sg->offset, data->sg->length);
......
...@@ -144,9 +144,9 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host, ...@@ -144,9 +144,9 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
return clk_get_rate(priv->clk); return clk_get_rate(priv->clk);
if (priv->clkh) { if (priv->clkh) {
/* HS400 with 4TAP needs different clock settings */
bool use_4tap = priv->quirks && priv->quirks->hs400_4taps; bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
bool need_slow_clkh = (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) || bool need_slow_clkh = host->mmc->ios.timing == MMC_TIMING_MMC_HS400;
(host->mmc->ios.timing == MMC_TIMING_MMC_HS400);
clkh_shift = use_4tap && need_slow_clkh ? 1 : 2; clkh_shift = use_4tap && need_slow_clkh ? 1 : 2;
ref_clk = priv->clkh; ref_clk = priv->clkh;
} }
...@@ -396,10 +396,10 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) ...@@ -396,10 +396,10 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) | SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2)); sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));
/* Set the sampling clock selection range of HS400 mode */
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL, sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN | SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
0x4 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT); sd_scc_read32(host, priv,
SH_MOBILE_SDHI_SCC_DTCNTL));
/* Avoid bad TAP */ /* Avoid bad TAP */
if (bad_taps & BIT(priv->tap_set)) { if (bad_taps & BIT(priv->tap_set)) {
......
...@@ -241,16 +241,6 @@ static void xenon_voltage_switch(struct sdhci_host *host) ...@@ -241,16 +241,6 @@ static void xenon_voltage_switch(struct sdhci_host *host)
{ {
/* Wait for 5ms after set 1.8V signal enable bit */ /* Wait for 5ms after set 1.8V signal enable bit */
usleep_range(5000, 5500); usleep_range(5000, 5500);
/*
* For some reason the controller's Host Control2 register reports
* the bit representing 1.8V signaling as 0 when read after it was
* written as 1. Subsequent read reports 1.
*
* Since this may cause some issues, do an empty read of the Host
* Control2 register here to circumvent this.
*/
sdhci_readw(host, SDHCI_HOST_CONTROL2);
} }
static unsigned int xenon_get_max_clock(struct sdhci_host *host) static unsigned int xenon_get_max_clock(struct sdhci_host *host)
......
...@@ -1633,7 +1633,7 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar) ...@@ -1633,7 +1633,7 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar)
return; return;
} }
ret = mmc_hw_reset(ar_sdio->func->card->host); ret = mmc_hw_reset(ar_sdio->func->card);
if (ret) if (ret)
ath10k_warn(ar, "unable to reset sdio: %d\n", ret); ath10k_warn(ar, "unable to reset sdio: %d\n", ret);
......
...@@ -4165,7 +4165,7 @@ static int brcmf_sdio_bus_reset(struct device *dev) ...@@ -4165,7 +4165,7 @@ static int brcmf_sdio_bus_reset(struct device *dev)
/* reset the adapter */ /* reset the adapter */
sdio_claim_host(sdiodev->func1); sdio_claim_host(sdiodev->func1);
mmc_hw_reset(sdiodev->func1->card->host); mmc_hw_reset(sdiodev->func1->card);
sdio_release_host(sdiodev->func1); sdio_release_host(sdiodev->func1);
brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN); brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
......
...@@ -2639,7 +2639,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) ...@@ -2639,7 +2639,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
/* Run a HW reset of the SDIO interface. */ /* Run a HW reset of the SDIO interface. */
sdio_claim_host(func); sdio_claim_host(func);
ret = mmc_hw_reset(func->card->host); ret = mmc_hw_reset(func->card);
sdio_release_host(func); sdio_release_host(func);
switch (ret) { switch (ret) {
......
...@@ -146,7 +146,7 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) ...@@ -146,7 +146,7 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
* To guarantee that the SDIO card is power cycled, as required to make * To guarantee that the SDIO card is power cycled, as required to make
* the FW programming to succeed, let's do a brute force HW reset. * the FW programming to succeed, let's do a brute force HW reset.
*/ */
mmc_hw_reset(card->host); mmc_hw_reset(card);
sdio_enable_func(func); sdio_enable_func(func);
sdio_release_host(func); sdio_release_host(func);
......
...@@ -175,7 +175,7 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq); ...@@ -175,7 +175,7 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq);
int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
int retries); int retries);
int mmc_hw_reset(struct mmc_host *host); int mmc_hw_reset(struct mmc_card *card);
int mmc_sw_reset(struct mmc_host *host); int mmc_sw_reset(struct mmc_host *host);
void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card); void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment