linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] Update the pad autocal procedure
@ 2018-07-24 14:29 Aapo Vienamo
  2018-07-24 14:29 ` [PATCH 01/10] mmc: tegra: Poll for calibration completion Aapo Vienamo
                   ` (3 more replies)
  0 siblings, 4 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Hi all,

Update the tegra_sdhci_pad_autocalib() pad drive strength calibration
procedure to match the ones specified in the TRMs of the more recent
SoCs. This was tested on Tegra186, Tegra210, and Tegra124, although it
should not break things older generations either.

This series depends on the "Tegra SDHCI enable 1.8 V signaling on
Tegar210 and Tegra186" series posted earlier.

Aapo Vienamo (10):
  mmc: tegra: Poll for calibration completion
  mmc: tegra: Set calibration pad voltage reference
  mmc: tegra: Power on the calibration pad
  mmc: tegra: Disable card clock during pad calibration
  dt-bindings: Add Tegra SDHCI pad pdpu offset bindings
  mmc: tegra: Program pad autocal offsets from dt
  arm64: dts: tegra186: Add sdmmc pad auto calibration offsets
  arm64: dts: tegra210: Add sdmmc pad auto calibration offsets
  mmc: tegra: Perform pad calibration after voltage switch
  mmc: tegra: Enable pad calibration on Tegra210 and Tegra186

 .../bindings/mmc/nvidia,tegra20-sdhci.txt          |  32 +++
 arch/arm64/boot/dts/nvidia/tegra186.dtsi           |  20 ++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  12 +
 drivers/mmc/host/sdhci-tegra.c                     | 242 ++++++++++++++++++++-
 4 files changed, 297 insertions(+), 9 deletions(-)

-- 
2.7.4


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

* [PATCH 01/10] mmc: tegra: Poll for calibration completion
  2018-07-24 14:29 [PATCH 00/10] Update the pad autocal procedure Aapo Vienamo
@ 2018-07-24 14:29 ` Aapo Vienamo
  2018-07-25  7:04   ` Mikko Perttunen
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:29 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Implement polling with 10 ms timeout for automatic pad drive strength
calibration.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f108c48..e40ca43 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -49,6 +49,9 @@
 #define SDHCI_AUTO_CAL_START			BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
 
+#define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
+#define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)
+
 #define NVQUIRK_FORCE_SDHCI_SPEC_200	BIT(0)
 #define NVQUIRK_ENABLE_BLOCK_GAP_DET	BIT(1)
 #define NVQUIRK_ENABLE_SDHCI_SPEC_300	BIT(2)
@@ -198,13 +201,24 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
-	u32 val;
+	unsigned timeout = 10;
+	u32 reg;
 
-	mdelay(1);
+	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+	reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
+	sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+	udelay(1);
+
+	do {
+		reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_STATUS);
+		if (!(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE))
+			break;
+		mdelay(1);
+		timeout--;
+	} while (timeout);
 
-	val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
-	val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
-	sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+	if (timeout == 0)
+		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
 
 static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
-- 
2.7.4


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

* [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference
  2018-07-24 14:29 [PATCH 00/10] Update the pad autocal procedure Aapo Vienamo
  2018-07-24 14:29 ` [PATCH 01/10] mmc: tegra: Poll for calibration completion Aapo Vienamo
@ 2018-07-24 14:34 ` Aapo Vienamo
  2018-07-24 14:34   ` [PATCH 03/10] mmc: tegra: Power on the calibration pad Aapo Vienamo
                     ` (7 more replies)
  2018-07-25 12:06 ` [PATCH 00/10] Update the pad autocal procedure Peter Geis
  2018-07-25 14:27 ` [PATCH 10/10] mmc: tegra: Enable pad calibration on Tegra210 and Tegra186 Aapo Vienamo
  3 siblings, 8 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Configure the voltage reference used by the automatic pad drive strength
calibration procedure. The value is a magic number from the TRM.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e40ca43..6008e2f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -49,6 +49,10 @@
 #define SDHCI_AUTO_CAL_START			BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
 
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL	0x7
+
 #define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
 #define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)
 
@@ -152,7 +156,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
 	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
-	u32 misc_ctrl, clk_ctrl;
+	u32 misc_ctrl, clk_ctrl, pad_ctrl;
 
 	sdhci_reset(host, mask);
 
@@ -193,8 +197,14 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 	sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
 	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
 
-	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
+	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) {
+		pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+		pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK;
+		pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL;
+		sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+
 		tegra_host->pad_calib_required = true;
+	}
 
 	tegra_host->ddr_signaling = false;
 }
-- 
2.7.4


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

* [PATCH 03/10] mmc: tegra: Power on the calibration pad
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-25  7:11     ` Mikko Perttunen
  2018-07-24 14:34   ` [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration Aapo Vienamo
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Automatic pad drive strength calibration is performed on a separate pad
identical to the ones used for driving the actual bus. Power on the
calibration pad during the calibration procedure and power it off
afterwards to save power.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 6008e2f..61067b7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -209,11 +209,30 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 	tegra_host->ddr_signaling = false;
 }
 
