Commit 371e4a1f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MMC fixes from Ulf Hansson:
 "MMC core:
   - Fix eMMC initialization with 1-bit bus connection

  MMC host:
   - mmci: Fix DMA API overlapping mappings for the stm32 variant
   - sdhci-xenon: Fix PHY stability issues"

* tag 'mmc-v6.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci-xenon: add timeout for PHY init complete
  mmc: sdhci-xenon: fix PHY init clock stability
  mmc: mmci: stm32: fix DMA API overlapping mappings warning
  mmc: core: Fix eMMC initialization with 1-bit bus connection
parents fafbad4a 09e23823
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1015,10 +1015,12 @@ static int mmc_select_bus_width(struct mmc_card *card)
	static unsigned ext_csd_bits[] = {
		EXT_CSD_BUS_WIDTH_8,
		EXT_CSD_BUS_WIDTH_4,
		EXT_CSD_BUS_WIDTH_1,
	};
	static unsigned bus_widths[] = {
		MMC_BUS_WIDTH_8,
		MMC_BUS_WIDTH_4,
		MMC_BUS_WIDTH_1,
	};
	struct mmc_host *host = card->host;
	unsigned idx, bus_width = 0;
+24 −0
Original line number Diff line number Diff line
@@ -225,6 +225,8 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
	struct scatterlist *sg;
	int i;

	host->dma_in_progress = true;

	if (!host->variant->dma_lli || data->sg_len == 1 ||
	    idma->use_bounce_buffer) {
		u32 dma_addr;
@@ -263,9 +265,30 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
	return 0;
}

static void sdmmc_idma_error(struct mmci_host *host)
{
	struct mmc_data *data = host->data;
	struct sdmmc_idma *idma = host->dma_priv;

	if (!dma_inprogress(host))
		return;

	writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);
	host->dma_in_progress = false;
	data->host_cookie = 0;

	if (!idma->use_bounce_buffer)
		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
			     mmc_get_dma_dir(data));
}

static void sdmmc_idma_finalize(struct mmci_host *host, struct mmc_data *data)
{
	if (!dma_inprogress(host))
		return;

	writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);
	host->dma_in_progress = false;

	if (!data->host_cookie)
		sdmmc_idma_unprep_data(host, data, 0);
@@ -676,6 +699,7 @@ static struct mmci_host_ops sdmmc_variant_ops = {
	.dma_setup = sdmmc_idma_setup,
	.dma_start = sdmmc_idma_start,
	.dma_finalize = sdmmc_idma_finalize,
	.dma_error = sdmmc_idma_error,
	.set_clkreg = mmci_sdmmc_set_clkreg,
	.set_pwrreg = mmci_sdmmc_set_pwrreg,
	.busy_complete = sdmmc_busy_complete,
+39 −9
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/iopoll.h>
#include <linux/of_address.h>

#include "sdhci-pltfm.h"
@@ -109,6 +110,8 @@
#define XENON_EMMC_PHY_LOGIC_TIMING_ADJUST	(XENON_EMMC_PHY_REG_BASE + 0x18)
#define XENON_LOGIC_TIMING_VALUE		0x00AA8977

#define XENON_MAX_PHY_TIMEOUT_LOOPS		100

/*
 * List offset of PHY registers and some special register values
 * in eMMC PHY 5.0 or eMMC PHY 5.1
@@ -216,6 +219,19 @@ static int xenon_alloc_emmc_phy(struct sdhci_host *host)
	return 0;
}

static int xenon_check_stability_internal_clk(struct sdhci_host *host)
{
	u32 reg;
	int err;

	err = read_poll_timeout(sdhci_readw, reg, reg & SDHCI_CLOCK_INT_STABLE,
				1100, 20000, false, host, SDHCI_CLOCK_CONTROL);
	if (err)
		dev_err(mmc_dev(host->mmc), "phy_init: Internal clock never stabilized.\n");

	return err;
}

/*
 * eMMC 5.0/5.1 PHY init/re-init.
 * eMMC PHY init should be executed after:
@@ -232,6 +248,11 @@ static int xenon_emmc_phy_init(struct sdhci_host *host)
	struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
	struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;

	int ret = xenon_check_stability_internal_clk(host);

	if (ret)
		return ret;

	reg = sdhci_readl(host, phy_regs->timing_adj);
	reg |= XENON_PHY_INITIALIZAION;
	sdhci_writel(host, reg, phy_regs->timing_adj);
@@ -259,18 +280,27 @@ static int xenon_emmc_phy_init(struct sdhci_host *host)
	/* get the wait time */
	wait /= clock;
	wait++;
	/* wait for host eMMC PHY init completes */
	udelay(wait);

	reg = sdhci_readl(host, phy_regs->timing_adj);
	reg &= XENON_PHY_INITIALIZAION;
	if (reg) {
	/*
	 * AC5X spec says bit must be polled until zero.
	 * We see cases in which timeout can take longer
	 * than the standard calculation on AC5X, which is
	 * expected following the spec comment above.
	 * According to the spec, we must wait as long as
	 * it takes for that bit to toggle on AC5X.
	 * Cap that with 100 delay loops so we won't get
	 * stuck here forever:
	 */

	ret = read_poll_timeout(sdhci_readl, reg,
				!(reg & XENON_PHY_INITIALIZAION),
				wait, XENON_MAX_PHY_TIMEOUT_LOOPS * wait,
				false, host, phy_regs->timing_adj);
	if (ret)
		dev_err(mmc_dev(host->mmc), "eMMC PHY init cannot complete after %d us\n",
			wait);
		return -ETIMEDOUT;
	}
			wait * XENON_MAX_PHY_TIMEOUT_LOOPS);

	return 0;
	return ret;
}

#define ARMADA_3700_SOC_PAD_1_8V	0x1