Compare commits

...

6 Commits

Author SHA1 Message Date
ee190d2a23 phy: xusb-tegra210: use same supplies for b01 2025-11-10 23:58:53 +00:00
2d7adead1a memory: tegra: populate dt subnodes
Tegra210b01 uses tegra186-emc driver as emc clock is controlled by BPMP.
However, this driver expects emc as subnode of mc. Adjust Tegra30 mc
probe routine to populate subnodes.
2025-11-10 23:58:21 +00:00
227ce80df8 tegra210b01: update emc node 2025-11-10 23:56:14 +00:00
8f6969be89 xusb: bulk commit to split 2025-11-08 03:23:57 +00:00
a67ac5bf97 clk: tegra210b01: add plle 2025-11-08 03:23:57 +00:00
Rohith Seelaboyina
3f9181c4cc 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-08 03:23:57 +00:00
10 changed files with 283 additions and 17 deletions

View File

@@ -4,6 +4,10 @@
/ {
compatible = "nvidia,tegra210b01", "nvidia,tegra210";
pcie@1003000 {
compatible = "nvidia,tegra210b01-pcie";
};
host1x@50000000 {
/delete-node/ sor@54540000;
/delete-node/ dpaux@545c0000;
@@ -34,8 +38,12 @@
};
mc: memory-controller@70019000 {
#address-cells = <2>;
#size-cells = <2>;
emc: external-memory-controller@7001b000 {
compatible = "nvidia,tegra210b01-emc";
status = "okay";
reg = <0x0 0x7001b000 0x0 0x1000>,
<0x0 0x7001e000 0x0 0x1000>,
<0x0 0x7001f000 0x0 0x1000>;
@@ -53,6 +61,7 @@
/delete-node/ external-memory-controller@7001b000;
actmon@6000c800 {
status = "disabled";
clocks = <&tegra_car TEGRA210_CLK_ACTMON>,
<&bpmp 0>;
};
@@ -119,6 +128,14 @@
padctl@7009f000 {
compatible = "nvidia,tegra210b01-xusb-padctl";
pads {
pcie {
clocks = <&tegra_car TEGRA210_CLK_PLL_E>,
<&tegra_car TEGRA210_CLK_PLL_P_UPHY_OUT>;
clock-names = "pll", "uphy_mgmt";
};
};
};
pinmux@700008d4 {

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

@@ -526,6 +526,10 @@ int tegra30_mc_probe(struct tegra_mc *mc)
return err;
}
err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
if (err < 0)
return err;
return 0;
}

View File

@@ -3003,7 +3003,6 @@ static int tegra_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pci_host_bridge *host;
struct tegra_pcie_port *port;
struct tegra_pcie *pcie;
int err;

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,64 @@ 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 bool plle_hw_sequence_is_enabled(struct tegra_xusb_padctl *padctl) {
if (t210b01_compatible(padctl))
return tegra210b01_plle_hw_sequence_is_enabled();
return tegra210_plle_hw_sequence_is_enabled();
}
static int plle_hw_sequence_start(struct tegra_xusb_padctl *padctl) {
if (t210b01_compatible(padctl))
return tegra210b01_plle_hw_sequence_start();
return tegra210_plle_hw_sequence_start();
}
static void xusb_pll_hw_control_enable(struct tegra_xusb_padctl *padctl) {
if (t210b01_compatible(padctl))
tegra210b01_xusb_pll_hw_control_enable();
else
return tegra210_xusb_pll_hw_control_enable();
}
static void xusb_pll_hw_sequence_start(struct tegra_xusb_padctl *padctl) {
if (t210b01_compatible(padctl))
tegra210b01_xusb_pll_hw_sequence_start();
else
tegra210_xusb_pll_hw_sequence_start();
}
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,13 +549,31 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
if (err < 0)
return err;
if (tegra210_plle_hw_sequence_is_enabled())
if (t210b01_compatible(padctl) == 1) {
err = clk_prepare_enable(pcie->uphy_mgmt_clk);
if (err < 0)
return err;
}
if (plle_hw_sequence_is_enabled(padctl))
goto skip_pll_init;
err = reset_control_deassert(pcie->rst);
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);
@@ -643,7 +734,7 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
tegra210_xusb_pll_hw_control_enable();
xusb_pll_hw_control_enable(padctl);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
@@ -659,7 +750,7 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
usleep_range(10, 20);
tegra210_xusb_pll_hw_sequence_start();
xusb_pll_hw_sequence_start(padctl);
skip_pll_init:
pcie->enable = true;
@@ -676,6 +767,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 +790,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 */
@@ -1008,8 +1103,8 @@ static int tegra210_uphy_init(struct tegra_xusb_padctl *padctl)
if (padctl->sata)
tegra210_sata_uphy_enable(padctl);
if (!tegra210_plle_hw_sequence_is_enabled())
tegra210_plle_hw_sequence_start();
if (!plle_hw_sequence_is_enabled(padctl))
plle_hw_sequence_start(padctl);
else
dev_dbg(padctl->dev, "PLLE is already in HW control\n");
@@ -2560,12 +2655,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 +2911,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 +3198,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 = {

View File

@@ -244,6 +244,7 @@ struct tegra_xusb_pcie_pad {
struct reset_control *rst;
struct clk *pll;
struct clk *uphy_mgmt_clk;
bool enable;
};

View File

@@ -2546,27 +2546,34 @@ static const struct tegra_xusb_soc tegra210_soc = {
};
MODULE_FIRMWARE("nvidia/tegra210/xusb.bin");
static const struct tegra_xusb_phy_type tegra210b01_phy_types[] = {
{ .name = "usb3", .num = 4, },
{ .name = "usb2", .num = 4, },
};
static const struct tegra_xusb_soc tegra210b01_soc = {
.firmware = "nvidia/tegra210b01/xusb.bin",
.supply_names = tegra210_supply_names,
.num_supplies = ARRAY_SIZE(tegra210_supply_names),
.phy_types = tegra210_phy_types,
.num_types = ARRAY_SIZE(tegra210_phy_types),
.phy_types = tegra210b01_phy_types,
.num_types = ARRAY_SIZE(tegra210b01_phy_types),
.context = &tegra124_xusb_context,
.ports = {
.usb2 = { .offset = 4, .count = 4, },
.hsic = { .offset = 8, .count = 1, },
.usb3 = { .offset = 0, .count = 4, },
},
.scale_ss_clock = false,
.has_ipfs = true,
.otg_reset_sspi = true,
.ops = &tegra124_ops,
.mbox = {
.cmd = 0xe4,
.data_in = 0xe8,
.data_out = 0xec,
.owner = 0xf0,
.smi_intr = XUSB_CFG_ARU_SMI_INTR,
},
.lpm_support = false,
};
MODULE_FIRMWARE("nvidia/tegra210b01/xusb.bin");

View File

@@ -487077,6 +487077,15 @@ elf_symbol {
type_id: 0x578fa618
full_name: "pci_find_next_capability"
}
elf_symbol {
id: 0xbbf8a63b
name: "pci_flags"
is_defined: true
symbol_type: OBJECT
crc: 0xf296206e
type_id: 0x4585663f
full_name: "pci_flags"
}
elf_symbol {
id: 0x08190210
name: "pci_free_irq"
@@ -504837,6 +504846,42 @@ elf_symbol {
type_id: 0x10985193
full_name: "tegra210_xusb_pll_hw_sequence_start"
}
elf_symbol {
id: 0xd2118b04
name: "tegra210b01_plle_hw_sequence_is_enabled"
is_defined: true
symbol_type: FUNCTION
crc: 0x5e505530
type_id: 0xfea45b04
full_name: "tegra210b01_plle_hw_sequence_is_enabled"
}
elf_symbol {
id: 0x56591275
name: "tegra210b01_plle_hw_sequence_start"
is_defined: true
symbol_type: FUNCTION
crc: 0x7851be11
type_id: 0x9d80e32f
full_name: "tegra210b01_plle_hw_sequence_start"
}
elf_symbol {
id: 0xa6a8ece8
name: "tegra210b01_xusb_pll_hw_control_enable"
is_defined: true
symbol_type: FUNCTION
crc: 0xd272d446
type_id: 0x10985193
full_name: "tegra210b01_xusb_pll_hw_control_enable"
}
elf_symbol {
id: 0xc1ac282e
name: "tegra210b01_xusb_pll_hw_sequence_start"
is_defined: true
symbol_type: FUNCTION
crc: 0xd272d446
type_id: 0x10985193
full_name: "tegra210b01_xusb_pll_hw_sequence_start"
}
elf_symbol {
id: 0xe54ea1f3
name: "tegra_bpmp_free_mrq"
@@ -522102,6 +522147,7 @@ interface {
symbol_id: 0x780d1110
symbol_id: 0xbbb674cc
symbol_id: 0xdea420f5
symbol_id: 0xbbf8a63b
symbol_id: 0x08190210
symbol_id: 0x8ffabaa9
symbol_id: 0x50bce06e
@@ -524075,6 +524121,10 @@ interface {
symbol_id: 0xdfb56896
symbol_id: 0x72c26996
symbol_id: 0x7ac45534
symbol_id: 0xd2118b04
symbol_id: 0x56591275
symbol_id: 0xa6a8ece8
symbol_id: 0xc1ac282e
symbol_id: 0xe54ea1f3
symbol_id: 0x4a1dceb2
symbol_id: 0xa2565005

View File

@@ -2070,6 +2070,7 @@
irq_set_chained_handler_and_data
of_irq_parse_and_map_pci
of_pci_get_devfn
pci_flags
pci_generic_config_read32
pci_generic_config_write32
pci_host_probe
@@ -2125,6 +2126,10 @@
phy_destroy
regulator_get
regulator_put
tegra210b01_plle_hw_sequence_is_enabled
tegra210b01_plle_hw_sequence_start
tegra210b01_xusb_pll_hw_control_enable
tegra210b01_xusb_pll_hw_sequence_start
tegra210_plle_hw_sequence_is_enabled
tegra210_plle_hw_sequence_start
tegra210_sata_pll_hw_control_enable

View File

@@ -208,9 +208,13 @@ tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb,
#ifdef CONFIG_ARCH_TEGRA_210_SOC
int tegra210_plle_hw_sequence_start(void);
int tegra210b01_plle_hw_sequence_start(void);
bool tegra210_plle_hw_sequence_is_enabled(void);
bool tegra210b01_plle_hw_sequence_is_enabled(void);
void tegra210_xusb_pll_hw_control_enable(void);
void tegra210b01_xusb_pll_hw_control_enable(void);
void tegra210_xusb_pll_hw_sequence_start(void);
void tegra210b01_xusb_pll_hw_sequence_start(void);
void tegra210_sata_pll_hw_control_enable(void);
void tegra210_sata_pll_hw_sequence_start(void);
void tegra210_set_sata_pll_seq_sw(bool state);