+static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable)
+{
+	u32 reg;
+
+	/*
+	 * Enable or disable the additional I/O pad used by the drive strength
+	 * calibration process.
+	 */
+	reg = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+	if (enable)
+		reg |= SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
+	else
+		reg &= ~SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
+	sdhci_writel(host, reg, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+	udelay(1);
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
 	unsigned timeout = 10;
 	u32 reg;
 
+	tegra_sdhci_configure_cal_pad(host, true);
+
 	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
 	reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
 	sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
@@ -227,6 +246,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 		timeout--;
 	} while (timeout);
 
+	tegra_sdhci_configure_cal_pad(host, false);
+
 	if (timeout == 0)
 		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
-- 
2.7.4


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

* [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
  2018-07-24 14:34   ` [PATCH 03/10] mmc: tegra: Power on the calibration pad Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-25  7:14     ` Mikko Perttunen
  2018-07-24 14:34   ` [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings Aapo Vienamo
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Disable the card clock during automatic pad drive strength calibration
and re-enable it aftewards.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 61067b7..0de74f4 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -52,6 +52,7 @@
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL	0x7
+#define SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD		BIT(31)
 
 #define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
 #define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)
@@ -226,11 +227,35 @@ static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable)
 	udelay(1);
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)
+{
+	bool orig_enabled;
+	u32 reg;
+
+	reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	orig_enabled = reg & SDHCI_CLOCK_CARD_EN;
+
+	if (orig_enabled == enable)
+		return orig_enabled;
+
+	if (enable)
+		reg |= SDHCI_CLOCK_CARD_EN;
+	else
+		reg &= ~SDHCI_CLOCK_CARD_EN;
+
+	sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+	return orig_enabled;
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
 	unsigned timeout = 10;
+	bool card_clk_enabled;
 	u32 reg;
 
+	card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
+
 	tegra_sdhci_configure_cal_pad(host, true);
 
 	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
@@ -248,6 +273,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 
 	tegra_sdhci_configure_cal_pad(host, false);
 
+	tegra_sdhci_configure_card_clk(host, card_clk_enabled);
+
 	if (timeout == 0)
 		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
-- 
2.7.4


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

* [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
  2018-07-24 14:34   ` [PATCH 03/10] mmc: tegra: Power on the calibration pad Aapo Vienamo
  2018-07-24 14:34   ` [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-25  7:16     ` Mikko Perttunen
  2018-07-24 14:34   ` [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt Aapo Vienamo
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Add bindings documentation for pad pull up and pull down offset values to be
programmed before executing automatic pad drive strength calibration.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 .../bindings/mmc/nvidia,tegra20-sdhci.txt          | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 90c214d..949f616 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -24,6 +24,7 @@ Required properties:
 Optional properties:
 - power-gpios : Specify GPIOs for power control
 
+Optional properties for Tegra210 and Tegra186:
 Example:
 
 sdhci@c8000200 {
@@ -45,6 +46,33 @@ Optional properties for Tegra210 and Tegra186:
   for controllers supporting multiple voltage levels. The order of names
   should correspond to the pin configuration states in pinctrl-0 and
   pinctrl-1.
+- pad-autocal-pull-up-offset-3v3, pad-autocal-pull-down-offset-3v3 :
+  Specify drive strength calibration offsets for 3.3 V signaling modes.
+- pad-autocal-pull-up-offset-1v8, pad-autocal-pull-down-offset-1v8 :
+  Specify drive strength calibration offsets for 1.8 V signaling modes.
+- pad-autocal-pull-up-offset-3v3-timeout,
+  pad-autocal-pull-down-offset-3v3-timeout : Specify drive strength
+  used as a fallback in case the automatic calibration times out on a
+  3.3 V signaling mode.
+- pad-autocal-pull-up-offset-1v8-timeout,
+  pad-autocal-pull-down-offset-1v8-timeout : Specify drive strength
+  used as a fallback in case the automatic calibration times out on a
+  1.8 V signaling mode.
+- pad-autocal-pull-up-offset-sdr104,
+  pad-autocal-pull-down-offset-sdr104 : Specify drive strength
+  calibration offsets for SDR104 mode.
+- pad-autocal-pull-up-offset-hs400,
+  pad-autocal-pull-down-offset-hs400 : Specify drive strength
+  calibration offsets for HS400 mode.
+
+  Notes on the pad calibration pull up and pulldown offset values:
+    - The property values are drive codes which are programmed into the
+      PD_OFFSET and PU_OFFSET sections of the
+      SDHCI_TEGRA_AUTO_CAL_CONFIG register.
+    - A higher value corresponds to higher drive strength. Please refer
+      to the reference manual of the SoC for correct values.
+    - The SDR104 and HS400 timing specific values are used in
+      corresponding modes if specified.
 
 Example:
 sdhci@700b0000 {
@@ -58,5 +86,9 @@ sdhci@700b0000 {
 	pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 	pinctrl-0 = <&sdmmc1_3v3>;
 	pinctrl-1 = <&sdmmc1_1v8>;
+	pad-autocal-pull-up-offset-3v3 = <0x00>;
+	pad-autocal-pull-down-offset-3v3 = <0x7d>;
+	pad-autocal-pull-up-offset-1v8 = <0x7b>;
+	pad-autocal-pull-down-offset-1v8 = <0x7b>;
 	status = "disabled";
 };
-- 
2.7.4


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

* [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
                     ` (2 preceding siblings ...)
  2018-07-24 14:34   ` [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-25  7:24     ` Mikko Perttunen
  2018-07-24 14:34   ` [PATCH 07/10] arm64: dts: tegra186: Add sdmmc pad auto calibration offsets Aapo Vienamo
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Parse the pad drive strength calibration offsets from the device tree.
Program the calibration offsets in accordance with the current signaling
mode.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 147 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 146 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 0de74f4..78781bd 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -48,6 +48,7 @@
 #define SDHCI_TEGRA_AUTO_CAL_CONFIG		0x1e4
 #define SDHCI_AUTO_CAL_START			BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
+#define SDHCI_AUTO_CAL_PDPU_OFFSET_MASK		0x0000ffff
 
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
@@ -71,6 +72,22 @@ struct sdhci_tegra_soc_data {
 	u32 nvquirks;
 };
 
+/* Magic pull up and pull down pad calibration offsets */
+struct sdhci_tegra_autocal_offsets {
+	u8 pull_up_3v3;
+	u8 pull_down_3v3;
+	u8 pull_up_3v3_timeout;
+	u8 pull_down_3v3_timeout;
+	u8 pull_up_1v8;
+	u8 pull_down_1v8;
+	u8 pull_up_1v8_timeout;
+	u8 pull_down_1v8_timeout;
+	u8 pull_up_sdr104;
+	u8 pull_down_sdr104;
+	u8 pull_up_hs400;
+	u8 pull_down_hs400;
+};
+
 struct sdhci_tegra {
 	const struct sdhci_tegra_soc_data *soc_data;
 	struct gpio_desc *power_gpio;
@@ -82,6 +99,8 @@ struct sdhci_tegra {
 	struct pinctrl *pinctrl_sdmmc;
 	struct pinctrl_state *pinctrl_state_3v3;
 	struct pinctrl_state *pinctrl_state_1v8;
+
+	struct sdhci_tegra_autocal_offsets autocal_offsets;
 };
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -248,12 +267,45 @@ static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)
 	return orig_enabled;
 }
 
+static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
+					       u16 pdpu)
+{
+	u32 reg;
+
+	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+	reg &= ~SDHCI_AUTO_CAL_PDPU_OFFSET_MASK;
+	reg |= pdpu;
+	sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_tegra_autocal_offsets offsets =
+			tegra_host->autocal_offsets;
+	struct mmc_ios *ios = &host->mmc->ios;
 	unsigned timeout = 10;
 	bool card_clk_enabled;
+	u16 pdpu;
 	u32 reg;
 
+	switch (ios->timing) {
+	case MMC_TIMING_UHS_SDR104:
+		pdpu = offsets.pull_down_sdr104 << 8 | offsets.pull_up_sdr104;
+		break;
+	case MMC_TIMING_MMC_HS400:
+		pdpu = offsets.pull_down_hs400 << 8 | offsets.pull_up_hs400;
+		break;
+	default:
+		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+			pdpu = offsets.pull_down_1v8 << 8 | offsets.pull_up_1v8;
+		else
+			pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3;
+	}
+
+	tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+
 	card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
 
 	tegra_sdhci_configure_cal_pad(host, true);
@@ -275,8 +327,99 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 
 	tegra_sdhci_configure_card_clk(host, card_clk_enabled);
 
-	if (timeout == 0)
+	if (timeout == 0) {
 		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
+
+		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+			pdpu = offsets.pull_down_1v8_timeout << 8 |
+			       offsets.pull_up_1v8_timeout;
+		else
+			pdpu = offsets.pull_down_3v3_timeout << 8 |
+			       offsets.pull_up_3v3_timeout;
+
+		tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+	}
+}
+
+static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_tegra_autocal_offsets *autocal =
+			&tegra_host->autocal_offsets;
+	int err;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-up-offset-3v3",
+				      &autocal->pull_up_3v3);
+	if (err)
+		autocal->pull_up_3v3 = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-down-offset-3v3",
+				      &autocal->pull_down_3v3);
+	if (err)
+		autocal->pull_down_3v3 = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-up-offset-1v8",
+				      &autocal->pull_up_1v8);
+	if (err)
+		autocal->pull_up_1v8 = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-down-offset-1v8",
+				      &autocal->pull_down_1v8);
+	if (err)
+		autocal->pull_down_1v8 = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-up-offset-3v3-timeout",
+				      &autocal->pull_up_3v3);
+	if (err)
+		autocal->pull_up_3v3_timeout = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+			"pad-autocal-pull-down-offset-3v3-timeout",
+			&autocal->pull_down_3v3);
+	if (err)
+		autocal->pull_down_3v3_timeout = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-up-offset-1v8-timeout",
+				      &autocal->pull_up_1v8);
+	if (err)
+		autocal->pull_up_1v8_timeout = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+			"pad-autocal-pull-down-offset-1v8-timeout",
+			&autocal->pull_down_1v8);
+	if (err)
+		autocal->pull_down_1v8_timeout = 0;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-up-offset-sdr104",
+				      &autocal->pull_up_sdr104);
+	if (err)
+		autocal->pull_up_sdr104 = autocal->pull_up_1v8;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-down-offset-sdr104",
+				      &autocal->pull_down_sdr104);
+	if (err)
+		autocal->pull_down_sdr104 = autocal->pull_down_1v8;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-up-offset-hs400",
+				      &autocal->pull_up_hs400);
+	if (err)
+		autocal->pull_up_hs400 = autocal->pull_up_1v8;
+
+	err = device_property_read_u8(host->mmc->parent,
+				      "pad-autocal-pull-down-offset-hs400",
+				      &autocal->pull_down_hs400);
+	if (err)
+		autocal->pull_down_hs400 = autocal->pull_down_1v8;
 }
 
 static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
@@ -638,6 +781,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 	if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
+	tegra_sdhci_parse_pad_autocal_dt(host);
+
 	tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
 							 GPIOD_OUT_HIGH);
 	if (IS_ERR(tegra_host->power_gpio)) {
-- 
2.7.4


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

* [PATCH 07/10] arm64: dts: tegra186: Add sdmmc pad auto calibration offsets
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
                     ` (3 preceding siblings ...)
  2018-07-24 14:34   ` [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-24 14:34   ` [PATCH 08/10] arm64: dts: tegra210: " Aapo Vienamo
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Add the calibration offset properties used for automatic pad drive
strength calibration.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 7669756..ee8e6cf 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -240,6 +240,12 @@
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 		pinctrl-0 = <&sdmmc1_3v3>;
 		pinctrl-1 = <&sdmmc1_1v8>;
+		pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+		pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+		pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+		pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+		pad-autocal-pull-up-offset-sdr104 = <0x03>;
+		pad-autocal-pull-down-offset-sdr104 = <0x05>;
 		status = "disabled";
 	};
 
@@ -254,6 +260,10 @@
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 		pinctrl-0 = <&sdmmc2_3v3>;
 		pinctrl-1 = <&sdmmc2_1v8>;
+		pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+		pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+		pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+		pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
 		status = "disabled";
 	};
 
