All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling
@ 2018-11-02 15:03 Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 02/13] mmc: tmio: Improve error handling Marek Vasut
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400
modes all use 1.8V signaling, while all the legacy modes use 3.3V
signaling. While there are extra modes which use 1.2V signaling,
the existing hardware does not support those.

Simplify the pinmux such that 3.3V signaling implies legacy mode
pinmux and the rest implies UHS mode pinmux. This prevents the
massive case statement from growing further. Moreover, it fixes
an edge case where during SD 1.8V switch, the bus mode is still
set to default while the signaling is already set to 1.8V, which
results in an attempt to communicate with a 1.8V card using pins
in 3.3V mode and thus communication failure.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 22 +++-------------------
 1 file changed, 3 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 138de59470..5f927c6150 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev)
 #endif
 
 #ifdef CONFIG_PINCTRL
-	switch (mmc->selected_mode) {
-	case MMC_LEGACY:
-	case SD_LEGACY:
-	case MMC_HS:
-	case SD_HS:
-	case MMC_HS_52:
-	case MMC_DDR_52:
-		pinctrl_select_state(dev, "default");
-		break;
-	case UHS_SDR12:
-	case UHS_SDR25:
-	case UHS_SDR50:
-	case UHS_DDR50:
-	case UHS_SDR104:
-	case MMC_HS_200:
+	if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
 		pinctrl_select_state(dev, "state_uhs");
-		break;
-	default:
-		break;
-	}
+	else
+		pinctrl_select_state(dev, "default");
 #endif
 }
 
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 02/13] mmc: tmio: Improve error handling
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 03/13] mmc: tmio: Silence transfer errors when tuning Marek Vasut
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Properly handle return values and abort operations when they are
non-zero. This is a minor improvement, which fixes two remaining
unchecked return values.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 5f927c6150..f1ce019db5 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -498,6 +498,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 			ret = tmio_sd_dma_xfer(dev, data);
 		else
 			ret = tmio_sd_pio_xfer(dev, data);
+		if (ret)
+			return ret;
 
 		ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
 					       TMIO_SD_INFO1_CMP);
@@ -505,9 +507,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 			return ret;
 	}
 
-	tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN);
-
-	return ret;
+	return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
+				    TMIO_SD_INFO2_SCLKDIVEN);
 }
 
 static int tmio_sd_set_bus_width(struct tmio_sd_priv *priv,
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 03/13] mmc: tmio: Silence transfer errors when tuning
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 02/13] mmc: tmio: Improve error handling Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 04/13] mmc: tmio: Configure clock before any other IOS Marek Vasut
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

In case the controller performs card tuning, that is, sends MMC
command 19 or 21, silence possible CRC error warning prints. The
warnings are bound to happen, since the tuning will fail for some
settings while searching for the optimal configuration of the bus
and that is perfectly OK.

This patch passes around the MMC command structure and adds check
into tmio_sd_check_error() to avoid printing CRC error warning
when the tuning happens.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 45 +++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index f1ce019db5..785b654671 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -95,7 +95,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size,
 		invalidate_dcache_range(addr, addr + size);
 }
 
-static int tmio_sd_check_error(struct udevice *dev)
+static int tmio_sd_check_error(struct udevice *dev, struct mmc_cmd *cmd)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	u32 info2 = tmio_sd_readl(priv, TMIO_SD_INFO2);
@@ -116,7 +116,9 @@ static int tmio_sd_check_error(struct udevice *dev)
 
 	if (info2 & (TMIO_SD_INFO2_ERR_END | TMIO_SD_INFO2_ERR_CRC |
 		     TMIO_SD_INFO2_ERR_IDX)) {
-		dev_err(dev, "communication out of sync\n");
+		if ((cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK) &&
+		    (cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200))
+			dev_err(dev, "communication out of sync\n");
 		return -EILSEQ;
 	}
 
@@ -129,8 +131,8 @@ static int tmio_sd_check_error(struct udevice *dev)
 	return 0;
 }
 
-static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
-				    u32 flag)
+static int tmio_sd_wait_for_irq(struct udevice *dev, struct mmc_cmd *cmd,
+				unsigned int reg, u32 flag)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	long wait = 1000000;
@@ -142,7 +144,7 @@ static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
 			return -ETIMEDOUT;
 		}
 
