Re: [PATCH] mmc: tegra: fix inconsistent IS_ERR and PTR_ERR

2018-09-04 Thread Aapo Vienamo
On Tue, 4 Sep 2018 10:59:09 +0800
YueHaibing  wrote:

> Fix inconsistent IS_ERR and PTR_ERR in tegra_sdhci_init_pinctrl_info,
> the proper pointer to be passed as argument is 'pinctrl_state_1v8'
> 
> Signed-off-by: YueHaibing 

Reviewed-by: Aapo Vienamo 

> ---
>  drivers/mmc/host/sdhci-tegra.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index e80716c..c789158 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -724,7 +724,7 @@ static int tegra_sdhci_init_pinctrl_info(struct device 
> *dev,
>   pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8");
>   if (IS_ERR(tegra_host->pinctrl_state_1v8)) {
>   dev_warn(dev, "Missing 1.8V pad state, err: %ld\n",
> -  PTR_ERR(tegra_host->pinctrl_state_3v3));
> +  PTR_ERR(tegra_host->pinctrl_state_1v8));
>   return -1;
>   }
>  



Re: [PATCH] mmc: tegra: fix inconsistent IS_ERR and PTR_ERR

2018-09-04 Thread Aapo Vienamo
On Tue, 4 Sep 2018 10:59:09 +0800
YueHaibing  wrote:

> Fix inconsistent IS_ERR and PTR_ERR in tegra_sdhci_init_pinctrl_info,
> the proper pointer to be passed as argument is 'pinctrl_state_1v8'
> 
> Signed-off-by: YueHaibing 

Reviewed-by: Aapo Vienamo 

> ---
>  drivers/mmc/host/sdhci-tegra.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index e80716c..c789158 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -724,7 +724,7 @@ static int tegra_sdhci_init_pinctrl_info(struct device 
> *dev,
>   pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8");
>   if (IS_ERR(tegra_host->pinctrl_state_1v8)) {
>   dev_warn(dev, "Missing 1.8V pad state, err: %ld\n",
> -  PTR_ERR(tegra_host->pinctrl_state_3v3));
> +  PTR_ERR(tegra_host->pinctrl_state_1v8));
>   return -1;
>   }
>  



[PATCH v3 14/38] mmc: tegra: Power on the calibration pad

2018-08-30 Thread 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 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 01a21e0af6d7..e63cd6b2fc9f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -54,6 +54,7 @@
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL 0x1e0
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK   0x000f
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL0x7
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD  BIT(31)
 
 #define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
 #define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(31)
@@ -238,11 +239,34 @@ 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 val;
+
+   /*
+* Enable or disable the additional I/O pad used by the drive strength
+* calibration process.
+*/
+   val = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+
+   if (enable)
+   val |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD;
+   else
+   val &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD;
+
+   sdhci_writel(host, val, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+
+   if (enable)
+   usleep_range(1, 2);
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
u32 reg;
int ret;
 
+   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);
@@ -253,6 +277,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
 reg, !(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE),
 1000, 1);
 
+   tegra_sdhci_configure_cal_pad(host, false);
+
if (ret)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
-- 
2.18.0



[PATCH v3 14/38] mmc: tegra: Power on the calibration pad

2018-08-30 Thread 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 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 01a21e0af6d7..e63cd6b2fc9f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -54,6 +54,7 @@
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL 0x1e0
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK   0x000f
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL0x7
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD  BIT(31)
 
 #define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
 #define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(31)
@@ -238,11 +239,34 @@ 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 val;
+
+   /*
+* Enable or disable the additional I/O pad used by the drive strength
+* calibration process.
+*/
+   val = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+
+   if (enable)
+   val |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD;
+   else
+   val &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD;
+
+   sdhci_writel(host, val, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+
+   if (enable)
+   usleep_range(1, 2);
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
u32 reg;
int ret;
 
+   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);
@@ -253,6 +277,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
 reg, !(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE),
 1000, 1);
 
+   tegra_sdhci_configure_cal_pad(host, false);
+
if (ret)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
-- 
2.18.0



[PATCH v3 38/38] arm64: dts: tegra210: Assign clocks for sdmmc1 and sdmmc4

2018-08-30 Thread Aapo Vienamo
Use assigned-clock properties to configure pllc4 as the parent clock
for sdmmc4 on Tegra210. pllc4 offers better jitter perfomance than
the default pllp and is required by HS200 and HS400 modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 0951acc69cc8..14da98ac65e8 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1057,6 +1057,11 @@
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
nvidia,default-tap = <0x2>;
nvidia,default-trim = <0x4>;
+   assigned-clocks = <_car TEGRA210_CLK_SDMMC4>,
+ <_car TEGRA210_CLK_PLL_C4_OUT0>,
+ <_car TEGRA210_CLK_PLL_C4>;
+   assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
+   assigned-clock-rates = <2>, <10>, <10>;
status = "disabled";
};
 
@@ -1107,6 +1112,9 @@
nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
nvidia,default-tap = <0x8>;
nvidia,default-trim = <0x0>;
+   assigned-clocks = <_car TEGRA210_CLK_SDMMC4>,
+ <_car TEGRA210_CLK_PLL_C4_OUT0>;
+   assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 38/38] arm64: dts: tegra210: Assign clocks for sdmmc1 and sdmmc4

2018-08-30 Thread Aapo Vienamo
Use assigned-clock properties to configure pllc4 as the parent clock
for sdmmc4 on Tegra210. pllc4 offers better jitter perfomance than
the default pllp and is required by HS200 and HS400 modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 0951acc69cc8..14da98ac65e8 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1057,6 +1057,11 @@
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
nvidia,default-tap = <0x2>;
nvidia,default-trim = <0x4>;
+   assigned-clocks = <_car TEGRA210_CLK_SDMMC4>,
+ <_car TEGRA210_CLK_PLL_C4_OUT0>,
+ <_car TEGRA210_CLK_PLL_C4>;
+   assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
+   assigned-clock-rates = <2>, <10>, <10>;
status = "disabled";
};
 
@@ -1107,6 +1112,9 @@
nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
nvidia,default-tap = <0x8>;
nvidia,default-trim = <0x0>;
+   assigned-clocks = <_car TEGRA210_CLK_SDMMC4>,
+ <_car TEGRA210_CLK_PLL_C4_OUT0>;
+   assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 35/38] arm64: dts: tegra210: Add SDHCI tap and trim values

2018-08-30 Thread Aapo Vienamo
Add SDHCI inbound and outbound SDHCI sampling trimmer values for
Tegra210.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 2a80f2bd80e5..0951acc69cc8 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1055,6 +1055,8 @@
nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
+   nvidia,default-tap = <0x2>;
+   nvidia,default-trim = <0x4>;
status = "disabled";
};
 
@@ -1068,6 +1070,8 @@
reset-names = "sdhci";
nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
+   nvidia,default-tap = <0x8>;
+   nvidia,default-trim = <0x0>;
status = "disabled";
};
 
@@ -1086,6 +1090,8 @@
nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
+   nvidia,default-tap = <0x3>;
+   nvidia,default-trim = <0x3>;
status = "disabled";
};
 
@@ -1099,6 +1105,8 @@
reset-names = "sdhci";
nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
+   nvidia,default-tap = <0x8>;
+   nvidia,default-trim = <0x0>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 37/38] arm64: dts: tegra186: Assign clocks for sdmmc1 and sdmmc4

2018-08-30 Thread Aapo Vienamo
Configure sdmmc4 parent clock to pllc4 and sdmmc1 to pllp_out0 by
setting the assigned-clocks device tree properties. pllc4 offer
better jitter performance and should be used with higher speed
modes like HS200 and HS400.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 3b2fe0d99aaf..6e9ef26a4253 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -248,6 +248,9 @@
nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>;
nvidia,default-tap = <0x5>;
nvidia,default-trim = <0xb>;
+   assigned-clocks = < TEGRA186_CLK_SDMMC1>,
+ < TEGRA186_CLK_PLLP_OUT0>;
+   assigned-clock-parents = < TEGRA186_CLK_PLLP_OUT0>;
status = "disabled";
};
 
@@ -299,6 +302,9 @@
interrupts = ;
clocks = < TEGRA186_CLK_SDMMC4>;
clock-names = "sdhci";
+   assigned-clocks = < TEGRA186_CLK_SDMMC4>,
+ < TEGRA186_CLK_PLLC4_VCO>;
+   assigned-clock-parents = < TEGRA186_CLK_PLLC4_VCO>;
resets = < TEGRA186_RESET_SDMMC4>;
reset-names = "sdhci";
nvidia,pad-autocal-pull-up-offset-hs400 = <0x05>;
-- 
2.18.0



[PATCH v3 35/38] arm64: dts: tegra210: Add SDHCI tap and trim values

2018-08-30 Thread Aapo Vienamo
Add SDHCI inbound and outbound SDHCI sampling trimmer values for
Tegra210.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 2a80f2bd80e5..0951acc69cc8 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1055,6 +1055,8 @@
nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
+   nvidia,default-tap = <0x2>;
+   nvidia,default-trim = <0x4>;
status = "disabled";
};
 
@@ -1068,6 +1070,8 @@
reset-names = "sdhci";
nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
+   nvidia,default-tap = <0x8>;
+   nvidia,default-trim = <0x0>;
status = "disabled";
};
 
@@ -1086,6 +1090,8 @@
nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
+   nvidia,default-tap = <0x3>;
+   nvidia,default-trim = <0x3>;
status = "disabled";
};
 
@@ -1099,6 +1105,8 @@
reset-names = "sdhci";
nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
+   nvidia,default-tap = <0x8>;
+   nvidia,default-trim = <0x0>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 37/38] arm64: dts: tegra186: Assign clocks for sdmmc1 and sdmmc4

2018-08-30 Thread Aapo Vienamo
Configure sdmmc4 parent clock to pllc4 and sdmmc1 to pllp_out0 by
setting the assigned-clocks device tree properties. pllc4 offer
better jitter performance and should be used with higher speed
modes like HS200 and HS400.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 3b2fe0d99aaf..6e9ef26a4253 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -248,6 +248,9 @@
nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>;
nvidia,default-tap = <0x5>;
nvidia,default-trim = <0xb>;
+   assigned-clocks = < TEGRA186_CLK_SDMMC1>,
+ < TEGRA186_CLK_PLLP_OUT0>;
+   assigned-clock-parents = < TEGRA186_CLK_PLLP_OUT0>;
status = "disabled";
};
 
@@ -299,6 +302,9 @@
interrupts = ;
clocks = < TEGRA186_CLK_SDMMC4>;
clock-names = "sdhci";
+   assigned-clocks = < TEGRA186_CLK_SDMMC4>,
+ < TEGRA186_CLK_PLLC4_VCO>;
+   assigned-clock-parents = < TEGRA186_CLK_PLLC4_VCO>;
resets = < TEGRA186_RESET_SDMMC4>;
reset-names = "sdhci";
nvidia,pad-autocal-pull-up-offset-hs400 = <0x05>;
-- 
2.18.0



[PATCH v3 36/38] arm64: dts: tegra186: Add SDHCI tap and trim values

2018-08-30 Thread Aapo Vienamo
Add SDHCI inbound and outbound SDHCI sampling trimmer values for
Tegra186.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b7020dd2be44..3b2fe0d99aaf 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -246,6 +246,8 @@
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
nvidia,pad-autocal-pull-up-offset-sdr104 = <0x03>;
nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0xb>;
status = "disabled";
};
 
@@ -264,6 +266,8 @@
nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0xb>;
status = "disabled";
};
 
@@ -284,6 +288,8 @@
nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0xb>;
status = "disabled";
};
 
@@ -299,6 +305,8 @@
nvidia,pad-autocal-pull-down-offset-hs400 = <0x05>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0x9>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 36/38] arm64: dts: tegra186: Add SDHCI tap and trim values

2018-08-30 Thread Aapo Vienamo
Add SDHCI inbound and outbound SDHCI sampling trimmer values for
Tegra186.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b7020dd2be44..3b2fe0d99aaf 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -246,6 +246,8 @@
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
nvidia,pad-autocal-pull-up-offset-sdr104 = <0x03>;
nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0xb>;
status = "disabled";
};
 
@@ -264,6 +266,8 @@
nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0xb>;
status = "disabled";
};
 
@@ -284,6 +288,8 @@
nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0xb>;
status = "disabled";
};
 
@@ -299,6 +305,8 @@
nvidia,pad-autocal-pull-down-offset-hs400 = <0x05>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
+   nvidia,default-tap = <0x5>;
+   nvidia,default-trim = <0x9>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 31/38] arm64: dts: tegra210-p2180: Correct sdmmc4 vqmmc-supply

2018-08-30 Thread Aapo Vienamo
On p2180 sdmmc4 is powered from a fixed 1.8 V regulator.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 84961017abd8..053458a5db55 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -273,6 +273,7 @@
status = "okay";
bus-width = <8>;
non-removable;
+   vqmmc-supply = <_1v8>;
};
 
clocks {
-- 
2.18.0



[PATCH v3 30/38] arm64: dts: tegra210-p2180: Allow ldo2 to go down to 1.8 V

2018-08-30 Thread Aapo Vienamo
Set regulator-min-microvolt property of ldo2 to 1.8 V in
tegra210-p2180.dtsi. ldo2 is used by the sdmmc1 SDHCI controller and its
voltage needs to be adjusted down to 1.8 V to support faster signaling
modes. It appears that the comment about the SDHCI driver requesting
invalid voltages no longer applies.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 212e6634c9ba..84961017abd8 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -178,16 +178,7 @@
 
vddio_sdmmc: ldo2 {
regulator-name = "VDDIO_SDMMC";
-   /*
-* Technically this supply should have
-* a supported range from 1.8 - 3.3 V.
-* However, that would cause the SDHCI
-* driver to request 2.7 V upon access
-* and that in turn will cause traffic
-* to be broken. Leave it at 3.3 V for
-* now.
-*/
-   regulator-min-microvolt = <330>;
+   regulator-min-microvolt = <180>;
regulator-max-microvolt = <330>;
regulator-always-on;
regulator-boot-on;
-- 
2.18.0



[PATCH v3 31/38] arm64: dts: tegra210-p2180: Correct sdmmc4 vqmmc-supply

2018-08-30 Thread Aapo Vienamo
On p2180 sdmmc4 is powered from a fixed 1.8 V regulator.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 84961017abd8..053458a5db55 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -273,6 +273,7 @@
status = "okay";
bus-width = <8>;
non-removable;
+   vqmmc-supply = <_1v8>;
};
 
clocks {
-- 
2.18.0



[PATCH v3 30/38] arm64: dts: tegra210-p2180: Allow ldo2 to go down to 1.8 V

2018-08-30 Thread Aapo Vienamo
Set regulator-min-microvolt property of ldo2 to 1.8 V in
tegra210-p2180.dtsi. ldo2 is used by the sdmmc1 SDHCI controller and its
voltage needs to be adjusted down to 1.8 V to support faster signaling
modes. It appears that the comment about the SDHCI driver requesting
invalid voltages no longer applies.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 212e6634c9ba..84961017abd8 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -178,16 +178,7 @@
 
vddio_sdmmc: ldo2 {
regulator-name = "VDDIO_SDMMC";
-   /*
-* Technically this supply should have
-* a supported range from 1.8 - 3.3 V.
-* However, that would cause the SDHCI
-* driver to request 2.7 V upon access
-* and that in turn will cause traffic
-* to be broken. Leave it at 3.3 V for
-* now.
-*/
-   regulator-min-microvolt = <330>;
+   regulator-min-microvolt = <180>;
regulator-max-microvolt = <330>;
regulator-always-on;
regulator-boot-on;
-- 
2.18.0



[PATCH v3 33/38] arm64: dts: tegra186: Add sdmmc pad auto calibration offsets

2018-08-30 Thread Aapo Vienamo
Add the calibration offset properties used for automatic pad drive
strength calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 7669756c060f..b7020dd2be44 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 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-up-offset-sdr104 = <0x03>;
+   nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>;
status = "disabled";
};
 
@@ -254,6 +260,10 @@
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
status = "disabled";
};
 
@@ -268,6 +278,12 @@
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7a>;
+   nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
status = "disabled";
};
 
@@ -279,6 +295,10 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC4>;
reset-names = "sdhci";
+   nvidia,pad-autocal-pull-up-offset-hs400 = <0x05>;
+   nvidia,pad-autocal-pull-down-offset-hs400 = <0x05>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 34/38] arm64: dts: tegra210: Add sdmmc pad auto calibration offsets

2018-08-30 Thread Aapo Vienamo
Add the calibration offset properties used for automatic pad drive
strength calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 bc1918e07cc3..2a80f2bd80e5 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 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
};
 
@@ -1062,6 +1066,8 @@
clock-names = "sdhci";
resets = <_car 9>;
reset-names = "sdhci";
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
status = "disabled";
};
 
@@ -1076,6 +1082,10 @@
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
};
 
@@ -1087,6 +1097,8 @@
clock-names = "sdhci";
resets = <_car 15>;
reset-names = "sdhci";
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 32/38] arm64: dts: tegra210-p2597: Remove no-1-8-v from sdmmc1

2018-08-30 Thread Aapo Vienamo
Allow sdmmc1 to set the signaling voltage to 1.8 V in order to support
faster signaling modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index 9d5a0e6b2ca4..365726ddd418 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1452,7 +1452,6 @@
sdhci@700b {
status = "okay";
bus-width = <4>;
-   no-1-8-v;
 
cd-gpios = < TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
 
-- 
2.18.0



[PATCH v3 33/38] arm64: dts: tegra186: Add sdmmc pad auto calibration offsets

2018-08-30 Thread Aapo Vienamo
Add the calibration offset properties used for automatic pad drive
strength calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 7669756c060f..b7020dd2be44 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 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-up-offset-sdr104 = <0x03>;
+   nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>;
status = "disabled";
};
 
@@ -254,6 +260,10 @@
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
status = "disabled";
};
 
@@ -268,6 +278,12 @@
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7a>;
+   nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
status = "disabled";
};
 
@@ -279,6 +295,10 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC4>;
reset-names = "sdhci";
+   nvidia,pad-autocal-pull-up-offset-hs400 = <0x05>;
+   nvidia,pad-autocal-pull-down-offset-hs400 = <0x05>;
+   nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
+   nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 34/38] arm64: dts: tegra210: Add sdmmc pad auto calibration offsets

2018-08-30 Thread Aapo Vienamo
Add the calibration offset properties used for automatic pad drive
strength calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 bc1918e07cc3..2a80f2bd80e5 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 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
};
 
@@ -1062,6 +1066,8 @@
clock-names = "sdhci";
resets = <_car 9>;
reset-names = "sdhci";
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
status = "disabled";
};
 
@@ -1076,6 +1082,10 @@
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
};
 
@@ -1087,6 +1097,8 @@
clock-names = "sdhci";
resets = <_car 15>;
reset-names = "sdhci";
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 32/38] arm64: dts: tegra210-p2597: Remove no-1-8-v from sdmmc1

2018-08-30 Thread Aapo Vienamo
Allow sdmmc1 to set the signaling voltage to 1.8 V in order to support
faster signaling modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index 9d5a0e6b2ca4..365726ddd418 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1452,7 +1452,6 @@
sdhci@700b {
status = "okay";
bus-width = <4>;
-   no-1-8-v;
 
cd-gpios = < TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
 
-- 
2.18.0



[PATCH v3 27/38] mmc: tegra: Enable UHS and HS200 modes for Tegra186

2018-08-30 Thread Aapo Vienamo
Set nvquirks to enable higher speed modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 73ea947e9c0c..e80716c6e0d2 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -921,7 +921,9 @@ static const struct sdhci_tegra_soc_data soc_data_tegra186 
= {
.pdata = _tegra186_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB |
-   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
+   NVQUIRK_ENABLE_SDR50 |
+   NVQUIRK_ENABLE_SDR104,
 };
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
-- 
2.18.0



[PATCH v3 28/38] arm64: dts: Add Tegra210 sdmmc pinctrl voltage states

2018-08-30 Thread Aapo Vienamo
Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra210.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 27 
 1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 3be920efee82..bc1918e07cc3 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -776,6 +777,26 @@
#power-domain-cells = <0>;
};
};
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
};
 
fuse@7000f800 {
@@ -1027,6 +1048,9 @@
clock-names = "sdhci";
resets = <_car 14>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -1049,6 +1073,9 @@
clock-names = "sdhci";
resets = <_car 69>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 29/38] arm64: dts: Add Tegra186 sdmmc pinctrl voltage states

2018-08-30 Thread Aapo Vienamo
Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra186.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 40 
 1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b762227f6aa1..7669756c060f 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -236,6 +237,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC1>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -247,6 +251,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC2>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -258,6 +265,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC3>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -368,6 +378,36 @@
  <0 0x0c38 0 0x1>,
  <0 0x0c39 0 0x1>;
