Skip to content

Commit fdb71c6

Browse files
author
Herton R. Krzesinski
committed
Merge: [RHEL for Edge] add changes to enable USB support on NVIDIA Orin
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/2043 # Merge Request Required Information Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2122414 Tested: Verify USB-A and USB-C are functional on Nvidia Orin board, and no regressions on other platforms. Enable USB support (Type-A and Type-C) for NVIDIA Orin. ## Summary of Changes Enable the UCSI_CCG support. Add device-tree support for the Cypress CCG UCSI driver. Add PMC compatible string for Tegra234 in GPIO driver. Add support for XUSB device mode controller support on Tegra234 SoC. Program USB2 pad PD controls to reduce power consumption on disconnect or suspend. Add a hub_control() callback to the xhci_driver_overrides structure. Export symbol on xhci_hub_control to allow the XHCI host drivers may override the default. Add Tegra234 XUSB host mode controller support. Support role-switch-default-mode property when usb-role-switch is enabled. Add support for the XUSB pad controller found on Tegra234 SoCs. Pad tracking is a one-time calibration for Tegra186 and Tegra194, disable after calibration. Remove redundant codes for getting the vbus supply of usb3 ports. Check to see if the 'phy' pointer passed to tegra_phy_xusb_utmi_pad_power_on/down is valid. Disable UCSI ALT support when reading the capability on Tegra. Don't warn on probe deferral. Enable the usb-role-switch attribute to let users check the current device role of the otg capability ports. Program USB2 UTMI pad PD controls during port connect/disconnect. Add utmi_pad_power_on/down ops for each SOC. Signed-off-by: David Marlin <dmarlin@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Approved-by: Torez Smith <torez@redhat.com> Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
2 parents a281c6b + 723cb3c commit fdb71c6

File tree

17 files changed

+579
-77
lines changed

17 files changed

+579
-77
lines changed

drivers/gpio/gpio-tegra186.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ static unsigned int tegra186_gpio_child_offset_to_irq(struct gpio_chip *chip,
669669
static const struct of_device_id tegra186_pmc_of_match[] = {
670670
{ .compatible = "nvidia,tegra186-pmc" },
671671
{ .compatible = "nvidia,tegra194-pmc" },
672+
{ .compatible = "nvidia,tegra234-pmc" },
672673
{ /* sentinel */ }
673674
};
674675

drivers/i2c/busses/i2c-nvidia-gpu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ static const struct pci_device_id gpu_i2c_ids[] = {
257257
MODULE_DEVICE_TABLE(pci, gpu_i2c_ids);
258258

259259
static const struct property_entry ccgx_props[] = {
260-
/* Use FW built for NVIDIA (nv) only */
261-
PROPERTY_ENTRY_U16("ccgx,firmware-build", ('n' << 8) | 'v'),
260+
/* Use FW built for NVIDIA GPU only */
261+
PROPERTY_ENTRY_STRING("firmware-name", "nvidia,gpu"),
262262
{ }
263263
};
264264

drivers/phy/tegra/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_132_SOC) += xusb-tegra124.o
77
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_210_SOC) += xusb-tegra210.o
88
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_186_SOC) += xusb-tegra186.o
99
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_194_SOC) += xusb-tegra186.o
10+
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_234_SOC) += xusb-tegra186.o
1011
obj-$(CONFIG_PHY_TEGRA194_P2U) += phy-tegra194-p2u.o

drivers/phy/tegra/xusb-tegra124.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1652,7 +1652,6 @@ tegra124_usb3_port_map(struct tegra_xusb_port *port)
16521652