-		ret = tmio_sd_check_error(dev);
+		ret = tmio_sd_check_error(dev, cmd);
 		if (ret)
 			return ret;
 
@@ -178,15 +180,15 @@ tmio_pio_read_fifo(64, q)
 tmio_pio_read_fifo(32, l)
 tmio_pio_read_fifo(16, w)
 
-static int tmio_sd_pio_read_one_block(struct udevice *dev, char *pbuf,
-					  uint blocksize)
+static int tmio_sd_pio_read_one_block(struct udevice *dev, struct mmc_cmd *cmd,
+				      char *pbuf, uint blocksize)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	int ret;
 
 	/* wait until the buffer is filled with data */
-	ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
-				       TMIO_SD_INFO2_BRE);
+	ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
+				   TMIO_SD_INFO2_BRE);
 	if (ret)
 		return ret;
 
@@ -231,15 +233,15 @@ tmio_pio_write_fifo(64, q)
 tmio_pio_write_fifo(32, l)
 tmio_pio_write_fifo(16, w)
 
-static int tmio_sd_pio_write_one_block(struct udevice *dev,
+static int tmio_sd_pio_write_one_block(struct udevice *dev, struct mmc_cmd *cmd,
 					   const char *pbuf, uint blocksize)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	int ret;
 
 	/* wait until the buffer becomes empty */
-	ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
-				    TMIO_SD_INFO2_BWE);
+	ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
+				   TMIO_SD_INFO2_BWE);
 	if (ret)
 		return ret;
 
@@ -255,7 +257,8 @@ static int tmio_sd_pio_write_one_block(struct udevice *dev,
 	return 0;
 }
 
-static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
+static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_cmd *cmd,
+			    struct mmc_data *data)
 {
 	const char *src = data->src;
 	char *dest = data->dest;
@@ -263,10 +266,10 @@ static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
 
 	for (i = 0; i < data->blocks; i++) {
 		if (data->flags & MMC_DATA_READ)
-			ret = tmio_sd_pio_read_one_block(dev, dest,
+			ret = tmio_sd_pio_read_one_block(dev, cmd, dest,
 							     data->blocksize);
 		else
-			ret = tmio_sd_pio_write_one_block(dev, src,
+			ret = tmio_sd_pio_write_one_block(dev, cmd, src,
 							      data->blocksize);
 		if (ret)
 			return ret;
@@ -468,8 +471,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 		cmd->cmdidx, tmp, cmd->cmdarg);
 	tmio_sd_writel(priv, tmp, TMIO_SD_CMD);
 
-	ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
-				       TMIO_SD_INFO1_RSP);
+	ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1,
+				   TMIO_SD_INFO1_RSP);
 	if (ret)
 		return ret;
 
@@ -497,17 +500,17 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 		    tmio_sd_addr_is_dmaable(data->src))
 			ret = tmio_sd_dma_xfer(dev, data);
 		else
-			ret = tmio_sd_pio_xfer(dev, data);
+			ret = tmio_sd_pio_xfer(dev, cmd, data);
 		if (ret)
 			return ret;
 
-		ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
-					       TMIO_SD_INFO1_CMP);
+		ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1,
+					   TMIO_SD_INFO1_CMP);
 		if (ret)
 			return ret;
 	}
 
-	return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
+	return tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
 				    TMIO_SD_INFO2_SCLKDIVEN);
 }
 
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 04/13] mmc: tmio: Configure clock before any other IOS
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 02/13] mmc: tmio: Improve error handling Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 03/13] mmc: tmio: Silence transfer errors when tuning Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 05/13] mmc: tmio: Preinitialize regulator to 3.3V Marek Vasut
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Configure the clock settings before reconfiguring any other IO settings.
This is required when the clock must be stopped before changing eg. the
pin configuration or any of the other properties of the bus. Running the
clock configuration first allows the MMC core to do just that.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 785b654671..2a73829d99 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -642,11 +642,11 @@ int tmio_sd_set_ios(struct udevice *dev)
 	dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n",
 		mmc->clock, mmc->ddr_mode, mmc->bus_width);
 