reg-names = "pmc", "wake", "aotag", "scratch";
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc2_3v3: sdmmc2-3v3 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc2_1v8: sdmmc2-1v8 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
};
 
ccplex@e00 {
-- 
2.18.0



[PATCH v3 23/38] mmc: tegra: Use standard SDHCI tuning on Tegra210 and Tegra186

2018-08-30 Thread Aapo Vienamo
Add a new sdhci_ops struct for Tegra210 and Tegra186 which doesn't
set the custom tuning callback used on previous SoC generations.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 704c82cf7adf..f68557a01d5d 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -831,6 +831,19 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 
= {
.pdata = _tegra124_pdata,
 };
 
+static const struct sdhci_ops tegra210_sdhci_ops = {
+   .get_ro = tegra_sdhci_get_ro,
+   .read_w = tegra_sdhci_readw,
+   .write_w= tegra_sdhci_writew,
+   .write_l= tegra_sdhci_writel,
+   .set_clock  = tegra_sdhci_set_clock,
+   .set_bus_width = sdhci_set_bus_width,
+   .reset  = tegra_sdhci_reset,
+   .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
+   .voltage_switch = tegra_sdhci_voltage_switch,
+   .get_max_clock = tegra_sdhci_get_max_clock,
+};
+
 static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -839,7 +852,7 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = 
{
  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
-   .ops  = _sdhci_ops,
+   .ops  = _sdhci_ops,
 };
 
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
@@ -865,7 +878,7 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
* But it is not supported as of now.
*/
   SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
-   .ops  = _sdhci_ops,
+   .ops  = _sdhci_ops,
 };
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
-- 
2.18.0



[PATCH v3 24/38] mmc: tegra: Remove tegra_sdhci_writew() from tegra210_sdhci_ops

2018-08-30 Thread Aapo Vienamo
tegra_sdhci_writew() defers the write to SDHCI_TRANSFER_MODE until
SDHCI_COMMAND is written. This is not necessary on Tegra210 and Tegra186
and it breaks read-modify-write operations on SDHCI_TRANSFER_MODE
because writes to SDHCI_TRANSFER_MODE aren't visible until SDHCI_COMMAND
has been written to. This results in tuning failures on Tegra210.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f68557a01d5d..0bdce437e752 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -834,7 +834,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 
= {
 static const struct sdhci_ops tegra210_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
-   .write_w= tegra_sdhci_writew,
.write_l= tegra_sdhci_writel,
.set_clock  = tegra_sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
-- 
2.18.0



[PATCH v3 25/38] mmc: tegra: Disable card clock during tuning cmd on Tegra210

2018-08-30 Thread Aapo Vienamo
Implement tegra210_sdhci_writew() to disable card clock and issue a
reset when the tuning command is sent. This is done to prevent an
intermittent hang with around 10 % failure rate during tuning.

Add tegra186_sdhci_ops because this workaround is specific to Tegra210.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 81 --
 1 file changed, 58 insertions(+), 23 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 0bdce437e752..aa1574b8d96c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -177,6 +177,50 @@ static void tegra_sdhci_writel(struct sdhci_host *host, 
u32 val, int reg)
}
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
+{
+   bool status;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   status = !!(reg & SDHCI_CLOCK_CARD_EN);
+
+   if (status == enable)
+   return status;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return status;
+}
+
+static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
+{
+   bool is_tuning_cmd = 0;
+   bool clk_enabled;
+   u8 cmd;
+
+   if (reg == SDHCI_COMMAND) {
+   cmd = SDHCI_GET_CMD(val);
+   is_tuning_cmd = cmd == MMC_SEND_TUNING_BLOCK ||
+   cmd == MMC_SEND_TUNING_BLOCK_HS200;
+   }
+
+   if (is_tuning_cmd)
+   clk_enabled = tegra_sdhci_configure_card_clk(host, 0);
+
+   writew(val, host->ioaddr + reg);
+
+   if (is_tuning_cmd) {
+   udelay(1);
+   tegra_sdhci_configure_card_clk(host, clk_enabled);
+   }
+}
+
 static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
 {
return mmc_gpio_get_ro(host->mmc);
@@ -215,28 +259,6 @@ static bool tegra_sdhci_is_pad_and_regulator_valid(struct 
sdhci_host *host)
return true;
 }
 
-static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
-{
-   bool status;
-   u32 reg;
-
-   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-   status = !!(reg & SDHCI_CLOCK_CARD_EN);
-
-   if (status == enable)
-   return status;
-
-   if (enable)
-   reg |= SDHCI_CLOCK_CARD_EN;
-   else
-   reg &= ~SDHCI_CLOCK_CARD_EN;
-
-   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
-
-   return status;
-}
-
-
 static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -834,6 +856,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 
= {
 static const struct sdhci_ops tegra210_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
+   .write_w= tegra210_sdhci_writew,
.write_l= tegra_sdhci_writel,
.set_clock  = tegra_sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
@@ -861,6 +884,18 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 
= {
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
 };
 
+static const struct sdhci_ops tegra186_sdhci_ops = {
+   .get_ro = tegra_sdhci_get_ro,
+   .read_w = tegra_sdhci_readw,
+   .write_l= tegra_sdhci_writel,
+   .set_clock  = tegra_sdhci_set_clock,
+   .set_bus_width = sdhci_set_bus_width,
+   .reset  = tegra_sdhci_reset,
+   .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
+   .voltage_switch = tegra_sdhci_voltage_switch,
+   .get_max_clock = tegra_sdhci_get_max_clock,
+};
+
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -877,7 +912,7 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
* But it is not supported as of now.
*/
   SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
-   .ops  = _sdhci_ops,
+   .ops  = _sdhci_ops,
 };
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
-- 
2.18.0



[PATCH v3 27/38] mmc: tegra: Enable UHS and HS200 modes for Tegra186

2018-08-30 Thread Aapo Vienamo
Set nvquirks to enable higher speed modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 73ea947e9c0c..e80716c6e0d2 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -921,7 +921,9 @@ static const struct sdhci_tegra_soc_data soc_data_tegra186 
= {
.pdata = _tegra186_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB |
-   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
+   NVQUIRK_ENABLE_SDR50 |
+   NVQUIRK_ENABLE_SDR104,
 };
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
-- 
2.18.0



[PATCH v3 28/38] arm64: dts: Add Tegra210 sdmmc pinctrl voltage states

2018-08-30 Thread Aapo Vienamo
Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra210.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 27 
 1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 3be920efee82..bc1918e07cc3 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -776,6 +777,26 @@
#power-domain-cells = <0>;
};
};
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
};
 
fuse@7000f800 {
@@ -1027,6 +1048,9 @@
clock-names = "sdhci";
resets = <_car 14>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -1049,6 +1073,9 @@
clock-names = "sdhci";
resets = <_car 69>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
-- 
2.18.0



[PATCH v3 29/38] arm64: dts: Add Tegra186 sdmmc pinctrl voltage states

2018-08-30 Thread Aapo Vienamo
Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra186.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Acked-by: Thierry Reding 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 40 
 1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b762227f6aa1..7669756c060f 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -236,6 +237,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC1>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -247,6 +251,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC2>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -258,6 +265,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC3>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
 
@@ -368,6 +378,36 @@
  <0 0x0c38 0 0x1>,
  <0 0x0c39 0 0x1>;
reg-names = "pmc", "wake", "aotag", "scratch";
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc2_3v3: sdmmc2-3v3 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc2_1v8: sdmmc2-1v8 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
};
 
ccplex@e00 {
-- 
2.18.0



[PATCH v3 23/38] mmc: tegra: Use standard SDHCI tuning on Tegra210 and Tegra186

2018-08-30 Thread Aapo Vienamo
Add a new sdhci_ops struct for Tegra210 and Tegra186 which doesn't
set the custom tuning callback used on previous SoC generations.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 704c82cf7adf..f68557a01d5d 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -831,6 +831,19 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 
= {
.pdata = _tegra124_pdata,
 };
 
+static const struct sdhci_ops tegra210_sdhci_ops = {
+   .get_ro = tegra_sdhci_get_ro,
+   .read_w = tegra_sdhci_readw,
+   .write_w= tegra_sdhci_writew,
+   .write_l= tegra_sdhci_writel,
+   .set_clock  = tegra_sdhci_set_clock,
+   .set_bus_width = sdhci_set_bus_width,
+   .reset  = tegra_sdhci_reset,
+   .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
+   .voltage_switch = tegra_sdhci_voltage_switch,
+   .get_max_clock = tegra_sdhci_get_max_clock,
+};
+
 static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -839,7 +852,7 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = 
{
  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
-   .ops  = _sdhci_ops,
+   .ops  = _sdhci_ops,
 };
 
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
@@ -865,7 +878,7 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
* But it is not supported as of now.
*/
   SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
-   .ops  = _sdhci_ops,
+   .ops  = _sdhci_ops,
 };
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
-- 
2.18.0



[PATCH v3 24/38] mmc: tegra: Remove tegra_sdhci_writew() from tegra210_sdhci_ops

2018-08-30 Thread Aapo Vienamo
tegra_sdhci_writew() defers the write to SDHCI_TRANSFER_MODE until
SDHCI_COMMAND is written. This is not necessary on Tegra210 and Tegra186
and it breaks read-modify-write operations on SDHCI_TRANSFER_MODE
because writes to SDHCI_TRANSFER_MODE aren't visible until SDHCI_COMMAND
has been written to. This results in tuning failures on Tegra210.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f68557a01d5d..0bdce437e752 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -834,7 +834,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 
= {
 static const struct sdhci_ops tegra210_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
-   .write_w= tegra_sdhci_writew,
.write_l= tegra_sdhci_writel,
.set_clock  = tegra_sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
-- 
2.18.0



[PATCH v3 25/38] mmc: tegra: Disable card clock during tuning cmd on Tegra210

2018-08-30 Thread Aapo Vienamo
Implement tegra210_sdhci_writew() to disable card clock and issue a
reset when the tuning command is sent. This is done to prevent an
intermittent hang with around 10 % failure rate during tuning.

Add tegra186_sdhci_ops because this workaround is specific to Tegra210.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 81 --
 1 file changed, 58 insertions(+), 23 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 0bdce437e752..aa1574b8d96c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -177,6 +177,50 @@ static void tegra_sdhci_writel(struct sdhci_host *host, 
u32 val, int reg)
}
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
+{
+   bool status;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   status = !!(reg & SDHCI_CLOCK_CARD_EN);
+
+   if (status == enable)
+   return status;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return status;
+}
+
+static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
+{
+   bool is_tuning_cmd = 0;
+   bool clk_enabled;
+   u8 cmd;
+
+   if (reg == SDHCI_COMMAND) {
+   cmd = SDHCI_GET_CMD(val);
+   is_tuning_cmd = cmd == MMC_SEND_TUNING_BLOCK ||
+   cmd == MMC_SEND_TUNING_BLOCK_HS200;
+   }
+
+   if (is_tuning_cmd)
+   clk_enabled = tegra_sdhci_configure_card_clk(host, 0);
+
+   writew(val, host->ioaddr + reg);
+
+   if (is_tuning_cmd) {
+   udelay(1);
+   tegra_sdhci_configure_card_clk(host, clk_enabled);
+   }
+}
+
 static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
 {
return mmc_gpio_get_ro(host->mmc);
@@ -215,28 +259,6 @@ static bool tegra_sdhci_is_pad_and_regulator_valid(struct 
sdhci_host *host)
return true;
 }
 
-static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
-{
-   bool status;
-   u32 reg;
-
-   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-   status = !!(reg & SDHCI_CLOCK_CARD_EN);
-
-   if (status == enable)
-   return status;
-
-   if (enable)
-   reg |= SDHCI_CLOCK_CARD_EN;
-   else
-   reg &= ~SDHCI_CLOCK_CARD_EN;
-
-   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
-
-   return status;
-}
-
-
 static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -834,6 +856,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 
= {
 static const struct sdhci_ops tegra210_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
+   .write_w= tegra210_sdhci_writew,
.write_l= tegra_sdhci_writel,
.set_clock  = tegra_sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
@@ -861,6 +884,18 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 
= {
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
 };
 
+static const struct sdhci_ops tegra186_sdhci_ops = {
+   .get_ro = tegra_sdhci_get_ro,
+   .read_w = tegra_sdhci_readw,
+   .write_l= tegra_sdhci_writel,
+   .set_clock  = tegra_sdhci_set_clock,
+   .set_bus_width = sdhci_set_bus_width,
+   .reset  = tegra_sdhci_reset,
+   .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
+   .voltage_switch = tegra_sdhci_voltage_switch,
+   .get_max_clock = tegra_sdhci_get_max_clock,
+};
+
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -877,7 +912,7 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
* But it is not supported as of now.
*/
   SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
-   .ops  = _sdhci_ops,
+   .ops  = _sdhci_ops,
 };
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
-- 
2.18.0



[PATCH v3 26/38] mmc: tegra: Enable UHS and HS200 modes for Tegra210

2018-08-30 Thread Aapo Vienamo
Set nvquirks to enable higher speed modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index aa1574b8d96c..73ea947e9c0c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -881,7 +881,9 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 
= {
.pdata = _tegra210_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB |
-   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
+   NVQUIRK_ENABLE_SDR50 |
+   NVQUIRK_ENABLE_SDR104,
 };
 
 static const struct sdhci_ops tegra186_sdhci_ops = {
-- 
2.18.0



[PATCH v3 21/38] mmc: tegra: Configure default tap values

2018-08-30 Thread Aapo Vienamo
Set the default inbound timing adjustment tap value on reset and on
non-tunable modes.

The default tap value is not programmed on tunable modes because the
tuning sequence is used instead to determine the tap value.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 132 +++--
 1 file changed, 77 insertions(+), 55 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index dd8cb3f3cecc..3fd54af05671 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -213,6 +213,58 @@ static bool tegra_sdhci_is_pad_and_regulator_valid(struct 
sdhci_host *host)
return true;
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
+{
+   bool status;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   status = !!(reg & SDHCI_CLOCK_CARD_EN);
+
+   if (status == enable)
+   return status;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return status;
+}
+
+
+static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
+{
+   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;
+   bool card_clk_enabled = false;
+   u32 reg;
+
+   /*
+* Touching the tap values is a bit tricky on some SoC generations.
+* The quirk enables a workaround for a glitch that sometimes occurs if
+* the tap values are changed.
+*/
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP)
+   card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
+
+   reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+   reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
+   reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
+   sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP &&
+   card_clk_enabled) {
+   udelay(1);
+   sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+   tegra_sdhci_configure_card_clk(host, card_clk_enabled);
+   }
+}
+
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -225,6 +277,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
if (!(mask & SDHCI_RESET_ALL))
return;
 
+   tegra_sdhci_set_tap(host, tegra_host->default_tap);
+
misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
 
@@ -286,27 +340,6 @@ static void tegra_sdhci_configure_cal_pad(struct 
sdhci_host *host, bool enable)
usleep_range(1, 2);
 }
 
-static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
-{
-   bool status;
-   u32 reg;
-
-   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-   status = !!(reg & SDHCI_CLOCK_CARD_EN);
-
-   if (status == enable)
-   return status;
-
-   if (enable)
-   reg |= SDHCI_CLOCK_CARD_EN;
-   else
-   reg &= ~SDHCI_CLOCK_CARD_EN;
-
-   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
-
-   return status;
-}
-
 static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
   u16 pdpu)
 {
@@ -517,19 +550,6 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
}
 }
 
-static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
- unsigned timing)
-{
-   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
-
-   if (timing == MMC_TIMING_UHS_DDR50 ||
-   timing == MMC_TIMING_MMC_DDR52)
-   tegra_host->ddr_signaling = true;
-
-   sdhci_set_uhs_signaling(host, timing);
-}
-
 static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -537,34 +557,36 @@ static unsigned int tegra_sdhci_get_max_clock(struct 
sdhci_host *host)
return clk_round_rate(pltfm_host->clk, UINT_MAX);
 }
 
-static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
+static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
+ unsigned timing)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
-   co

[PATCH v3 22/38] mmc: tegra: Configure default trim value on reset

2018-08-30 Thread Aapo Vienamo
Program the outbound sampling trim value in tegra_sdhci_reset(). Unlike
the outbound tap value this does not depend on the signaling mode and
needs to be only programmed once.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 3fd54af05671..704c82cf7adf 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -37,6 +37,8 @@
 #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL  0x100
 #define SDHCI_CLOCK_CTRL_TAP_MASK  0x00ff
 #define SDHCI_CLOCK_CTRL_TAP_SHIFT 16
+#define SDHCI_CLOCK_CTRL_TRIM_MASK 0x1f00
+#define SDHCI_CLOCK_CTRL_TRIM_SHIFT24
 #define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5)
 #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDEBIT(3)
 #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE   BIT(2)
@@ -287,7 +289,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
   SDHCI_MISC_CTRL_ENABLE_DDR50 |
   SDHCI_MISC_CTRL_ENABLE_SDR104);
 
-   clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
+   clk_ctrl &= ~(SDHCI_CLOCK_CTRL_TRIM_MASK |
+ SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE);
 
if (tegra_sdhci_is_pad_and_regulator_valid(host)) {
/* Erratum: Enable SDHCI spec v3.00 support */
@@ -304,6 +307,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
}
 
+   clk_ctrl |= tegra_host->default_trim << SDHCI_CLOCK_CTRL_TRIM_SHIFT;
+
sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
 
-- 
2.18.0



[PATCH v3 26/38] mmc: tegra: Enable UHS and HS200 modes for Tegra210

2018-08-30 Thread Aapo Vienamo
Set nvquirks to enable higher speed modes.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index aa1574b8d96c..73ea947e9c0c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -881,7 +881,9 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 
= {
.pdata = _tegra210_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB |
-   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
+   NVQUIRK_ENABLE_SDR50 |
+   NVQUIRK_ENABLE_SDR104,
 };
 
 static const struct sdhci_ops tegra186_sdhci_ops = {
-- 
2.18.0



[PATCH v3 21/38] mmc: tegra: Configure default tap values

2018-08-30 Thread Aapo Vienamo
Set the default inbound timing adjustment tap value on reset and on
non-tunable modes.

The default tap value is not programmed on tunable modes because the
tuning sequence is used instead to determine the tap value.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 132 +++--
 1 file changed, 77 insertions(+), 55 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index dd8cb3f3cecc..3fd54af05671 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -213,6 +213,58 @@ static bool tegra_sdhci_is_pad_and_regulator_valid(struct 
sdhci_host *host)
return true;
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
+{
+   bool status;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   status = !!(reg & SDHCI_CLOCK_CARD_EN);
+
+   if (status == enable)
+   return status;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return status;
+}
+
+
+static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
+{
+   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;
+   bool card_clk_enabled = false;
+   u32 reg;
+
+   /*
+* Touching the tap values is a bit tricky on some SoC generations.
+* The quirk enables a workaround for a glitch that sometimes occurs if
+* the tap values are changed.
+*/
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP)
+   card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
+
+   reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+   reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
+   reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
+   sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP &&
+   card_clk_enabled) {
+   udelay(1);
+   sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+   tegra_sdhci_configure_card_clk(host, card_clk_enabled);
+   }
+}
+
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -225,6 +277,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
if (!(mask & SDHCI_RESET_ALL))
return;
 
+   tegra_sdhci_set_tap(host, tegra_host->default_tap);
+
misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
 
@@ -286,27 +340,6 @@ static void tegra_sdhci_configure_cal_pad(struct 
sdhci_host *host, bool enable)
usleep_range(1, 2);
 }
 
-static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
-{
-   bool status;
-   u32 reg;
-
-   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-   status = !!(reg & SDHCI_CLOCK_CARD_EN);
-
-   if (status == enable)
-   return status;
-
-   if (enable)
-   reg |= SDHCI_CLOCK_CARD_EN;
-   else
-   reg &= ~SDHCI_CLOCK_CARD_EN;
-
-   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
-
-   return status;
-}
-
 static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
   u16 pdpu)
 {
@@ -517,19 +550,6 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
}
 }
 
-static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
- unsigned timing)
-{
-   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
-
-   if (timing == MMC_TIMING_UHS_DDR50 ||
-   timing == MMC_TIMING_MMC_DDR52)
-   tegra_host->ddr_signaling = true;
-
-   sdhci_set_uhs_signaling(host, timing);
-}
-
 static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -537,34 +557,36 @@ static unsigned int tegra_sdhci_get_max_clock(struct 
sdhci_host *host)
return clk_round_rate(pltfm_host->clk, UINT_MAX);
 }
 
-static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
+static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
+ unsigned timing)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
-   co

[PATCH v3 22/38] mmc: tegra: Configure default trim value on reset

