Re: [PATCH v2 04/12] phy: tegra: xusb: t210: add lane_iddq operations

2020-09-06 Thread JC Kuo
Hi Thierry,
Thanks for review. I will amend accordingly and submit a new patch.

JC

On 8/31/20 7:53 PM, Thierry Reding wrote:
> On Mon, Aug 31, 2020 at 12:40:35PM +0800, JC Kuo wrote:
>> As per Tegra210 TRM, before changing lane assignments, driver should
>> keep lanes in IDDQ and sleep state; after changing lane assignments,
>> driver should bring lanes out of IDDQ.
>> This commit implements the required operations.
>>
>> Signed-off-by: JC Kuo 
>> ---
>>  drivers/phy/tegra/xusb-tegra210.c | 94 +++
>>  drivers/phy/tegra/xusb.c  |  6 ++
>>  drivers/phy/tegra/xusb.h  |  4 +-
>>  3 files changed, 103 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/phy/tegra/xusb-tegra210.c 
>> b/drivers/phy/tegra/xusb-tegra210.c
>> index 3a2d9797fb9f..fe1ab440424d 100644
>> --- a/drivers/phy/tegra/xusb-tegra210.c
>> +++ b/drivers/phy/tegra/xusb-tegra210.c
>> @@ -198,6 +198,18 @@
>>  #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18)
>>  #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13)
>>  
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(x) (0x464 + (x) * 0x40)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ BIT(0)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD BIT(1)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK (0x3 << 4)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL (0x3 << 4)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD BIT(24)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ BIT(8)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD BIT(9)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK (0x3 << 12)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL (0x3 << 12)
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
>> +
>>  #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
>>  
>>  #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
>> @@ -209,6 +221,7 @@
>>  #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
>>  
>>  #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
>> +#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
>>  
>>  #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40)
>>  #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16
>> @@ -1636,6 +1649,63 @@ static const struct tegra_xusb_pad_soc 
>> tegra210_hsic_pad = {
>>  .ops = _hsic_ops,
>>  };
>>  
>> +static void
>> +tegra210_uphy_lane_iddq_enable(struct tegra_xusb_padctl *padctl, unsigned 
>> lane)
>> +{
>> +u32 val, offset;
>> +
>> +if (lane <= 6)
>> +offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(lane);
>> +else if (lane == 7)
>> +offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2;
>> +else {
>> +WARN(true, "invalid lane %u\n", lane);
>> +return;
>> +}
>> +
>> +val = padctl_readl(padctl, offset);
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
>> +padctl_writel(padctl, val, offset);
>> +}
>> +
>> +static void
>> +tegra210_uphy_lane_iddq_disable(struct tegra_xusb_padctl *padctl, unsigned 
>> lane)
>> +{
>> +u32 val, offset;
>> +
>> +if (lane <= 6)
>> +offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(lane);
>> +else if (lane == 7)
>> +offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2;
>> +else {
>> +WARN(true, "invalid lane %d\n", lane);
>> +return;
>> +}
>> +
>> +val = padctl_readl(padctl, offset);
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
>> +val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
>> +val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
>> +padctl_writel(padctl, val, offset);
>> +}
>> +
>> +
>>  static const char *tegra210_pcie_functions[] = {
>>  "pcie-x1",
>>  "usb3-ss",
>> @@ -1808,9 +1878,21 @@ static void tegra210_pcie_lane_remove(struct 
>> tegra_xusb_lane *lane)
>>  kfree(pcie);
>>  }
>>  
>> +static void tegra210_pcie_lane_iddq_enable(struct tegra_xusb_lane *lane)
>> +{
>> +tegra210_uphy_lane_iddq_enable(lane->pad->padctl, lane->index);
>> +}
>> +
>> +static void 

Re: [PATCH v2 04/12] phy: tegra: xusb: t210: add lane_iddq operations