@@ -268,6 +278,12 @@
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 		pinctrl-0 = <&sdmmc3_3v3>;
 		pinctrl-1 = <&sdmmc3_1v8>;
+		pad-autocal-pull-up-offset-1v8 = <0x00>;
+		pad-autocal-pull-down-offset-1v8 = <0x7a>;
+		pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+		pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+		pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+		pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
 		status = "disabled";
 	};
 
@@ -279,6 +295,10 @@
 		clock-names = "sdhci";
 		resets = <&bpmp TEGRA186_RESET_SDMMC4>;
 		reset-names = "sdhci";
+		pad-autocal-pull-up-offset-hs400 = <0x05>;
+		pad-autocal-pull-down-offset-hs400 = <0x05>;
+		pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
+		pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
 		status = "disabled";
 	};
 
-- 
2.7.4


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

* [PATCH 08/10] arm64: dts: tegra210: Add sdmmc pad auto calibration offsets
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
                     ` (4 preceding siblings ...)
  2018-07-24 14:34   ` [PATCH 07/10] arm64: dts: tegra186: Add sdmmc pad auto calibration offsets Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-24 14:34   ` [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch Aapo Vienamo
  2018-07-25  7:08   ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Mikko Perttunen
  7 siblings, 0 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Add the calibration offset properties used for automatic pad drive
strength calibration.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index bc1918e..467bdfc 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1051,6 +1051,10 @@
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 		pinctrl-0 = <&sdmmc1_3v3>;
 		pinctrl-1 = <&sdmmc1_1v8>;
+		pad-autocal-pull-up-offset-3v3 = <0x00>;
+		pad-autocal-pull-down-offset-3v3 = <0x7d>;
+		pad-autocal-pull-up-offset-1v8 = <0x7b>;
+		pad-autocal-pull-down-offset-1v8 = <0x7b>;
 		status = "disabled";
 	};
 
@@ -1062,6 +1066,8 @@
 		clock-names = "sdhci";
 		resets = <&tegra_car 9>;
 		reset-names = "sdhci";
+		pad-autocal-pull-up-offset-1v8 = <0x05>;
+		pad-autocal-pull-down-offset-1v8 = <0x05>;
 		status = "disabled";
 	};
 
@@ -1076,6 +1082,10 @@
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 		pinctrl-0 = <&sdmmc3_3v3>;
 		pinctrl-1 = <&sdmmc3_1v8>;
+		pad-autocal-pull-up-offset-3v3 = <0x00>;
+		pad-autocal-pull-down-offset-3v3 = <0x7d>;
+		pad-autocal-pull-up-offset-1v8 = <0x7b>;
+		pad-autocal-pull-down-offset-1v8 = <0x7b>;
 		status = "disabled";
 	};
 
@@ -1087,6 +1097,8 @@
 		clock-names = "sdhci";
 		resets = <&tegra_car 15>;
 		reset-names = "sdhci";
+		pad-autocal-pull-up-offset-1v8 = <0x05>;
+		pad-autocal-pull-down-offset-1v8 = <0x05>;
 		status = "disabled";
 	};
 
-- 
2.7.4


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

* [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
                     ` (5 preceding siblings ...)
  2018-07-24 14:34   ` [PATCH 08/10] arm64: dts: tegra210: " Aapo Vienamo
@ 2018-07-24 14:34   ` Aapo Vienamo
  2018-07-25  7:25     ` Mikko Perttunen
  2018-07-25  7:08   ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Mikko Perttunen
  7 siblings, 1 reply; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-24 14:34 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Run the automatic pad calibration after voltage switching if
tegra_host->pad_calib_required is set.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 78781bd..529aa4e7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -537,6 +537,8 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
 						   struct mmc_ios *ios)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
 	int ret = 0;
 
 	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
@@ -551,6 +553,9 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
 		ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
 	}
 
+	if (tegra_host->pad_calib_required)
+		tegra_sdhci_pad_autocalib(host);
+
 	return ret;
 }
 
-- 
2.7.4


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

* Re: [PATCH 01/10] mmc: tegra: Poll for calibration completion
  2018-07-24 14:29 ` [PATCH 01/10] mmc: tegra: Poll for calibration completion Aapo Vienamo