+	tmio_sd_set_clk_rate(priv, mmc);
 	ret = tmio_sd_set_bus_width(priv, mmc);
 	if (ret)
 		return ret;
 	tmio_sd_set_ddr_mode(priv, mmc);
-	tmio_sd_set_clk_rate(priv, mmc);
 	tmio_sd_set_pins(dev);
 
 	return 0;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 05/13] mmc: tmio: Preinitialize regulator to 3.3V
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (2 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 04/13] mmc: tmio: Configure clock before any other IOS Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 06/13] mmc: tmio: Switch to clock framework Marek Vasut
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Preinitialize the SD card signals regulator to 3.3V, which is the
default post-reset setting, to be sure the regulator is set to a
valid value.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 2a73829d99..0eca83a0f4 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -720,6 +720,8 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 
 #ifdef CONFIG_DM_REGULATOR
 	device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev);
+	if (priv->vqmmc_dev)
+		regulator_set_value(priv->vqmmc_dev, 3300000);
 #endif
 
 	ret = mmc_of_parse(dev, &plat->cfg);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 06/13] mmc: tmio: Switch to clock framework
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (3 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 05/13] mmc: tmio: Preinitialize regulator to 3.3V Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 07/13] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Switch the driver to using clk_get_rate()/clk_set_rate() instead of
caching the mclk frequency in it's private data. This is required on
the SDHI variant of the controller, where the upstream mclk need to
be adjusted when using UHS modes.

Platforms which do not support clock framework or do not support it
in eg. SPL default to 100 MHz clock.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: - Fix build on certain platforms using SPL without clock framework
V3: - Turn clk_get_rate into a callback and fill it as needed on both
      renesas and socionext platforms
---
 drivers/mmc/renesas-sdhi.c | 21 +++++++++++++--------
 drivers/mmc/tmio-common.c  | 17 ++++++++++++++---
 drivers/mmc/tmio-common.h  |  5 ++++-
 drivers/mmc/uniphier-sd.c  | 30 ++++++++++++++++++++----------
 4 files changed, 51 insertions(+), 22 deletions(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index f8dc5f57ce..edb8e22d3c 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -328,15 +328,21 @@ static const struct udevice_id renesas_sdhi_match[] = {
 	{ /* sentinel */ }
 };
 
+static ulong renesas_sdhi_clk_get_rate(struct tmio_sd_priv *priv)
+{
+	return clk_get_rate(&priv->clk);
+}
+
 static int renesas_sdhi_probe(struct udevice *dev)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	u32 quirks = dev_get_driver_data(dev);
 	struct fdt_resource reg_res;
-	struct clk clk;
 	DECLARE_GLOBAL_DATA_PTR;
 	int ret;
 
+	priv->clk_get_rate = renesas_sdhi_clk_get_rate;
+
 	if (quirks == RENESAS_GEN2_QUIRKS) {
 		ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev),
 				       "reg", 0, &reg_res);
@@ -350,22 +356,21 @@ static int renesas_sdhi_probe(struct udevice *dev)
 			quirks |= TMIO_SD_CAP_16BIT;
 	}
 
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get host clock\n");
 		return ret;
 	}
 
 	/* set to max rate */
