On 10/28/22 20:56, Thierry Reding wrote: > On Mon, Oct 24, 2022 at 03:41:26PM +0800, Wayne Chang wrote: >> From: Sing-Han Chen<singhanc@xxxxxxxxxx> >> >> Add support for the XUSB pad controller found on Tegra234 SoCs. It is >> mostly similar to the same IP found on Tegra194, because most of >> the Tegra234 XUSB PADCTL registers definition and programming sequence >> are the same as Tegra194, Tegra234 XUSB PADCTL can share the same >> driver with Tegra186 and Tegra194 XUSB PADCTL. >> >> Introduce a new feature, USB2 HW tracking, for Tegra234. >> The feature is to enable HW periodical PAD tracking which measure >> and capture the electric parameters of USB2.0 PAD. >> >> Signed-off-by: Sing-Han Chen<singhanc@xxxxxxxxxx> >> Co-developed-by: Wayne Chang<waynec@xxxxxxxxxx> >> Signed-off-by: Wayne Chang<waynec@xxxxxxxxxx> >> --- >> drivers/phy/tegra/Makefile | 1 + >> drivers/phy/tegra/xusb-tegra186.c | 65 +++++++++++++++++++++++++++++-- >> drivers/phy/tegra/xusb.c | 6 +++ >> drivers/phy/tegra/xusb.h | 23 +++++++++++ >> 4 files changed, 92 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/phy/tegra/Makefile b/drivers/phy/tegra/Makefile >> index 89b84067cb4c..eeeea72de117 100644 >> --- a/drivers/phy/tegra/Makefile >> +++ b/drivers/phy/tegra/Makefile >> @@ -7,4 +7,5 @@ phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_132_SOC) += xusb-tegra124.o >> phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_210_SOC) += xusb-tegra210.o >> phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_186_SOC) += xusb-tegra186.o >> phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_194_SOC) += xusb-tegra186.o >> +phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_234_SOC) += xusb-tegra186.o >> obj-$(CONFIG_PHY_TEGRA194_P2U) += phy-tegra194-p2u.o >> diff --git a/drivers/phy/tegra/xusb-tegra186.c b/drivers/phy/tegra/xusb-tegra186.c >> index f121b4ffbbfd..cc02cea65a21 100644 >> --- a/drivers/phy/tegra/xusb-tegra186.c >> +++ b/drivers/phy/tegra/xusb-tegra186.c >> @@ -89,6 +89,11 @@ >> #define USB2_TRK_START_TIMER(x) (((x) & 0x7f) << 12) >> #define USB2_TRK_DONE_RESET_TIMER(x) (((x) & 0x7f) << 19) >> #define USB2_PD_TRK BIT(26) >> +#define USB2_TRK_COMPLETED BIT(31) >> + >> +#define XUSB_PADCTL_USB2_BIAS_PAD_CTL2 0x28c >> +#define USB2_TRK_HW_MODE BIT(0) >> +#define CYA_TRK_CODE_UPDATE_ON_IDLE BIT(31) >> >> #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20) >> #define HSIC_PD_TX_DATA0 BIT(1) >> @@ -609,9 +614,32 @@ static void tegra186_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl) >> value &= ~USB2_PD_TRK; >> padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); >> >> - udelay(100); >> + if (padctl->soc->poll_trk_completed) { >> + err = padctl_readl_poll(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1, >> + USB2_TRK_COMPLETED, USB2_TRK_COMPLETED, 100); >> + if (err) { >> + /* The failure with polling on trk complete will not >> + * cause the failure of powering on the bias pad. >> + */ >> + dev_warn(dev, "failed to poll USB2 trk completed: %d\n", >> + err); >> + } >> >> - clk_disable_unprepare(priv->usb2_trk_clk); >> + value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); >> + value |= USB2_TRK_COMPLETED; >> + padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); >> + } else { >> + udelay(100); >> + } >> + >> + if (padctl->soc->trk_hw_mode) { >> + value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); >> + value |= USB2_TRK_HW_MODE; >> + value &= ~CYA_TRK_CODE_UPDATE_ON_IDLE; >> + padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); >> + } else { >> + clk_disable_unprepare(priv->usb2_trk_clk); >> + } >> >> mutex_unlock(&padctl->lock); >> } >> @@ -637,6 +665,13 @@ static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl) >> value |= USB2_PD_TRK; >> padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); >> >> + if (padctl->soc->trk_hw_mode) { >> + value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); >> + value &= ~USB2_TRK_HW_MODE; >> + padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); >> + clk_disable_unprepare(priv->usb2_trk_clk); >> + } >> + >> mutex_unlock(&padctl->lock); >> } >> >> @@ -1560,7 +1595,8 @@ const struct tegra_xusb_padctl_soc tegra186_xusb_padctl_soc = { >> EXPORT_SYMBOL_GPL(tegra186_xusb_padctl_soc); >> #endif >> >> -#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) >> +#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ >> + IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) >> static const char * const tegra194_xusb_padctl_supply_names[] = { >> "avdd-usb", >> "vclamp-usb", >> @@ -1616,8 +1652,31 @@ const struct tegra_xusb_padctl_soc tegra194_xusb_padctl_soc = { >> .supply_names = tegra194_xusb_padctl_supply_names, >> .num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names), >> .supports_gen2 = true, >> + .poll_trk_completed = true, >> }; >> EXPORT_SYMBOL_GPL(tegra194_xusb_padctl_soc); >> + >> +const struct tegra_xusb_padctl_soc tegra234_xusb_padctl_soc = { >> + .num_pads = ARRAY_SIZE(tegra194_pads), >> + .pads = tegra194_pads, >> + .ports = { >> + .usb2 = { >> + .ops = &tegra186_usb2_port_ops, >> + .count = 4, >> + }, >> + .usb3 = { >> + .ops = &tegra186_usb3_port_ops, >> + .count = 4, >> + }, >> + }, >> + .ops = &tegra186_xusb_padctl_ops, >> + .supply_names = tegra194_xusb_padctl_supply_names, >> + .num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names), >> + .supports_gen2 = true, >> + .poll_trk_completed = true, >> + .trk_hw_mode = true, >> +}; >> +EXPORT_SYMBOL_GPL(tegra234_xusb_padctl_soc); > I'm beginning to wonder if we perhaps went a bit overboard with this. > These symbols are used exclusively by drivers/phy/tegra/xusb.c, which > ends up in the same link unit as xusb-tegra186.c, so the export should > not be necessary. > > Not necessarily something that needs fixing right now, but certainly > something to circle back to eventually. Yes, exactly. OK. We will refactor it the next time. Thanks for the review. > >> #endif >> >> MODULE_AUTHOR("JC Kuo<jckuo@xxxxxxxxxx>"); >> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c >> index 95091876c422..23d179b1a5b5 100644 >> --- a/drivers/phy/tegra/xusb.c >> +++ b/drivers/phy/tegra/xusb.c >> @@ -71,6 +71,12 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = { >> .compatible = "nvidia,tegra194-xusb-padctl", >> .data = &tegra194_xusb_padctl_soc, >> }, >> +#endif >> +#if defined(CONFIG_ARCH_TEGRA_234_SOC) >> + { >> + .compatible = "nvidia,tegra234-xusb-padctl", >> + .data = &tegra234_xusb_padctl_soc, >> + }, >> #endif >> { } >> }; >> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h >> index 8cfbbdbd6e0c..ec0b5b023ad1 100644 >> --- a/drivers/phy/tegra/xusb.h >> +++ b/drivers/phy/tegra/xusb.h >> @@ -8,6 +8,7 @@ >> #define __PHY_TEGRA_XUSB_H >> >> #include <linux/io.h> >> +#include <linux/iopoll.h> >> #include <linux/mutex.h> >> #include <linux/workqueue.h> >> >> @@ -433,6 +434,8 @@ struct tegra_xusb_padctl_soc { >> unsigned int num_supplies; >> bool supports_gen2; >> bool need_fake_usb3_port; >> + bool poll_trk_completed; >> + bool trk_hw_mode; >> }; >> >> struct tegra_xusb_padctl { >> @@ -475,6 +478,23 @@ static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, >> return value; >> } >> >> +static inline u32 padctl_readl_poll(struct tegra_xusb_padctl *padctl, >> + unsigned long offset, u32 val, u32 mask, int us) >> +{ >> + u32 regval; >> + int err; >> + >> + err = readl_poll_timeout_atomic(padctl->regs + offset, regval, >> + (regval & mask) == val, 1, us); > Do we really need the atomic variant here? The function that calls this > already uses a mutex for protection, so it can already sleep anyway. > Thanks for the review. No, we don't need it to be atomic. I'll update it in the next patch series. > Also, do we really need the helper here? We use this exactly once and > this doesn't make the invocation more readable, either. > Not at all. Removed. Thanks. thanks, Wayne. > Thierry > >> + dev_dbg(padctl->dev, "%08lx poll > %08x\n", offset, regval); >> + if (err) { >> + dev_err(padctl->dev, "%08lx poll timeout > %08x\n", offset, >> + regval); >> + } >> + >> + return err; >> +} >> + >> struct tegra_xusb_lane *tegra_xusb_find_lane(struct tegra_xusb_padctl *padctl, >> const char *name, >> unsigned int index); >> @@ -491,5 +511,8 @@ extern const struct tegra_xusb_padctl_soc tegra186_xusb_padctl_soc; >> #if defined(CONFIG_ARCH_TEGRA_194_SOC) >> extern const struct tegra_xusb_padctl_soc tegra194_xusb_padctl_soc; >> #endif >> +#if defined(CONFIG_ARCH_TEGRA_234_SOC) >> +extern const struct tegra_xusb_padctl_soc tegra234_xusb_padctl_soc; >> +#endif >> >> #endif /* __PHY_TEGRA_XUSB_H */ >> -- >> 2.25.1