@ 2018-07-25  7:04   ` Mikko Perttunen
  0 siblings, 0 replies; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:04 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

On 24.07.2018 17:29, Aapo Vienamo wrote:
> Implement polling with 10 ms timeout for automatic pad drive strength
> calibration.
> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   drivers/mmc/host/sdhci-tegra.c | 24 +++++++++++++++++++-----
>   1 file changed, 19 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index f108c48..e40ca43 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -49,6 +49,9 @@
>   #define SDHCI_AUTO_CAL_START			BIT(31)
>   #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
>   
> +#define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
> +#define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)

Please align the definition value with tabs. Also it looks like the 
alignments for the defines here are all over the place, would be nice to 
fix those up so they line up.

> +
>   #define NVQUIRK_FORCE_SDHCI_SPEC_200	BIT(0)
>   #define NVQUIRK_ENABLE_BLOCK_GAP_DET	BIT(1)
>   #define NVQUIRK_ENABLE_SDHCI_SPEC_300	BIT(2)
> @@ -198,13 +201,24 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
>   
>   static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   {
> -	u32 val;
> +	unsigned timeout = 10;

I prefer "unsigned int" instead of just "unsigned", but I guess that's 
just a personal preference..

> +	u32 reg;
>   
> -	mdelay(1);
> +	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> +	reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
> +	sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> +	udelay(1);
> +
> +	do {
> +		reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_STATUS);
> +		if (!(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE))
> +			break;
> +		mdelay(1);
> +		timeout--;
> +	} while (timeout);

Can we use readl_poll_timeout here? We'll need to calculate the address 
directly but it'd still look nicer.

Cheers,
Mikko

>   
> -	val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> -	val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
> -	sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> +	if (timeout == 0)
> +		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
>   }
>   
>   static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
> 

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

* Re: [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
                     ` (6 preceding siblings ...)
  2018-07-24 14:34   ` [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch Aapo Vienamo
@ 2018-07-25  7:08   ` Mikko Perttunen
  2018-07-25 10:00     ` Aapo Vienamo
  7 siblings, 1 reply; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:08 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

On 24.07.2018 17:34, Aapo Vienamo wrote:
> Configure the voltage reference used by the automatic pad drive strength
> calibration procedure. The value is a magic number from the TRM.
> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   drivers/mmc/host/sdhci-tegra.c | 14 ++++++++++++--
>   1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index e40ca43..6008e2f 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -49,6 +49,10 @@
>   #define SDHCI_AUTO_CAL_START			BIT(31)
>   #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
>   
> +#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
> +#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
> +#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL	0x7
> +
>   #define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
>   #define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)
>   
> @@ -152,7 +156,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
>   	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>   	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
>   	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
> -	u32 misc_ctrl, clk_ctrl;
> +	u32 misc_ctrl, clk_ctrl, pad_ctrl;
>   
>   	sdhci_reset(host, mask);
>   
> @@ -193,8 +197,14 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
>   	sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
>   	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
>   
> -	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
> +	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) {
> +		pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
> +		pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK;
> +		pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL;
> +		sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
> +

Will this happen to only eMMC controllers or for all controllers? My 
docs are saying this should be set to 0x7 for SDMMC2/4 and 0x1 or 0x2 
for SDMMC1/3 depending on voltage. Not sure how downstream is 
programming it, though.

>   		tegra_host->pad_calib_required = true;
> +	}
>   
>   	tegra_host->ddr_signaling = false;
>   }
> 

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

* Re: [PATCH 03/10] mmc: tegra: Power on the calibration pad
  2018-07-24 14:34   ` [PATCH 03/10] mmc: tegra: Power on the calibration pad Aapo Vienamo