2018-08-30 Thread Aapo Vienamo
Program the outbound sampling trim value in tegra_sdhci_reset(). Unlike
the outbound tap value this does not depend on the signaling mode and
needs to be only programmed once.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 3fd54af05671..704c82cf7adf 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -37,6 +37,8 @@
 #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL  0x100
 #define SDHCI_CLOCK_CTRL_TAP_MASK  0x00ff
 #define SDHCI_CLOCK_CTRL_TAP_SHIFT 16
+#define SDHCI_CLOCK_CTRL_TRIM_MASK 0x1f00
+#define SDHCI_CLOCK_CTRL_TRIM_SHIFT24
 #define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5)
 #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDEBIT(3)
 #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE   BIT(2)
@@ -287,7 +289,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
   SDHCI_MISC_CTRL_ENABLE_DDR50 |
   SDHCI_MISC_CTRL_ENABLE_SDR104);
 
-   clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
+   clk_ctrl &= ~(SDHCI_CLOCK_CTRL_TRIM_MASK |
+ SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE);
 
if (tegra_sdhci_is_pad_and_regulator_valid(host)) {
/* Erratum: Enable SDHCI spec v3.00 support */
@@ -304,6 +307,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
}
 
+   clk_ctrl |= tegra_host->default_trim << SDHCI_CLOCK_CTRL_TRIM_SHIFT;
+
sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
 
-- 
2.18.0



[PATCH v3 20/38] mmc: tegra: Parse default trim and tap from dt

2018-08-30 Thread Aapo Vienamo
Parse the default inbound and outbound sampling trimmer values from
the device tree.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index d0a536f1b994..dd8cb3f3cecc 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -107,6 +107,9 @@ struct sdhci_tegra {
struct pinctrl_state *pinctrl_state_1v8;
 
struct sdhci_tegra_autocal_offsets autocal_offsets;
+
+   u32 default_tap;
+   u32 default_trim;
 };
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -461,6 +464,23 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct 
sdhci_host *host)
autocal->pull_down_hs400 = autocal->pull_down_1v8;
 }
 
+static void tegra_sdhci_parse_default_tap_and_trim(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   int err;
+
+   err = device_property_read_u32(host->mmc->parent, "nvidia,default-tap",
+  _host->default_tap);
+   if (err)
+   tegra_host->default_tap = 0;
+
+   err = device_property_read_u32(host->mmc->parent, "nvidia,default-trim",
+  _host->default_trim);
+   if (err)
+   tegra_host->default_trim = 0;
+}
+
 static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -881,6 +901,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 
tegra_sdhci_parse_pad_autocal_dt(host);
 
+   tegra_sdhci_parse_default_tap_and_trim(host);
+
tegra_host->power_gpio = devm_gpiod_get_optional(>dev, "power",
 GPIOD_OUT_HIGH);
if (IS_ERR(tegra_host->power_gpio)) {
-- 
2.18.0



[PATCH v3 16/38] mmc: tegra: Program pad autocal offsets from dt

2018-08-30 Thread 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 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 152 -
 1 file changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index ec07a3ce0247..a3e31f18db48 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -50,6 +50,7 @@
 #define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
 #define SDHCI_AUTO_CAL_START   BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE  BIT(29)
+#define SDHCI_AUTO_CAL_PDPU_OFFSET_MASK0x
 
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL 0x1e0
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK   0x000f
@@ -73,6 +74,22 @@ struct sdhci_tegra_soc_data {
u32 nvquirks;
 };
 
+/* Magic pull up and pull down pad calibration offsets */
+struct sdhci_tegra_autocal_offsets {
+   u32 pull_up_3v3;
+   u32 pull_down_3v3;
+   u32 pull_up_3v3_timeout;
+   u32 pull_down_3v3_timeout;
+   u32 pull_up_1v8;
+   u32 pull_down_1v8;
+   u32 pull_up_1v8_timeout;
+   u32 pull_down_1v8_timeout;
+   u32 pull_up_sdr104;
+   u32 pull_down_sdr104;
+   u32 pull_up_hs400;
+   u32 pull_down_hs400;
+};
+
 struct sdhci_tegra {
const struct sdhci_tegra_soc_data *soc_data;
struct gpio_desc *power_gpio;
@@ -84,6 +101,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)
@@ -281,12 +300,45 @@ static bool tegra_sdhci_configure_card_clk(struct 
sdhci_host *host, bool enable)
return status;
 }
 
+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 = >mmc->ios;
bool card_clk_enabled;
+   u16 pdpu;
u32 reg;
int ret;
 
+   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);
@@ -305,8 +357,104 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
 
tegra_sdhci_configure_card_clk(host, card_clk_enabled);
 
-   if (ret)
+   if (ret) {
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;
+
+   /* Disable automatic calibration and use fixed offsets */
+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   reg &= ~SDHCI_AUTO_CAL_ENABLE;
+   sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+
+   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 =
+   _host->autocal_offsets;
+   int err;
+
+   err = device_property_read_u32(hos

[PATCH v3 19/38] mmc: tegra: Add a workaround for tap value change glitch

2018-08-30 Thread Aapo Vienamo
Add quirk to disable the card clock during configuration of the tap
value in tegra_sdhci_set_tap() and issue sdhci_reset() after value
change. This is a workaround to avoid propagation of a potential
glitch caused by setting the tap value.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 30 --
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index caa9a1b30d2e..d0a536f1b994 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -47,6 +47,9 @@
 #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300  0x20
 #define SDHCI_MISC_CTRL_ENABLE_DDR50   0x200
 
+#define SDHCI_VNDR_TUN_CTRL0_0 0x1c0
+#define SDHCI_VNDR_TUN_CTRL0_TUN_HW_TAP0x2
+
 #define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
 #define SDHCI_AUTO_CAL_START   BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE  BIT(29)
@@ -68,6 +71,7 @@
 #define NVQUIRK_ENABLE_DDR50   BIT(5)
 #define NVQUIRK_HAS_PADCALIB   BIT(6)
 #define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
+#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAPBIT(8)
 
 struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -515,12 +519,32 @@ static unsigned int tegra_sdhci_get_max_clock(struct 
sdhci_host *host)
 
 static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
 {
+   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;
+   bool card_clk_enabled = false;
u32 reg;
 
+   /*
+* Touching the tap values is a bit tricky on some SoC generations.
+* The quirk enables a workaround for a glitch that sometimes occurs if
+* the tap values are changed.
+*/
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP)
+   card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
+
reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP &&
+   card_clk_enabled) {
+   usleep_range(1, 2);
+   sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+   tegra_sdhci_configure_card_clk(host, card_clk_enabled);
+   }
 }
 
 static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
@@ -774,7 +798,8 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = 
{
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
.pdata = _tegra210_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
-   NVQUIRK_HAS_PADCALIB,
+   NVQUIRK_HAS_PADCALIB |
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -799,7 +824,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
.pdata = _tegra186_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
-   NVQUIRK_HAS_PADCALIB,
+   NVQUIRK_HAS_PADCALIB |
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
 };
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
-- 
2.18.0



[PATCH v3 17/38] mmc: tegra: Perform pad calibration after voltage switch

2018-08-30 Thread Aapo Vienamo
Run the automatic pad calibration after voltage switching if
tegra_host->pad_calib_required is set.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 a3e31f18db48..71b3b3e1c648 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -587,6 +587,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) {
@@ -601,6 +603,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.18.0



[PATCH v3 18/38] mmc: tegra: Enable pad calibration on Tegra210 and Tegra186

2018-08-30 Thread Aapo Vienamo
Set NVQUIRK_HAS_PADCALIB on Tegra210 and Tegra186 to enable automatic
pad drive strength calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 71b3b3e1c648..caa9a1b30d2e 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -773,7 +773,8 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = 
{
 
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
.pdata = _tegra210_pdata,
-   .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL,
+   .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
+   NVQUIRK_HAS_PADCALIB,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -797,7 +798,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
.pdata = _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.18.0



[PATCH v3 20/38] mmc: tegra: Parse default trim and tap from dt

2018-08-30 Thread Aapo Vienamo
Parse the default inbound and outbound sampling trimmer values from
the device tree.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index d0a536f1b994..dd8cb3f3cecc 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -107,6 +107,9 @@ struct sdhci_tegra {
struct pinctrl_state *pinctrl_state_1v8;
 
struct sdhci_tegra_autocal_offsets autocal_offsets;
+
+   u32 default_tap;
+   u32 default_trim;
 };
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -461,6 +464,23 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct 
sdhci_host *host)
autocal->pull_down_hs400 = autocal->pull_down_1v8;
 }
 
+static void tegra_sdhci_parse_default_tap_and_trim(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   int err;
+
+   err = device_property_read_u32(host->mmc->parent, "nvidia,default-tap",
+  _host->default_tap);
+   if (err)
+   tegra_host->default_tap = 0;
+
+   err = device_property_read_u32(host->mmc->parent, "nvidia,default-trim",
+  _host->default_trim);
+   if (err)
+   tegra_host->default_trim = 0;
+}
+
 static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -881,6 +901,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 
tegra_sdhci_parse_pad_autocal_dt(host);
 
+   tegra_sdhci_parse_default_tap_and_trim(host);
+
tegra_host->power_gpio = devm_gpiod_get_optional(>dev, "power",
 GPIOD_OUT_HIGH);
if (IS_ERR(tegra_host->power_gpio)) {
-- 
2.18.0



[PATCH v3 16/38] mmc: tegra: Program pad autocal offsets from dt

2018-08-30 Thread 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 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 152 -
 1 file changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index ec07a3ce0247..a3e31f18db48 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -50,6 +50,7 @@
 #define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
 #define SDHCI_AUTO_CAL_START   BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE  BIT(29)
+#define SDHCI_AUTO_CAL_PDPU_OFFSET_MASK0x
 
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL 0x1e0
 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK   0x000f
@@ -73,6 +74,22 @@ struct sdhci_tegra_soc_data {
u32 nvquirks;
 };
 
+/* Magic pull up and pull down pad calibration offsets */
+struct sdhci_tegra_autocal_offsets {
+   u32 pull_up_3v3;
+   u32 pull_down_3v3;
+   u32 pull_up_3v3_timeout;
+   u32 pull_down_3v3_timeout;
+   u32 pull_up_1v8;
+   u32 pull_down_1v8;
+   u32 pull_up_1v8_timeout;
+   u32 pull_down_1v8_timeout;
+   u32 pull_up_sdr104;
+   u32 pull_down_sdr104;
+   u32 pull_up_hs400;
+   u32 pull_down_hs400;
+};
+
 struct sdhci_tegra {
const struct sdhci_tegra_soc_data *soc_data;
struct gpio_desc *power_gpio;
@@ -84,6 +101,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)
@@ -281,12 +300,45 @@ static bool tegra_sdhci_configure_card_clk(struct 
sdhci_host *host, bool enable)
return status;
 }
 
+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 = >mmc->ios;
bool card_clk_enabled;
+   u16 pdpu;
u32 reg;
int ret;
 
+   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);
@@ -305,8 +357,104 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
 
tegra_sdhci_configure_card_clk(host, card_clk_enabled);
 
-   if (ret)
+   if (ret) {
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;
+
+   /* Disable automatic calibration and use fixed offsets */
+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   reg &= ~SDHCI_AUTO_CAL_ENABLE;
+   sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+
+   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 =
+   _host->autocal_offsets;
+   int err;
+
+   err = device_property_read_u32(hos

[PATCH v3 19/38] mmc: tegra: Add a workaround for tap value change glitch

2018-08-30 Thread Aapo Vienamo
Add quirk to disable the card clock during configuration of the tap
value in tegra_sdhci_set_tap() and issue sdhci_reset() after value
change. This is a workaround to avoid propagation of a potential
glitch caused by setting the tap value.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 30 --
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index caa9a1b30d2e..d0a536f1b994 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -47,6 +47,9 @@
 #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300  0x20
 #define SDHCI_MISC_CTRL_ENABLE_DDR50   0x200
 
+#define SDHCI_VNDR_TUN_CTRL0_0 0x1c0
+#define SDHCI_VNDR_TUN_CTRL0_TUN_HW_TAP0x2
+
 #define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
 #define SDHCI_AUTO_CAL_START   BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE  BIT(29)
@@ -68,6 +71,7 @@
 #define NVQUIRK_ENABLE_DDR50   BIT(5)
 #define NVQUIRK_HAS_PADCALIB   BIT(6)
 #define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
+#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAPBIT(8)
 
 struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -515,12 +519,32 @@ static unsigned int tegra_sdhci_get_max_clock(struct 
sdhci_host *host)
 
 static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
 {
+   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;
+   bool card_clk_enabled = false;
u32 reg;
 
+   /*
+* Touching the tap values is a bit tricky on some SoC generations.
+* The quirk enables a workaround for a glitch that sometimes occurs if
+* the tap values are changed.
+*/
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP)
+   card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
+
reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+
+   if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP &&
+   card_clk_enabled) {
+   usleep_range(1, 2);
+   sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+   tegra_sdhci_configure_card_clk(host, card_clk_enabled);
+   }
 }
 
 static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
@@ -774,7 +798,8 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = 
{
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
.pdata = _tegra210_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
-   NVQUIRK_HAS_PADCALIB,
+   NVQUIRK_HAS_PADCALIB |
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -799,7 +824,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
.pdata = _tegra186_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
-   NVQUIRK_HAS_PADCALIB,
+   NVQUIRK_HAS_PADCALIB |
+   NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
 };
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
-- 
2.18.0



[PATCH v3 17/38] mmc: tegra: Perform pad calibration after voltage switch

2018-08-30 Thread Aapo Vienamo
Run the automatic pad calibration after voltage switching if
tegra_host->pad_calib_required is set.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 a3e31f18db48..71b3b3e1c648 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -587,6 +587,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) {
@@ -601,6 +603,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.18.0



[PATCH v3 18/38] mmc: tegra: Enable pad calibration on Tegra210 and Tegra186

2018-08-30 Thread Aapo Vienamo
Set NVQUIRK_HAS_PADCALIB on Tegra210 and Tegra186 to enable automatic
pad drive strength calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 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 71b3b3e1c648..caa9a1b30d2e 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -773,7 +773,8 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = 
{
 
 static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
.pdata = _tegra210_pdata,
-   .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL,
+   .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
+   NVQUIRK_HAS_PADCALIB,
 };
 
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -797,7 +798,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = 
{
 
 static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
.pdata = _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.18.0



[PATCH v3 09/38] soc/tegra: pmc: Remove public pad voltage APIs

2018-08-30 Thread Aapo Vienamo
Make tegra_io_pad_set_voltage() and tegra_io_pad_get_voltage() static
and remove the prototypes from pmc.h. Remove enum tegra_io_pad_voltage
and use the defines from 
instead.

These functions aren't used outside of the pmc driver and new use cases
should use the pinctrl interface instead.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 17 -
 include/soc/tegra/pmc.h | 19 ---
 2 files changed, 8 insertions(+), 28 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 3b844b0fd8ac..de6832df2e9a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -45,6 +45,8 @@
 #include 
 #include 
 
+#include 
+
 #define PMC_CNTRL  0x0
 #define  PMC_CNTRL_INTR_POLARITY   BIT(17) /* inverts INTR polarity */
 #define  PMC_CNTRL_CPU_PWRREQ_OE   BIT(16) /* CPU pwr req enable */
@@ -1091,8 +1093,7 @@ static int tegra_io_pad_is_powered(enum tegra_io_pad id)
return !(value & mask);
 }
 
-int tegra_io_pad_set_voltage(enum tegra_io_pad id,
-enum tegra_io_pad_voltage voltage)
+static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
 {
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1109,7 +1110,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
if (pmc->soc->has_impl_33v_pwr) {
value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
 
-   if (voltage == TEGRA_IO_PAD_180UV)
+   if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
@@ -1124,7 +1125,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
/* update I/O voltage */
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
-   if (voltage == TEGRA_IO_PAD_180UV)
+   if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
@@ -1138,9 +1139,8 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
 
return 0;
 }
-EXPORT_SYMBOL(tegra_io_pad_set_voltage);
 
-int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
 {
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1158,11 +1158,10 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id)
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
if ((value & BIT(pad->voltage)) == 0)
-   return TEGRA_IO_PAD_180UV;
+   return TEGRA_IO_PAD_VOLTAGE_1V8;
 
-   return TEGRA_IO_PAD_330UV;
+   return TEGRA_IO_PAD_VOLTAGE_3V3;
 }
-EXPORT_SYMBOL(tegra_io_pad_get_voltage);
 
 /**
  * tegra_io_rail_power_on() - enable power to I/O rail
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index 445aa66514e9..562426812ab2 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -141,16 +141,6 @@ enum tegra_io_pad {
 #define TEGRA_IO_RAIL_HDMI TEGRA_IO_PAD_HDMI
 #define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS
 
-/**
- * enum tegra_io_pad_voltage - voltage level of the I/O pad's source rail
- * @TEGRA_IO_PAD_180UV: 1.8 V
- * @TEGRA_IO_PAD_330UV: 3.3 V
- */
-enum tegra_io_pad_voltage {
-   TEGRA_IO_PAD_180UV,
-   TEGRA_IO_PAD_330UV,
-};
-
 #ifdef CONFIG_SOC_TEGRA_PMC
 int tegra_powergate_is_powered(unsigned int id);
 int tegra_powergate_power_on(unsigned int id);
@@ -163,9 +153,6 @@ int tegra_powergate_sequence_power_up(unsigned int id, 
struct clk *clk,
 
 int tegra_io_pad_power_enable(enum tegra_io_pad id);
 int tegra_io_pad_power_disable(enum tegra_io_pad id);
-int tegra_io_pad_set_voltage(enum tegra_io_pad id,
-enum tegra_io_pad_voltage voltage);
-int tegra_io_pad_get_voltage(enum tegra_io_pad id);
 
 /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
 int tegra_io_rail_power_on(unsigned int id);
@@ -213,12 +200,6 @@ static inline int tegra_io_pad_power_disable(enum 
tegra_io_pad id)
return -ENOSYS;
 }
 
-static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
-  enum tegra_io_pad_voltage voltage)
-{
-   return -ENOSYS;
-}
-
 static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
 {
return -ENOSYS;
-- 
2.18.0



[PATCH v3 11/38] mmc: tegra: Reconfigure pad voltages during voltage switching

2018-08-30 Thread Aapo Vienamo
Parse the pinctrl state and nvidia,only-1-8-v properties from the device
tree. Validate the pinctrl and regulator configuration before unmasking
UHS modes. Implement pad voltage state reconfiguration in the mmc
start_signal_voltage_switch() callback. Add NVQUIRK_NEEDS_PAD_CONTROL
and add set it for Tegra210 and Tegra186.

The pad configuration is done in the mmc callback because the order of
pad reconfiguration and sdhci voltage switch depend on the voltage to
which the transition occurs.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 136 +++--
 1 file changed, 129 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 908b23e6a03c..11185e96f3c3 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -55,6 +57,7 @@
 #define NVQUIRK_ENABLE_SDR104  BIT(4)
 #define NVQUIRK_ENABLE_DDR50   BIT(5)
 #define NVQUIRK_HAS_PADCALIB   BIT(6)
+#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
 
 struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -66,8 +69,12 @@ struct sdhci_tegra {
struct gpio_desc *power_gpio;
bool ddr_signaling;
bool pad_calib_required;
+   bool pad_control_available;
 
struct reset_control *rst;
+   struct pinctrl *pinctrl_sdmmc;
+   struct pinctrl_state *pinctrl_state_3v3;
+   struct pinctrl_state *pinctrl_state_1v8;
 };
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -138,6 +145,39 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host 
*host)
return mmc_gpio_get_ro(host->mmc);
 }
 
+static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   int has_1v8, has_3v3;
+
+   /*
+* The SoCs which have NVQUIRK_NEEDS_PAD_CONTROL require software pad
+* voltage configuration in order to perform voltage switching. This
+* means that valid pinctrl info is required on SDHCI instances capable
+* of performing voltage switching. Whether or not an SDHCI instance is
+* capable of voltage switching is determined based on the regulator.
+*/
+
+   if (!(tegra_host->soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL))
+   return true;
+
+   if (IS_ERR(host->mmc->supply.vqmmc))
+   return false;
+
+   has_1v8 = regulator_is_supported_voltage(host->mmc->supply.vqmmc,
+170, 195);
+
+   has_3v3 = regulator_is_supported_voltage(host->mmc->supply.vqmmc,
+270, 360);
+
+   if (has_1v8 == 1 && has_3v3 == 1)
+   return tegra_host->pad_control_available;
+
+   /* Fixed voltage, no pad control required. */
+   return true;
+}
+
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -160,13 +200,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
 
clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
 
-   /*
-* If the board does not define a regulator for the SDHCI
-* IO voltage, then don't advertise support for UHS modes
-* even if the device supports it because the IO voltage
-* cannot be configured.
-*/
-   if (!IS_ERR(host->mmc->supply.vqmmc)) {
+   if (tegra_sdhci_is_pad_and_regulator_valid(host)) {
/* Erratum: Enable SDHCI spec v3.00 support */
if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
@@ -301,6 +335,84 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host 
*host, u32 opcode)
return mmc_send_tuning(host->mmc, opcode, NULL);
 }
 
