#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)
        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);
 }
        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);
 }
 
 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",
        .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>");
 
 #define __PHY_TEGRA_XUSB_H
 
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 
        unsigned int num_supplies;
        bool supports_gen2;
        bool need_fake_usb3_port;
+       bool poll_trk_completed;
+       bool trk_hw_mode;
 };
 
 struct tegra_xusb_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);
 #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 */