-	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
-	if (IS_ERR_VALUE(priv->mclk)) {
+	ret = clk_set_rate(&priv->clk, 200000000);
+	if (ret < 0) {
 		dev_err(dev, "failed to set rate for host clock\n");
-		clk_free(&clk);
-		return priv->mclk;
+		clk_free(&priv->clk);
+		return ret;
 	}
 
-	ret = clk_enable(&clk);
-	clk_free(&clk);
+	ret = clk_enable(&priv->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable host clock\n");
 		return ret;
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 0eca83a0f4..3ba2f07460 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -555,16 +555,24 @@ static void tmio_sd_set_ddr_mode(struct tmio_sd_priv *priv,
 	tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
 }
 
+static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+	return priv->clk_get_rate(priv);
+}
+
 static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
 				     struct mmc *mmc)
 {
 	unsigned int divisor;
 	u32 val, tmp;
+	ulong mclk;
 
 	if (!mmc->clock)
 		return;
 
-	divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
+	mclk = tmio_sd_clk_get_rate(priv);
+
+	divisor = DIV_ROUND_UP(mclk, mmc->clock);
 
 	if (divisor <= 1)
 		val = (priv->caps & TMIO_SD_CAP_RCAR) ?
@@ -708,6 +716,7 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	fdt_addr_t base;
+	ulong mclk;
 	int ret;
 
 	base = devfdt_get_addr(dev);
@@ -750,10 +759,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 
 	tmio_sd_host_init(priv);
 
+	mclk = tmio_sd_clk_get_rate(priv);
+
 	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
-	plat->cfg.f_min = priv->mclk /
+	plat->cfg.f_min = mclk /
 			(priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
-	plat->cfg.f_max = priv->mclk;
+	plat->cfg.f_max = mclk;
 	plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
 
 	upriv->mmc = &plat->mmc;
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 792b1ba5ae..6591c61c3c 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -117,7 +117,6 @@ struct tmio_sd_plat {
 
 struct tmio_sd_priv {
 	void __iomem			*regbase;
-	unsigned long			mclk;
 	unsigned int			version;
 	u32				caps;
 #define TMIO_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
@@ -133,6 +132,10 @@ struct tmio_sd_priv {
 #ifdef CONFIG_DM_REGULATOR
 	struct udevice *vqmmc_dev;
 #endif
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk			clk;
+#endif
+	ulong (*clk_get_rate)(struct tmio_sd_priv *);
 };
 
 int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 813c28494c..6539880ab5 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -31,35 +31,45 @@ static const struct udevice_id uniphier_sd_match[] = {
 	{ /* sentinel */ }
 };
 
+static ulong uniphier_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+#if CONFIG_IS_ENABLED(CLK)
+	return clk_get_rate(&priv->clk);
+#elif CONFIG_SPL_BUILD
+	return 100000000;
+#else
+	return 0;
+#endif
+}
+
 static int uniphier_sd_probe(struct udevice *dev)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	priv->clk_get_rate = uniphier_sd_clk_get_rate;
+
 #ifndef CONFIG_SPL_BUILD
-	struct clk clk;
 	int ret;
 
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get host clock\n");
 		return ret;
 	}
 
 	/* set to max rate */
-	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
-	if (IS_ERR_VALUE(priv->mclk)) {
+	ret = clk_set_rate(&priv->clk, ULONG_MAX);
+	if (ret < 0) {
 		dev_err(dev, "failed to set rate for host clock\n");
-		clk_free(&clk);
-		return priv->mclk;
+		clk_free(&priv->clk);
+		return ret;
 	}
 
-	ret = clk_enable(&clk);
-	clk_free(&clk);
+	ret = clk_enable(&priv->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable host clock\n");
 		return ret;
 	}
-#else
-	priv->mclk = 100000000;
 #endif
 
 	return tmio_sd_probe(dev, 0);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 07/13] mmc: tmio: Do not set divider to 1 in DDR mode
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (4 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 06/13] mmc: tmio: Switch to clock framework Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 08/13] mmc: tmio: Keep generating clock when clock are enabled Marek Vasut
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

The TMIO core has a quirk where divider == 1 must not be set in DDR modes.
Handle this by setting divider to 2, as suggested in the documentation.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 3ba2f07460..424b60ce52 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -574,6 +574,10 @@ static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
 
 	divisor = DIV_ROUND_UP(mclk, mmc->clock);
 
+	/* Do not set divider to 0xff in DDR mode */
+	if (mmc->ddr_mode && (divisor == 1))
+		divisor = 2;
+
 	if (divisor <= 1)
 		val = (priv->caps & TMIO_SD_CAP_RCAR) ?
 		      TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 08/13] mmc: tmio: Keep generating clock when clock are enabled
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (5 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 07/13] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 09/13] mmc: tmio: sdhi: Touch SCC only when UHS capable Marek Vasut
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

The TMIO core has a feature where it can automatically disable clock output
when the bus is not in use. While this is useful, it also interferes with
switching the bus to 1.8V and other background tasks of the SD/MMC cards,
which require clock to be enabled.

This patch respects the mmc->clk_disable and only disables the clock when
the MMC core requests it. Otherwise the clock are continuously generated
on the bus.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/tmio-common.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 424b60ce52..fad2816ca5 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -612,10 +612,16 @@ static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
 	tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