2020-08-31 Thread Thierry Reding
On Mon, Aug 31, 2020 at 12:40:35PM +0800, JC Kuo wrote:
> As per Tegra210 TRM, before changing lane assignments, driver should
> keep lanes in IDDQ and sleep state; after changing lane assignments,
> driver should bring lanes out of IDDQ.
> This commit implements the required operations.
> 
> Signed-off-by: JC Kuo 
> ---
>  drivers/phy/tegra/xusb-tegra210.c | 94 +++
>  drivers/phy/tegra/xusb.c  |  6 ++
>  drivers/phy/tegra/xusb.h  |  4 +-
>  3 files changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/tegra/xusb-tegra210.c 
> b/drivers/phy/tegra/xusb-tegra210.c
> index 3a2d9797fb9f..fe1ab440424d 100644
> --- a/drivers/phy/tegra/xusb-tegra210.c
> +++ b/drivers/phy/tegra/xusb-tegra210.c
> @@ -198,6 +198,18 @@
>  #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18)
>  #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13)
>  
> +#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(x) (0x464 + (x) * 0x40)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ BIT(0)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD BIT(1)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK (0x3 << 4)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL (0x3 << 4)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD BIT(24)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ BIT(8)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD BIT(9)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK (0x3 << 12)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL (0x3 << 12)
> +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
> +
>  #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
>  
>  #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
> @@ -209,6 +221,7 @@
>  #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
>  
>  #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
> +#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
>  
>  #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40)
>  #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16
> @@ -1636,6 +1649,63 @@ static const struct tegra_xusb_pad_soc 
> tegra210_hsic_pad = {
>   .ops = _hsic_ops,
>  };
>  
> +static void
> +tegra210_uphy_lane_iddq_enable(struct tegra_xusb_padctl *padctl, unsigned 
> lane)
> +{
> + u32 val, offset;
> +
> + if (lane <= 6)
> + offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(lane);
> + else if (lane == 7)
> + offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2;
> + else {
> + WARN(true, "invalid lane %u\n", lane);
> + return;
> + }
> +
> + val = padctl_readl(padctl, offset);
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
> + padctl_writel(padctl, val, offset);
> +}
> +
> +static void
> +tegra210_uphy_lane_iddq_disable(struct tegra_xusb_padctl *padctl, unsigned 
> lane)
> +{
> + u32 val, offset;
> +
> + if (lane <= 6)
> + offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(lane);
> + else if (lane == 7)
> + offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2;
> + else {
> + WARN(true, "invalid lane %d\n", lane);
> + return;
> + }
> +
> + val = padctl_readl(padctl, offset);
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
> + val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
> + val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
> + padctl_writel(padctl, val, offset);
> +}
> +
> +
>  static const char *tegra210_pcie_functions[] = {
>   "pcie-x1",
>   "usb3-ss",
> @@ -1808,9 +1878,21 @@ static void tegra210_pcie_lane_remove(struct 
> tegra_xusb_lane *lane)
>   kfree(pcie);
>  }
>  
> +static void tegra210_pcie_lane_iddq_enable(struct tegra_xusb_lane *lane)
> +{
> + tegra210_uphy_lane_iddq_enable(lane->pad->padctl, lane->index);
> +}
> +
> +static void tegra210_pcie_lane_iddq_disable(struct tegra_xusb_lane *lane)
> +{
> + tegra210_uphy_lane_iddq_disable(lane->pad->padctl, lane->index);
> +}
> +
>  static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = {
>   

[PATCH v2 04/12] phy: tegra: xusb: t210: add lane_iddq operations

2020-08-30 Thread JC Kuo
As per Tegra210 TRM, before changing lane assignments, driver should
keep lanes in IDDQ and sleep state; after changing lane assignments,
driver should bring lanes out of IDDQ.
This commit implements the required operations.

Signed-off-by: JC Kuo 
---
 drivers/phy/tegra/xusb-tegra210.c | 94 +++
 drivers/phy/tegra/xusb.c  |  6 ++
 drivers/phy/tegra/xusb.h  |  4 +-
 3 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/tegra/xusb-tegra210.c 
b/drivers/phy/tegra/xusb-tegra210.c
index 3a2d9797fb9f..fe1ab440424d 100644
--- a/drivers/phy/tegra/xusb-tegra210.c
+++ b/drivers/phy/tegra/xusb-tegra210.c
@@ -198,6 +198,18 @@
 #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18)
 #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13)
 
+#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(x) (0x464 + (x) * 0x40)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ BIT(0)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD BIT(1)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK (0x3 << 4)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL (0x3 << 4)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD BIT(24)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ BIT(8)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD BIT(9)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK (0x3 << 12)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL (0x3 << 12)
+#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
+
 #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
 
 #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
@@ -209,6 +221,7 @@
 #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
 
 #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
+#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
 
 #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40)
 #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16
@@ -1636,6 +1649,63 @@ static const struct tegra_xusb_pad_soc tegra210_hsic_pad 
= {
.ops = _hsic_ops,
 };
 
+static void
+tegra210_uphy_lane_iddq_enable(struct tegra_xusb_padctl *padctl, unsigned lane)
+{
+   u32 val, offset;
+
+   if (lane <= 6)
+   offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(lane);
+   else if (lane == 7)
+   offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2;
+   else {
+   WARN(true, "invalid lane %u\n", lane);
+   return;
+   }
+
+   val = padctl_readl(padctl, offset);
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
+   padctl_writel(padctl, val, offset);
+}
+
+static void
+tegra210_uphy_lane_iddq_disable(struct tegra_xusb_padctl *padctl, unsigned 
lane)
+{
+   u32 val, offset;
+
+   if (lane <= 6)
+   offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(lane);
+   else if (lane == 7)
+   offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2;
+   else {
+   WARN(true, "invalid lane %d\n", lane);
+   return;
+   }
+
+   val = padctl_readl(padctl, offset);
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
+   val &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
+   val |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
+   padctl_writel(padctl, val, offset);
+}
+
+
 static const char *tegra210_pcie_functions[] = {
"pcie-x1",
"usb3-ss",
@@ -1808,9 +1878,21 @@ static void tegra210_pcie_lane_remove(struct 
tegra_xusb_lane *lane)
kfree(pcie);
 }
 
+static void tegra210_pcie_lane_iddq_enable(struct tegra_xusb_lane *lane)
+{
+   tegra210_uphy_lane_iddq_enable(lane->pad->padctl, lane->index);
+}
+
+static void tegra210_pcie_lane_iddq_disable(struct tegra_xusb_lane *lane)
+{
+   tegra210_uphy_lane_iddq_disable(lane->pad->padctl, lane->index);
+}
+
 static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = {
.probe = tegra210_pcie_lane_probe,
.remove = tegra210_pcie_lane_remove,
+   .iddq_enable = tegra210_pcie_lane_iddq_enable,
+   .iddq_disable = tegra210_pcie_lane_iddq_disable,
 };
 
 static int