+static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   int ret;
+
+   if (!tegra_host->pad_control_available)
+   return 0;
+
+   if (voltage == MMC_SIGNAL_VOLTAGE_180) {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+  tegra_host->pinctrl_state_1v8);
+   if (ret < 0)
+   dev_err(mmc_dev(host->mmc),
+   "setting 1.8V failed, ret: %d\n", ret);
+   } else {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+   

[PATCH v3 10/38] soc/tegra: pmc: Implement pad configuration via pinctrl

2018-08-30 Thread Aapo Vienamo
Register a pinctrl device and implement get and set functions for
PIN_CONFIG_LOW_POWER_MODE and PIN_CONFIG_POWER_SOURCE parameters.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 187 +++-
 1 file changed, 185 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index de6832df2e9a..f66699579e95 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -33,6 +33,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -164,6 +167,9 @@ struct tegra_pmc_soc {
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
 
+   const struct pinctrl_pin_desc *pin_descs;
+   unsigned int num_pin_descs;
+
const struct tegra_pmc_regs *regs;
void (*init)(struct tegra_pmc *pmc);
void (*setup_irq_polarity)(struct tegra_pmc *pmc,
@@ -222,6 +228,8 @@ struct tegra_pmc {
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
 
struct mutex powergates_lock;
+
+   struct pinctrl_dev *pctl_dev;
 };
 
 static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -1399,6 +1407,142 @@ static void tegra_pmc_init_tsense_reset(struct 
tegra_pmc *pmc)
of_node_put(np);
 }
 
+static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
+{
+   return pmc->soc->num_io_pads;
+}
+
+static const char *tegra_io_pad_pinctrl_get_group_name(
+   struct pinctrl_dev *pctl, unsigned int group)
+{
+   return pmc->soc->io_pads[group].name;
+}
+
+static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
+  unsigned int group,
+  const unsigned int **pins,
+  unsigned int *num_pins)
+{
+   *pins = >soc->io_pads[group].id;
+   *num_pins = 1;
+   return 0;
+}
+
+static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
+   .get_groups_count = tegra_io_pad_pinctrl_get_groups_count,
+   .get_group_name = tegra_io_pad_pinctrl_get_group_name,
+   .get_group_pins = tegra_io_pad_pinctrl_get_group_pins,
+   .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+   .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
+   unsigned int pin, unsigned long *config)
+{
+   const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+   enum pin_config_param param = pinconf_to_config_param(*config);
+   int ret;
+   u32 arg;
+
+   if (!pad)
+   return -EINVAL;
+
+   switch (param) {
+   case PIN_CONFIG_POWER_SOURCE:
+   ret = tegra_io_pad_get_voltage(pad->id);
+   if (ret < 0)
+   return ret;
+   arg = ret;
+   break;
+   case PIN_CONFIG_LOW_POWER_MODE:
+   ret = tegra_io_pad_is_powered(pad->id);
+   if (ret < 0)
+   return ret;
+   arg = !ret;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   *config = pinconf_to_config_packed(param, arg);
+
+   return 0;
+}
+
+static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
+   unsigned int pin, unsigned long *configs,
+   unsigned int num_configs)
+{
+   const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+   enum pin_config_param param;
+   unsigned int i;
+   int err;
+   u32 arg;
+
+   if (!pad)
+   return -EINVAL;
+
+   for (i = 0; i < num_configs; ++i) {
+   param = pinconf_to_config_param(configs[i]);
+   arg = pinconf_to_config_argument(configs[i]);
+
+   switch (param) {
+   case PIN_CONFIG_LOW_POWER_MODE:
+   if (arg)
+   err = tegra_io_pad_power_disable(pad->id);
+   else
+   err = tegra_io_pad_power_enable(pad->id);
+   if (err)
+   return err;
+   break;
+   case PIN_CONFIG_POWER_SOURCE:
+   if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
+   arg != TEGRA_IO_PAD_VOLTAGE_3V3)
+   return -EINVAL;
+   err = tegra_io_pad_set_voltage(pad->id, arg);
+   if (err)
+   return err;
+   break;
+   default:
+   return -EINVAL;
+   }
+   }
+
+   return 0;
+}
+
+static const struct pinconf_ops tegra_io_pad_pinconf_ops 

[PATCH v3 09/38] soc/tegra: pmc: Remove public pad voltage APIs

2018-08-30 Thread Aapo Vienamo
Make tegra_io_pad_set_voltage() and tegra_io_pad_get_voltage() static
and remove the prototypes from pmc.h. Remove enum tegra_io_pad_voltage
and use the defines from 
instead.

These functions aren't used outside of the pmc driver and new use cases
should use the pinctrl interface instead.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 17 -
 include/soc/tegra/pmc.h | 19 ---
 2 files changed, 8 insertions(+), 28 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 3b844b0fd8ac..de6832df2e9a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -45,6 +45,8 @@
 #include 
 #include 
 
+#include 
+
 #define PMC_CNTRL  0x0
 #define  PMC_CNTRL_INTR_POLARITY   BIT(17) /* inverts INTR polarity */
 #define  PMC_CNTRL_CPU_PWRREQ_OE   BIT(16) /* CPU pwr req enable */
@@ -1091,8 +1093,7 @@ static int tegra_io_pad_is_powered(enum tegra_io_pad id)
return !(value & mask);
 }
 
-int tegra_io_pad_set_voltage(enum tegra_io_pad id,
-enum tegra_io_pad_voltage voltage)
+static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
 {
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1109,7 +1110,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
if (pmc->soc->has_impl_33v_pwr) {
value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
 
-   if (voltage == TEGRA_IO_PAD_180UV)
+   if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
@@ -1124,7 +1125,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
/* update I/O voltage */
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
-   if (voltage == TEGRA_IO_PAD_180UV)
+   if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
@@ -1138,9 +1139,8 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
 
return 0;
 }
-EXPORT_SYMBOL(tegra_io_pad_set_voltage);
 
-int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
 {
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1158,11 +1158,10 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id)
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
if ((value & BIT(pad->voltage)) == 0)
-   return TEGRA_IO_PAD_180UV;
+   return TEGRA_IO_PAD_VOLTAGE_1V8;
 
-   return TEGRA_IO_PAD_330UV;
+   return TEGRA_IO_PAD_VOLTAGE_3V3;
 }
-EXPORT_SYMBOL(tegra_io_pad_get_voltage);
 
 /**
  * tegra_io_rail_power_on() - enable power to I/O rail
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index 445aa66514e9..562426812ab2 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -141,16 +141,6 @@ enum tegra_io_pad {
 #define TEGRA_IO_RAIL_HDMI TEGRA_IO_PAD_HDMI
 #define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS
 
-/**
- * enum tegra_io_pad_voltage - voltage level of the I/O pad's source rail
- * @TEGRA_IO_PAD_180UV: 1.8 V
- * @TEGRA_IO_PAD_330UV: 3.3 V
- */
-enum tegra_io_pad_voltage {
-   TEGRA_IO_PAD_180UV,
-   TEGRA_IO_PAD_330UV,
-};
-
 #ifdef CONFIG_SOC_TEGRA_PMC
 int tegra_powergate_is_powered(unsigned int id);
 int tegra_powergate_power_on(unsigned int id);
@@ -163,9 +153,6 @@ int tegra_powergate_sequence_power_up(unsigned int id, 
struct clk *clk,
 
 int tegra_io_pad_power_enable(enum tegra_io_pad id);
 int tegra_io_pad_power_disable(enum tegra_io_pad id);
-int tegra_io_pad_set_voltage(enum tegra_io_pad id,
-enum tegra_io_pad_voltage voltage);
-int tegra_io_pad_get_voltage(enum tegra_io_pad id);
 
 /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
 int tegra_io_rail_power_on(unsigned int id);
@@ -213,12 +200,6 @@ static inline int tegra_io_pad_power_disable(enum 
tegra_io_pad id)
return -ENOSYS;
 }
 
-static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
-  enum tegra_io_pad_voltage voltage)
-{
-   return -ENOSYS;
-}
-
 static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
 {
return -ENOSYS;
-- 
2.18.0



[PATCH v3 11/38] mmc: tegra: Reconfigure pad voltages during voltage switching

2018-08-30 Thread Aapo Vienamo
Parse the pinctrl state and nvidia,only-1-8-v properties from the device
tree. Validate the pinctrl and regulator configuration before unmasking
UHS modes. Implement pad voltage state reconfiguration in the mmc
start_signal_voltage_switch() callback. Add NVQUIRK_NEEDS_PAD_CONTROL
and add set it for Tegra210 and Tegra186.

The pad configuration is done in the mmc callback because the order of
pad reconfiguration and sdhci voltage switch depend on the voltage to
which the transition occurs.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 136 +++--
 1 file changed, 129 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 908b23e6a03c..11185e96f3c3 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -55,6 +57,7 @@
 #define NVQUIRK_ENABLE_SDR104  BIT(4)
 #define NVQUIRK_ENABLE_DDR50   BIT(5)
 #define NVQUIRK_HAS_PADCALIB   BIT(6)
+#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
 
 struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -66,8 +69,12 @@ struct sdhci_tegra {
struct gpio_desc *power_gpio;
bool ddr_signaling;
bool pad_calib_required;
+   bool pad_control_available;
 
struct reset_control *rst;
+   struct pinctrl *pinctrl_sdmmc;
+   struct pinctrl_state *pinctrl_state_3v3;
+   struct pinctrl_state *pinctrl_state_1v8;
 };
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -138,6 +145,39 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host 
*host)
return mmc_gpio_get_ro(host->mmc);
 }
 
+static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   int has_1v8, has_3v3;
+
+   /*
+* The SoCs which have NVQUIRK_NEEDS_PAD_CONTROL require software pad
+* voltage configuration in order to perform voltage switching. This
+* means that valid pinctrl info is required on SDHCI instances capable
+* of performing voltage switching. Whether or not an SDHCI instance is
+* capable of voltage switching is determined based on the regulator.
+*/
+
+   if (!(tegra_host->soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL))
+   return true;
+
+   if (IS_ERR(host->mmc->supply.vqmmc))
+   return false;
+
+   has_1v8 = regulator_is_supported_voltage(host->mmc->supply.vqmmc,
+170, 195);
+
+   has_3v3 = regulator_is_supported_voltage(host->mmc->supply.vqmmc,
+270, 360);
+
+   if (has_1v8 == 1 && has_3v3 == 1)
+   return tegra_host->pad_control_available;
+
+   /* Fixed voltage, no pad control required. */
+   return true;
+}
+
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -160,13 +200,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
 
clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
 
-   /*
-* If the board does not define a regulator for the SDHCI
-* IO voltage, then don't advertise support for UHS modes
-* even if the device supports it because the IO voltage
-* cannot be configured.
-*/
-   if (!IS_ERR(host->mmc->supply.vqmmc)) {
+   if (tegra_sdhci_is_pad_and_regulator_valid(host)) {
/* Erratum: Enable SDHCI spec v3.00 support */
if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
@@ -301,6 +335,84 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host 
*host, u32 opcode)
return mmc_send_tuning(host->mmc, opcode, NULL);
 }
 
+static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   int ret;
+
+   if (!tegra_host->pad_control_available)
+   return 0;
+
+   if (voltage == MMC_SIGNAL_VOLTAGE_180) {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+  tegra_host->pinctrl_state_1v8);
+   if (ret < 0)
+   dev_err(mmc_dev(host->mmc),
+   "setting 1.8V failed, ret: %d\n", ret);
+   } else {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+   

[PATCH v3 10/38] soc/tegra: pmc: Implement pad configuration via pinctrl

2018-08-30 Thread Aapo Vienamo
Register a pinctrl device and implement get and set functions for
PIN_CONFIG_LOW_POWER_MODE and PIN_CONFIG_POWER_SOURCE parameters.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 187 +++-
 1 file changed, 185 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index de6832df2e9a..f66699579e95 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -33,6 +33,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -164,6 +167,9 @@ struct tegra_pmc_soc {
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
 
+   const struct pinctrl_pin_desc *pin_descs;
+   unsigned int num_pin_descs;
+
const struct tegra_pmc_regs *regs;
void (*init)(struct tegra_pmc *pmc);
void (*setup_irq_polarity)(struct tegra_pmc *pmc,
@@ -222,6 +228,8 @@ struct tegra_pmc {
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
 
struct mutex powergates_lock;
+
+   struct pinctrl_dev *pctl_dev;
 };
 
 static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -1399,6 +1407,142 @@ static void tegra_pmc_init_tsense_reset(struct 
tegra_pmc *pmc)
of_node_put(np);
 }
 
+static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
+{
+   return pmc->soc->num_io_pads;
+}
+
+static const char *tegra_io_pad_pinctrl_get_group_name(
+   struct pinctrl_dev *pctl, unsigned int group)
+{
+   return pmc->soc->io_pads[group].name;
+}
+
+static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
+  unsigned int group,
+  const unsigned int **pins,
+  unsigned int *num_pins)
+{
+   *pins = >soc->io_pads[group].id;
+   *num_pins = 1;
+   return 0;
+}
+
+static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
+   .get_groups_count = tegra_io_pad_pinctrl_get_groups_count,
+   .get_group_name = tegra_io_pad_pinctrl_get_group_name,
+   .get_group_pins = tegra_io_pad_pinctrl_get_group_pins,
+   .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+   .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
+   unsigned int pin, unsigned long *config)
+{
+   const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+   enum pin_config_param param = pinconf_to_config_param(*config);
+   int ret;
+   u32 arg;
+
+   if (!pad)
+   return -EINVAL;
+
+   switch (param) {
+   case PIN_CONFIG_POWER_SOURCE:
+   ret = tegra_io_pad_get_voltage(pad->id);
+   if (ret < 0)
+   return ret;
+   arg = ret;
+   break;
+   case PIN_CONFIG_LOW_POWER_MODE:
+   ret = tegra_io_pad_is_powered(pad->id);
+   if (ret < 0)
+   return ret;
+   arg = !ret;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   *config = pinconf_to_config_packed(param, arg);
+
+   return 0;
+}
+
+static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
+   unsigned int pin, unsigned long *configs,
+   unsigned int num_configs)
+{
+   const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+   enum pin_config_param param;
+   unsigned int i;
+   int err;
+   u32 arg;
+
+   if (!pad)
+   return -EINVAL;
+
+   for (i = 0; i < num_configs; ++i) {
+   param = pinconf_to_config_param(configs[i]);
+   arg = pinconf_to_config_argument(configs[i]);
+
+   switch (param) {
+   case PIN_CONFIG_LOW_POWER_MODE:
+   if (arg)
+   err = tegra_io_pad_power_disable(pad->id);
+   else
+   err = tegra_io_pad_power_enable(pad->id);
+   if (err)
+   return err;
+   break;
+   case PIN_CONFIG_POWER_SOURCE:
+   if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
+   arg != TEGRA_IO_PAD_VOLTAGE_3V3)
+   return -EINVAL;
+   err = tegra_io_pad_set_voltage(pad->id, arg);
+   if (err)
+   return err;
+   break;
+   default:
+   return -EINVAL;
+   }
+   }
+
+   return 0;
+}
+
+static const struct pinconf_ops tegra_io_pad_pinconf_ops 

[PATCH v3 12/38] mmc: tegra: Poll for calibration completion

2018-08-30 Thread Aapo Vienamo
Implement polling with 10 ms timeout for automatic pad drive strength
calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 11185e96f3c3..56b637c5b594 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -50,6 +51,9 @@
 #define SDHCI_AUTO_CAL_START   BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE  BIT(29)
 
+#define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
+#define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(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)
@@ -226,13 +230,21 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
 
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
-   u32 val;
+   u32 reg;
+   int ret;
+
+   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);
 
-   mdelay(1);
+   usleep_range(1, 2);
+   /* 10 ms timeout */
+   ret = readl_poll_timeout(host->ioaddr + SDHCI_TEGRA_AUTO_CAL_STATUS,
+reg, !(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE),
+1000, 1);
 
-   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 (ret)
+   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.18.0



[PATCH v3 13/38] mmc: tegra: Set calibration pad voltage reference

2018-08-30 Thread 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 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 56 --
 1 file changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 56b637c5b594..01a21e0af6d7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -41,27 +41,31 @@
 #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDEBIT(3)
 #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE   BIT(2)
 
-#define SDHCI_TEGRA_VENDOR_MISC_CTRL   0x120
-#define SDHCI_MISC_CTRL_ENABLE_SDR104  0x8
-#define SDHCI_MISC_CTRL_ENABLE_SDR50   0x10
-#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300  0x20
-#define SDHCI_MISC_CTRL_ENABLE_DDR50   0x200
-
-#define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
-#define SDHCI_AUTO_CAL_START   BIT(31)
-#define SDHCI_AUTO_CAL_ENABLE  BIT(29)
-
-#define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
-#define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(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)
-#define NVQUIRK_ENABLE_SDR50   BIT(3)
-#define NVQUIRK_ENABLE_SDR104  BIT(4)
-#define NVQUIRK_ENABLE_DDR50   BIT(5)
-#define NVQUIRK_HAS_PADCALIB   BIT(6)
-#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
+#define SDHCI_TEGRA_VENDOR_MISC_CTRL   0x120
+#define SDHCI_MISC_CTRL_ENABLE_SDR104  0x8
+#define SDHCI_MISC_CTRL_ENABLE_SDR50   0x10
+#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300  0x20
+#define SDHCI_MISC_CTRL_ENABLE_DDR50   0x200
+
+#define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
+#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   0x000f
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL0x7
+
+#define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
+#define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(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)
+#define NVQUIRK_ENABLE_SDR50   BIT(3)
+#define NVQUIRK_ENABLE_SDR104  BIT(4)
+#define NVQUIRK_ENABLE_DDR50   BIT(5)
+#define NVQUIRK_HAS_PADCALIB   BIT(6)
+#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
 
 struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -187,7 +191,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);
 
@@ -222,8 +226,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.18.0



[PATCH v3 15/38] mmc: tegra: Disable card clock during pad calibration

2018-08-30 Thread Aapo Vienamo
Disable the card clock during automatic pad drive strength calibration
and re-enable it afterwards.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e63cd6b2fc9f..ec07a3ce0247 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -260,11 +260,35 @@ static void tegra_sdhci_configure_cal_pad(struct 
sdhci_host *host, bool enable)
usleep_range(1, 2);
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
+{
+   bool status;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   status = !!(reg & SDHCI_CLOCK_CARD_EN);
+
+   if (status == enable)
+   return status;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return status;
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
+   bool card_clk_enabled;
u32 reg;
int ret;
 
+   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);
@@ -279,6 +303,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 (ret)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
-- 
2.18.0



[PATCH v3 12/38] mmc: tegra: Poll for calibration completion

2018-08-30 Thread Aapo Vienamo
Implement polling with 10 ms timeout for automatic pad drive strength
calibration.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 11185e96f3c3..56b637c5b594 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -50,6 +51,9 @@
 #define SDHCI_AUTO_CAL_START   BIT(31)
 #define SDHCI_AUTO_CAL_ENABLE  BIT(29)
 
+#define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
+#define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(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)
@@ -226,13 +230,21 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
 
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
-   u32 val;
+   u32 reg;
+   int ret;
+
+   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);
 
-   mdelay(1);
+   usleep_range(1, 2);
+   /* 10 ms timeout */
+   ret = readl_poll_timeout(host->ioaddr + SDHCI_TEGRA_AUTO_CAL_STATUS,
+reg, !(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE),
+1000, 1);
 
-   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 (ret)
+   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.18.0



[PATCH v3 13/38] mmc: tegra: Set calibration pad voltage reference

2018-08-30 Thread 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 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 56 --
 1 file changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 56b637c5b594..01a21e0af6d7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -41,27 +41,31 @@
 #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDEBIT(3)
 #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE   BIT(2)
 
-#define SDHCI_TEGRA_VENDOR_MISC_CTRL   0x120
-#define SDHCI_MISC_CTRL_ENABLE_SDR104  0x8
-#define SDHCI_MISC_CTRL_ENABLE_SDR50   0x10
-#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300  0x20
-#define SDHCI_MISC_CTRL_ENABLE_DDR50   0x200
-
-#define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
-#define SDHCI_AUTO_CAL_START   BIT(31)
-#define SDHCI_AUTO_CAL_ENABLE  BIT(29)
-
-#define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
-#define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(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)
-#define NVQUIRK_ENABLE_SDR50   BIT(3)
-#define NVQUIRK_ENABLE_SDR104  BIT(4)
-#define NVQUIRK_ENABLE_DDR50   BIT(5)
-#define NVQUIRK_HAS_PADCALIB   BIT(6)
-#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
+#define SDHCI_TEGRA_VENDOR_MISC_CTRL   0x120
+#define SDHCI_MISC_CTRL_ENABLE_SDR104  0x8
+#define SDHCI_MISC_CTRL_ENABLE_SDR50   0x10
+#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300  0x20
+#define SDHCI_MISC_CTRL_ENABLE_DDR50   0x200
+
+#define SDHCI_TEGRA_AUTO_CAL_CONFIG0x1e4
+#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   0x000f
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL0x7
+
+#define SDHCI_TEGRA_AUTO_CAL_STATUS0x1ec
+#define SDHCI_TEGRA_AUTO_CAL_ACTIVEBIT(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)
+#define NVQUIRK_ENABLE_SDR50   BIT(3)
+#define NVQUIRK_ENABLE_SDR104  BIT(4)
+#define NVQUIRK_ENABLE_DDR50   BIT(5)
+#define NVQUIRK_HAS_PADCALIB   BIT(6)
+#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
 
 struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -187,7 +191,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);
 