16531653
static const struct tegra_xusb_port_ops tegra124_usb3_port_ops = {
16541654
.release = tegra_xusb_usb3_port_release,
1655-
.remove = tegra_xusb_usb3_port_remove,
16561655
.enable = tegra124_usb3_port_enable,
16571656
.disable = tegra124_usb3_port_disable,
16581657
.map = tegra124_usb3_port_map,

drivers/phy/tegra/xusb-tegra186.c

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/*
3-
* Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved.
3+
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
44
*/
55

66
#include <linux/delay.h>
@@ -89,6 +89,11 @@
8989
#define USB2_TRK_START_TIMER(x) (((x) & 0x7f) << 12)
9090
#define USB2_TRK_DONE_RESET_TIMER(x) (((x) & 0x7f) << 19)
9191
#define USB2_PD_TRK BIT(26)
92+
#define USB2_TRK_COMPLETED BIT(31)
93+
94+
#define XUSB_PADCTL_USB2_BIAS_PAD_CTL2 0x28c
95+
#define USB2_TRK_HW_MODE BIT(0)
96+
#define CYA_TRK_CODE_UPDATE_ON_IDLE BIT(31)
9297

9398
#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20)
9499
#define HSIC_PD_TX_DATA0 BIT(1)
@@ -609,6 +614,32 @@ static void tegra186_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl)
609614
value &= ~USB2_PD_TRK;
610615
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
611616

617+
if (padctl->soc->poll_trk_completed) {
618+
err = padctl_readl_poll(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1,
619+
USB2_TRK_COMPLETED, USB2_TRK_COMPLETED, 100);
620+
if (err) {
621+
/* The failure with polling on trk complete will not
622+
* cause the failure of powering on the bias pad.
623+
*/
624+
dev_warn(dev, "failed to poll USB2 trk completed: %d\n", err);
625+
}
626+
627+
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
628+
value |= USB2_TRK_COMPLETED;
629+
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
630+
} else {
631+
udelay(100);
632+
}
633+
634+
if (padctl->soc->trk_hw_mode) {
635+
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2);
636+
value |= USB2_TRK_HW_MODE;
637+
value &= ~CYA_TRK_CODE_UPDATE_ON_IDLE;
638+
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2);
639+
} else {
640+
clk_disable_unprepare(priv->usb2_trk_clk);
641+
}
642+
612643
mutex_unlock(&padctl->lock);
613644
}
614645

@@ -633,12 +664,17 @@ static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl)
633664
value |= USB2_PD_TRK;
634665
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
635666

636-
clk_disable_unprepare(priv->usb2_trk_clk);
667+
if (padctl->soc->trk_hw_mode) {
668+
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2);
669+
value &= ~USB2_TRK_HW_MODE;
670+
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2);
671+
clk_disable_unprepare(priv->usb2_trk_clk);
672+
}
637673

638674
mutex_unlock(&padctl->lock);
639675
}
640676

641-
static void tegra_phy_xusb_utmi_pad_power_on(struct phy *phy)
677+
static void tegra186_utmi_pad_power_on(struct phy *phy)
642678
{
643679
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
644680
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
@@ -656,6 +692,8 @@ static void tegra_phy_xusb_utmi_pad_power_on(struct phy *phy)
656692
return;
657693
}
658694

695+
dev_dbg(dev, "power on UTMI pad %u\n", index);
696+
659697
tegra186_utmi_bias_pad_power_on(padctl);
660698

661699
udelay(2);
@@ -669,7 +707,7 @@ static void tegra_phy_xusb_utmi_pad_power_on(struct phy *phy)
669707
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
670708
}
671709

672-
static void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy)
710+
static void tegra186_utmi_pad_power_down(struct phy *phy)
673711
{
674712
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
675713
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
@@ -679,6 +717,8 @@ static void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy)
679717
if (!phy)
680718
return;
681719

720+
dev_dbg(padctl->dev, "power down UTMI pad %u\n", index);
721+
682722
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
683723
value |= USB2_OTG_PD;
684724
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
@@ -849,15 +889,14 @@ static int tegra186_utmi_phy_power_on(struct phy *phy)
849889
value |= RPD_CTRL(priv->calib.rpd_ctrl);
850890
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
851891

852-
/* TODO: pad power saving */
853-
tegra_phy_xusb_utmi_pad_power_on(phy);
892+
tegra186_utmi_pad_power_on(phy);
893+
854894
return 0;
855895
}
856896