@ 2018-07-25  7:11     ` Mikko Perttunen
  0 siblings, 0 replies; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:11 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>

On 24.07.2018 17:34, Aapo Vienamo wrote:
> Automatic pad drive strength calibration is performed on a separate pad
> identical to the ones used for driving the actual bus. Power on the
> calibration pad during the calibration procedure and power it off
> afterwards to save power.
> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   drivers/mmc/host/sdhci-tegra.c | 21 +++++++++++++++++++++
>   1 file changed, 21 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index 6008e2f..61067b7 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -209,11 +209,30 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
>   	tegra_host->ddr_signaling = false;
>   }
>   
> +static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable)
> +{
> +	u32 reg;
> +
> +	/*
> +	 * Enable or disable the additional I/O pad used by the drive strength
> +	 * calibration process.
> +	 */
> +	reg = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
> +	if (enable)
> +		reg |= SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
> +	else
> +		reg &= ~SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
> +	sdhci_writel(host, reg, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
> +	udelay(1);
> +}
> +
>   static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   {
>   	unsigned timeout = 10;
>   	u32 reg;
>   
> +	tegra_sdhci_configure_cal_pad(host, true);
> +
>   	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
>   	reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
>   	sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> @@ -227,6 +246,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   		timeout--;
>   	} while (timeout);
>   
> +	tegra_sdhci_configure_cal_pad(host, false);
> +
>   	if (timeout == 0)
>   		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
>   }
> 

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

* Re: [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration
  2018-07-24 14:34   ` [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration Aapo Vienamo
@ 2018-07-25  7:14     ` Mikko Perttunen
  0 siblings, 0 replies; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:14 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

On 24.07.2018 17:34, Aapo Vienamo wrote:
> Disable the card clock during automatic pad drive strength calibration
> and re-enable it aftewards.

s/aftewards/afterwards/.

> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   drivers/mmc/host/sdhci-tegra.c | 27 +++++++++++++++++++++++++++
>   1 file changed, 27 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index 61067b7..0de74f4 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -52,6 +52,7 @@
>   #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
>   #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
>   #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL	0x7
> +#define SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD		BIT(31)

Looks like this should be in the previous patch.

>   
>   #define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
>   #define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)
> @@ -226,11 +227,35 @@ static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable)
>   	udelay(1);
>   }
>   
> +static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)
> +{
> +	bool orig_enabled;
> +	u32 reg;
> +
> +	reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> +	orig_enabled = reg & SDHCI_CLOCK_CARD_EN;

I would do !!(reg & SDHCI_CLOCK_CARD_EN) here.

> +
> +	if (orig_enabled == enable)
> +		return orig_enabled;
> +
> +	if (enable)
> +		reg |= SDHCI_CLOCK_CARD_EN;
> +	else
> +		reg &= ~SDHCI_CLOCK_CARD_EN;
> +
> +	sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
> +
> +	return orig_enabled;
> +}
> +
>   static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   {
>   	unsigned timeout = 10;
> +	bool card_clk_enabled;
>   	u32 reg;
>   
> +	card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
> +
>   	tegra_sdhci_configure_cal_pad(host, true);
>   
>   	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> @@ -248,6 +273,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   
>   	tegra_sdhci_configure_cal_pad(host, false);
>   
> +	tegra_sdhci_configure_card_clk(host, card_clk_enabled);
> +
>   	if (timeout == 0)
>   		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
>   }
> 

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

* Re: [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings
  2018-07-24 14:34   ` [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings Aapo Vienamo
@ 2018-07-25  7:16     ` Mikko Perttunen
  0 siblings, 0 replies; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:16 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

On 24.07.2018 17:34, Aapo Vienamo wrote:
> Add bindings documentation for pad pull up and pull down offset values to be
> programmed before executing automatic pad drive strength calibration.
> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   .../bindings/mmc/nvidia,tegra20-sdhci.txt          | 32 ++++++++++++++++++++++
>   1 file changed, 32 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
> index 90c214d..949f616 100644
> --- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
> +++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
> @@ -24,6 +24,7 @@ Required properties:
>   Optional properties:
>   - power-gpios : Specify GPIOs for power control
>   
> +Optional properties for Tegra210 and Tegra186:
>   Example:
>   
>   sdhci@c8000200 {
> @@ -45,6 +46,33 @@ Optional properties for Tegra210 and Tegra186:
>     for controllers supporting multiple voltage levels. The order of names
>     should correspond to the pin configuration states in pinctrl-0 and
>     pinctrl-1.
> +- pad-autocal-pull-up-offset-3v3, pad-autocal-pull-down-offset-3v3 :
> +  Specify drive strength calibration offsets for 3.3 V signaling modes.
> +- pad-autocal-pull-up-offset-1v8, pad-autocal-pull-down-offset-1v8 :
> +  Specify drive strength calibration offsets for 1.8 V signaling modes.
> +- pad-autocal-pull-up-offset-3v3-timeout,
> +  pad-autocal-pull-down-offset-3v3-timeout : Specify drive strength
> +  used as a fallback in case the automatic calibration times out on a
> +  3.3 V signaling mode.
> +- pad-autocal-pull-up-offset-1v8-timeout,
> +  pad-autocal-pull-down-offset-1v8-timeout : Specify drive strength
> +  used as a fallback in case the automatic calibration times out on a
> +  1.8 V signaling mode.
> +- pad-autocal-pull-up-offset-sdr104,
> +  pad-autocal-pull-down-offset-sdr104 : Specify drive strength
> +  calibration offsets for SDR104 mode.
> +- pad-autocal-pull-up-offset-hs400,
> +  pad-autocal-pull-down-offset-hs400 : Specify drive strength
> +  calibration offsets for HS400 mode.

All of these need an "nvidia," prefix.

> +
> +  Notes on the pad calibration pull up and pulldown offset values:
> +    - The property values are drive codes which are programmed into the
> +      PD_OFFSET and PU_OFFSET sections of the
> +      SDHCI_TEGRA_AUTO_CAL_CONFIG register.
> +    - A higher value corresponds to higher drive strength. Please refer
> +      to the reference manual of the SoC for correct values.
> +    - The SDR104 and HS400 timing specific values are used in
> +      corresponding modes if specified.
>   
>   Example:
>   sdhci@700b0000 {
> @@ -58,5 +86,9 @@ sdhci@700b0000 {
>   	pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
>   	pinctrl-0 = <&sdmmc1_3v3>;
>   	pinctrl-1 = <&sdmmc1_1v8>;
> +	pad-autocal-pull-up-offset-3v3 = <0x00>;
> +	pad-autocal-pull-down-offset-3v3 = <0x7d>;
> +	pad-autocal-pull-up-offset-1v8 = <0x7b>;
> +	pad-autocal-pull-down-offset-1v8 = <0x7b>;
>   	status = "disabled";
>   };
> 

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

* Re: [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt
  2018-07-24 14:34   ` [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt Aapo Vienamo
@ 2018-07-25  7:24     ` Mikko Perttunen
  0 siblings, 0 replies; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:24 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

On 24.07.2018 17:34, Aapo Vienamo wrote:
> Parse the pad drive strength calibration offsets from the device tree.
> Program the calibration offsets in accordance with the current signaling
> mode.
> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   drivers/mmc/host/sdhci-tegra.c | 147 ++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 146 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index 0de74f4..78781bd 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -48,6 +48,7 @@
>   #define SDHCI_TEGRA_AUTO_CAL_CONFIG		0x1e4
>   #define SDHCI_AUTO_CAL_START			BIT(31)
>   #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
> +#define SDHCI_AUTO_CAL_PDPU_OFFSET_MASK		0x0000ffff
>   
>   #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
>   #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
> @@ -71,6 +72,22 @@ struct sdhci_tegra_soc_data {
>   	u32 nvquirks;
>   };
>   
> +/* Magic pull up and pull down pad calibration offsets */
> +struct sdhci_tegra_autocal_offsets {
> +	u8 pull_up_3v3;
> +	u8 pull_down_3v3;
> +	u8 pull_up_3v3_timeout;
> +	u8 pull_down_3v3_timeout;
> +	u8 pull_up_1v8;
> +	u8 pull_down_1v8;
> +	u8 pull_up_1v8_timeout;
> +	u8 pull_down_1v8_timeout;
> +	u8 pull_up_sdr104;
> +	u8 pull_down_sdr104;
> +	u8 pull_up_hs400;
> +	u8 pull_down_hs400;
> +}; > +
>   struct sdhci_tegra {
>   	const struct sdhci_tegra_soc_data *soc_data;
>   	struct gpio_desc *power_gpio;
> @@ -82,6 +99,8 @@ struct sdhci_tegra {
>   	struct pinctrl *pinctrl_sdmmc;
>   	struct pinctrl_state *pinctrl_state_3v3;
>   	struct pinctrl_state *pinctrl_state_1v8;
> +
> +	struct sdhci_tegra_autocal_offsets autocal_offsets;
>   };
>   
>   static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
> @@ -248,12 +267,45 @@ static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)
>   	return orig_enabled;
>   }
>   
> +static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
> +					       u16 pdpu)
> +{
> +	u32 reg;
> +
> +	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> +	reg &= ~SDHCI_AUTO_CAL_PDPU_OFFSET_MASK;
> +	reg |= pdpu;
> +	sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
> +}
> +
>   static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   {
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
> +	struct sdhci_tegra_autocal_offsets offsets =
> +			tegra_host->autocal_offsets;
> +	struct mmc_ios *ios = &host->mmc->ios;
>   	unsigned timeout = 10;
>   	bool card_clk_enabled;
> +	u16 pdpu;
>   	u32 reg;
>   
> +	switch (ios->timing) {
> +	case MMC_TIMING_UHS_SDR104:
> +		pdpu = offsets.pull_down_sdr104 << 8 | offsets.pull_up_sdr104;
> +		break;
> +	case MMC_TIMING_MMC_HS400:
> +		pdpu = offsets.pull_down_hs400 << 8 | offsets.pull_up_hs400;
> +		break;
> +	default:
> +		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
> +			pdpu = offsets.pull_down_1v8 << 8 | offsets.pull_up_1v8;
> +		else
> +			pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3;
> +	}
> +
> +	tegra_sdhci_set_pad_autocal_offset(host, pdpu);
> +
>   	card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
>   
>   	tegra_sdhci_configure_cal_pad(host, true);
> @@ -275,8 +327,99 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
>   
>   	tegra_sdhci_configure_card_clk(host, card_clk_enabled);
>   
> -	if (timeout == 0)
> +	if (timeout == 0) {
>   		dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
> +
> +		if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
> +			pdpu = offsets.pull_down_1v8_timeout << 8 |
> +			       offsets.pull_up_1v8_timeout;
> +		else
> +			pdpu = offsets.pull_down_3v3_timeout << 8 |
> +			       offsets.pull_up_3v3_timeout;
> +
> +		tegra_sdhci_set_pad_autocal_offset(host, pdpu);
> +	}
> +}
> +
> +static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
> +	struct sdhci_tegra_autocal_offsets *autocal =
> +			&tegra_host->autocal_offsets;
> +	int err;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-up-offset-3v3",
> +				      &autocal->pull_up_3v3);
> +	if (err)
> +		autocal->pull_up_3v3 = 0;
> +

If you read these properties using read_u8, they'll need to be specified 
in the device tree as "property = /bits/ 8 <...>;", which might not be 
desirable.

> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-down-offset-3v3",
> +				      &autocal->pull_down_3v3);
> +	if (err)
> +		autocal->pull_down_3v3 = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-up-offset-1v8",
> +				      &autocal->pull_up_1v8);
> +	if (err)
> +		autocal->pull_up_1v8 = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-down-offset-1v8",
> +				      &autocal->pull_down_1v8);
> +	if (err)
> +		autocal->pull_down_1v8 = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-up-offset-3v3-timeout",
> +				      &autocal->pull_up_3v3);
> +	if (err)
> +		autocal->pull_up_3v3_timeout = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +			"pad-autocal-pull-down-offset-3v3-timeout",
> +			&autocal->pull_down_3v3);
> +	if (err)
> +		autocal->pull_down_3v3_timeout = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-up-offset-1v8-timeout",
> +				      &autocal->pull_up_1v8);
> +	if (err)
> +		autocal->pull_up_1v8_timeout = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +			"pad-autocal-pull-down-offset-1v8-timeout",
> +			&autocal->pull_down_1v8);
> +	if (err)
> +		autocal->pull_down_1v8_timeout = 0;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-up-offset-sdr104",
> +				      &autocal->pull_up_sdr104);
> +	if (err)
> +		autocal->pull_up_sdr104 = autocal->pull_up_1v8;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-down-offset-sdr104",
> +				      &autocal->pull_down_sdr104);
> +	if (err)
> +		autocal->pull_down_sdr104 = autocal->pull_down_1v8;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-up-offset-hs400",
> +				      &autocal->pull_up_hs400);
> +	if (err)
> +		autocal->pull_up_hs400 = autocal->pull_up_1v8;
> +
> +	err = device_property_read_u8(host->mmc->parent,
> +				      "pad-autocal-pull-down-offset-hs400",
> +				      &autocal->pull_down_hs400);
> +	if (err)
> +		autocal->pull_down_hs400 = autocal->pull_down_1v8;
>   }
>   
>   static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
> @@ -638,6 +781,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
>   	if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
>   		host->mmc->caps |= MMC_CAP_1_8V_DDR;
>   
> +	tegra_sdhci_parse_pad_autocal_dt(host);
> +
>   	tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
>   							 GPIOD_OUT_HIGH);
>   	if (IS_ERR(tegra_host->power_gpio)) {
> 

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

* Re: [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch
  2018-07-24 14:34   ` [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch Aapo Vienamo
@ 2018-07-25  7:25     ` Mikko Perttunen
  2018-07-25 10:43       ` Aapo Vienamo
  0 siblings, 1 reply; 22+ messages in thread
From: Mikko Perttunen @ 2018-07-25  7:25 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel



On 24.07.2018 17:34, Aapo Vienamo wrote:
> Run the automatic pad calibration after voltage switching if
> tegra_host->pad_calib_required is set.
> 
> Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> ---
>   drivers/mmc/host/sdhci-tegra.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index 78781bd..529aa4e7 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -537,6 +537,8 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
>   						   struct mmc_ios *ios)
>   {
>   	struct sdhci_host *host = mmc_priv(mmc);
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
>   	int ret = 0;
>   
>   	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
> @@ -551,6 +553,9 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
>   		ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
>   	}
>   
> +	if (tegra_host->pad_calib_required)
> +		tegra_sdhci_pad_autocalib(host);

What if the autocalibration fails? Should we return an error?

> +
>   	return ret;
>   }
>   
> 

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

* Re: [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference
  2018-07-25  7:08   ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Mikko Perttunen
@ 2018-07-25 10:00     ` Aapo Vienamo
  0 siblings, 0 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-25 10:00 UTC (permalink / raw)
  To: Mikko Perttunen
  Cc: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen, linux-mmc,
	devicetree, linux-tegra, linux-kernel

On Wed, 25 Jul 2018 10:08:46 +0300
Mikko Perttunen <cyndis@kapsi.fi> wrote:

> On 24.07.2018 17:34, Aapo Vienamo wrote:
> > Configure the voltage reference used by the automatic pad drive strength
> > calibration procedure. The value is a magic number from the TRM.
> > 
> > Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> > ---
> >   drivers/mmc/host/sdhci-tegra.c | 14 ++++++++++++--
> >   1 file changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> > index e40ca43..6008e2f 100644
> > --- a/drivers/mmc/host/sdhci-tegra.c
> > +++ b/drivers/mmc/host/sdhci-tegra.c
> > @@ -49,6 +49,10 @@
> >   #define SDHCI_AUTO_CAL_START			BIT(31)
> >   #define SDHCI_AUTO_CAL_ENABLE			BIT(29)
> >   
> > +#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0
> > +#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK	0x0000000f
> > +#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL	0x7
> > +
> >   #define SDHCI_TEGRA_AUTO_CAL_STATUS     0x1ec
> >   #define SDHCI_TEGRA_AUTO_CAL_ACTIVE     BIT(31)
> >   
> > @@ -152,7 +156,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
> >   	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> >   	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
> >   	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
> > -	u32 misc_ctrl, clk_ctrl;
> > +	u32 misc_ctrl, clk_ctrl, pad_ctrl;
> >   
> >   	sdhci_reset(host, mask);
> >   
> > @@ -193,8 +197,14 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
> >   	sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
> >   	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
> >   
> > -	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
> > +	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) {
> > +		pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
> > +		pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK;
> > +		pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL;
> > +		sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
> > +  
> 
> Will this happen to only eMMC controllers or for all controllers? My 
> docs are saying this should be set to 0x7 for SDMMC2/4 and 0x1 or 0x2 
> for SDMMC1/3 depending on voltage. Not sure how downstream is 
> programming it, though.

The Tegra210 TRM specifies that VREF_SEL should be set 0x7 for all of
the controllers, there's no mention of this depending on the mode. The
same value is also programmed by the downstream kernels for Tegra210
and Tegra186.

 -Aapo

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

* Re: [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch
  2018-07-25  7:25     ` Mikko Perttunen
@ 2018-07-25 10:43       ` Aapo Vienamo
  0 siblings, 0 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-25 10:43 UTC (permalink / raw)
  To: Mikko Perttunen
  Cc: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen, linux-mmc,
	devicetree, linux-tegra, linux-kernel

On Wed, 25 Jul 2018 10:25:16 +0300
Mikko Perttunen <cyndis@kapsi.fi> wrote:

> On 24.07.2018 17:34, Aapo Vienamo wrote:
> > Run the automatic pad calibration after voltage switching if
> > tegra_host->pad_calib_required is set.
> > 
> > Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
> > ---
> >   drivers/mmc/host/sdhci-tegra.c | 5 +++++
> >   1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> > index 78781bd..529aa4e7 100644
> > --- a/drivers/mmc/host/sdhci-tegra.c
> > +++ b/drivers/mmc/host/sdhci-tegra.c
> > @@ -537,6 +537,8 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
> >   						   struct mmc_ios *ios)
> >   {
> >   	struct sdhci_host *host = mmc_priv(mmc);
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
> >   	int ret = 0;
> >   
> >   	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
> > @@ -551,6 +553,9 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
> >   		ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
> >   	}
> >   
> > +	if (tegra_host->pad_calib_required)
> > +		tegra_sdhci_pad_autocalib(host);  
> 
> What if the autocalibration fails? Should we return an error?

I would assume that aborting the signal voltage switch due to a
calibration timeout would not be necessary as the TRM specifies drive
strength values which are to be programmed in case a timeout occurs.

However, I don't know what are the exact implications of running the bus
with the timeout values instead of the calibrated ones. The TRM does not
comment on that. I guess tuning would fail and catch the error that way
in case the timeout default values aren't sufficient.

 -Aapo

> > +
> >   	return ret;
> >   }
> >   
> >   


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

* Re: [PATCH 00/10] Update the pad autocal procedure
  2018-07-24 14:29 [PATCH 00/10] Update the pad autocal procedure Aapo Vienamo
  2018-07-24 14:29 ` [PATCH 01/10] mmc: tegra: Poll for calibration completion Aapo Vienamo
  2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
@ 2018-07-25 12:06 ` Peter Geis
  2018-07-25 14:28   ` Aapo Vienamo
  2018-07-25 14:27 ` [PATCH 10/10] mmc: tegra: Enable pad calibration on Tegra210 and Tegra186 Aapo Vienamo
  3 siblings, 1 reply; 22+ messages in thread
From: Peter Geis @ 2018-07-25 12:06 UTC (permalink / raw)
  To: Aapo Vienamo, Ulf Hansson, Rob Herring, Mark Rutland,
	Thierry Reding, Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel

On 07/24/2018 10:29 AM, Aapo Vienamo wrote:
> Aapo Vienamo (10):
> 
>    mmc: tegra: Enable pad calibration on Tegra210 and Tegra186

Good Morning,

You seem to be missing patch 10/10.
Checked 
https://lore.kernel.org/patchwork/project/lkml/list/?series=360525 to be 
sure.

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

* [PATCH 10/10] mmc: tegra: Enable pad calibration on Tegra210 and Tegra186
  2018-07-24 14:29 [PATCH 00/10] Update the pad autocal procedure Aapo Vienamo
                   ` (2 preceding siblings ...)
  2018-07-25 12:06 ` [PATCH 00/10] Update the pad autocal procedure Peter Geis
@ 2018-07-25 14:27 ` Aapo Vienamo
  3 siblings, 0 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-25 14:27 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen
  Cc: linux-mmc, devicetree, linux-tegra, linux-kernel, Aapo Vienamo

Set NVQUIRK_HAS_PADCALIB on Tegra210 and Tegra186 to enable automatic
pad drive strength calibration.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
---
 drivers/mmc/host/sdhci-tegra.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 529aa4e7..a865160 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -709,7 +709,8 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
 
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
 	.pdata = &sdhci_tegra210_pdata,
-	.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL,
+	.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
+		    NVQUIRK_HAS_PADCALIB,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -733,7 +734,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
 	.pdata = &sdhci_tegra186_pdata,
-	.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL,
+	.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
+		    NVQUIRK_HAS_PADCALIB,
 };
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
-- 
2.7.4


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

* Re: [PATCH 00/10] Update the pad autocal procedure
  2018-07-25 12:06 ` [PATCH 00/10] Update the pad autocal procedure Peter Geis
@ 2018-07-25 14:28   ` Aapo Vienamo
  0 siblings, 0 replies; 22+ messages in thread
From: Aapo Vienamo @ 2018-07-25 14:28 UTC (permalink / raw)
  To: Peter Geis
  Cc: Ulf Hansson, Rob Herring, Mark Rutland, Thierry Reding,
	Jonathan Hunter, Adrian Hunter, Mikko Perttunen, linux-mmc,
	devicetree, linux-tegra, linux-kernel

On Wed, 25 Jul 2018 08:06:18 -0400
Peter Geis <pgwipeout@gmail.com> wrote:

> On 07/24/2018 10:29 AM, Aapo Vienamo wrote:
> > Aapo Vienamo (10):
> > 
> >    mmc: tegra: Enable pad calibration on Tegra210 and Tegra186  
> 
> Good Morning,
> 
> You seem to be missing patch 10/10.
> Checked 
> https://lore.kernel.org/patchwork/project/lkml/list/?series=360525 to be 
> sure.

Missing patch sent. Thanks for pointing that out.

 -Aapo

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

end of thread, other threads:[~2018-07-25 14:28 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-24 14:29 [PATCH 00/10] Update the pad autocal procedure Aapo Vienamo
2018-07-24 14:29 ` [PATCH 01/10] mmc: tegra: Poll for calibration completion Aapo Vienamo
2018-07-25  7:04   ` Mikko Perttunen
2018-07-24 14:34 ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Aapo Vienamo
2018-07-24 14:34   ` [PATCH 03/10] mmc: tegra: Power on the calibration pad Aapo Vienamo
2018-07-25  7:11     ` Mikko Perttunen
2018-07-24 14:34   ` [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration Aapo Vienamo
2018-07-25  7:14     ` Mikko Perttunen
2018-07-24 14:34   ` [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings Aapo Vienamo
2018-07-25  7:16     ` Mikko Perttunen
2018-07-24 14:34   ` [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt Aapo Vienamo
2018-07-25  7:24     ` Mikko Perttunen
2018-07-24 14:34   ` [PATCH 07/10] arm64: dts: tegra186: Add sdmmc pad auto calibration offsets Aapo Vienamo
2018-07-24 14:34   ` [PATCH 08/10] arm64: dts: tegra210: " Aapo Vienamo
2018-07-24 14:34   ` [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch Aapo Vienamo
2018-07-25  7:25     ` Mikko Perttunen
2018-07-25 10:43       ` Aapo Vienamo
2018-07-25  7:08   ` [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference Mikko Perttunen
2018-07-25 10:00     ` Aapo Vienamo
2018-07-25 12:06 ` [PATCH 00/10] Update the pad autocal procedure Peter Geis
2018-07-25 14:28   ` Aapo Vienamo
2018-07-25 14:27 ` [PATCH 10/10] mmc: tegra: Enable pad calibration on Tegra210 and Tegra186 Aapo Vienamo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).