@@ -222,8 +226,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.18.0



[PATCH v3 15/38] mmc: tegra: Disable card clock during pad calibration

2018-08-30 Thread Aapo Vienamo
Disable the card clock during automatic pad drive strength calibration
and re-enable it afterwards.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/mmc/host/sdhci-tegra.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e63cd6b2fc9f..ec07a3ce0247 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -260,11 +260,35 @@ static void tegra_sdhci_configure_cal_pad(struct 
sdhci_host *host, bool enable)
usleep_range(1, 2);
 }
 
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool 
enable)
+{
+   bool status;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   status = !!(reg & SDHCI_CLOCK_CARD_EN);
+
+   if (status == enable)
+   return status;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return status;
+}
+
 static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
 {
+   bool card_clk_enabled;
u32 reg;
int ret;
 
+   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);
@@ -279,6 +303,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 (ret)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
 }
-- 
2.18.0



[PATCH v3 08/38] soc/tegra: pmc: Use X macro to generate IO pad tables

2018-08-30 Thread Aapo Vienamo
Refactor the IO pad tables into macro tables so that they can be reused
to generate pinctrl pin descriptors. Also add a name field which is
needed by pinctrl.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 233 ++--
 1 file changed, 127 insertions(+), 106 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index eb9385fa88c4..3b844b0fd8ac 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -137,6 +137,7 @@ struct tegra_io_pad_soc {
enum tegra_io_pad id;
unsigned int dpd;
unsigned int voltage;
+   const char *name;
 };
 
 struct tegra_pmc_regs {
@@ -1697,37 +1698,49 @@ static const u8 tegra124_cpu_powergates[] = {
TEGRA_POWERGATE_CPU3,
 };
 
+#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name)   \
+   ((struct tegra_io_pad_soc) {\
+   .id = (_id),\
+   .dpd= (_dpd),   \
+   .voltage = (_voltage),  \
+   .name   = (_name),  \
+   })
+
+#define TEGRA124_IO_PAD_TABLE(_pad)\
+   /* .id  .dpd.voltage  .name */  \
+   _pad(TEGRA_IO_PAD_AUDIO,17, UINT_MAX, "audio"), \
+   _pad(TEGRA_IO_PAD_BB,   15, UINT_MAX, "bb"),\
+   _pad(TEGRA_IO_PAD_CAM,  36, UINT_MAX, "cam"),   \
+   _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"),  \
+   _pad(TEGRA_IO_PAD_CSIA, 0,  UINT_MAX, "csia"),  \
+   _pad(TEGRA_IO_PAD_CSIB, 1,  UINT_MAX, "csb"),   \
+   _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"),   \
+   _pad(TEGRA_IO_PAD_DSI,  2,  UINT_MAX, "dsi"),   \
+   _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"),  \
+   _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"),  \
+   _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"),  \
+   _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"),  \
+   _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"),  \
+   _pad(TEGRA_IO_PAD_HV,   38, UINT_MAX, "hv"),\
+   _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"),  \
+   _pad(TEGRA_IO_PAD_MIPI_BIAS,3,  UINT_MAX, "mipi-bias"), \
+   _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"),  \
+   _pad(TEGRA_IO_PAD_PEX_BIAS, 4,  UINT_MAX, "pex-bias"),  \
+   _pad(TEGRA_IO_PAD_PEX_CLK1, 5,  UINT_MAX, "pex-clk1"),  \
+   _pad(TEGRA_IO_PAD_PEX_CLK2, 6,  UINT_MAX, "pex-clk2"),  \
+   _pad(TEGRA_IO_PAD_PEX_CNTRL,32, UINT_MAX, "pex-cntrl"), \
+   _pad(TEGRA_IO_PAD_SDMMC1,   33, UINT_MAX, "sdmmc1"),\
+   _pad(TEGRA_IO_PAD_SDMMC3,   34, UINT_MAX, "sdmmc3"),\
+   _pad(TEGRA_IO_PAD_SDMMC4,   35, UINT_MAX, "sdmmc4"),\
+   _pad(TEGRA_IO_PAD_SYS_DDC,  58, UINT_MAX, "sys_ddc"),   \
+   _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"),  \
+   _pad(TEGRA_IO_PAD_USB0, 9,  UINT_MAX, "usb0"),  \
+   _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"),  \
+   _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"),  \
+   _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias")
+
 static const struct tegra_io_pad_soc tegra124_io_pads[] = {
-   { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_BB, .dpd = 15, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_COMP, .dpd = 22, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_HV, .dpd = 38, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }

[PATCH v3 08/38] soc/tegra: pmc: Use X macro to generate IO pad tables

2018-08-30 Thread Aapo Vienamo
Refactor the IO pad tables into macro tables so that they can be reused
to generate pinctrl pin descriptors. Also add a name field which is
needed by pinctrl.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 233 ++--
 1 file changed, 127 insertions(+), 106 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index eb9385fa88c4..3b844b0fd8ac 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -137,6 +137,7 @@ struct tegra_io_pad_soc {
enum tegra_io_pad id;
unsigned int dpd;
unsigned int voltage;
+   const char *name;
 };
 
 struct tegra_pmc_regs {
@@ -1697,37 +1698,49 @@ static const u8 tegra124_cpu_powergates[] = {
TEGRA_POWERGATE_CPU3,
 };
 
+#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name)   \
+   ((struct tegra_io_pad_soc) {\
+   .id = (_id),\
+   .dpd= (_dpd),   \
+   .voltage = (_voltage),  \
+   .name   = (_name),  \
+   })
+
+#define TEGRA124_IO_PAD_TABLE(_pad)\
+   /* .id  .dpd.voltage  .name */  \
+   _pad(TEGRA_IO_PAD_AUDIO,17, UINT_MAX, "audio"), \
+   _pad(TEGRA_IO_PAD_BB,   15, UINT_MAX, "bb"),\
+   _pad(TEGRA_IO_PAD_CAM,  36, UINT_MAX, "cam"),   \
+   _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"),  \
+   _pad(TEGRA_IO_PAD_CSIA, 0,  UINT_MAX, "csia"),  \
+   _pad(TEGRA_IO_PAD_CSIB, 1,  UINT_MAX, "csb"),   \
+   _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"),   \
+   _pad(TEGRA_IO_PAD_DSI,  2,  UINT_MAX, "dsi"),   \
+   _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"),  \
+   _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"),  \
+   _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"),  \
+   _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"),  \
+   _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"),  \
+   _pad(TEGRA_IO_PAD_HV,   38, UINT_MAX, "hv"),\
+   _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"),  \
+   _pad(TEGRA_IO_PAD_MIPI_BIAS,3,  UINT_MAX, "mipi-bias"), \
+   _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"),  \
+   _pad(TEGRA_IO_PAD_PEX_BIAS, 4,  UINT_MAX, "pex-bias"),  \
+   _pad(TEGRA_IO_PAD_PEX_CLK1, 5,  UINT_MAX, "pex-clk1"),  \
+   _pad(TEGRA_IO_PAD_PEX_CLK2, 6,  UINT_MAX, "pex-clk2"),  \
+   _pad(TEGRA_IO_PAD_PEX_CNTRL,32, UINT_MAX, "pex-cntrl"), \
+   _pad(TEGRA_IO_PAD_SDMMC1,   33, UINT_MAX, "sdmmc1"),\
+   _pad(TEGRA_IO_PAD_SDMMC3,   34, UINT_MAX, "sdmmc3"),\
+   _pad(TEGRA_IO_PAD_SDMMC4,   35, UINT_MAX, "sdmmc4"),\
+   _pad(TEGRA_IO_PAD_SYS_DDC,  58, UINT_MAX, "sys_ddc"),   \
+   _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"),  \
+   _pad(TEGRA_IO_PAD_USB0, 9,  UINT_MAX, "usb0"),  \
+   _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"),  \
+   _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"),  \
+   _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias")
+
 static const struct tegra_io_pad_soc tegra124_io_pads[] = {
-   { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_BB, .dpd = 15, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_COMP, .dpd = 22, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_HV, .dpd = 38, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }

[PATCH v3 06/38] soc/tegra: pmc: Factor out DPD register bit calculation

2018-08-30 Thread Aapo Vienamo
Factor out the the code to calculate the correct DPD register and bit
number for a given pad. This logic will be needed to query the status
register.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 20 +---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index d3ce6d12c8ff..f88bcb60430b 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -922,11 +922,12 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum 
tegra_io_pad id)
return NULL;
 }
 
