Skip to content

Commit da11022

Browse files
Wayne Changvinodkoul
authored andcommitted
phy: tegra: xusb: Fix per-pad high-speed termination calibration
The existing code reads a single hs_term_range_adj value from bit field [10:7] of FUSE_SKU_CALIB_0 and applies it to all USB2 pads uniformly. However, on SoCs that support per-pad termination, each pad has its own hs_term_range_adj field: pad 0 in FUSE_SKU_CALIB_0[10:7], and pads 1-3 in FUSE_USB_CALIB_EXT_0 at bit offsets [8:5], [12:9], and [16:13] respectively. Fix the calibration by reading per-pad values from the appropriate fuse registers. For SoCs that do not support per-pad termination, replicate pad 0's value to all pads to maintain existing behavior. Add a has_per_pad_term flag to the SoC data to indicate whether per-pad termination values are available in FUSE_USB_CALIB_EXT_0. Fixes: 1ef535c ("phy: tegra: xusb: Add Tegra194 support") Cc: stable@vger.kernel.org Signed-off-by: Wayne Chang <waynec@nvidia.com> Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com> Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Tested-by: Jon Hunter <jonathanh@nvidia.com> Link: https://patch.msgid.link/20260504033305.2283145-1-weichengc@nvidia.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 91ddf6f commit da11022

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

drivers/phy/tegra/xusb-tegra186.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
/* FUSE USB_CALIB registers */
2121
#define HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? (11 + (x - 1) * 6) : 0)
2222
#define HS_CURR_LEVEL_PAD_MASK 0x3f
23-
#define HS_TERM_RANGE_ADJ_SHIFT 7
24-
#define HS_TERM_RANGE_ADJ_MASK 0xf
23+
#define HS_TERM_RANGE_ADJ_PADX_SHIFT(x) ((x) ? (5 + (x - 1) * 4) : 7)
24+
#define HS_TERM_RANGE_ADJ_PAD_MASK 0xf
2525
#define HS_SQUELCH_SHIFT 29
2626
#define HS_SQUELCH_MASK 0x7
2727

@@ -253,7 +253,7 @@
253253
struct tegra_xusb_fuse_calibration {
254254
u32 *hs_curr_level;
255255
u32 hs_squelch;
256-
u32 hs_term_range_adj;
256+
u32 *hs_term_range_adj;
257257
u32 rpd_ctrl;
258258
};
259259

@@ -930,7 +930,7 @@ static int tegra186_utmi_phy_power_on(struct phy *phy)
930930

931931
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
932932
value &= ~TERM_RANGE_ADJ(~0);
933-
value |= TERM_RANGE_ADJ(priv->calib.hs_term_range_adj);
933+
value |= TERM_RANGE_ADJ(priv->calib.hs_term_range_adj[index]);
934934
value &= ~RPD_CTRL(~0);
935935
value |= RPD_CTRL(priv->calib.rpd_ctrl);
936936
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
@@ -1464,17 +1464,23 @@ static const char * const tegra186_usb3_functions[] = {
14641464
static int
14651465
tegra186_xusb_read_fuse_calibration(struct tegra186_xusb_padctl *padctl)
14661466
{
1467+
const struct tegra_xusb_padctl_soc *soc = padctl->base.soc;
14671468
struct device *dev = padctl->base.dev;
14681469
unsigned int i, count;
14691470
u32 value, *level;
1471+
u32 *hs_term_range_adj;
14701472
int err;
14711473

1472-
count = padctl->base.soc->ports.usb2.count;
1474+
count = soc->ports.usb2.count;
14731475

14741476
level = devm_kcalloc(dev, count, sizeof(u32), GFP_KERNEL);
14751477
if (!level)
14761478
return -ENOMEM;
14771479

1480+
hs_term_range_adj = devm_kcalloc(dev, count, sizeof(u32), GFP_KERNEL);
1481+
if (!hs_term_range_adj)
1482+
return -ENOMEM;
1483+
14781484
err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
14791485
if (err)
14801486
return dev_err_probe(dev, err,
@@ -1490,8 +1496,8 @@ tegra186_xusb_read_fuse_calibration(struct tegra186_xusb_padctl *padctl)
14901496

14911497
padctl->calib.hs_squelch = (value >> HS_SQUELCH_SHIFT) &
14921498
HS_SQUELCH_MASK;
1493-
padctl->calib.hs_term_range_adj = (value >> HS_TERM_RANGE_ADJ_SHIFT) &
1494-
HS_TERM_RANGE_ADJ_MASK;
1499+
hs_term_range_adj[0] = (value >> HS_TERM_RANGE_ADJ_PADX_SHIFT(0)) &
1500+
HS_TERM_RANGE_ADJ_PAD_MASK;
14951501

14961502
err = tegra_fuse_readl(TEGRA_FUSE_USB_CALIB_EXT_0, &value);
14971503
if (err) {
@@ -1503,6 +1509,17 @@ tegra186_xusb_read_fuse_calibration(struct tegra186_xusb_padctl *padctl)
15031509

15041510
padctl->calib.rpd_ctrl = (value >> RPD_CTRL_SHIFT) & RPD_CTRL_MASK;
15051511

1512+
for (i = 1; i < count; i++) {
1513+
if (soc->has_per_pad_term)
1514+
hs_term_range_adj[i] =
1515+
(value >> HS_TERM_RANGE_ADJ_PADX_SHIFT(i)) &
1516+
HS_TERM_RANGE_ADJ_PAD_MASK;
1517+
else
1518+
hs_term_range_adj[i] = hs_term_range_adj[0];
1519+
}
1520+
1521+
padctl->calib.hs_term_range_adj = hs_term_range_adj;
1522+
15061523
return 0;
15071524
}
15081525

@@ -1708,6 +1725,7 @@ const struct tegra_xusb_padctl_soc tegra194_xusb_padctl_soc = {
17081725
.num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names),
17091726
.supports_gen2 = true,
17101727
.poll_trk_completed = true,
1728+
.has_per_pad_term = true,
17111729
};
17121730
EXPORT_SYMBOL_GPL(tegra194_xusb_padctl_soc);
17131731

@@ -1732,6 +1750,7 @@ const struct tegra_xusb_padctl_soc tegra234_xusb_padctl_soc = {
17321750
.trk_hw_mode = false,
17331751
.trk_update_on_idle = true,
17341752
.supports_lp_cfg_en = true,
1753+
.has_per_pad_term = true,
17351754
};
17361755
EXPORT_SYMBOL_GPL(tegra234_xusb_padctl_soc);
17371756
#endif

drivers/phy/tegra/xusb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ struct tegra_xusb_padctl_soc {
435435
bool trk_hw_mode;
436436
bool trk_update_on_idle;
437437
bool supports_lp_cfg_en;
438+
bool has_per_pad_term;
438439
};
439440

440441
struct tegra_xusb_padctl {

0 commit comments

Comments
 (0)