Message ID | 20221114124053.1873316-12-waynec@nvidia.com |
---|---|
State | New |
Headers | show |
Series | Enable USB host and device functions on Jetson | expand |
On 14/11/2022 12:40, Wayne Chang wrote: > From: Sing-Han Chen <singhanc@nvidia.com> > > 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@nvidia.com> > Co-developed-by: Wayne Chang <waynec@nvidia.com> > Signed-off-by: Wayne Chang <waynec@nvidia.com> > --- > V2 -> V3:nothing has changed > V1 -> V2:remove atomic and the helper in padctl_readl_poll func. > drivers/phy/tegra/Makefile | 1 + > drivers/phy/tegra/xusb-tegra186.c | 64 +++++++++++++++++++++++++++++-- > drivers/phy/tegra/xusb.c | 6 +++ > drivers/phy/tegra/xusb.h | 22 +++++++++++ > 4 files changed, 90 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..5ae3cea19c84 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,31 @@ 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 +664,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 +1594,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 +1651,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); > #endif > > MODULE_AUTHOR("JC Kuo <jckuo@nvidia.com>"); > diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c > index dce45fbbd699..c2f160628552 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..a21826c730d7 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,22 @@ 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(padctl->regs + offset, regval, > + (regval & mask) == val, 1, us); > + 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 +510,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 */ Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Thanks Jon
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..5ae3cea19c84 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,31 @@ 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 +664,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 +1594,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 +1651,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); #endif MODULE_AUTHOR("JC Kuo <jckuo@nvidia.com>"); diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index dce45fbbd699..c2f160628552 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..a21826c730d7 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,22 @@ 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(padctl->regs + offset, regval, + (regval & mask) == val, 1, us); + 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 +510,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 */