-static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
-   unsigned long *status, u32 *mask)
+static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
+unsigned long *request,
+unsigned long *status,
+u32 *mask)
 {
const struct tegra_io_pad_soc *pad;
-   unsigned long rate, value;
 
pad = tegra_io_pad_find(pmc, id);
if (!pad) {
@@ -947,6 +948,19 @@ static int tegra_io_pad_prepare(enum tegra_io_pad id, 
unsigned long *request,
*request = pmc->soc->regs->dpd2_req;
}
 
+   return 0;
+}
+
+static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
+   unsigned long *status, u32 *mask)
+{
+   unsigned long rate, value;
+   int err;
+
+   err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask);
+   if (err)
+   return err;
+
if (pmc->clk) {
rate = clk_get_rate(pmc->clk);
if (!rate) {
-- 
2.18.0



[PATCH v3 05/38] soc/tegra: pmc: Fix pad voltage configuration for Tegra186

2018-08-30 Thread Aapo Vienamo
Implement support for the PMC_IMPL_E_33V_PWR register which replaces
PMC_PWR_DET register interface of the SoC generations preceding
Tegra186. Also add the voltage bit offsets to the tegra186_io_pads[]
table and the AO_HV pad.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 55 +
 include/soc/tegra/pmc.h |  1 +
 2 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 2d6f3fcf3211..d3ce6d12c8ff 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -65,6 +65,8 @@
 
 #define PWRGATE_STATUS 0x38
 
+#define PMC_IMPL_E_33V_PWR 0x40
+
 #define PMC_PWR_DET0x48
 
 #define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
@@ -154,6 +156,7 @@ struct tegra_pmc_soc {
bool has_tsense_reset;
bool has_gpu_clamps;
bool needs_mbist_war;
+   bool has_impl_33v_pwr;
 
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
@@ -1073,20 +1076,31 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
 
mutex_lock(>powergates_lock);
 
-   /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
-   value = tegra_pmc_readl(PMC_PWR_DET);
-   value |= BIT(pad->voltage);
-   tegra_pmc_writel(value, PMC_PWR_DET);
+   if (pmc->soc->has_impl_33v_pwr) {
+   value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
 
-   /* update I/O voltage */
-   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+   if (voltage == TEGRA_IO_PAD_180UV)
+   value &= ~BIT(pad->voltage);
+   else
+   value |= BIT(pad->voltage);
 
-   if (voltage == TEGRA_IO_PAD_180UV)
-   value &= ~BIT(pad->voltage);
-   else
+   tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR);
+   } else {
+   /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
+   value = tegra_pmc_readl(PMC_PWR_DET);
value |= BIT(pad->voltage);
+   tegra_pmc_writel(value, PMC_PWR_DET);
+
+   /* update I/O voltage */
+   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
-   tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+   if (voltage == TEGRA_IO_PAD_180UV)
+   value &= ~BIT(pad->voltage);
+   else
+   value |= BIT(pad->voltage);
+
+   tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+   }
 
mutex_unlock(>powergates_lock);
 
@@ -1108,7 +1122,10 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id)
if (pad->voltage == UINT_MAX)
return -ENOTSUPP;
 
-   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+   if (pmc->soc->has_impl_33v_pwr)
+   value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
+   else
+   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
if ((value & BIT(pad->voltage)) == 0)
return TEGRA_IO_PAD_180UV;
@@ -1567,6 +1584,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.cpu_powergates = tegra30_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+   .has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
.regs = _pmc_regs,
@@ -1609,6 +1627,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.cpu_powergates = tegra114_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+   .has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
.regs = _pmc_regs,
@@ -1689,6 +1708,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.cpu_powergates = tegra124_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+   .has_impl_33v_pwr = false,
.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
.io_pads = tegra124_io_pads,
.regs = _pmc_regs,
@@ -1778,6 +1798,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.cpu_powergates = tegra210_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+   .has_impl_33v_pwr = false,
.needs_mbist_war = true,
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
@@ -1806,7 +1827,7 @@ static const struct tegra_io_pad_soc tegra186_io_pads[] = 
{
{ .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = UINT_MAX },
+   { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = 5 },
{ .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
{ .id 

[PATCH v3 07/38] soc/tegra: pmc: Implement tegra_io_pad_is_powered()

2018-08-30 Thread Aapo Vienamo
Implement a function to query whether a pad is in deep power down mode.
This is needed by the pinctrl callbacks.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index f88bcb60430b..eb9385fa88c4 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1075,6 +1075,21 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
 }
 EXPORT_SYMBOL(tegra_io_pad_power_disable);
 
+static int tegra_io_pad_is_powered(enum tegra_io_pad id)
+{
+   unsigned long request, status;
+   u32 mask, value;
+   int err;
+
+   err = tegra_io_pad_get_dpd_register_bit(id, , , );
+   if (err)
+   return err;
+
+   value = tegra_pmc_readl(status);
+
+   return !(value & mask);
+}
+
 int tegra_io_pad_set_voltage(enum tegra_io_pad id,
 enum tegra_io_pad_voltage voltage)
 {
-- 
2.18.0



[PATCH v3 06/38] soc/tegra: pmc: Factor out DPD register bit calculation

2018-08-30 Thread Aapo Vienamo
Factor out the the code to calculate the correct DPD register and bit
number for a given pad. This logic will be needed to query the status
register.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 20 +---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index d3ce6d12c8ff..f88bcb60430b 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -922,11 +922,12 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum 
tegra_io_pad id)
return NULL;
 }
 
-static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
-   unsigned long *status, u32 *mask)
+static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
+unsigned long *request,
+unsigned long *status,
+u32 *mask)
 {
const struct tegra_io_pad_soc *pad;
-   unsigned long rate, value;
 
pad = tegra_io_pad_find(pmc, id);
if (!pad) {
@@ -947,6 +948,19 @@ static int tegra_io_pad_prepare(enum tegra_io_pad id, 
unsigned long *request,
*request = pmc->soc->regs->dpd2_req;
}
 
+   return 0;
+}
+
+static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
+   unsigned long *status, u32 *mask)
+{
+   unsigned long rate, value;
+   int err;
+
+   err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask);
+   if (err)
+   return err;
+
if (pmc->clk) {
rate = clk_get_rate(pmc->clk);
if (!rate) {
-- 
2.18.0



[PATCH v3 05/38] soc/tegra: pmc: Fix pad voltage configuration for Tegra186

2018-08-30 Thread Aapo Vienamo
Implement support for the PMC_IMPL_E_33V_PWR register which replaces
PMC_PWR_DET register interface of the SoC generations preceding
Tegra186. Also add the voltage bit offsets to the tegra186_io_pads[]
table and the AO_HV pad.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 55 +
 include/soc/tegra/pmc.h |  1 +
 2 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 2d6f3fcf3211..d3ce6d12c8ff 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -65,6 +65,8 @@
 
 #define PWRGATE_STATUS 0x38
 
+#define PMC_IMPL_E_33V_PWR 0x40
+
 #define PMC_PWR_DET0x48
 
 #define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
@@ -154,6 +156,7 @@ struct tegra_pmc_soc {
bool has_tsense_reset;
bool has_gpu_clamps;
bool needs_mbist_war;
+   bool has_impl_33v_pwr;
 
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
@@ -1073,20 +1076,31 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
 
mutex_lock(>powergates_lock);
 
-   /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
-   value = tegra_pmc_readl(PMC_PWR_DET);
-   value |= BIT(pad->voltage);
-   tegra_pmc_writel(value, PMC_PWR_DET);
+   if (pmc->soc->has_impl_33v_pwr) {
+   value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
 
-   /* update I/O voltage */
-   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+   if (voltage == TEGRA_IO_PAD_180UV)
+   value &= ~BIT(pad->voltage);
+   else
+   value |= BIT(pad->voltage);
 
-   if (voltage == TEGRA_IO_PAD_180UV)
-   value &= ~BIT(pad->voltage);
-   else
+   tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR);
+   } else {
+   /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
+   value = tegra_pmc_readl(PMC_PWR_DET);
value |= BIT(pad->voltage);
+   tegra_pmc_writel(value, PMC_PWR_DET);
+
+   /* update I/O voltage */
+   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
-   tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+   if (voltage == TEGRA_IO_PAD_180UV)
+   value &= ~BIT(pad->voltage);
+   else
+   value |= BIT(pad->voltage);
+
+   tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+   }
 
mutex_unlock(>powergates_lock);
 
@@ -1108,7 +1122,10 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id)
if (pad->voltage == UINT_MAX)
return -ENOTSUPP;
 
-   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+   if (pmc->soc->has_impl_33v_pwr)
+   value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
+   else
+   value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
 
if ((value & BIT(pad->voltage)) == 0)
return TEGRA_IO_PAD_180UV;
@@ -1567,6 +1584,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.cpu_powergates = tegra30_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+   .has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
.regs = _pmc_regs,
@@ -1609,6 +1627,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.cpu_powergates = tegra114_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+   .has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
.regs = _pmc_regs,
@@ -1689,6 +1708,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.cpu_powergates = tegra124_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+   .has_impl_33v_pwr = false,
.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
.io_pads = tegra124_io_pads,
.regs = _pmc_regs,
@@ -1778,6 +1798,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.cpu_powergates = tegra210_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+   .has_impl_33v_pwr = false,
.needs_mbist_war = true,
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
@@ -1806,7 +1827,7 @@ static const struct tegra_io_pad_soc tegra186_io_pads[] = 
{
{ .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
-   { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = UINT_MAX },
+   { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = 5 },
{ .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
{ .id 

[PATCH v3 07/38] soc/tegra: pmc: Implement tegra_io_pad_is_powered()

2018-08-30 Thread Aapo Vienamo
Implement a function to query whether a pad is in deep power down mode.
This is needed by the pinctrl callbacks.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Acked-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index f88bcb60430b..eb9385fa88c4 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1075,6 +1075,21 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
 }
 EXPORT_SYMBOL(tegra_io_pad_power_disable);
 
+static int tegra_io_pad_is_powered(enum tegra_io_pad id)
+{
+   unsigned long request, status;
+   u32 mask, value;
+   int err;
+
+   err = tegra_io_pad_get_dpd_register_bit(id, , , );
+   if (err)
+   return err;
+
+   value = tegra_pmc_readl(status);
+
+   return !(value & mask);
+}
+
 int tegra_io_pad_set_voltage(enum tegra_io_pad id,
 enum tegra_io_pad_voltage voltage)
 {
-- 
2.18.0



[PATCH v3 04/38] dt-bindings: mmc: Add Tegra SDHCI sampling trimmer values

2018-08-30 Thread Aapo Vienamo
Document the Tegra SDHCI inbound and outbound sampling trimmer values.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 .../devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt  | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 9713e052f736..edecf97231b9 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -67,6 +67,10 @@ Optional properties for Tegra210 and Tegra186:
 - nvidia,pad-autocal-pull-up-offset-hs400,
   nvidia,pad-autocal-pull-down-offset-hs400 : Specify drive strength
   calibration offsets for HS400 mode.
+- nvidia,default-tap : Specify the default inbound sampling clock
+  trimmer value for non-tunable modes.
+- nvidia,default-trim : Specify the default outbound clock trimmer
+  value.
 
   Notes on the pad calibration pull up and pulldown offset values:
 - The property values are drive codes which are programmed into the
@@ -77,6 +81,13 @@ Optional properties for Tegra210 and Tegra186:
 - The SDR104 and HS400 timing specific values are used in
   corresponding modes if specified.
 
+  Notes on tap and trim values:
+- The values are used for compensating trace length differences
+  by adjusting the sampling point.
+- The values are programmed to the Vendor Clock Control Register.
+  Please refer to the reference manual of the SoC for correct
+  values.
+
 Example:
 sdhci@700b {
compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
-- 
2.18.0



[PATCH v3 04/38] dt-bindings: mmc: Add Tegra SDHCI sampling trimmer values

2018-08-30 Thread Aapo Vienamo
Document the Tegra SDHCI inbound and outbound sampling trimmer values.

Signed-off-by: Aapo Vienamo 
Acked-by: Thierry Reding 
---
 .../devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt  | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 9713e052f736..edecf97231b9 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -67,6 +67,10 @@ Optional properties for Tegra210 and Tegra186:
 - nvidia,pad-autocal-pull-up-offset-hs400,
   nvidia,pad-autocal-pull-down-offset-hs400 : Specify drive strength
   calibration offsets for HS400 mode.
+- nvidia,default-tap : Specify the default inbound sampling clock
+  trimmer value for non-tunable modes.
+- nvidia,default-trim : Specify the default outbound clock trimmer
+  value.
 
   Notes on the pad calibration pull up and pulldown offset values:
 - The property values are drive codes which are programmed into the
@@ -77,6 +81,13 @@ Optional properties for Tegra210 and Tegra186:
 - The SDR104 and HS400 timing specific values are used in
   corresponding modes if specified.
 
+  Notes on tap and trim values:
+- The values are used for compensating trace length differences
+  by adjusting the sampling point.
+- The values are programmed to the Vendor Clock Control Register.
+  Please refer to the reference manual of the SoC for correct
+  values.
+
 Example:
 sdhci@700b {
compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
-- 
2.18.0



[PATCH v3 02/38] dt-bindings: mmc: tegra: Add pad voltage control properties

2018-08-30 Thread Aapo Vienamo
Document the pinctrl bindings used by the SDHCI driver to reconfigure
pad voltages on controllers supporting multiple voltage levels.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Reviewed-by: Rob Herring 
Acked-by: Thierry Reding 
---
 .../bindings/mmc/nvidia,tegra20-sdhci.txt | 22 +++
 1 file changed, 22 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 9bce57862ed6..90c214dbfb16 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -38,3 +38,25 @@ sdhci@c8000200 {
power-gpios = < 155 0>; /* gpio PT3 */
bus-width = <8>;
 };
+
+Optional properties for Tegra210 and Tegra186:
+- pinctrl-names, pinctrl-0, pinctrl-1 : Specify pad voltage
+  configurations. Valid pinctrl-names are "sdmmc-3v3" and "sdmmc-1v8"
+  for controllers supporting multiple voltage levels. The order of names
+  should correspond to the pin configuration states in pinctrl-0 and
+  pinctrl-1.
+
+Example:
+sdhci@700b {
+   compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
+   reg = <0x0 0x700b 0x0 0x200>;
+   interrupts = ;
+   clocks = <_car TEGRA210_CLK_SDMMC1>;
+   clock-names = "sdhci";
+   resets = <_car 14>;
+   reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
+   status = "disabled";
+};
-- 
2.18.0



[PATCH v3 01/38] dt-bindings: Add Tegra PMC pad configuration bindings

2018-08-30 Thread Aapo Vienamo
Document the PMC pinctrl bindings for pad power state and signaling
voltage configuration. Both nvidia,tegra186-pmc.txt and
nvidia,tegra20-pmc.txt are modified as they both cover SoC generations
for which these bindings apply.

Add a header defining Tegra PMC pad voltage configurations.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Reviewed-by: Rob Herring 
Acked-by: Thierry Reding 
---
 .../arm/tegra/nvidia,tegra186-pmc.txt |  93 
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 103 ++
 .../pinctrl/pinctrl-tegra-io-pad.h|  18 +++
 3 files changed, 214 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
index 5a3bf7c5a7a0..c9fd6d1de57e 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
@@ -34,3 +34,96 @@ Board DTS:
pmc@c36 {
nvidia,invert-interrupt;
};
+
+== Pad Control ==
+
+On Tegra SoCs a pad is a set of pins which are configured as a group.
+The pin grouping is a fixed attribute of the hardware. The PMC can be
+used to set pad power state and signaling voltage. A pad can be either
+in active or power down mode. The support for power state and signaling
+voltage configuration varies depending on the pad in question. 3.3 V and
+1.8 V signaling voltages are supported on pins where software
+controllable signaling voltage switching is available.
+
+Pad configurations are described with pin configuration nodes which
+are placed under the pmc node and they are referred to by the pinctrl
+client properties. For more information see
+Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
+
+The following pads are present on Tegra186:
+csia   csibdsi mipi-bias
+pex-clk-bias   pex-clk3pex-clk2pex-clk1
+usb0   usb1usb2usb-bias
+uart   audio   hsicdbg
+hdmi-dp0   hdmi-dp1pex-cntrl   sdmmc2-hv
+sdmmc4 cam dsibdsic
+dsid   csiccsidcsie
+dsif   spi ufs dmic-hv
+edpsdmmc1-hv   sdmmc3-hv   conn
+audio-hv   ao-hv
+
+Required pin configuration properties:
+  - pins: A list of strings, each of which contains the name of a pad
+ to be configured.
+
+Optional pin configuration properties:
+  - low-power-enable: Configure the pad into power down mode
+  - low-power-disable: Configure the pad into active mode
+  - power-source: Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 or
+TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages.
+The values are defined in
+include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
+
+Note: The power state can be configured on all of the above pads except
+  for ao-hv. Following pads have software configurable signaling
+  voltages: sdmmc2-hv, dmic-hv, sdmmc1-hv, sdmmc3-hv, audio-hv,
+  ao-hv.
+
+Pad configuration state example:
+   pmc: pmc@7000e400 {
+   compatible = "nvidia,tegra186-pmc";
+   reg = <0 0x0c36 0 0x1>,
+ <0 0x0c37 0 0x1>,
+ <0 0x0c38 0 0x1>,
+ <0 0x0c39 0 0x1>;
+   reg-names = "pmc", "wake", "aotag", "scratch";
+
+   ...
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   hdmi_off: hdmi-off {
+   pins = "hdmi";
+   low-power-enable;
+   }
+
+   hdmi_on: hdmi-on {
+   pins = "hdmi";
+   low-power-disable;
+   }
+   };
+
+Pinctrl client example:
+   sdmmc1: sdhci@340 {
+   ...
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
+   };
+
+   ...
+
+   sor0: sor@1554 {
+   ...
+   pinctrl-0 = <_off>;
+   pinctrl-1 = <_on>;
+   pinctrl-names = "hdmi-on", "hdmi-off";
+   };
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index a74b37b07e5c..cb12f33a247f 1006

[PATCH v3 03/38] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings

2018-08-30 Thread 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 
Acked-by: Thierry Reding 
---
 .../bindings/mmc/nvidia,tegra20-sdhci.txt | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 90c214dbfb16..9713e052f736 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -45,6 +45,37 @@ 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.
+- nvidia,only-1-8-v : The presence of this property indicates that the
+  controller operates at a 1.8 V fixed I/O voltage.
+- nvidia,pad-autocal-pull-up-offset-3v3,
+  nvidia,pad-autocal-pull-down-offset-3v3 : Specify drive strength
+  calibration offsets for 3.3 V signaling modes.
+- nvidia,pad-autocal-pull-up-offset-1v8,
+  nvidia,pad-autocal-pull-down-offset-1v8 : Specify drive strength
+  calibration offsets for 1.8 V signaling modes.
+- nvidia,pad-autocal-pull-up-offset-3v3-timeout,
+  nvidia,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.
+- nvidia,pad-autocal-pull-up-offset-1v8-timeout,
+  nvidia,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.
+- nvidia,pad-autocal-pull-up-offset-sdr104,
+  nvidia,pad-autocal-pull-down-offset-sdr104 : Specify drive strength
+  calibration offsets for SDR104 mode.
+- nvidia,pad-autocal-pull-up-offset-hs400,
+  nvidia,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@700b {
@@ -58,5 +89,9 @@ sdhci@700b {
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
 };
-- 
2.18.0



[PATCH v3 02/38] dt-bindings: mmc: tegra: Add pad voltage control properties

2018-08-30 Thread Aapo Vienamo
Document the pinctrl bindings used by the SDHCI driver to reconfigure
pad voltages on controllers supporting multiple voltage levels.

Signed-off-by: Aapo Vienamo 
Reviewed-by: Mikko Perttunen 
Reviewed-by: Rob Herring 
Acked-by: Thierry Reding 
---
 .../bindings/mmc/nvidia,tegra20-sdhci.txt | 22 +++
 1 file changed, 22 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 9bce57862ed6..90c214dbfb16 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -38,3 +38,25 @@ sdhci@c8000200 {
power-gpios = < 155 0>; /* gpio PT3 */
bus-width = <8>;
 };
+
+Optional properties for Tegra210 and Tegra186:
+- pinctrl-names, pinctrl-0, pinctrl-1 : Specify pad voltage
+  configurations. Valid pinctrl-names are "sdmmc-3v3" and "sdmmc-1v8"
+  for controllers supporting multiple voltage levels. The order of names
+  should correspond to the pin configuration states in pinctrl-0 and
+  pinctrl-1.
+
+Example:
+sdhci@700b {
+   compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
+   reg = <0x0 0x700b 0x0 0x200>;
+   interrupts = ;
+   clocks = <_car TEGRA210_CLK_SDMMC1>;
+   clock-names = "sdhci";
+   resets = <_car 14>;
+   reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
+   status = "disabled";
+};
-- 
2.18.0



[PATCH v3 01/38] dt-bindings: Add Tegra PMC pad configuration bindings

2018-08-30 Thread Aapo Vienamo
Document the PMC pinctrl bindings for pad power state and signaling
voltage configuration. Both nvidia,tegra186-pmc.txt and
nvidia,tegra20-pmc.txt are modified as they both cover SoC generations
for which these bindings apply.

Add a header defining Tegra PMC pad voltage configurations.

Signed-off-by: Aapo Vienamo 
Acked-by: Jon Hunter 
Reviewed-by: Rob Herring 
Acked-by: Thierry Reding 
---
 .../arm/tegra/nvidia,tegra186-pmc.txt |  93 
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 103 ++
 .../pinctrl/pinctrl-tegra-io-pad.h|  18 +++
 3 files changed, 214 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
index 5a3bf7c5a7a0..c9fd6d1de57e 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
@@ -34,3 +34,96 @@ Board DTS:
pmc@c36 {
nvidia,invert-interrupt;
};
+
+== Pad Control ==
+
+On Tegra SoCs a pad is a set of pins which are configured as a group.
+The pin grouping is a fixed attribute of the hardware. The PMC can be
+used to set pad power state and signaling voltage. A pad can be either
+in active or power down mode. The support for power state and signaling
+voltage configuration varies depending on the pad in question. 3.3 V and
+1.8 V signaling voltages are supported on pins where software
+controllable signaling voltage switching is available.
+
+Pad configurations are described with pin configuration nodes which
+are placed under the pmc node and they are referred to by the pinctrl
+client properties. For more information see
+Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
+
+The following pads are present on Tegra186:
+csia   csibdsi mipi-bias
+pex-clk-bias   pex-clk3pex-clk2pex-clk1
+usb0   usb1usb2usb-bias
+uart   audio   hsicdbg
+hdmi-dp0   hdmi-dp1pex-cntrl   sdmmc2-hv
+sdmmc4 cam dsibdsic
+dsid   csiccsidcsie
+dsif   spi ufs dmic-hv
+edpsdmmc1-hv   sdmmc3-hv   conn
+audio-hv   ao-hv
+
+Required pin configuration properties:
+  - pins: A list of strings, each of which contains the name of a pad
+ to be configured.
+
+Optional pin configuration properties:
+  - low-power-enable: Configure the pad into power down mode
+  - low-power-disable: Configure the pad into active mode
+  - power-source: Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 or
+TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages.
+The values are defined in
+include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
+
+Note: The power state can be configured on all of the above pads except
+  for ao-hv. Following pads have software configurable signaling
+  voltages: sdmmc2-hv, dmic-hv, sdmmc1-hv, sdmmc3-hv, audio-hv,
+  ao-hv.
+
+Pad configuration state example:
+   pmc: pmc@7000e400 {
+   compatible = "nvidia,tegra186-pmc";
+   reg = <0 0x0c36 0 0x1>,
+ <0 0x0c37 0 0x1>,
+ <0 0x0c38 0 0x1>,
+ <0 0x0c39 0 0x1>;
+   reg-names = "pmc", "wake", "aotag", "scratch";
+
+   ...
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   hdmi_off: hdmi-off {
+   pins = "hdmi";
+   low-power-enable;
+   }
+
+   hdmi_on: hdmi-on {
+   pins = "hdmi";
+   low-power-disable;
+   }
+   };
+
+Pinctrl client example:
+   sdmmc1: sdhci@340 {
+   ...
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
+   };
+
+   ...
+
+   sor0: sor@1554 {
+   ...
+   pinctrl-0 = <_off>;
+   pinctrl-1 = <_on>;
+   pinctrl-names = "hdmi-on", "hdmi-off";
+   };
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index a74b37b07e5c..cb12f33a247f 1006

[PATCH v3 03/38] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings

2018-08-30 Thread 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 
Acked-by: Thierry Reding 
---
 .../bindings/mmc/nvidia,tegra20-sdhci.txt | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 90c214dbfb16..9713e052f736 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -45,6 +45,37 @@ 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.
+- nvidia,only-1-8-v : The presence of this property indicates that the
+  controller operates at a 1.8 V fixed I/O voltage.
+- nvidia,pad-autocal-pull-up-offset-3v3,
+  nvidia,pad-autocal-pull-down-offset-3v3 : Specify drive strength
+  calibration offsets for 3.3 V signaling modes.
+- nvidia,pad-autocal-pull-up-offset-1v8,
+  nvidia,pad-autocal-pull-down-offset-1v8 : Specify drive strength
+  calibration offsets for 1.8 V signaling modes.
+- nvidia,pad-autocal-pull-up-offset-3v3-timeout,
+  nvidia,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.
+- nvidia,pad-autocal-pull-up-offset-1v8-timeout,
+  nvidia,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.
+- nvidia,pad-autocal-pull-up-offset-sdr104,
+  nvidia,pad-autocal-pull-down-offset-sdr104 : Specify drive strength
+  calibration offsets for SDR104 mode.
+- nvidia,pad-autocal-pull-up-offset-hs400,
+  nvidia,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@700b {
@@ -58,5 +89,9 @@ sdhci@700b {
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+   nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
 };
-- 
2.18.0



[PATCH v3 00/38] Tegra SDHCI add support for HS200 and UHS signaling

2018-08-30 Thread Aapo Vienamo
Hi all,

This series implements support for faster signaling modes on Tegra
SDHCI controllers. This series consist of several parts: changes
required for 1.8 V signaling and pad control, pad calibration, and
tuning. Following earlies patch sets have been merged into this
larger set: "Tegra PMC pinctrl pad configuration", "Tegra SDHCI enable
1.8 V signaling on Tegar210 and Tegra186", "Tegra SDHCI update the
padautocal procedure". Also the patches for enabling SDHCI tuning
are added.

Changelog:
v3:
- Remove tegra_sdhci_writew() from tegra210_sdhci_ops to prevent
  incorrect access to SDHCI_TRANSFER_MODE on Tegra210.
- Drop "mmc: sdhci: Add a quirk to skip clearing the transfer
  mode register on tuning". This is no longer needed since it
  was effectively a workaround to the behavior caused by
  tegra_sdhci_writew() on Tegra210.
- Implement disabling of the card clock during issuing of the
  tuning command in tegra210_sdhci_writew().
- Drop "mmc: sdhci: Add a quirk to disable card clock during
  tuning". This is now implemented in the sdhci-tegra driver.

v2:
- Fix grammar in PMC device tree bindings docs
- Remove a stray line from tegra sdhci bindings
- Cosmetic changes to PMC pinctrl driver
- Fix a typo in "soc/tegra: pmc: Implement
  tegra_io_pad_is_powered()" commit message
- Declare mask and value on the same line in
  tegra_io_pad_is_powered()
- Move the call to tegra_sdhci_is_pad_and_regulator_valid() to
  inside the if condition in tegra_sdhci_reset()
- Use usleep_range() in tegra_sdhci_configure_cal_pad()
- Move sdhci_writel() out of the enable if-else body in
  tegra_sdhci_configure_cal_pad()
- Add a delay before starting polling in
  tegra_sdhci_pad_autocalib()
- Use usleep_range() in tegra_sdhci_set_tap()
- Rename orig_enabled to status in
  tegra_sdhci_configure_card_clk()
- Fix if condition wrapping alignment in tegra_sdhci_set_tap()

v1:
- Probe the regulator voltage capabilities to determine whether pinctrl
  is needed in tegra_sdhci_r eset
- Don't remove tegra_sdhci_voltage_switch()
- Use dev_warn() in tegra_sdhci_init_pinctrl_info()
- Don't change start_signal_voltage_switch callback if pinctrl info
  invalid
- Only call udelay(1) on enable in tegra_sdhci_configure_cal_pad()
- Add nvidia, prefix to pad autocal offset dt props in the example

See the original patch sets for earlier changelogs.


Aapo Vienamo (38):
  dt-bindings: Add Tegra PMC pad configuration bindings
  dt-bindings: mmc: tegra: Add pad voltage control properties
  dt-bindings: Add Tegra SDHCI pad pdpu offset bindings
  dt-bindings: mmc: Add Tegra SDHCI sampling trimmer values
  soc/tegra: pmc: Fix pad voltage configuration for Tegra186
  soc/tegra: pmc: Factor out DPD register bit calculation
  soc/tegra: pmc: Implement tegra_io_pad_is_powered()
  soc/tegra: pmc: Use X macro to generate IO pad tables
  soc/tegra: pmc: Remove public pad voltage APIs
  soc/tegra: pmc: Implement pad configuration via pinctrl
  mmc: tegra: Reconfigure pad voltages during voltage switching
  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
  mmc: tegra: Program pad autocal offsets from dt
  mmc: tegra: Perform pad calibration after voltage switch
  mmc: tegra: Enable pad calibration on Tegra210 and Tegra186
  mmc: tegra: Add a workaround for tap value change glitch
  mmc: tegra: Parse default trim and tap from dt
  mmc: tegra: Configure default tap values
  mmc: tegra: Configure default trim value on reset
  mmc: tegra: Use standard SDHCI tuning on Tegra210 and Tegra186
  mmc: tegra: Remove tegra_sdhci_writew() from tegra210_sdhci_ops
  mmc: tegra: Disable card clock during tuning cmd on Tegra210
  mmc: tegra: Enable UHS and HS200 modes for Tegra210
  mmc: tegra: Enable UHS and HS200 modes for Tegra186
  arm64: dts: Add Tegra210 sdmmc pinctrl voltage states
  arm64: dts: Add Tegra186 sdmmc pinctrl voltage states
  arm64: dts: tegra210-p2180: Allow ldo2 to go down to 1.8 V
  arm64: dts: tegra210-p2180: Correct sdmmc4 vqmmc-supply
  arm64: dts: tegra210-p2597: Remove no-1-8-v from sdmmc1
  arm64: dts: tegra186: Add sdmmc pad auto calibration offsets
  arm64: dts: tegra210: Add sdmmc pad auto calibration offsets
  arm64: dts: tegra210: Add SDHCI tap and trim values
  arm64: dts: tegra186: Add SDHCI tap and trim values
  arm64: dts: tegra186: Assign clocks for sdmmc1 and sdmmc4
  arm64: dts: tegra210: Assign clocks for sdmmc1 and sdmmc4

 .../arm/tegra/nvidia,tegra186-pmc.txt |  93 +++
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 103 
 

[PATCH v3 00/38] Tegra SDHCI add support for HS200 and UHS signaling

2018-08-30 Thread Aapo Vienamo
Hi all,

This series implements support for faster signaling modes on Tegra
SDHCI controllers. This series consist of several parts: changes
required for 1.8 V signaling and pad control, pad calibration, and
tuning. Following earlies patch sets have been merged into this
larger set: "Tegra PMC pinctrl pad configuration", "Tegra SDHCI enable
1.8 V signaling on Tegar210 and Tegra186", "Tegra SDHCI update the
padautocal procedure". Also the patches for enabling SDHCI tuning
are added.

Changelog:
v3:
- Remove tegra_sdhci_writew() from tegra210_sdhci_ops to prevent
  incorrect access to SDHCI_TRANSFER_MODE on Tegra210.
- Drop "mmc: sdhci: Add a quirk to skip clearing the transfer
  mode register on tuning". This is no longer needed since it
  was effectively a workaround to the behavior caused by
  tegra_sdhci_writew() on Tegra210.
- Implement disabling of the card clock during issuing of the
  tuning command in tegra210_sdhci_writew().
- Drop "mmc: sdhci: Add a quirk to disable card clock during
  tuning". This is now implemented in the sdhci-tegra driver.

v2:
- Fix grammar in PMC device tree bindings docs
- Remove a stray line from tegra sdhci bindings
- Cosmetic changes to PMC pinctrl driver
- Fix a typo in "soc/tegra: pmc: Implement
  tegra_io_pad_is_powered()" commit message
- Declare mask and value on the same line in
  tegra_io_pad_is_powered()
- Move the call to tegra_sdhci_is_pad_and_regulator_valid() to
  inside the if condition in tegra_sdhci_reset()
- Use usleep_range() in tegra_sdhci_configure_cal_pad()
- Move sdhci_writel() out of the enable if-else body in
  tegra_sdhci_configure_cal_pad()
- Add a delay before starting polling in
  tegra_sdhci_pad_autocalib()
- Use usleep_range() in tegra_sdhci_set_tap()
- Rename orig_enabled to status in
  tegra_sdhci_configure_card_clk()
- Fix if condition wrapping alignment in tegra_sdhci_set_tap()

v1:
- Probe the regulator voltage capabilities to determine whether pinctrl
  is needed in tegra_sdhci_r eset
- Don't remove tegra_sdhci_voltage_switch()
- Use dev_warn() in tegra_sdhci_init_pinctrl_info()
- Don't change start_signal_voltage_switch callback if pinctrl info
  invalid
- Only call udelay(1) on enable in tegra_sdhci_configure_cal_pad()
- Add nvidia, prefix to pad autocal offset dt props in the example

See the original patch sets for earlier changelogs.


Aapo Vienamo (38):
  dt-bindings: Add Tegra PMC pad configuration bindings
  dt-bindings: mmc: tegra: Add pad voltage control properties
  dt-bindings: Add Tegra SDHCI pad pdpu offset bindings
  dt-bindings: mmc: Add Tegra SDHCI sampling trimmer values
  soc/tegra: pmc: Fix pad voltage configuration for Tegra186
  soc/tegra: pmc: Factor out DPD register bit calculation
  soc/tegra: pmc: Implement tegra_io_pad_is_powered()
  soc/tegra: pmc: Use X macro to generate IO pad tables
  soc/tegra: pmc: Remove public pad voltage APIs
  soc/tegra: pmc: Implement pad configuration via pinctrl
  mmc: tegra: Reconfigure pad voltages during voltage switching
  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
  mmc: tegra: Program pad autocal offsets from dt
  mmc: tegra: Perform pad calibration after voltage switch
  mmc: tegra: Enable pad calibration on Tegra210 and Tegra186
  mmc: tegra: Add a workaround for tap value change glitch
  mmc: tegra: Parse default trim and tap from dt
  mmc: tegra: Configure default tap values
  mmc: tegra: Configure default trim value on reset
  mmc: tegra: Use standard SDHCI tuning on Tegra210 and Tegra186
  mmc: tegra: Remove tegra_sdhci_writew() from tegra210_sdhci_ops
  mmc: tegra: Disable card clock during tuning cmd on Tegra210
  mmc: tegra: Enable UHS and HS200 modes for Tegra210
  mmc: tegra: Enable UHS and HS200 modes for Tegra186
  arm64: dts: Add Tegra210 sdmmc pinctrl voltage states
  arm64: dts: Add Tegra186 sdmmc pinctrl voltage states
  arm64: dts: tegra210-p2180: Allow ldo2 to go down to 1.8 V
  arm64: dts: tegra210-p2180: Correct sdmmc4 vqmmc-supply
  arm64: dts: tegra210-p2597: Remove no-1-8-v from sdmmc1
  arm64: dts: tegra186: Add sdmmc pad auto calibration offsets
  arm64: dts: tegra210: Add sdmmc pad auto calibration offsets
  arm64: dts: tegra210: Add SDHCI tap and trim values
  arm64: dts: tegra186: Add SDHCI tap and trim values
  arm64: dts: tegra186: Assign clocks for sdmmc1 and sdmmc4
  arm64: dts: tegra210: Assign clocks for sdmmc1 and sdmmc4

 .../arm/tegra/nvidia,tegra186-pmc.txt |  93 +++
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 103 
 

Re: [PATCH v2 25/40] mmc: sdhci: Add a quirk to disable card clock during tuning

2018-08-28 Thread Aapo Vienamo
On Mon, 27 Aug 2018 14:25:44 +0300
Adrian Hunter  wrote:

> On 10/08/18 21:08, Aapo Vienamo wrote:
> > Add a quirk to disable card clock when the tuning command is sent.
> > 
> > This has to be done to prevent the SDHCI controller from hanging on
> > Tegra210. Without the quirk enabled there appears to be around 10%
> > chance that the tuning sequence will fail and time out due to the
> > controller locking up.
> > 
> > Signed-off-by: Aapo Vienamo 
> > ---
> >  drivers/mmc/host/sdhci.c | 15 +++
> >  drivers/mmc/host/sdhci.h |  2 ++
> >  2 files changed, 17 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 04dc443..166b16f 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -2175,6 +2175,7 @@ static void sdhci_send_tuning(struct sdhci_host 
> > *host, u32 opcode)
> > struct mmc_request mrq = {};
> > unsigned long flags;
> > u32 b = host->sdma_boundary;
> > +   u16 clk;
> >  
> > spin_lock_irqsave(>lock, flags);
> >  
> > @@ -2183,6 +2184,13 @@ static void sdhci_send_tuning(struct sdhci_host 
> > *host, u32 opcode)
> > cmd.mrq = 
> >  
> > mrq.cmd = 
> > +
> > +   if (host->quirks2 & SDHCI_QUIRK2_TUNE_DIS_CARD_CLK) {
> > +   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> > +   clk &= ~SDHCI_CLOCK_CARD_EN;
> > +   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);  
> 
> Rather than using a quirk, could you use the sdhci I/O accessors to disable
> the clock before the tuning comment is written, udelay(1), and then enable
> it again?

This was the way it was implemented in the downstream kernel. However,
doing it in the IO accessor when a tuning command is sent seems to work
too.

 -Aapo


Re: [PATCH v2 25/40] mmc: sdhci: Add a quirk to disable card clock during tuning

2018-08-28 Thread Aapo Vienamo
On Mon, 27 Aug 2018 14:25:44 +0300
Adrian Hunter  wrote:

> On 10/08/18 21:08, Aapo Vienamo wrote:
> > Add a quirk to disable card clock when the tuning command is sent.
> > 
> > This has to be done to prevent the SDHCI controller from hanging on
> > Tegra210. Without the quirk enabled there appears to be around 10%
> > chance that the tuning sequence will fail and time out due to the
> > controller locking up.
> > 
> > Signed-off-by: Aapo Vienamo 
> > ---
> >  drivers/mmc/host/sdhci.c | 15 +++
> >  drivers/mmc/host/sdhci.h |  2 ++
> >  2 files changed, 17 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 04dc443..166b16f 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -2175,6 +2175,7 @@ static void sdhci_send_tuning(struct sdhci_host 
> > *host, u32 opcode)
> > struct mmc_request mrq = {};
> > unsigned long flags;
> > u32 b = host->sdma_boundary;
> > +   u16 clk;
> >  
> > spin_lock_irqsave(>lock, flags);
> >  
> > @@ -2183,6 +2184,13 @@ static void sdhci_send_tuning(struct sdhci_host 
> > *host, u32 opcode)
> > cmd.mrq = 
> >  
> > mrq.cmd = 
> > +
> > +   if (host->quirks2 & SDHCI_QUIRK2_TUNE_DIS_CARD_CLK) {
> > +   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> > +   clk &= ~SDHCI_CLOCK_CARD_EN;
> > +   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);  
> 
> Rather than using a quirk, could you use the sdhci I/O accessors to disable
> the clock before the tuning comment is written, udelay(1), and then enable
> it again?

This was the way it was implemented in the downstream kernel. However,
doing it in the IO accessor when a tuning command is sent seems to work
too.

 -Aapo


Re: [PATCH v2 11/40] mmc: sdhci: Add a quirk to skip clearing the transfer mode register on tuning

2018-08-28 Thread Aapo Vienamo
On Mon, 27 Aug 2018 14:01:52 +0300
Adrian Hunter  wrote:

> On 10/08/18 21:08, Aapo Vienamo wrote:
> > Add SDHCI_QUIRK2_TUNE_SKIP_XFERRMODE_REG_PROG to skip programming the
> > SDHCI_TRANSFER_MODE in sdhci_set_transfer_mode() if tuning command is
> > being sent.
> > 
> > On Tegra210 and Tegra186 the tuning sequence hangs if the SDHCI
> > transfer mode register is touched.
> > 
> > Signed-off-by: Aapo Vienamo 
> > ---
> >  drivers/mmc/host/sdhci.c | 6 ++
> >  drivers/mmc/host/sdhci.h | 2 ++
> >  2 files changed, 8 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index a7b5602..04dc443 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -1028,6 +1028,12 @@ static void sdhci_set_transfer_mode(struct 
> > sdhci_host *host,
> >  
> > if (data == NULL) {
> > if (host->quirks2 &
> > +   SDHCI_QUIRK2_TUNE_SKIP_XFERMODE_REG_PROG &&
> > +   (cmd->opcode == MMC_SEND_TUNING_BLOCK ||
> > +cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)) {
> > +   return;
> > +   }  
> 
> Rather than introduce a quirk, can't we just dodge the unnecessary write e.g.
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1b3fbd9bd5c5..68af6a67e397 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1033,10 +1033,19 @@ static void sdhci_set_transfer_mode(struct sdhci_host 
> *host,
>   if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
>   sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
>   } else {
> - /* clear Auto CMD settings for no data CMDs */
> + u16 orig;
> +
> + /* clear Auto CMD settings for no data CMDs */
>   mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
> - sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
> - SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
> + orig = mode;
> + mode &= ~(SDHCI_TRNS_AUTO_CMD12 | 
> SDHCI_TRNS_AUTO_CMD23);
> + /*
> +  * Do not write transfer mode unnecessarily because it
> +  * can upset some host controllers (e.g. sdhci-tregra)
> +  * during tuning.
> +  */
> + if (mode != orig)
> + sdhci_writew(host, new_mode, 
> SDHCI_TRANSFER_MODE);
>   }
>   return;
>   }
> 
> 
> Alternatively 
> 
> > +   if (host->quirks2 &
> > SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
> > sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
> > } else {
> > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> > index 23966f8..0a99008 100644
> > --- a/drivers/mmc/host/sdhci.h
> > +++ b/drivers/mmc/host/sdhci.h
> > @@ -450,6 +450,8 @@ struct sdhci_host {
> >   * obtainable timeout.
> >   */
> >  #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT(1<<17)
> > +/* Don't clear the SDHCI_TRANSFER_MODE register on tuning commands */
> > +#define SDHCI_QUIRK2_TUNE_SKIP_XFERMODE_REG_PROG   (1<<18)
> >  
> > int irq;/* Device IRQ */
> > void __iomem *ioaddr;   /* Mapped address */
> >   
> 

Looks like writes to the transfer mode register are deferred until the
command register is written by tegra_sdhci_writew(). This code was
introduced due to a quirk in Tegra114/124. The Tegra114 ops struct was
probably just copied over when support for Tegra210 was added, so we
end up with this code also getting run on Tegra210.

The issue with tegra_sdhci_writew() is that it breaks successive
read-modify-write operations. The value written to the transfer mode
register isn't returned on read until the command register is also
touched. Removing the write_w accessor from tegra210_sdhci_ops seems to
make the issue originally addressed by this patch to go away.

 -Aapo


Re: [PATCH v2 11/40] mmc: sdhci: Add a quirk to skip clearing the transfer mode register on tuning

2018-08-28 Thread Aapo Vienamo
On Mon, 27 Aug 2018 14:01:52 +0300
Adrian Hunter  wrote:

> On 10/08/18 21:08, Aapo Vienamo wrote:
> > Add SDHCI_QUIRK2_TUNE_SKIP_XFERRMODE_REG_PROG to skip programming the
> > SDHCI_TRANSFER_MODE in sdhci_set_transfer_mode() if tuning command is
> > being sent.
> > 
> > On Tegra210 and Tegra186 the tuning sequence hangs if the SDHCI
> > transfer mode register is touched.
> > 
> > Signed-off-by: Aapo Vienamo 
> > ---
> >  drivers/mmc/host/sdhci.c | 6 ++
> >  drivers/mmc/host/sdhci.h | 2 ++
> >  2 files changed, 8 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index a7b5602..04dc443 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -1028,6 +1028,12 @@ static void sdhci_set_transfer_mode(struct 
> > sdhci_host *host,
> >  
> > if (data == NULL) {
> > if (host->quirks2 &
> > +   SDHCI_QUIRK2_TUNE_SKIP_XFERMODE_REG_PROG &&
> > +   (cmd->opcode == MMC_SEND_TUNING_BLOCK ||
> > +cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)) {
> > +   return;
> > +   }  
> 
> Rather than introduce a quirk, can't we just dodge the unnecessary write e.g.
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1b3fbd9bd5c5..68af6a67e397 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1033,10 +1033,19 @@ static void sdhci_set_transfer_mode(struct sdhci_host 
> *host,
>   if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
>   sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
>   } else {
> - /* clear Auto CMD settings for no data CMDs */
> + u16 orig;
> +
> + /* clear Auto CMD settings for no data CMDs */
>   mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
> - sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
> - SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
> + orig = mode;
> + mode &= ~(SDHCI_TRNS_AUTO_CMD12 | 
> SDHCI_TRNS_AUTO_CMD23);
> + /*
> +  * Do not write transfer mode unnecessarily because it
> +  * can upset some host controllers (e.g. sdhci-tregra)
> +  * during tuning.
> +  */
> + if (mode != orig)
> + sdhci_writew(host, new_mode, 
> SDHCI_TRANSFER_MODE);
>   }
>   return;
>   }
> 
> 
> Alternatively 
> 
> > +   if (host->quirks2 &
> > SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
> > sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
> > } else {
> > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> > index 23966f8..0a99008 100644
> > --- a/drivers/mmc/host/sdhci.h
> > +++ b/drivers/mmc/host/sdhci.h
> > @@ -450,6 +450,8 @@ struct sdhci_host {
> >   * obtainable timeout.
> >   */
> >  #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT(1<<17)
> > +/* Don't clear the SDHCI_TRANSFER_MODE register on tuning commands */
> > +#define SDHCI_QUIRK2_TUNE_SKIP_XFERMODE_REG_PROG   (1<<18)
> >  
> > int irq;/* Device IRQ */
> > void __iomem *ioaddr;   /* Mapped address */
> >   
> 

Looks like writes to the transfer mode register are deferred until the
command register is written by tegra_sdhci_writew(). This code was
introduced due to a quirk in Tegra114/124. The Tegra114 ops struct was
probably just copied over when support for Tegra210 was added, so we
end up with this code also getting run on Tegra210.

The issue with tegra_sdhci_writew() is that it breaks successive
read-modify-write operations. The value written to the transfer mode
register isn't returned on read until the command register is also
touched. Removing the write_w accessor from tegra210_sdhci_ops seems to
make the issue originally addressed by this patch to go away.

 -Aapo


Re: [PATCH v2 00/40] Tegra SDHCI add support for HS200 and UHS signaling

2018-08-27 Thread Aapo Vienamo
On Mon, 27 Aug 2018 17:50:53 +0200
Thierry Reding  wrote:

> On Mon, Aug 27, 2018 at 02:10:58PM +, Marcel Ziswiler wrote:
> > On Fri, 2018-08-10 at 21:08 +0300, Aapo Vienamo wrote:  
> > > Hi all,
> > > 
> > > This series implements support for faster signaling modes on Tegra
> > > SDHCI controllers. This series consist of several parts: changes
> > > requried for 1.8 V signaling and pad control, pad calibration, and
> > > tuning. Following earlies patch sets have been merged into this
> > > larger set: "Tegra PMC pinctrl pad configuration", "Tegra SDHCI
> > > enable
> > > 1.8 V signaling on Tegar210 and Tegra186", "Tegra SDHCI update the
> > > padautocal procedure". Also the patches for enabling SDHCI tuning
> > > are added.  
> > 
> > I tried your tkln/hs200 branch on Colibri T20, Apalis/Colibri T30 and
> > Apalis TK1. It at least does not seem to make things any worse but
> > HS200 on TK1 still seems to behave strangely. During boot I do get the
> > following message (mmc0 being the SDHCI instance of one of them SD card
> > slots):
> > 
> > [3.238360] mmc0: Internal clock never stabilised.
> > [3.243183] mmc0: sdhci:  SDHCI REGISTER DUMP
> > ===
> > [3.249649] mmc0: sdhci: Sys addr:  0x |
> > Version:  0x0303
> > [3.256138] mmc0: sdhci: Blk size:  0x | Blk
> > cnt:  0x
> > [3.262657] mmc0: sdhci: Argument:  0x | Trn mode:
> > 0x
> > [3.269119] mmc0: sdhci: Present:   0x01fb00f0 | Host ctl:
> > 0x
> > [3.275580] mmc0: sdhci: Power: 0x000f | Blk
> > gap:  0x
> > [3.282041] mmc0: sdhci: Wake-up:   0x |
> > Clock:0x0401
> > [3.288485] mmc0: sdhci: Timeout:   0x | Int stat:
> > 0x
> > [3.295037] mmc0: sdhci: Int enab:  0x00ff0003 | Sig enab:
> > 0x00fc0003
> > [3.301559] mmc0: sdhci: AC12 err:  0x | Slot int:
> > 0x
> > [3.308022] mmc0: sdhci: Caps:  0x376fd080 |
> > Caps_1:   0x1f70
> > [3.314527] mmc0: sdhci: Cmd:   0x | Max curr:
> > 0x
> > [3.321159] mmc0: sdhci: Resp[0]:   0x |
> > Resp[1]:  0x
> > [3.327642] mmc0: sdhci: Resp[2]:   0x |
> > Resp[3]:  0x
> > [3.334144] mmc0: sdhci: Host ctl2: 0x
> > [3.338613] mmc0: sdhci: ADMA Err:  0x | ADMA Ptr:
> > 0x
> > [3.345110] mmc0: sdhci:
> > 
> > 
> > And it subsequently stalls waiting for interrupt for more than 8
> > seconds before continuing to mount the rootfs as follows (mmc2 being
> > the SDHCI instance of the eMMC):
> > 
> > [4.874017] tegra-hdmi 5428.hdmi: cannot set audio to 48000 Hz
> > at 29700 Hz pixel clock
> > [   13.930136] mmc2: Timeout waiting for hardware interrupt.
> > [   13.935603] mmc2: sdhci:  SDHCI REGISTER DUMP
> > ===
> > [   13.942071] mmc2: sdhci: Sys addr:  0x |
> > Version:  0x0303
> > [   13.948511] mmc2: sdhci: Blk size:  0x7080 | Blk
> > cnt:  0x0001
> > [   13.954948] mmc2: sdhci: Argument:  0x | Trn mode:
> > 0x0013
> > [   13.961385] mmc2: sdhci: Present:   0x01fb00f0 | Host ctl:
> > 0x0031
> > [   13.967821] mmc2: sdhci: Power: 0x0001 | Blk
> > gap:  0x
> > [   13.974263] mmc2: sdhci: Wake-up:   0x |
> > Clock:0x0007
> > [   13.980692] mmc2: sdhci: Timeout:   0x000e | Int stat:
> > 0x
> > [   13.987119] mmc2: sdhci: Int enab:  0x02ff000b | Sig enab:
> > 0x02fc000b
> > [   13.993546] mmc2: sdhci: AC12 err:  0x | Slot int:
> > 0x
> > [   13.74] mmc2: sdhci: Caps:  0x376fd080 |
> > Caps_1:   0x1f70
> > [   14.006415] mmc2: sdhci: Cmd:   0x153a | Max curr:
> > 0x
> > [   14.012845] mmc2: sdhci: Resp[0]:   0x0b00 |
> > Resp[1]:  0x048062bf
> > [   14.019272] mmc2: sdhci: Resp[2]:   0x314a8000 |
> > Resp[3]:  0x0240
> > [   14.025697] mmc2: sdhci: Host ctl2: 0x000b
> > [   14.030132] mmc2: sdhci: ADMA Err:  0x | ADMA Ptr:
> > 0xfbc6b208
> > [   14.036561] mmc2: sdhci:
> > 
> > [   14.044332] mmc2: new HS200 MMC card at address 0001
> > [   14.050656] mmcblk2: mmc2:0001 016G30 14.7 GiB
> > [   14.056376] mmcblk2boot0: mmc2:0001 016G30 partitio

Re: [PATCH v2 00/40] Tegra SDHCI add support for HS200 and UHS signaling

2018-08-27 Thread Aapo Vienamo
On Mon, 27 Aug 2018 17:50:53 +0200
Thierry Reding  wrote:

> On Mon, Aug 27, 2018 at 02:10:58PM +, Marcel Ziswiler wrote:
> > On Fri, 2018-08-10 at 21:08 +0300, Aapo Vienamo wrote:  
> > > Hi all,
> > > 
> > > This series implements support for faster signaling modes on Tegra
> > > SDHCI controllers. This series consist of several parts: changes
> > > requried for 1.8 V signaling and pad control, pad calibration, and
> > > tuning. Following earlies patch sets have been merged into this
> > > larger set: "Tegra PMC pinctrl pad configuration", "Tegra SDHCI
> > > enable
> > > 1.8 V signaling on Tegar210 and Tegra186", "Tegra SDHCI update the
> > > padautocal procedure". Also the patches for enabling SDHCI tuning
> > > are added.  
> > 
> > I tried your tkln/hs200 branch on Colibri T20, Apalis/Colibri T30 and
> > Apalis TK1. It at least does not seem to make things any worse but
> > HS200 on TK1 still seems to behave strangely. During boot I do get the
> > following message (mmc0 being the SDHCI instance of one of them SD card
> > slots):
> > 
> > [3.238360] mmc0: Internal clock never stabilised.
> > [3.243183] mmc0: sdhci:  SDHCI REGISTER DUMP
> > ===
> > [3.249649] mmc0: sdhci: Sys addr:  0x |
> > Version:  0x0303
> > [3.256138] mmc0: sdhci: Blk size:  0x | Blk
> > cnt:  0x
> > [3.262657] mmc0: sdhci: Argument:  0x | Trn mode:
> > 0x
> > [3.269119] mmc0: sdhci: Present:   0x01fb00f0 | Host ctl:
> > 0x
> > [3.275580] mmc0: sdhci: Power: 0x000f | Blk
> > gap:  0x
> > [3.282041] mmc0: sdhci: Wake-up:   0x |
> > Clock:0x0401
> > [3.288485] mmc0: sdhci: Timeout:   0x | Int stat:
> > 0x
> > [3.295037] mmc0: sdhci: Int enab:  0x00ff0003 | Sig enab:
> > 0x00fc0003
> > [3.301559] mmc0: sdhci: AC12 err:  0x | Slot int:
> > 0x
> > [3.308022] mmc0: sdhci: Caps:  0x376fd080 |
> > Caps_1:   0x1f70
> > [3.314527] mmc0: sdhci: Cmd:   0x | Max curr:
> > 0x
> > [3.321159] mmc0: sdhci: Resp[0]:   0x |
> > Resp[1]:  0x
> > [3.327642] mmc0: sdhci: Resp[2]:   0x |
> > Resp[3]:  0x
> > [3.334144] mmc0: sdhci: Host ctl2: 0x
> > [3.338613] mmc0: sdhci: ADMA Err:  0x | ADMA Ptr:
> > 0x
> > [3.345110] mmc0: sdhci:
> > 
> > 
> > And it subsequently stalls waiting for interrupt for more than 8
> > seconds before continuing to mount the rootfs as follows (mmc2 being
> > the SDHCI instance of the eMMC):
> > 
> > [4.874017] tegra-hdmi 5428.hdmi: cannot set audio to 48000 Hz
> > at 29700 Hz pixel clock
> > [   13.930136] mmc2: Timeout waiting for hardware interrupt.
> > [   13.935603] mmc2: sdhci:  SDHCI REGISTER DUMP
> > ===
> > [   13.942071] mmc2: sdhci: Sys addr:  0x |
> > Version:  0x0303
> > [   13.948511] mmc2: sdhci: Blk size:  0x7080 | Blk
> > cnt:  0x0001
> > [   13.954948] mmc2: sdhci: Argument:  0x | Trn mode:
> > 0x0013
> > [   13.961385] mmc2: sdhci: Present:   0x01fb00f0 | Host ctl:
> > 0x0031
> > [   13.967821] mmc2: sdhci: Power: 0x0001 | Blk
> > gap:  0x
> > [   13.974263] mmc2: sdhci: Wake-up:   0x |
> > Clock:0x0007
> > [   13.980692] mmc2: sdhci: Timeout:   0x000e | Int stat:
> > 0x
> > [   13.987119] mmc2: sdhci: Int enab:  0x02ff000b | Sig enab:
> > 0x02fc000b
> > [   13.993546] mmc2: sdhci: AC12 err:  0x | Slot int:
> > 0x
> > [   13.74] mmc2: sdhci: Caps:  0x376fd080 |
> > Caps_1:   0x1f70
> > [   14.006415] mmc2: sdhci: Cmd:   0x153a | Max curr:
> > 0x
> > [   14.012845] mmc2: sdhci: Resp[0]:   0x0b00 |
> > Resp[1]:  0x048062bf
> > [   14.019272] mmc2: sdhci: Resp[2]:   0x314a8000 |
> > Resp[3]:  0x0240
> > [   14.025697] mmc2: sdhci: Host ctl2: 0x000b
> > [   14.030132] mmc2: sdhci: ADMA Err:  0x | ADMA Ptr:
> > 0xfbc6b208
> > [   14.036561] mmc2: sdhci:
> > 
> > [   14.044332] mmc2: new HS200 MMC card at address 0001
> > [   14.050656] mmcblk2: mmc2:0001 016G30 14.7 GiB
> > [   14.056376] mmcblk2boot0: mmc2:0001 016G30 partitio

[PATCH 2/2] mmc: tegra: Implement periodic pad calibration

2018-08-20 Thread Aapo Vienamo
Rerun the pad calibration procedure before sdhci_request() if
the 100 ms recalibration interval has been exceeded.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 94624ec..ef18a0c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -122,6 +123,7 @@ struct sdhci_tegra {
struct pinctrl_state *pinctrl_state_1v8;
 
struct sdhci_tegra_autocal_offsets autocal_offsets;
+   ktime_t last_calib;
 
u32 default_tap;
u32 default_trim;
@@ -533,6 +535,22 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct 
sdhci_host *host)
autocal->pull_down_hs400 = autocal->pull_down_1v8;
 }
 
+static void tegra_sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+   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);
+   ktime_t since_calib = ktime_sub(ktime_get(), tegra_host->last_calib);
+
+   /* 100 ms calibration interval is specified in the TRM */
+   if (ktime_to_ms(since_calib) > 100) {
+   tegra_sdhci_pad_autocalib(host);
+   tegra_host->last_calib = ktime_get();
+   }
+
+   sdhci_request(mmc, mrq);
+}
+
 static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -1014,6 +1032,10 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
sdhci_tegra_start_signal_voltage_switch;
}
 
+   /* Hook to periodically rerun pad calibration */
+   if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
+   host->mmc_host_ops.request = tegra_sdhci_request;
+
host->mmc_host_ops.hs400_enhanced_strobe =
tegra_sdhci_hs400_enhanced_strobe;
 
-- 
2.7.4



[PATCH 2/2] mmc: tegra: Implement periodic pad calibration

2018-08-20 Thread Aapo Vienamo
Rerun the pad calibration procedure before sdhci_request() if
the 100 ms recalibration interval has been exceeded.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 94624ec..ef18a0c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -122,6 +123,7 @@ struct sdhci_tegra {
struct pinctrl_state *pinctrl_state_1v8;
 
struct sdhci_tegra_autocal_offsets autocal_offsets;
+   ktime_t last_calib;
 
u32 default_tap;
u32 default_trim;
@@ -533,6 +535,22 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct 
sdhci_host *host)
autocal->pull_down_hs400 = autocal->pull_down_1v8;
 }
 
+static void tegra_sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+   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);
+   ktime_t since_calib = ktime_sub(ktime_get(), tegra_host->last_calib);
+
+   /* 100 ms calibration interval is specified in the TRM */
+   if (ktime_to_ms(since_calib) > 100) {
+   tegra_sdhci_pad_autocalib(host);
+   tegra_host->last_calib = ktime_get();
+   }
+
+   sdhci_request(mmc, mrq);
+}
+
 static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -1014,6 +1032,10 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
sdhci_tegra_start_signal_voltage_switch;
}
 
+   /* Hook to periodically rerun pad calibration */
+   if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
+   host->mmc_host_ops.request = tegra_sdhci_request;
+
host->mmc_host_ops.hs400_enhanced_strobe =
tegra_sdhci_hs400_enhanced_strobe;
 
-- 
2.7.4



[PATCH 1/2] mmc: sdhci: Export sdhci_request()

2018-08-20 Thread Aapo Vienamo
Allow SDHCI drivers to hook code before and after sdhci_request() by
making it externally visible.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci.c | 3 ++-
 drivers/mmc/host/sdhci.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index da47f7b..1e0c0a6 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1636,7 +1636,7 @@ EXPORT_SYMBOL_GPL(sdhci_set_power);
  *   *
 \*/
 
-static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
struct sdhci_host *host;
int present;
@@ -1675,6 +1675,7 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
mmiowb();
spin_unlock_irqrestore(>lock, flags);
 }
+EXPORT_SYMBOL_GPL(sdhci_request);
 
 void sdhci_set_bus_width(struct sdhci_host *host, int width)
 {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index cc963a5..73c4744 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -729,6 +729,7 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char 
mode,
 unsigned short vdd);
 void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
   unsigned short vdd);
+void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq);
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
 void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
-- 
2.7.4



[PATCH 0/2] Tegra SDHCI rerun pad calibration periodically

2018-08-20 Thread Aapo Vienamo
Hi all,

This series implements pad drive strength recalibration. The calibration
is rerun to compensate possible changes in temperature. The calibration
procedure is rerun as part of mmc_host_ops.request before
sdhci_request() is run. The calibration is executed only if the 100 ms
recalibration interval has passed.

This series depends on the "Tegra SDHCI add support for HS200 and UHS
signaling" series.

Aapo Vienamo (2):
  mmc: sdhci: Export sdhci_request()
  mmc: tegra: Implement periodic pad calibration

 drivers/mmc/host/sdhci-tegra.c | 22 ++
 drivers/mmc/host/sdhci.c   |  3 ++-
 drivers/mmc/host/sdhci.h   |  1 +
 3 files changed, 25 insertions(+), 1 deletion(-)

-- 
2.7.4



[PATCH 1/2] mmc: sdhci: Export sdhci_request()

2018-08-20 Thread Aapo Vienamo
Allow SDHCI drivers to hook code before and after sdhci_request() by
making it externally visible.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci.c | 3 ++-
 drivers/mmc/host/sdhci.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index da47f7b..1e0c0a6 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1636,7 +1636,7 @@ EXPORT_SYMBOL_GPL(sdhci_set_power);
  *   *
 \*/
 
-static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
struct sdhci_host *host;
int present;
@@ -1675,6 +1675,7 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
mmiowb();
spin_unlock_irqrestore(>lock, flags);
 }
+EXPORT_SYMBOL_GPL(sdhci_request);
 
 void sdhci_set_bus_width(struct sdhci_host *host, int width)
 {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index cc963a5..73c4744 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -729,6 +729,7 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char 
mode,
 unsigned short vdd);
 void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
   unsigned short vdd);
+void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq);
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
 void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
-- 
2.7.4



[PATCH 0/2] Tegra SDHCI rerun pad calibration periodically

2018-08-20 Thread Aapo Vienamo
Hi all,

This series implements pad drive strength recalibration. The calibration
is rerun to compensate possible changes in temperature. The calibration
procedure is rerun as part of mmc_host_ops.request before
sdhci_request() is run. The calibration is executed only if the 100 ms
recalibration interval has passed.

This series depends on the "Tegra SDHCI add support for HS200 and UHS
signaling" series.

Aapo Vienamo (2):
  mmc: sdhci: Export sdhci_request()
  mmc: tegra: Implement periodic pad calibration

 drivers/mmc/host/sdhci-tegra.c | 22 ++
 drivers/mmc/host/sdhci.c   |  3 ++-
 drivers/mmc/host/sdhci.h   |  1 +
 3 files changed, 25 insertions(+), 1 deletion(-)

-- 
2.7.4



[PATCH v2 0/8] Tegra SDHCI support HS400 on Tegra210 and Tegra186

2018-08-10 Thread Aapo Vienamo
Hi all,
This series implements support for HS400 signaling on Tegra210 and
Tegra186. This includes programming the DQS trimmer values, implementing
enhanced strobe and HS400 delay line calibration.

This series depends on the "Tegra SDHCI add support for HS200 and UHS
signaling" series.

Changelog:
v2:
- Document in dt-bindings which controllers support HS400
- Use val instead of reg in tegra_sdhci_set_dqs_trim()
- Change "dt" to "DT" in "mmc: tegra: Parse and program DQS trim
  value" commit message
- Add spaces around << in tegra_sdhci_set_dqs_trim()
- Make the "mmc: tegra: Implement HS400 enhanced strobe" commit
  message more detailed
- Remove a debug print from tegra_sdhci_hs400_enhanced_strobe()
- Add blank lines around if-else-block in
  tegra_sdhci_hs400_enhanced_strobe()
- Use val instead of reg in tegra_sdhci_hs400_enhanced_strobe()
- Make commit message of "mmc: tegra: Implement HS400 delay line
  calibration" more detailed

Aapo Vienamo (8):
  dt-bindings: mmc: Add DQS trim value to Tegra SDHCI
  mmc: tegra: Parse and program DQS trim value
  mmc: tegra: Implement HS400 enhanced strobe
  mmc: tegra: Implement HS400 delay line calibration
  arm64: dts: tegra186: Add SDMMC4 DQS trim value
  arm64: dts: tegra210: Add SDMMC4 DQS trim value
  arm64: dts: tegra186: Enable HS400
  arm64: dts: tegra210: Enable HS400

 .../bindings/mmc/nvidia,tegra20-sdhci.txt  |  4 ++
 arch/arm64/boot/dts/nvidia/tegra186.dtsi   |  2 +
 arch/arm64/boot/dts/nvidia/tegra210.dtsi   |  2 +
 drivers/mmc/host/sdhci-tegra.c | 84 +-
 4 files changed, 89 insertions(+), 3 deletions(-)

-- 
2.7.4



[PATCH v2 3/8] mmc: tegra: Implement HS400 enhanced strobe

2018-08-10 Thread Aapo Vienamo
Implement eMMC HS400 enhanced strobe. Enhanced strobe is an alternative
mechanism to the HS400 tuning procedure.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 6ec92bc..c0bb0f0 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -43,6 +43,9 @@
 #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDEBIT(3)
 #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE   BIT(2)
 
+#define SDHCI_TEGRA_VENDOR_SYS_SW_CTRL 0x104
+#define SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBEBIT(31)
+
 #define SDHCI_TEGRA_VENDOR_CAP_OVERRIDES   0x10c
 #define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_MASK0x3f00
 #define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_SHIFT   8
@@ -272,6 +275,23 @@ static void tegra_sdhci_set_tap(struct sdhci_host *host, 
unsigned int tap)
}
 }
 