857897
static int tegra186_utmi_phy_power_off(struct phy *phy)
858898
{
859-
/* TODO: pad power saving */
860-
tegra_phy_xusb_utmi_pad_power_down(phy);
899+
tegra186_utmi_pad_power_down(phy);
861900

862901
return 0;
863902
}
@@ -1182,7 +1221,6 @@ tegra186_usb3_port_map(struct tegra_xusb_port *port)
11821221

11831222
static const struct tegra_xusb_port_ops tegra186_usb3_port_ops = {
11841223
.release = tegra_xusb_usb3_port_release,
1185-
.remove = tegra_xusb_usb3_port_remove,
11861224
.enable = tegra186_usb3_port_enable,
11871225
.disable = tegra186_usb3_port_disable,
11881226
.map = tegra186_usb3_port_map,
@@ -1486,6 +1524,8 @@ static const struct tegra_xusb_padctl_ops tegra186_xusb_padctl_ops = {
14861524
.suspend_noirq = tegra186_xusb_padctl_suspend_noirq,
14871525
.resume_noirq = tegra186_xusb_padctl_resume_noirq,
14881526
.vbus_override = tegra186_xusb_padctl_vbus_override,
1527+
.utmi_pad_power_on = tegra186_utmi_pad_power_on,
1528+
.utmi_pad_power_down = tegra186_utmi_pad_power_down,
14891529
};
14901530

14911531
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
@@ -1556,7 +1596,8 @@ const struct tegra_xusb_padctl_soc tegra186_xusb_padctl_soc = {
15561596
EXPORT_SYMBOL_GPL(tegra186_xusb_padctl_soc);
15571597
#endif
15581598

1559-
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
1599+
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
1600+
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
15601601
static const char * const tegra194_xusb_padctl_supply_names[] = {
15611602
"avdd-usb",
15621603
"vclamp-usb",
@@ -1612,8 +1653,31 @@ const struct tegra_xusb_padctl_soc tegra194_xusb_padctl_soc = {
16121653
.supply_names = tegra194_xusb_padctl_supply_names,
16131654
.num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names),
16141655
.supports_gen2 = true,
1656+
.poll_trk_completed = true,
16151657
};
16161658
EXPORT_SYMBOL_GPL(tegra194_xusb_padctl_soc);
1659+
1660+
const struct tegra_xusb_padctl_soc tegra234_xusb_padctl_soc = {
1661+
.num_pads = ARRAY_SIZE(tegra194_pads),
1662+
.pads = tegra194_pads,
1663+
.ports = {
1664+
.usb2 = {
1665+
.ops = &tegra186_usb2_port_ops,
1666+
.count = 4,
1667+
},
1668+
.usb3 = {
1669+
.ops = &tegra186_usb3_port_ops,
1670+
.count = 4,
1671+
},
1672+
},
1673+
.ops = &tegra186_xusb_padctl_ops,
1674+
.supply_names = tegra194_xusb_padctl_supply_names,
1675+
.num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names),
1676+
.supports_gen2 = true,
1677+
.poll_trk_completed = true,
1678+
.trk_hw_mode = true,
1679+
};
1680+
EXPORT_SYMBOL_GPL(tegra234_xusb_padctl_soc);
16171681
#endif
16181682

16191683
MODULE_AUTHOR("JC Kuo <jckuo@nvidia.com>");

drivers/phy/tegra/xusb-tegra210.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3078,7 +3078,6 @@ tegra210_usb3_port_map(struct tegra_xusb_port *port)
30783078

30793079
static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
30803080
.release = tegra_xusb_usb3_port_release,
3081-
.remove = tegra_xusb_usb3_port_remove,
30823081
.enable = tegra210_usb3_port_enable,
30833082
.disable = tegra210_usb3_port_disable,
30843083
.map = tegra210_usb3_port_map,

drivers/phy/tegra/xusb.c

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved.
3+
* Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved.
44
*/
55

66
#include <linux/delay.h>
@@ -71,6 +71,12 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = {
7171
.compatible = "nvidia,tegra194-xusb-padctl",
7272
.data = &tegra194_xusb_padctl_soc,
7373
},
74+
#endif
75+
#if defined(CONFIG_ARCH_TEGRA_234_SOC)
76+
{
77+
.compatible = "nvidia,tegra234-xusb-padctl",
78+
.data = &tegra234_xusb_padctl_soc,
79+
},
7480
#endif
7581
{ }
7682
};
@@ -656,6 +662,7 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
656662
struct usb_role_switch_desc role_sx_desc = {
657663
.fwnode = dev_fwnode(&port->dev),
658664
.set = tegra_xusb_role_sw_set,
665+
.allow_userspace_control = true,
659666
};
660667
int err = 0;
661668

