Re: [PATCH v2 04/12] phy: tegra: xusb: t210: add lane_iddq operations
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 = &tegra210_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_lan
Re: [PATCH v2 04/12] phy: tegra: xusb: t210: add lane_iddq operations
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 = &tegra210_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 = {