-	tmp |= val | TMIO_SD_CLKCTL_OFFEN;
+	tmp |= val;
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
-	tmp |= TMIO_SD_CLKCTL_SCLKEN;
+	if (!mmc->clk_disable) {
+		tmp &= ~TMIO_SD_CLKCTL_OFFEN;
+		tmp |= TMIO_SD_CLKCTL_SCLKEN;
+	} else {
+		tmp |= TMIO_SD_CLKCTL_OFFEN;
+		tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+	}
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
 	udelay(1000);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 09/13] mmc: tmio: sdhi: Touch SCC only when UHS capable
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (6 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 08/13] mmc: tmio: Keep generating clock when clock are enabled Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 10/13] mmc: tmio: sdhi: Clear HS400 settings when resetting SCC Marek Vasut
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Add check to avoid touching the SCC tuning registers in case the IP
doesn't support them or if the support isn't in place yet.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/renesas-sdhi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index edb8e22d3c..465663ba97 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -294,7 +294,8 @@ static int renesas_sdhi_set_ios(struct udevice *dev)
 #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 
-	renesas_sdhi_reset_tuning(priv);
+	if (priv->caps & TMIO_SD_CAP_RCAR_UHS)
+		renesas_sdhi_reset_tuning(priv);
 #endif
 
 	return ret;
@@ -378,7 +379,7 @@ static int renesas_sdhi_probe(struct udevice *dev)
 
 	ret = tmio_sd_probe(dev, quirks);
 #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
-	if (!ret)
+	if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS))
 		renesas_sdhi_reset_tuning(priv);
 #endif
 	return ret;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 10/13] mmc: tmio: sdhi: Clear HS400 settings when resetting SCC
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (7 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 09/13] mmc: tmio: sdhi: Touch SCC only when UHS capable Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 11/13] mmc: tmio: sdhi: Implement waiting for DAT0 line state Marek Vasut
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Make sure to clear HS400 configuration when resetting the SCC block.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/renesas-sdhi.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 465663ba97..884b4a5cc8 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -34,6 +34,8 @@
 #define   RENESAS_SDHI_SCC_RVSREQ_RVSERR		BIT(2)
 #define RENESAS_SDHI_SCC_SMPCMP			0x818
 #define RENESAS_SDHI_SCC_TMPPORT2			0x81c
+#define   RENESAS_SDHI_SCC_TMPPORT2_HS400EN		BIT(31)
+#define   RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL		BIT(4)
 
 #define RENESAS_SDHI_MAX_TAP 3
 
@@ -90,6 +92,11 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
 	reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL;
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
 
+	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2);
+	reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
+		 RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
+	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
+
 	reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
 	reg |= TMIO_SD_CLKCTL_SCLKEN;
 	tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 11/13] mmc: tmio: sdhi: Implement waiting for DAT0 line state
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (8 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 10/13] mmc: tmio: sdhi: Clear HS400 settings when resetting SCC Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 12/13] mmc: tmio: sdhi: Switch CPG settings in UHS modes Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 13/13] mmc: tmio: sdhi: Merge DTCNTL access into single register write Marek Vasut
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

When the bus switches to 1.8V mode of operation, it is necessary to
verify that the card correctly initiated and completed the voltage
switch. This is done by reading out the state of DATA0 line.

This patch implement support for reading out the state of the DATA0
line, so the MMC core code can correctly switch to 1.8V mode.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/renesas-sdhi.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 884b4a5cc8..73f6bf1562 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -308,13 +308,38 @@ static int renesas_sdhi_set_ios(struct udevice *dev)
 	return ret;
 }
 
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout)
+{
+	int ret = -ETIMEDOUT;
+	bool dat0_high;
+	bool target_dat0_high = !!state;
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */
+	while (timeout--) {
+		dat0_high = !!(tmio_sd_readl(priv, TMIO_SD_INFO2) & TMIO_SD_INFO2_DAT0);
+		if (dat0_high == target_dat0_high) {
+			ret = 0;
+			break;
+		}
+		udelay(10);
+	}
+
+	return ret;
+}
+#endif
+
 static const struct dm_mmc_ops renesas_sdhi_ops = {
 	.send_cmd = tmio_sd_send_cmd,
 	.set_ios = renesas_sdhi_set_ios,
 	.get_cd = tmio_sd_get_cd,
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
 	.execute_tuning = renesas_sdhi_execute_tuning,
 #endif
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+	.wait_dat0 = renesas_sdhi_wait_dat0,
+#endif
 };
 
 #define RENESAS_GEN2_QUIRKS	TMIO_SD_CAP_RCAR_GEN2
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 12/13] mmc: tmio: sdhi: Switch CPG settings in UHS modes
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (9 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 11/13] mmc: tmio: sdhi: Implement waiting for DAT0 line state Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 13/13] mmc: tmio: sdhi: Merge DTCNTL access into single register write Marek Vasut
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