+static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   u32 val;
+
+   val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
+
+   if (ios->enhanced_strobe)
+   val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
+   else
+   val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
+
+   sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
+
+}
+
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -950,6 +970,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
sdhci_tegra_start_signal_voltage_switch;
}
 
+   host->mmc_host_ops.hs400_enhanced_strobe =
+   tegra_sdhci_hs400_enhanced_strobe;
+
rc = mmc_of_parse(host->mmc);
if (rc)
goto err_parse_dt;
-- 
2.7.4



[PATCH v2 8/8] arm64: dts: tegra210: Enable HS400

2018-08-10 Thread Aapo Vienamo
Enable HS400 signaling on Tegra210 SDMMC4 controller.

Signed-off-by: Aapo Vienamo 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index f8e5f09..8fe47d6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1116,6 +1116,7 @@
  <_car TEGRA210_CLK_PLL_C4_OUT0>;
assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
nvidia,dqs-trim = <40>;
+   mmc-hs400-1_8v;
status = "disabled";
};
 
-- 
2.7.4



[PATCH v2 0/8] Tegra SDHCI support HS400 on Tegra210 and Tegra186

2018-08-10 Thread Aapo Vienamo
Hi all,
This series implements support for HS400 signaling on Tegra210 and
Tegra186. This includes programming the DQS trimmer values, implementing
enhanced strobe and HS400 delay line calibration.