@@ -711,6 +718,22 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
711718
return err;
712719
}
713720

721+
static void tegra_xusb_parse_usb_role_default_mode(struct tegra_xusb_port *port)
722+
{
723+
enum usb_role role = USB_ROLE_NONE;
724+
enum usb_dr_mode mode = usb_get_role_switch_default_mode(&port->dev);
725+
726+
if (mode == USB_DR_MODE_HOST)
727+
role = USB_ROLE_HOST;
728+
else if (mode == USB_DR_MODE_PERIPHERAL)
729+
role = USB_ROLE_DEVICE;
730+
731+
if (role != USB_ROLE_NONE) {
732+
usb_role_switch_set_role(port->usb_role_sw, role);
733+
dev_dbg(&port->dev, "usb role default mode is %s", modes[mode]);
734+
}
735+
}
736+
714737
static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
715738
{
716739
struct tegra_xusb_port *port = &usb2->base;
@@ -740,6 +763,7 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
740763
err = tegra_xusb_setup_usb_role_switch(port);
741764
if (err < 0)
742765
return err;
766+
tegra_xusb_parse_usb_role_default_mode(port);
743767
} else {
744768
dev_err(&port->dev, "usb-role-switch not found for %s mode",
745769
modes[usb2->mode]);
@@ -953,8 +977,7 @@ static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3)
953977
return -EINVAL;
954978
}
955979

956-
usb3->supply = regulator_get(&port->dev, "vbus");
957-
return PTR_ERR_OR_ZERO(usb3->supply);
980+
return 0;
958981
}
959982

960983
static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl,
@@ -1011,13 +1034,6 @@ void tegra_xusb_usb3_port_release(struct tegra_xusb_port *port)
10111034
kfree(usb3);
10121035
}
10131036

1014-
void tegra_xusb_usb3_port_remove(struct tegra_xusb_port *port)
1015-
{
1016-
struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
1017-
1018-
regulator_put(usb3->supply);
1019-
}
1020-
10211037
static void __tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl)
10221038
{
10231039
struct tegra_xusb_port *port, *tmp;
@@ -1458,6 +1474,38 @@ int tegra_phy_xusb_utmi_port_reset(struct phy *phy)
14581474
}
14591475
EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_port_reset);
14601476

1477+
void tegra_phy_xusb_utmi_pad_power_on(struct phy *phy)
1478+
{
1479+
struct tegra_xusb_lane *lane;
1480+
struct tegra_xusb_padctl *padctl;
1481+
1482+
if (!phy)
1483+
return;
1484+
1485+
lane = phy_get_drvdata(phy);
1486+
padctl = lane->pad->padctl;
1487+
1488+
if (padctl->soc->ops->utmi_pad_power_on)
1489+
padctl->soc->ops->utmi_pad_power_on(phy);
1490+
}
1491+
EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_pad_power_on);
1492+
1493+
void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy)
1494+
{
1495+
struct tegra_xusb_lane *lane;
1496+
struct tegra_xusb_padctl *padctl;
1497+
1498+
if (!phy)
1499+
return;
1500+
1501+
lane = phy_get_drvdata(phy);
1502+
padctl = lane->pad->padctl;
1503+
1504+
if (padctl->soc->ops->utmi_pad_power_down)
1505+
padctl->soc->ops->utmi_pad_power_down(phy);
1506+
}
1507+
EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_pad_power_down);
1508+
14611509
int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
14621510
unsigned int port)
14631511
{

0 commit comments

Comments
 (0)