Compare commits

...

3 Commits

Author SHA1 Message Date
2c90f5e347 clk: tegra210b01: add plle 2025-11-08 03:16:49 +00:00
Rohith Seelaboyina
6aba9ba3f1 phy: tegra: xusb: Add T210B01 support
- Add T210b01 soc data for xusb_padctl driver
- Add uphy_management clock support
- Add PLL defaults programming

Bug 200340262

Change-Id: Ie5a685a49542221142a0a8e31e5a9ebb729a3035
Signed-off-by: Rohith Seelaboyina <rseelaboyina@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1584421
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Rakesh Babu Bodla <rbodla@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
2025-11-07 05:48:48 +00:00
a78a344fd0 [DEBUG] add stupid prints to xusb 2025-11-07 05:46:51 +00:00
3 changed files with 189 additions and 10 deletions

View File

@@ -503,6 +503,72 @@ static unsigned long tegra210_input_freq[] = {
#define PLLE_SS_COEFFICIENTS_VAL \
(PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
bool tegra210b01_plle_hw_sequence_is_enabled(void)
{
u32 value;
value = readl_relaxed(clk_base + PLLE_AUX);
if (value & PLLE_AUX_SEQ_ENABLE)
return true;
return false;
}
EXPORT_SYMBOL_GPL(tegra210b01_plle_hw_sequence_is_enabled);
int tegra210b01_plle_hw_sequence_start(void)
{
u32 value;
if (tegra210b01_plle_hw_sequence_is_enabled())
return 0;
/* skip if PLLE is not enabled yet */
value = readl_relaxed(clk_base + PLLE_MISC0);
if (!(value & PLLE_MISC_LOCK))
return -EIO;
value &= ~PLLE_MISC_IDDQ_SW_CTRL;
writel_relaxed(value, clk_base + PLLE_MISC0);
value = readl_relaxed(clk_base + PLLE_AUX);
value |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE);
value &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
writel_relaxed(value, clk_base + PLLE_AUX);
fence_udelay(1, clk_base);
value |= PLLE_AUX_SEQ_ENABLE;
writel_relaxed(value, clk_base + PLLE_AUX);
fence_udelay(1, clk_base);
return 0;
}
EXPORT_SYMBOL_GPL(tegra210b01_plle_hw_sequence_start);
void tegra210b01_xusb_pll_hw_control_enable(void)
{
u32 val;
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
val |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ;
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
}
EXPORT_SYMBOL_GPL(tegra210b01_xusb_pll_hw_control_enable);
void tegra210b01_xusb_pll_hw_sequence_start(void)
{
u32 val;
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
}
EXPORT_SYMBOL_GPL(tegra210b01_xusb_pll_hw_sequence_start);
static inline void _pll_misc_chk_default(void __iomem *base,
struct tegra_clk_pll_params *params,
u8 misc_num, u32 default_val, u32 mask)

View File

@@ -230,6 +230,12 @@
#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL GENMASK(13, 12)
#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL8(x) (0x460 + (x) * (0x1c))
#define CFG_ADDR(x) (((x) & 0xff) << 16)
#define CFG_WDATA(x) (((x) & 0xffff) << 0)
#define CFG_RESET (1 << 27)
#define CFG_WS (1 << 24)
#define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
#define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
@@ -240,6 +246,8 @@
#define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
#define XUSB_PADCTL_UPHY_PLL_S0_CTL10 0x384
#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
@@ -407,6 +415,18 @@
#define UHSIC_STROBE_RPD_C BIT(16)
#define UHSIC_STROBE_RPD_D BIT(24)
struct init_data {
u8 cfg_addr;
u16 cfg_wdata;
};
static struct init_data usb3_pll_g1_init_data[] = {
{.cfg_addr = 0x2, .cfg_wdata = 0x0000},
{.cfg_addr = 0x3, .cfg_wdata = 0x7051},
{.cfg_addr = 0x25, .cfg_wdata = 0x0130},
{.cfg_addr = 0x1E, .cfg_wdata = 0x0017},
};
struct tegra210_xusb_fuse_calibration {
u32 hs_curr_level[4];
u32 hs_term_range_adj;
@@ -444,11 +464,38 @@ static const struct tegra_xusb_lane_map tegra210_usb3_map[] = {
{ 0, NULL, 0 }
};
static const struct tegra_xusb_lane_map tegra210b01_usb3_map[] = {
{ 0, "pcie", 5 },
{ 1, "pcie", 4 },
{ 2, "pcie", 1 },
{ 0, NULL, 0 }
};
static int t210b01_compatible(struct tegra_xusb_padctl *padctl)
{
struct device_node *np;
const char *compatible;
np = padctl->dev->of_node;
compatible = of_get_property(np, "compatible", NULL);
if (!compatible) {
dev_err(padctl->dev, "Failed to get compatible property\n");
return -ENODEV;
}
if (strstr(compatible, "tegra210b01") != NULL)
return 1;
return 0;
}
static int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane)
{
const struct tegra_xusb_lane_map *map;
for (map = tegra210_usb3_map; map->type; map++) {
for (map = t210b01_compatible(lane->pad->padctl) ?
tegra210b01_usb3_map : tegra210_usb3_map;
map->type; map++) {
if (map->index == lane->index &&
strcmp(map->type, lane->pad->soc->name) == 0) {
dev_dbg(lane->pad->padctl->dev, "lane = %s map to port = usb3-%d\n",
@@ -476,6 +523,12 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
if (err < 0)
return err;
if (t210b01_compatible(padctl) == 1) {
err = clk_prepare_enable(pcie->uphy_mgmt_clk);
if (err < 0)
return err;
}
if (tegra210_plle_hw_sequence_is_enabled())
goto skip_pll_init;
@@ -483,6 +536,18 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
if (err < 0)
goto disable;
if (t210b01_compatible(padctl) == 1) {
for (i = 0; i < ARRAY_SIZE(usb3_pll_g1_init_data); i++) {
value = 0;
value |= CFG_ADDR(usb3_pll_g1_init_data[i].cfg_addr);
value |= CFG_WDATA(usb3_pll_g1_init_data[i].cfg_wdata);
value |= CFG_RESET;
value |= CFG_WS;
padctl_writel(padctl, value,
XUSB_PADCTL_UPHY_PLL_S0_CTL10);
}
}
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
@@ -676,6 +741,8 @@ reset:
reset_control_assert(pcie->rst);
disable:
clk_disable_unprepare(pcie->pll);
if (t210b01_compatible(padctl) == 1)
clk_disable_unprepare(pcie->uphy_mgmt_clk);
return err;
}
@@ -697,6 +764,8 @@ static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl)
}
clk_disable_unprepare(pcie->pll);
if (t210b01_compatible(padctl) == 1)
clk_disable_unprepare(pcie->uphy_mgmt_clk);
}
/* must be called under padctl->lock */
@@ -2560,12 +2629,12 @@ static const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = {
};
static const struct tegra_xusb_lane_soc tegra210b01_pcie_lanes[] = {
TEGRA210_UPHY_LANE("pcie-0", 0x028, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
TEGRA210_UPHY_LANE("pcie-1", 0x028, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(1)),
TEGRA210_UPHY_LANE("pcie-2", 0x028, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(2)),
TEGRA210_UPHY_LANE("pcie-3", 0x028, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(3)),
TEGRA210_UPHY_LANE("pcie-4", 0x028, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(4)),
TEGRA210_UPHY_LANE("pcie-5", 0x028, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(5)),
TEGRA210_UPHY_LANE("pcie-0", 0x28, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
TEGRA210_UPHY_LANE("pcie-1", 0x28, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
TEGRA210_UPHY_LANE("pcie-2", 0x28, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
TEGRA210_UPHY_LANE("pcie-3", 0x28, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
TEGRA210_UPHY_LANE("pcie-4", 0x28, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
TEGRA210_UPHY_LANE("pcie-5", 0x28, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
};
static struct tegra_xusb_usb3_port *
@@ -2816,6 +2885,15 @@ tegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl,
goto unregister;
}
if (t210b01_compatible(padctl) == 1) {
pcie->uphy_mgmt_clk = devm_clk_get(&pad->dev, "uphy_mgmt");
if (IS_ERR(pcie->uphy_mgmt_clk)) {
err = PTR_ERR(pcie->uphy_mgmt_clk);
dev_err(&pad->dev,
"failed to get uphy_mgmt_clk clock: %d\n", err);
}
}
pcie->rst = devm_reset_control_get(&pad->dev, "phy");
if (IS_ERR(pcie->rst)) {
err = PTR_ERR(pcie->rst);
@@ -3094,7 +3172,16 @@ static void tegra210_usb3_port_disable(struct tegra_xusb_port *port)
static struct tegra_xusb_lane *
tegra210_usb3_port_map(struct tegra_xusb_port *port)
{
return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss");
int err = t210b01_compatible(port->padctl);
if (err == 1)
return tegra_xusb_port_find_lane(port,
tegra210b01_usb3_map, "usb3-ss");
else if (err == 0)
return tegra_xusb_port_find_lane(port,
tegra210_usb3_map, "usb3-ss");
else
return NULL;
}
static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
@@ -3287,6 +3374,14 @@ static const char * const tegra210_xusb_padctl_supply_names[] = {
"hvdd-pex-pll-e",
};
static const char * const tegra210b01_supply_names[] = {
"avdd_pll_uerefe",
"hvdd_pex_pll_e",
"dvdd_pex_pll",
"hvddio_pex",
"dvddio_pex",
};
const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = {
.num_pads = ARRAY_SIZE(tegra210_pads),
.pads = tegra210_pads,
@@ -3325,8 +3420,8 @@ const struct tegra_xusb_padctl_soc tegra210b01_xusb_padctl_soc = {
},
},
.ops = &tegra210_xusb_padctl_ops,
.supply_names = tegra210_xusb_padctl_supply_names,
.num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names),
.supply_names = tegra210b01_supply_names,
.num_supplies = ARRAY_SIZE(tegra210b01_supply_names),
.need_fake_usb3_port = true,
};
EXPORT_SYMBOL_GPL(tegra210b01_xusb_padctl_soc);

View File

@@ -564,6 +564,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
if (err < 0)
goto put_device;
printk("init done!\n");
return 0;
put_device:
@@ -799,24 +800,31 @@ static int tegra_xusb_add_usb2_port(struct tegra_xusb_padctl *padctl,
struct device_node *np;
int err = 0;
printk("adding usb2 port");
/*
* USB2 ports don't require additional properties, but if the port is
* marked as disabled there is no reason to register it.
*/
printk("find port node");
np = tegra_xusb_find_port_node(padctl, "usb2", index);
if (!np || !of_device_is_available(np))
goto out;
printk("kzalloc");
usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
if (!usb2) {
err = -ENOMEM;
goto out;
}
printk("init usb2 xusb port");
err = tegra_xusb_port_init(&usb2->base, padctl, np, "usb2", index);
if (err < 0)
goto out;
printk("set usb2 ops");
usb2->base.ops = padctl->soc->ports.usb2.ops;
usb2->base.lane = usb2->base.ops->map(&usb2->base);
@@ -880,6 +888,8 @@ static int tegra_xusb_add_ulpi_port(struct tegra_xusb_padctl *padctl,
goto out;
}
printk("init ulpi xusb port");
err = tegra_xusb_port_init(&ulpi->base, padctl, np, "ulpi", index);
if (err < 0)
goto out;
@@ -926,6 +936,7 @@ static int tegra_xusb_add_hsic_port(struct tegra_xusb_padctl *padctl,
struct device_node *np;
int err = 0;
printk("find hsic port node");
np = tegra_xusb_find_port_node(padctl, "hsic", index);
if (!np || !of_device_is_available(np))
goto out;
@@ -936,10 +947,13 @@ static int tegra_xusb_add_hsic_port(struct tegra_xusb_padctl *padctl,
goto out;
}
printk("init hsic xusb port");
err = tegra_xusb_port_init(&hsic->base, padctl, np, "hsic", index);
if (err < 0)
goto out;
printk("setting hsic ops");
hsic->base.ops = padctl->soc->ports.hsic.ops;
hsic->base.lane = hsic->base.ops->map(&hsic->base);
@@ -1028,10 +1042,14 @@ static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl,
if (err < 0)
goto out;
printk("xusb port inited. setting ops");
usb3->base.ops = padctl->soc->ports.usb3.ops;
printk("set lane");
usb3->base.lane = usb3->base.ops->map(&usb3->base);
if (IS_ERR(usb3->base.lane)) {
printk("usb3 lane is error!");
err = PTR_ERR(usb3->base.lane);
goto out;
}