This series depends on the "Tegra SDHCI add support for HS200 and UHS
signaling" series.

Changelog:
v2:
- Document in dt-bindings which controllers support HS400
- Use val instead of reg in tegra_sdhci_set_dqs_trim()
- Change "dt" to "DT" in "mmc: tegra: Parse and program DQS trim
  value" commit message
- Add spaces around << in tegra_sdhci_set_dqs_trim()
- Make the "mmc: tegra: Implement HS400 enhanced strobe" commit
  message more detailed
- Remove a debug print from tegra_sdhci_hs400_enhanced_strobe()
- Add blank lines around if-else-block in
  tegra_sdhci_hs400_enhanced_strobe()
- Use val instead of reg in tegra_sdhci_hs400_enhanced_strobe()
- Make commit message of "mmc: tegra: Implement HS400 delay line
  calibration" more detailed

Aapo Vienamo (8):
  dt-bindings: mmc: Add DQS trim value to Tegra SDHCI
  mmc: tegra: Parse and program DQS trim value
  mmc: tegra: Implement HS400 enhanced strobe
  mmc: tegra: Implement HS400 delay line calibration
  arm64: dts: tegra186: Add SDMMC4 DQS trim value
  arm64: dts: tegra210: Add SDMMC4 DQS trim value
  arm64: dts: tegra186: Enable HS400
  arm64: dts: tegra210: Enable HS400

 .../bindings/mmc/nvidia,tegra20-sdhci.txt  |  4 ++
 arch/arm64/boot/dts/nvidia/tegra186.dtsi   |  2 +
 arch/arm64/boot/dts/nvidia/tegra210.dtsi   |  2 +
 drivers/mmc/host/sdhci-tegra.c | 84 +-
 4 files changed, 89 insertions(+), 3 deletions(-)

-- 
2.7.4



[PATCH v2 3/8] mmc: tegra: Implement HS400 enhanced strobe

2018-08-10 Thread Aapo Vienamo
Implement eMMC HS400 enhanced strobe. Enhanced strobe is an alternative
mechanism to the HS400 tuning procedure.

Signed-off-by: Aapo Vienamo 
---
 drivers/mmc/host/sdhci-tegra.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 6ec92bc..c0bb0f0 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -43,6 +43,9 @@
 #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDEBIT(3)
 #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE   BIT(2)
 
+#define SDHCI_TEGRA_VENDOR_SYS_SW_CTRL 0x104
+#define SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBEBIT(31)
+
 #define SDHCI_TEGRA_VENDOR_CAP_OVERRIDES   0x10c
 #define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_MASK0x3f00
 #define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_SHIFT   8
@@ -272,6 +275,23 @@ static void tegra_sdhci_set_tap(struct sdhci_host *host, 
unsigned int tap)
}
 }
 
+static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   u32 val;
+
+   val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
+
+   if (ios->enhanced_strobe)
+   val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
+   else
+   val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
+
+   sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
+
+}
+
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -950,6 +970,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
sdhci_tegra_start_signal_voltage_switch;
}
 
+   host->mmc_host_ops.hs400_enhanced_strobe =
+   tegra_sdhci_hs400_enhanced_strobe;
+
rc = mmc_of_parse(host->mmc);
if (rc)
goto err_parse_dt;
-- 
2.7.4



[PATCH v2 8/8] arm64: dts: tegra210: Enable HS400

2018-08-10 Thread Aapo Vienamo
Enable HS400 signaling on Tegra210 SDMMC4 controller.

Signed-off-by: Aapo Vienamo 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index f8e5f09..8fe47d6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1116,6 +1116,7 @@
  <_car TEGRA210_CLK_PLL_C4_OUT0>;
assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
nvidia,dqs-trim = <40>;
+   mmc-hs400-1_8v;
status = "disabled";
};
 
-- 
2.7.4



[PATCH v2 6/8] arm64: dts: tegra210: Add SDMMC4 DQS trim value

2018-08-10 Thread Aapo Vienamo
Add the HS400 DQS trim value for Tegra210 SDMMC4.

Signed-off-by: Aapo Vienamo 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 14da98a..f8e5f09 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1115,6 +1115,7 @@
assigned-clocks = <_car TEGRA210_CLK_SDMMC4>,
  <_car TEGRA210_CLK_PLL_C4_OUT0>;
assigned-clock-parents = <_car TEGRA210_CLK_PLL_C4_OUT0>;
+   nvidia,dqs-trim = <40>;
status = "disabled";
};
 
-- 
2.7.4



[PATCH v2 5/8] arm64: dts: tegra186: Add SDMMC4 DQS trim value

2018-08-10 Thread Aapo Vienamo
Add the HS400 DQS trim value for Tegra186 SDMMC4.

Signed-off-by: Aapo Vienamo 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 6e9ef26..9e07bc6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -313,6 +313,7 @@
nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
nvidia,default-tap = <0x5>;
nvidia,default-trim = <0x9>;
+   nvidia,dqs-trim = <63>;
status = "disabled";
};
 
-- 
2.7.4



  1   2   3   4   5   6   7   >