Switch CPG settings when transitioning between HS200/HS400/SDR104
and regular modes. This is required for the SCC block to operate
correctly.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/renesas-sdhi.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 73f6bf1562..9a454ef949 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -292,9 +292,35 @@ out:
 }
 #endif
 
+static void renesas_sdhi_set_clk(struct udevice *dev)
+{
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	u32 tmp;
+
+	if (!mmc->clock)
+		return;
+
+	/* Stop the clock before changing its rate to avoid a glitch signal */
+	tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
+	tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+
+	if ((mmc->selected_mode == UHS_SDR104) ||
+	    (mmc->selected_mode == MMC_HS_200)) {
+		clk_set_rate(&priv->clk, 400000000);
+	} else {
+		clk_set_rate(&priv->clk, 200000000);
+	}
+}
+
 static int renesas_sdhi_set_ios(struct udevice *dev)
 {
-	int ret = tmio_sd_set_ios(dev);
+	int ret;
+
+	renesas_sdhi_set_clk(dev);
+
+	ret = tmio_sd_set_ios(dev);
 
 	mdelay(10);
 
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH V3 13/13] mmc: tmio: sdhi: Merge DTCNTL access into single register write
  2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
                   ` (10 preceding siblings ...)
  2018-11-02 15:03 ` [U-Boot] [PATCH V3 12/13] mmc: tmio: sdhi: Switch CPG settings in UHS modes Marek Vasut
@ 2018-11-02 15:03 ` Marek Vasut
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Vasut @ 2018-11-02 15:03 UTC (permalink / raw)
  To: u-boot

It is perfectly fine to write th DTCNTL TAP count and enable the
SCC sampling clock operation in the same write.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: No change
V3: No change
---
 drivers/mmc/renesas-sdhi.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 9a454ef949..fd2a361a6d 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -51,12 +51,9 @@ static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv)
 	tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
 
 	/* Set sampling clock selection range */
-	tmio_sd_writel(priv, 0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT,
-			   RENESAS_SDHI_SCC_DTCNTL);
-
-	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL);
-	reg |= RENESAS_SDHI_SCC_DTCNTL_TAPEN;
-	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_DTCNTL);
+	tmio_sd_writel(priv, (0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
+			     RENESAS_SDHI_SCC_DTCNTL_TAPEN,
+			     RENESAS_SDHI_SCC_DTCNTL);
 
 	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
 	reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2018-11-02 15:03 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-02 15:03 [U-Boot] [PATCH V3 01/13] mmc: tmio: Simplify pinmux handling Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 02/13] mmc: tmio: Improve error handling Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 03/13] mmc: tmio: Silence transfer errors when tuning Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 04/13] mmc: tmio: Configure clock before any other IOS Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 05/13] mmc: tmio: Preinitialize regulator to 3.3V Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 06/13] mmc: tmio: Switch to clock framework Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 07/13] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 08/13] mmc: tmio: Keep generating clock when clock are enabled Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 09/13] mmc: tmio: sdhi: Touch SCC only when UHS capable Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 10/13] mmc: tmio: sdhi: Clear HS400 settings when resetting SCC Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 11/13] mmc: tmio: sdhi: Implement waiting for DAT0 line state Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 12/13] mmc: tmio: sdhi: Switch CPG settings in UHS modes Marek Vasut
2018-11-02 15:03 ` [U-Boot] [PATCH V3 13/13] mmc: tmio: sdhi: Merge DTCNTL access into single register write Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.