.../bindings/thunderbolt/qcom,usb4-hr.yaml | 263 +++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 264 insertions(+)
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Several Qualcomm platforms feature an in-house Host Router IP block,
which enables USB4 and Thunderbolt 3 functionality. It implements the
common NHI interface, allowing for easier integration with existing
Thunderbolt driver implementations.
The Host Router features a microcontroller (with loadable firmware),
which takes care of detecting and acting upon plug events, initiating
high-speed link establishment or performing HW power management
operations.
Each instance is connected to a single USB3.x host, a PCIe RC and a
DisplayPort controller through a fitting Protocol Adapter, allowing
for the tunneling of the respective protocols between the USB4/TBT3
device and the on-SoC controller.
Describe the block, as present on the X1E family of SoCs, where it
implements the USB4v1 standard.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
Hello!
This is our stab at USB4/Thunderbolt dt-bindings.
This submission, as stated in the commit message, describes our USB4
Host Router block, which is roughly the same class of hardware that you
can find on add-in PCIe cards aimed at x86 machines.
This specific patch is NOT supposed to be merged, since the bindings
may still ever so slightly change, as we continue work on the driver
(i.e. it's still possible that we omitted some resource).
It is however published early to create grounds for a discussion.
This is the first bring-up of USB4/TBT3 on a DT platform, so this
binding is likely going to influence all subsequent submissions. I've
added various DT and TBT folks to the recipient list to make everyone
aware of any decisions we settle on.
Comments very welcome!
P.S.
The driver part (which has quite some dependencies) is not yet 100%
ready to share and will be published at a later date.
---
.../bindings/thunderbolt/qcom,usb4-hr.yaml | 263 +++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 264 insertions(+)
diff --git a/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml b/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1cf3d083c6129a492010a4b98fea0e8dec9746cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml
@@ -0,0 +1,263 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thunderbolt/qcom,usb4-hr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm USB4 Host Router
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+
+description:
+ The Qualcomm USB4 Host Router IP block implements the NHI standard
+ as described in the USB4 specification.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - qcom,x1e80100-usb4-hr # USB4v1
+ - const: qcom,usb4-hr
+
+ reg:
+ maxItems: 17
+
+ reg-names:
+ items:
+ - const: router
+ - const: router_config
+ - const: tmu_config
+ - const: port_group
+ - const: sideband
+ - const: uc_ram
+ - const: uc_per
+ - const: uc_mbox
+ - const: nhi
+ - const: cfg
+ - const: debug
+ - const: usbap_config
+ - const: pcieap_config
+ - const: dpap0_aux
+ - const: dpap0_config
+ - const: dpap1_aux
+ - const: dpap1_config
+
+ interrupts:
+ items:
+ - description: Combined event interrupt for all three rings
+ - description: OOB Firmware interrupt
+
+ interrupt-names:
+ items:
+ - const: ring
+ - const: fw
+
+ clocks:
+ maxItems: 10
+
+ clock-names:
+ items:
+ - const: sys
+ - const: tmu
+ - const: ahb
+ - const: axi
+ - const: master
+ - const: phy_rx0
+ - const: phy_rx1
+ - const: sb
+ - const: dp0
+ - const: dp1
+
+ resets:
+ maxItems: 13
+
+ reset-names:
+ items:
+ - const: core
+ - const: phy_nocsr
+ - const: sys
+ - const: rx0
+ - const: rx1
+ - const: usb_pipe
+ - const: pcie_pipe
+ - const: tmu
+ - const: sideband_iface
+ - const: hia_master
+ - const: ahb
+ - const: dp0
+ - const: dp1
+
+ power-domains:
+ maxItems: 1
+
+ required-opps:
+ maxItems: 1
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: usb4
+
+ iommus:
+ maxItems: 1
+
+ interconnects:
+ maxItems: 2
+
+ interconnect-names:
+ items:
+ - const: usb4-ddr
+ - const: apps-usb4
+
+ mode-switch: true
+
+ wakeup-source: true
+
+allOf:
+ - $ref: /schemas/usb/usb-switch.yaml#
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+ - phys
+ - phy-names
+ - iommus
+ - interconnects
+ - interconnect-names
+ - mode-switch
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,x1e80100-gcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ usb4_router0: usb4-host-router@15600000 {
+ compatible = "qcom,x1e80100-usb4-hr",
+ "qcom,usb4-hr";
+ reg = <0x0 0x15600000 0x0 0x8000>,
+ <0x0 0x15608000 0x0 0x70>,
+ <0x0 0x15608070 0x0 0x500>,
+ <0x0 0x1560d000 0x0 0x1000>,
+ <0x0 0x15612000 0x0 0x1000>,
+ <0x0 0x15613000 0x0 0xe000>,
+ <0x0 0x15621000 0x0 0x2000>,
+ <0x0 0x15623000 0x0 0x2000>,
+ <0x0 0x1563f000 0x0 0x40000>,
+ <0x0 0x1567f000 0x0 0x1000>,
+ <0x0 0x15680000 0x0 0x1000>,
+ <0x0 0x15681000 0x0 0x1000>,
+ <0x0 0x15682000 0x0 0x1000>,
+ <0x0 0x15683000 0x0 0x1000>,
+ <0x0 0x15685000 0x0 0x1000>,
+ <0x0 0x15686000 0x0 0x1000>,
+ <0x0 0x15688000 0x0 0x1000>;
+ reg-names = "router",
+ "router_config",
+ "tmu_config",
+ "port_group",
+ "sideband",
+ "uc_ram",
+ "uc_per",
+ "uc_mbox",
+ "nhi",
+ "cfg",
+ "debug",
+ "usbap_config",
+ "pcieap_config",
+ "dpap0_aux",
+ "dpap0_config",
+ "dpap1_aux",
+ "dpap1_config";
+
+ interrupts = <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ring",
+ "fw";
+
+ clocks = <&gcc_usb4_0_sys_clk>,
+ <&gcc_usb4_0_tmu_clk>,
+ <&gcc_usb4_0_cfg_ahb_clk>,
+ <&gcc_aggre_usb4_0_axi_clk>,
+ <&gcc_usb4_0_master_clk>,
+ <&gcc_usb4_0_phy_rx0_clk>,
+ <&gcc_usb4_0_phy_rx1_clk>,
+ <&gcc_usb4_0_sb_if_clk>,
+ <&gcc_usb4_0_dp0_clk>,
+ <&gcc_usb4_0_dp1_clk>;
+ clock-names = "sys",
+ "tmu",
+ "ahb",
+ "axi",
+ "master",
+ "phy_rx0",
+ "phy_rx1",
+ "sb",
+ "dp0",
+ "dp1";
+
+ resets = <&gcc_usb4_0_bcr>,
+ <&gcc_usb4phy_phy_prim_bcr>,
+ <&gcc_usb4_0_misc_usb4_sys_bcr>,
+ <&gcc_usb4_0_misc_rx_clk_0_bcr>,
+ <&gcc_usb4_0_misc_rx_clk_1_bcr>,
+ <&gcc_usb4_0_misc_usb_pipe_bcr>,
+ <&gcc_usb4_0_misc_pcie_pipe_bcr>,
+ <&gcc_usb4_0_misc_tmu_bcr>,
+ <&gcc_usb4_0_misc_sb_if_bcr>,
+ <&gcc_usb4_0_misc_hia_mstr_bcr>,
+ <&gcc_usb4_0_misc_ahb_bcr>,
+ <&gcc_usb4_0_misc_dp0_max_pclk_bcr>,
+ <&gcc_usb4_0_misc_dp1_max_pclk_bcr>;
+ reset-names = "core",
+ "phy_nocsr",
+ "sys",
+ "rx0",
+ "rx1",
+ "usb_pipe",
+ "pcie_pipe",
+ "tmu",
+ "sideband_iface",
+ "hia_master",
+ "ahb",
+ "dp0",
+ "dp1";
+
+ power-domains = <&gcc GCC_USB4_0_GDSC>;
+
+ phys = <&usb4_phy>;
+ phy-names = "usb4";
+
+ iommus = <&apps_smmu 0x1440 0x0>;
+
+ interconnects = <&icc0 &icc1>,
+ <&icc2 &icc3>;
+ interconnect-names = "usb4-ddr",
+ "apps-usb4";
+
+ mode-switch;
+
+ port {
+ usb4_0_mode_in: endpoint {
+ };
+ };
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 9da37c8dee69de9421d4f70906b4e623a442d171..b607f0a66f953fb1ea72e3405820288850004dfe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25428,6 +25428,7 @@ L: linux-usb@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
F: Documentation/admin-guide/thunderbolt.rst
+F: Documentation/devicetree/bindings/thunderbolt/
F: drivers/thunderbolt/
F: include/linux/thunderbolt.h
---
base-commit: 05af764719214d6568adb55c8749dec295228da8
change-id: 20250916-topic-qcom_usb4_bindings-3e83e2209e1e
Best regards,
--
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Hi Konrad, On Tue, Sep 16, 2025 at 10:06:01PM +0200, Konrad Dybcio wrote: > From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > > Several Qualcomm platforms feature an in-house Host Router IP block, > which enables USB4 and Thunderbolt 3 functionality. It implements the > common NHI interface, allowing for easier integration with existing > Thunderbolt driver implementations. > > The Host Router features a microcontroller (with loadable firmware), > which takes care of detecting and acting upon plug events, initiating > high-speed link establishment or performing HW power management > operations. > > Each instance is connected to a single USB3.x host, a PCIe RC and a > DisplayPort controller through a fitting Protocol Adapter, allowing > for the tunneling of the respective protocols between the USB4/TBT3 > device and the on-SoC controller. > > Describe the block, as present on the X1E family of SoCs, where it > implements the USB4v1 standard. This is nice! > Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > --- > Hello! > > This is our stab at USB4/Thunderbolt dt-bindings. > > This submission, as stated in the commit message, describes our USB4 > Host Router block, which is roughly the same class of hardware that you > can find on add-in PCIe cards aimed at x86 machines. > > This specific patch is NOT supposed to be merged, since the bindings > may still ever so slightly change, as we continue work on the driver > (i.e. it's still possible that we omitted some resource). > > It is however published early to create grounds for a discussion. > This is the first bring-up of USB4/TBT3 on a DT platform, so this > binding is likely going to influence all subsequent submissions. I've > added various DT and TBT folks to the recipient list to make everyone > aware of any decisions we settle on. > > Comments very welcome! > > P.S. > The driver part (which has quite some dependencies) is not yet 100% > ready to share and will be published at a later date. Okay, I think it is beter to submit the bindings with the driver changes so that we can see the big picture. > --- > .../bindings/thunderbolt/qcom,usb4-hr.yaml | 263 +++++++++++++++++++++ > MAINTAINERS | 1 + > 2 files changed, 264 insertions(+) > > diff --git a/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml b/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml > new file mode 100644 > index 0000000000000000000000000000000000000000..1cf3d083c6129a492010a4b98fea0e8dec9746cf > --- /dev/null > +++ b/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml > @@ -0,0 +1,263 @@ > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/thunderbolt/qcom,usb4-hr.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Qualcomm USB4 Host Router > + > +maintainers: > + - Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > + > +description: > + The Qualcomm USB4 Host Router IP block implements the NHI standard > + as described in the USB4 specification. > + > +properties: > + compatible: > + items: > + - enum: > + - qcom,x1e80100-usb4-hr # USB4v1 > + - const: qcom,usb4-hr > + > + reg: > + maxItems: 17 > + > + reg-names: > + items: > + - const: router > + - const: router_config > + - const: tmu_config > + - const: port_group > + - const: sideband > + - const: uc_ram > + - const: uc_per > + - const: uc_mbox > + - const: nhi > + - const: cfg > + - const: debug > + - const: usbap_config > + - const: pcieap_config > + - const: dpap0_aux > + - const: dpap0_config > + - const: dpap1_aux > + - const: dpap1_config Are these the specific to the host controller? I mean route_config sounds pretty much like Router Config space and that is available through the USB4 fabric so not sure why this is listed? Also this does not list the standard Host Interface registers, is that on purpose? > + > + interrupts: > + items: > + - description: Combined event interrupt for all three rings > + - description: OOB Firmware interrupt No MSI? If not then at least I suggest to support it in the DT description. > + > + interrupt-names: > + items: > + - const: ring > + - const: fw > + > + clocks: > + maxItems: 10 > + > + clock-names: > + items: > + - const: sys > + - const: tmu > + - const: ahb > + - const: axi > + - const: master > + - const: phy_rx0 > + - const: phy_rx1 > + - const: sb > + - const: dp0 > + - const: dp1 > + > + resets: > + maxItems: 13 > + > + reset-names: > + items: > + - const: core > + - const: phy_nocsr > + - const: sys > + - const: rx0 > + - const: rx1 > + - const: usb_pipe > + - const: pcie_pipe > + - const: tmu > + - const: sideband_iface > + - const: hia_master > + - const: ahb > + - const: dp0 > + - const: dp1 > + > + power-domains: > + maxItems: 1 > + > + required-opps: > + maxItems: 1 > + > + phys: > + maxItems: 1 > + > + phy-names: > + const: usb4 > + > + iommus: > + maxItems: 1 > + > + interconnects: > + maxItems: 2 > + > + interconnect-names: > + items: > + - const: usb4-ddr > + - const: apps-usb4 > + > + mode-switch: true > + > + wakeup-source: true What about the "power contract"? Are you using the existing we have for ACPI: https://learn.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#map-native-protocols-pcie-displayport-tunneled-through-usb4-to-usb4-host-routers It was designed DT in mind but I don't think we have DT bindings for it. This is needed to make sure the driver (Connection Manager) creates the tunnels before the native protocol stacks get enumerated (e.g during power transitions). > + > +allOf: > + - $ref: /schemas/usb/usb-switch.yaml# > + > +required: > + - compatible > + - reg > + - reg-names > + - interrupts > + - interrupt-names > + - clocks > + - clock-names > + - resets > + - reset-names > + - power-domains > + - phys > + - phy-names > + - iommus > + - interconnects > + - interconnect-names > + - mode-switch > + - port > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/interrupt-controller/irq.h> > + > + soc { > + #address-cells = <2>; > + #size-cells = <2>; > + > + usb4_router0: usb4-host-router@15600000 { > + compatible = "qcom,x1e80100-usb4-hr", > + "qcom,usb4-hr"; > + reg = <0x0 0x15600000 0x0 0x8000>, > + <0x0 0x15608000 0x0 0x70>, > + <0x0 0x15608070 0x0 0x500>, > + <0x0 0x1560d000 0x0 0x1000>, > + <0x0 0x15612000 0x0 0x1000>, > + <0x0 0x15613000 0x0 0xe000>, > + <0x0 0x15621000 0x0 0x2000>, > + <0x0 0x15623000 0x0 0x2000>, > + <0x0 0x1563f000 0x0 0x40000>, > + <0x0 0x1567f000 0x0 0x1000>, > + <0x0 0x15680000 0x0 0x1000>, > + <0x0 0x15681000 0x0 0x1000>, > + <0x0 0x15682000 0x0 0x1000>, > + <0x0 0x15683000 0x0 0x1000>, > + <0x0 0x15685000 0x0 0x1000>, > + <0x0 0x15686000 0x0 0x1000>, > + <0x0 0x15688000 0x0 0x1000>; > + reg-names = "router", > + "router_config", > + "tmu_config", > + "port_group", > + "sideband", > + "uc_ram", > + "uc_per", > + "uc_mbox", > + "nhi", > + "cfg", > + "debug", > + "usbap_config", > + "pcieap_config", > + "dpap0_aux", > + "dpap0_config", > + "dpap1_aux", > + "dpap1_config"; > + > + interrupts = <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, > + <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>; > + interrupt-names = "ring", > + "fw"; > + > + clocks = <&gcc_usb4_0_sys_clk>, > + <&gcc_usb4_0_tmu_clk>, > + <&gcc_usb4_0_cfg_ahb_clk>, > + <&gcc_aggre_usb4_0_axi_clk>, > + <&gcc_usb4_0_master_clk>, > + <&gcc_usb4_0_phy_rx0_clk>, > + <&gcc_usb4_0_phy_rx1_clk>, > + <&gcc_usb4_0_sb_if_clk>, > + <&gcc_usb4_0_dp0_clk>, > + <&gcc_usb4_0_dp1_clk>; > + clock-names = "sys", > + "tmu", > + "ahb", > + "axi", > + "master", > + "phy_rx0", > + "phy_rx1", > + "sb", > + "dp0", > + "dp1"; > + > + resets = <&gcc_usb4_0_bcr>, > + <&gcc_usb4phy_phy_prim_bcr>, > + <&gcc_usb4_0_misc_usb4_sys_bcr>, > + <&gcc_usb4_0_misc_rx_clk_0_bcr>, > + <&gcc_usb4_0_misc_rx_clk_1_bcr>, > + <&gcc_usb4_0_misc_usb_pipe_bcr>, > + <&gcc_usb4_0_misc_pcie_pipe_bcr>, > + <&gcc_usb4_0_misc_tmu_bcr>, > + <&gcc_usb4_0_misc_sb_if_bcr>, > + <&gcc_usb4_0_misc_hia_mstr_bcr>, > + <&gcc_usb4_0_misc_ahb_bcr>, > + <&gcc_usb4_0_misc_dp0_max_pclk_bcr>, > + <&gcc_usb4_0_misc_dp1_max_pclk_bcr>; > + reset-names = "core", > + "phy_nocsr", > + "sys", > + "rx0", > + "rx1", > + "usb_pipe", > + "pcie_pipe", > + "tmu", > + "sideband_iface", > + "hia_master", > + "ahb", > + "dp0", > + "dp1"; > + > + power-domains = <&gcc GCC_USB4_0_GDSC>; > + > + phys = <&usb4_phy>; > + phy-names = "usb4"; > + > + iommus = <&apps_smmu 0x1440 0x0>; > + > + interconnects = <&icc0 &icc1>, > + <&icc2 &icc3>; > + interconnect-names = "usb4-ddr", > + "apps-usb4"; > + > + mode-switch; > + > + port { > + usb4_0_mode_in: endpoint { > + }; This describes the Downstream Facing Port (e.g USB4 port), right? We have something similar used in Chromebooks so it would be good if we can make the bindings close to each other if possible. This allows binding firmware description to retimers (and also to "fixed/embedded" device routers as recent changes to the USB4 spec makes possible). See drivers/thunderbolt/acpi.c::tb_acpi_find_companion(). > + }; > + }; > + }; > +... > diff --git a/MAINTAINERS b/MAINTAINERS > index 9da37c8dee69de9421d4f70906b4e623a442d171..b607f0a66f953fb1ea72e3405820288850004dfe 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -25428,6 +25428,7 @@ L: linux-usb@vger.kernel.org > S: Maintained > T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git > F: Documentation/admin-guide/thunderbolt.rst > +F: Documentation/devicetree/bindings/thunderbolt/ > F: drivers/thunderbolt/ > F: include/linux/thunderbolt.h > > > --- > base-commit: 05af764719214d6568adb55c8749dec295228da8 > change-id: 20250916-topic-qcom_usb4_bindings-3e83e2209e1e > > Best regards, > -- > Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
On 9/17/25 8:12 AM, Mika Westerberg wrote: > Hi Konrad, > > On Tue, Sep 16, 2025 at 10:06:01PM +0200, Konrad Dybcio wrote: >> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> [...] >> P.S. >> The driver part (which has quite some dependencies) is not yet 100% >> ready to share and will be published at a later date. > > Okay, I think it is beter to submit the bindings with the driver changes so > that we can see the big picture. We're not going to do that just yet, but I'll give you the gist of it (partially also responding to Dmitry's other reply to this email): - The current thunderbolt implementation is almost entirely reused - Our HR is MMIO-mapped and always present (i.e. it's not a PCIe device). Since the NHI code already uses I/O accessors, we simply ioremap() the NHI region and feed the existing code the __iomem ptr (really cool) - Because it's not a PCIe device, all the places where the code assumes it can freehand dereference nhi->pdev are altered to instead consume a struct device *, i.e.: diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index 75247486616b..d05f8d6896e7 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -493,22 +493,37 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) * MSI-X is used. * @hop_count: Number of rings (end point hops) supported by NHI. * @quirks: NHI specific quirks if any + * @is_pci: Whether the NHI is a PCI device */ struct tb_nhi { spinlock_t lock; - struct pci_dev *pdev; + struct device *dev; const struct tb_nhi_ops *ops; void __iomem *iobase; struct tb_ring **tx_rings; struct tb_ring **rx_rings; - struct ida msix_ida; bool going_away; bool iommu_dma_protection; struct work_struct interrupt_work; u32 hop_count; unsigned long quirks; + bool is_pcie; }; +struct tb_nhi_pci { + struct pci_dev *pdev; + struct ida msix_ida; + struct tb_nhi nhi; +}; + +static inline struct tb_nhi_pci *nhi_to_pci(struct tb_nhi *nhi) +{ + if (WARN_ON(!nhi->is_pcie)) + return NULL; + + return container_of(nhi, struct tb_nhi_pci, nhi); +} I suppose I can probably get this decoupling sent in advance of the rest.. It's quite delicate so I'm hoping I won't cause any random nullptrs for you - Additional steps are necessary to take the hardware out of reset, set some magic values here and there, load the firmware (i.e. memcpy_toio()) wake up the MCU and perform Type-C magic (more on that below), all of which is handled in a new qcom_usb4.c, which does that and ends its probe function with a nhi_probe_common(). PM of the hardware and its providers also takes place in Linux, just like with any other IP block on embedded systems - Because the Type-C pipeline varies wildly across Qualcomm SoCs and even devices using the same SoC, we need to register a typec_mux to receive generic (alt)mode notifications. The is more or less: pmic_glink_altmode/ucsi (altmode notification provider) |-> QMPPHY (Qualcomm proprietary USB4/TBT3/USB3/DP mode switchable PHY) |-> (optionally) Onboard switch (e.g. FSA4480) |-> (optionally) Onboard retimer (e.g. Parade PS883x) |-> USB4 HR (pinging the MCU with some mode/cable info) The actual entry logic (sanity checking, magic VDMs, SOP/'/'' comms) happen on a remote processor - Audio DSP (yes) in the case of X1E and the OS is graciously presented with a trimmed-down notification that the altmode has been entered and it better cooperate [...] >> + reg-names: >> + items: >> + - const: router >> + - const: router_config >> + - const: tmu_config >> + - const: port_group >> + - const: sideband >> + - const: uc_ram >> + - const: uc_per >> + - const: uc_mbox >> + - const: nhi >> + - const: cfg >> + - const: debug >> + - const: usbap_config >> + - const: pcieap_config >> + - const: dpap0_aux >> + - const: dpap0_config >> + - const: dpap1_aux >> + - const: dpap1_config > > Are these the specific to the host controller? I mean route_config sounds > pretty much like Router Config space and that is available through the USB4 > fabric so not sure why this is listed? > > Also this does not list the standard Host Interface registers, is that on > purpose? The 'nhi' region contains the entire spec-standardized set of registers, everything else is qc-specific. The host router has internal connections to the native protocol controllers, so the XXXap_config regions include some tunables related to that. The uc_ regions relate to the block's MCU. router/router_config refer to top-level tunables or control/state registers. tmu_config is the same, for the internal timing management unit. debug/cfg are self-explanatory Most of those will be left unused, but the binding has to be forward looking, in case some sort of a software workaround is required down the line > >> + >> + interrupts: >> + items: >> + - description: Combined event interrupt for all three rings >> + - description: OOB Firmware interrupt > > No MSI? If not then at least I suggest to support it in the DT description. No, it seems like across the SoC we only have MSIs on the PCIe RCs Because I don't know what a valid MSI setup would look like, I'd like to defer adding that description to when a platform with them pops up [...] >> + wakeup-source: true > > What about the "power contract"? Are you using the existing we have for > ACPI: > > https://learn.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#map-native-protocols-pcie-displayport-tunneled-through-usb4-to-usb4-host-routers > > It was designed DT in mind but I don't think we have DT bindings for it. > This is needed to make sure the driver (Connection Manager) creates the > tunnels before the native protocol stacks get enumerated (e.g during power > transitions). I added a custom entry to drivers/of/property.c, matching that name. Seems to work fine (tm) so far, but then we haven't yet tested sus/res much.. Just to make sure - are we expected to ensure that the NHI device is resumed before any protocol controller drivers (at runtime), or do the latter have to *probe* only after they're necessary? I firmly believe the former, but doesn't hurt to ask.. [...] >> + port { >> + usb4_0_mode_in: endpoint { >> + }; > > This describes the Downstream Facing Port (e.g USB4 port), right? We have > something similar used in Chromebooks so it would be good if we can make > the bindings close to each other if possible. This allows binding firmware > description to retimers (and also to "fixed/embedded" device routers as > recent changes to the USB4 spec makes possible). > > See drivers/thunderbolt/acpi.c::tb_acpi_find_companion(). Yes, this binding assumes the Host Router has precisely 1 DFP (Linux Type-C infra isn't ready for anything more, at least not on the DT side to my knowledge) and this port (which isn't necessarily the same as a connector, i.e. a physical receptacle in DT speak, it simply refers to an abstract data connection between two devices) Notably, I don't think we currently describe the USB4 port (as in, the usb4_port.c meaning of it) at all, but for on-SoC HRs we know all about them, so perhaps a subnode description could make sense. This way we could also point them to the compatible = "usb-c-connector" node Konrad
Hi, On Wed, Sep 17, 2025 at 08:36:19PM +0200, Konrad Dybcio wrote: > On 9/17/25 8:12 AM, Mika Westerberg wrote: > > Hi Konrad, > > > > On Tue, Sep 16, 2025 at 10:06:01PM +0200, Konrad Dybcio wrote: > >> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > > [...] > > >> P.S. > >> The driver part (which has quite some dependencies) is not yet 100% > >> ready to share and will be published at a later date. > > > > Okay, I think it is beter to submit the bindings with the driver changes so > > that we can see the big picture. > > We're not going to do that just yet, but I'll give you the gist of it > (partially also responding to Dmitry's other reply to this email): Fair enough. > - The current thunderbolt implementation is almost entirely reused > > - Our HR is MMIO-mapped and always present (i.e. it's not a PCIe device). > Since the NHI code already uses I/O accessors, we simply ioremap() the > NHI region and feed the existing code the __iomem ptr (really cool) > > - Because it's not a PCIe device, all the places where the code assumes > it can freehand dereference nhi->pdev are altered to instead consume > a struct device *, i.e.: > > diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h > index 75247486616b..d05f8d6896e7 100644 > --- a/include/linux/thunderbolt.h > +++ b/include/linux/thunderbolt.h > @@ -493,22 +493,37 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) > * MSI-X is used. > * @hop_count: Number of rings (end point hops) supported by NHI. > * @quirks: NHI specific quirks if any > + * @is_pci: Whether the NHI is a PCI device > */ > struct tb_nhi { > spinlock_t lock; > - struct pci_dev *pdev; > + struct device *dev; > const struct tb_nhi_ops *ops; > void __iomem *iobase; > struct tb_ring **tx_rings; > struct tb_ring **rx_rings; > - struct ida msix_ida; > bool going_away; > bool iommu_dma_protection; > struct work_struct interrupt_work; > u32 hop_count; > unsigned long quirks; > + bool is_pcie; > }; > > +struct tb_nhi_pci { > + struct pci_dev *pdev; > + struct ida msix_ida; > + struct tb_nhi nhi; > +}; > + > +static inline struct tb_nhi_pci *nhi_to_pci(struct tb_nhi *nhi) > +{ > + if (WARN_ON(!nhi->is_pcie)) > + return NULL; > + > + return container_of(nhi, struct tb_nhi_pci, nhi); > +} > > I suppose I can probably get this decoupling sent in advance of the rest.. > It's quite delicate so I'm hoping I won't cause any random nullptrs for you Instead of the above is_pcie thing, can you split it so that the PCI parts live in pci.c and the "platform" parts live in platform.c (or perhaps this is fauxbus now). Then the core part of the NHI code (nhi.c) just works regardless of how the controller is wired to the SoC. There are plenty of examples in the kernel how to do this. > - Additional steps are necessary to take the hardware out of reset, set > some magic values here and there, load the firmware (i.e. memcpy_toio()) > wake up the MCU and perform Type-C magic (more on that below), all of > which is handled in a new qcom_usb4.c, which does that and ends its probe > function with a nhi_probe_common(). PM of the hardware and its providers > also takes place in Linux, just like with any other IP block on embedded > systems Call it qcom.c. But please try to move all the non-PCI generic parts into platform.c and then only the Qualcomm specific things live in qcom.c. Idea is that we can re-use all that when for example Apple Silicon support is added and so on. > - Because the Type-C pipeline varies wildly across Qualcomm SoCs and even > devices using the same SoC, we need to register a typec_mux to receive > generic (alt)mode notifications. The is more or less: > > pmic_glink_altmode/ucsi (altmode notification provider) > |-> QMPPHY (Qualcomm proprietary USB4/TBT3/USB3/DP mode switchable PHY) > |-> (optionally) Onboard switch (e.g. FSA4480) > |-> (optionally) Onboard retimer (e.g. Parade PS883x) > |-> USB4 HR (pinging the MCU with some mode/cable info) > > The actual entry logic (sanity checking, magic VDMs, SOP/'/'' comms) > happen on a remote processor - Audio DSP (yes) in the case of X1E and > the OS is graciously presented with a trimmed-down notification that > the altmode has been entered and it better cooperate Okay. > [...] > > >> + reg-names: > >> + items: > >> + - const: router > >> + - const: router_config > >> + - const: tmu_config > >> + - const: port_group > >> + - const: sideband > >> + - const: uc_ram > >> + - const: uc_per > >> + - const: uc_mbox > >> + - const: nhi > >> + - const: cfg > >> + - const: debug > >> + - const: usbap_config > >> + - const: pcieap_config > >> + - const: dpap0_aux > >> + - const: dpap0_config > >> + - const: dpap1_aux > >> + - const: dpap1_config > > > > Are these the specific to the host controller? I mean route_config sounds > > pretty much like Router Config space and that is available through the USB4 > > fabric so not sure why this is listed? > > > > Also this does not list the standard Host Interface registers, is that on > > purpose? > > The 'nhi' region contains the entire spec-standardized set of registers, > everything else is qc-specific. The host router has internal connections > to the native protocol controllers, so the XXXap_config regions include some > tunables related to that. > > The uc_ regions relate to the block's MCU. > > router/router_config refer to top-level tunables or control/state registers. > > tmu_config is the same, for the internal timing management unit. > > debug/cfg are self-explanatory > > Most of those will be left unused, but the binding has to be forward > looking, in case some sort of a software workaround is required down > the line Got it, thanks for the explanation. > >> + > >> + interrupts: > >> + items: > >> + - description: Combined event interrupt for all three rings > >> + - description: OOB Firmware interrupt > > > > No MSI? If not then at least I suggest to support it in the DT description. > > No, it seems like across the SoC we only have MSIs on the PCIe RCs > > Because I don't know what a valid MSI setup would look like, I'd like > to defer adding that description to when a platform with them pops up I it hard to change these DT bindings later on? If yes then I would definitely think forward and make this support MSI from the get-go. > [...] > > >> + wakeup-source: true > > > > What about the "power contract"? Are you using the existing we have for > > ACPI: > > > > https://learn.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#map-native-protocols-pcie-displayport-tunneled-through-usb4-to-usb4-host-routers > > > > It was designed DT in mind but I don't think we have DT bindings for it. > > This is needed to make sure the driver (Connection Manager) creates the > > tunnels before the native protocol stacks get enumerated (e.g during power > > transitions). > > I added a custom entry to drivers/of/property.c, matching that name. > Seems to work fine (tm) so far, but then we haven't yet tested sus/res > much.. > > Just to make sure - are we expected to ensure that the NHI device is > resumed before any protocol controller drivers (at runtime), or do the > latter have to *probe* only after they're necessary? I firmly believe > the former, but doesn't hurt to ask.. The former. The TB driver needs to setup tunnels before native protocol stacks and their drivers (e.g PCIe and the like) resume. We have the device_link from the native "port" / device to the NHI that deals with it but it expects the property to be there. > [...] > >> + port { > >> + usb4_0_mode_in: endpoint { > >> + }; > > > > This describes the Downstream Facing Port (e.g USB4 port), right? We have > > something similar used in Chromebooks so it would be good if we can make > > the bindings close to each other if possible. This allows binding firmware > > description to retimers (and also to "fixed/embedded" device routers as > > recent changes to the USB4 spec makes possible). > > > > See drivers/thunderbolt/acpi.c::tb_acpi_find_companion(). > > Yes, this binding assumes the Host Router has precisely 1 DFP (Linux > Type-C infra isn't ready for anything more, at least not on the DT side > to my knowledge) and this port (which isn't necessarily the same as a > connector, i.e. a physical receptacle in DT speak, it simply refers to > an abstract data connection between two devices) Okay I'm not too familiar with the current DT bindings. > Notably, I don't think we currently describe the USB4 port (as in, the > usb4_port.c meaning of it) at all, but for on-SoC HRs we know all about > them, so perhaps a subnode description could make sense. This way we > could also point them to the compatible = "usb-c-connector" node It should be something (eventually at least :-)) that allows us to describe the USB4 ports and on-board retimers (to make it possible to upgrade firmwares on those even if there is no link). But also if there is "embedded link" device router.
On 9/18/25 7:12 AM, Mika Westerberg wrote: > Hi, > > On Wed, Sep 17, 2025 at 08:36:19PM +0200, Konrad Dybcio wrote: >> On 9/17/25 8:12 AM, Mika Westerberg wrote: >>> Hi Konrad, >>> >>> On Tue, Sep 16, 2025 at 10:06:01PM +0200, Konrad Dybcio wrote: >>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> [...] >> struct tb_nhi { >> spinlock_t lock; >> - struct pci_dev *pdev; >> + struct device *dev; >> const struct tb_nhi_ops *ops; >> void __iomem *iobase; >> struct tb_ring **tx_rings; >> struct tb_ring **rx_rings; >> - struct ida msix_ida; >> bool going_away; >> bool iommu_dma_protection; >> struct work_struct interrupt_work; >> u32 hop_count; >> unsigned long quirks; >> + bool is_pcie; >> }; >> >> +struct tb_nhi_pci { >> + struct pci_dev *pdev; >> + struct ida msix_ida; >> + struct tb_nhi nhi; >> +}; >> + >> +static inline struct tb_nhi_pci *nhi_to_pci(struct tb_nhi *nhi) >> +{ >> + if (WARN_ON(!nhi->is_pcie)) >> + return NULL; >> + >> + return container_of(nhi, struct tb_nhi_pci, nhi); >> +} >> >> I suppose I can probably get this decoupling sent in advance of the rest.. >> It's quite delicate so I'm hoping I won't cause any random nullptrs for you > > Instead of the above is_pcie thing, can you split it so that the PCI parts > live in pci.c and the "platform" parts live in platform.c (or perhaps this > is fauxbus now). Then the core part of the NHI code (nhi.c) just works > regardless of how the controller is wired to the SoC. I'll simply try to get this decoupling sent soon, so we can debate over material changes > There are plenty of examples in the kernel how to do this. > >> - Additional steps are necessary to take the hardware out of reset, set >> some magic values here and there, load the firmware (i.e. memcpy_toio()) >> wake up the MCU and perform Type-C magic (more on that below), all of >> which is handled in a new qcom_usb4.c, which does that and ends its probe >> function with a nhi_probe_common(). PM of the hardware and its providers >> also takes place in Linux, just like with any other IP block on embedded >> systems > > Call it qcom.c. But please try to move all the non-PCI generic parts into > platform.c and then only the Qualcomm specific things live in qcom.c. Idea > is that we can re-use all that when for example Apple Silicon support is > added and so on. That's the plan [...] >>>> + >>>> + interrupts: >>>> + items: >>>> + - description: Combined event interrupt for all three rings >>>> + - description: OOB Firmware interrupt >>> >>> No MSI? If not then at least I suggest to support it in the DT description. >> >> No, it seems like across the SoC we only have MSIs on the PCIe RCs >> >> Because I don't know what a valid MSI setup would look like, I'd like >> to defer adding that description to when a platform with them pops up > > I it hard to change these DT bindings later on? If yes then I would > definitely think forward and make this support MSI from the get-go. dt-bindings (attempt to) promise an ABI-like interface, so bindings for *a given IP block* ("dt-bindings describe the hardware") should not change, unless there's something critically wrong (e.g. "this could have never really worked"). Adding new properties is always OK, marking the new properties as 'required' is not (unless it falls into the aforementioned case). It's also totally OK to add MSI properties to e.g. Apple Host Router bindings specifically when they come around, as it's simply a different piece of hardware. It's also OK to create a usb4-host-router.yaml down the line, which will act as a common include and perform any maintenance/code churn, so long as it doesn't end up in the bindings for any specific hw block (e.g. this QC one) becoming more strict than they were on HEAD^. > >> [...] >> >>>> + wakeup-source: true >>> >>> What about the "power contract"? Are you using the existing we have for >>> ACPI: >>> >>> https://learn.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#map-native-protocols-pcie-displayport-tunneled-through-usb4-to-usb4-host-routers >>> >>> It was designed DT in mind but I don't think we have DT bindings for it. >>> This is needed to make sure the driver (Connection Manager) creates the >>> tunnels before the native protocol stacks get enumerated (e.g during power >>> transitions). >> >> I added a custom entry to drivers/of/property.c, matching that name. >> Seems to work fine (tm) so far, but then we haven't yet tested sus/res >> much.. >> >> Just to make sure - are we expected to ensure that the NHI device is >> resumed before any protocol controller drivers (at runtime), or do the >> latter have to *probe* only after they're necessary? I firmly believe >> the former, but doesn't hurt to ask.. > > The former. The TB driver needs to setup tunnels before native protocol > stacks and their drivers (e.g PCIe and the like) resume. We have the > device_link from the native "port" / device to the NHI that deals with it > but it expects the property to be there. OK then we're on the same page, good > >> [...] >>>> + port { >>>> + usb4_0_mode_in: endpoint { >>>> + }; >>> >>> This describes the Downstream Facing Port (e.g USB4 port), right? We have >>> something similar used in Chromebooks so it would be good if we can make >>> the bindings close to each other if possible. This allows binding firmware >>> description to retimers (and also to "fixed/embedded" device routers as >>> recent changes to the USB4 spec makes possible). >>> >>> See drivers/thunderbolt/acpi.c::tb_acpi_find_companion(). >> >> Yes, this binding assumes the Host Router has precisely 1 DFP (Linux >> Type-C infra isn't ready for anything more, at least not on the DT side >> to my knowledge) and this port (which isn't necessarily the same as a >> connector, i.e. a physical receptacle in DT speak, it simply refers to >> an abstract data connection between two devices) > > Okay I'm not too familiar with the current DT bindings. > >> Notably, I don't think we currently describe the USB4 port (as in, the >> usb4_port.c meaning of it) at all, but for on-SoC HRs we know all about >> them, so perhaps a subnode description could make sense. This way we >> could also point them to the compatible = "usb-c-connector" node > > It should be something (eventually at least :-)) that allows us to describe the > USB4 ports and on-board retimers (to make it possible to upgrade firmwares > on those even if there is no link). But also if there is "embedded link" > device router. FWIW on DT platforms, onboard retimers (such as the PS883x) are often described as children of the I2C bus (see e.g. "parade,ps8830" in: arch/arm64/boot/dts/qcom/x1-crd.dtsi), marked as 'retimer-switch', which then typec_retimer_xxx() APIs look for using of/fwnode_graph. Because they're not opaque, but rather self-contained platform devices, FW updates can/will happen without the tbt subsystem in the picture. That said, the retimer being TBT-compliant, still shows up in the topology: thunderbolt 1-0:2.1: new retimer found, vendor=0x1da0 device=0x8830 I think adding description of a usb4 port should be quite simple, I'll look into that. Konrad
Hi, On Thu, Sep 18, 2025 at 11:05:42AM +0200, Konrad Dybcio wrote: > > I it hard to change these DT bindings later on? If yes then I would > > definitely think forward and make this support MSI from the get-go. > > dt-bindings (attempt to) promise an ABI-like interface, so bindings > for *a given IP block* ("dt-bindings describe the hardware") should > not change, unless there's something critically wrong (e.g. "this > could have never really worked"). Then I think it is good to think few steps forward and make sure when Qualcomm adds MSI to their IP it can be easily desribed in the DT bindings. > Adding new properties is always OK, marking the new properties as > 'required' is not (unless it falls into the aforementioned case). > > It's also totally OK to add MSI properties to e.g. Apple Host Router > bindings specifically when they come around, as it's simply a different > piece of hardware. It's also OK to create a usb4-host-router.yaml down > the line, which will act as a common include and perform any > maintenance/code churn, so long as it doesn't end up in the bindings > for any specific hw block (e.g. this QC one) becoming more strict > than they were on HEAD^. Okay thanks for the explanation.
On 9/18/25 5:23 PM, Mika Westerberg wrote: > Hi, > > On Thu, Sep 18, 2025 at 11:05:42AM +0200, Konrad Dybcio wrote: >>> I it hard to change these DT bindings later on? If yes then I would >>> definitely think forward and make this support MSI from the get-go. >> >> dt-bindings (attempt to) promise an ABI-like interface, so bindings >> for *a given IP block* ("dt-bindings describe the hardware") should >> not change, unless there's something critically wrong (e.g. "this >> could have never really worked"). > > Then I think it is good to think few steps forward and make sure when > Qualcomm adds MSI to their IP it can be easily desribed in the DT bindings. Your reply makes me believe I glossed over an important detail.. If qcom,x1e80100-hr doesn't have MSIs, qcom,nextsoc-hr can add them without any issues too, just that the X1E80100 binding can't be altered, e.g. "binding" refers to the (compatible, allowed_props, required_props) tuple Konrad > >> Adding new properties is always OK, marking the new properties as >> 'required' is not (unless it falls into the aforementioned case). >> >> It's also totally OK to add MSI properties to e.g. Apple Host Router >> bindings specifically when they come around, as it's simply a different >> piece of hardware. It's also OK to create a usb4-host-router.yaml down >> the line, which will act as a common include and perform any >> maintenance/code churn, so long as it doesn't end up in the bindings >> for any specific hw block (e.g. this QC one) becoming more strict >> than they were on HEAD^. > > Okay thanks for the explanation.
On Thu, Sep 18, 2025 at 05:38:13PM +0200, Konrad Dybcio wrote: > On 9/18/25 5:23 PM, Mika Westerberg wrote: > > Hi, > > > > On Thu, Sep 18, 2025 at 11:05:42AM +0200, Konrad Dybcio wrote: > >>> I it hard to change these DT bindings later on? If yes then I would > >>> definitely think forward and make this support MSI from the get-go. > >> > >> dt-bindings (attempt to) promise an ABI-like interface, so bindings > >> for *a given IP block* ("dt-bindings describe the hardware") should > >> not change, unless there's something critically wrong (e.g. "this > >> could have never really worked"). > > > > Then I think it is good to think few steps forward and make sure when > > Qualcomm adds MSI to their IP it can be easily desribed in the DT bindings. > > Your reply makes me believe I glossed over an important detail.. > > If qcom,x1e80100-hr doesn't have MSIs, qcom,nextsoc-hr can add them > without any issues too, just that the X1E80100 binding can't be altered, > e.g. "binding" refers to the (compatible, allowed_props, required_props) > tuple OK then it is all good and allows extension in the future generations.
On Tue, Sep 16, 2025 at 10:06:01PM +0200, Konrad Dybcio wrote: > From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > > Several Qualcomm platforms feature an in-house Host Router IP block, > which enables USB4 and Thunderbolt 3 functionality. It implements the > common NHI interface, allowing for easier integration with existing > Thunderbolt driver implementations. > > The Host Router features a microcontroller (with loadable firmware), > which takes care of detecting and acting upon plug events, initiating > high-speed link establishment or performing HW power management > operations. > > Each instance is connected to a single USB3.x host, a PCIe RC and a > DisplayPort controller through a fitting Protocol Adapter, allowing > for the tunneling of the respective protocols between the USB4/TBT3 > device and the on-SoC controller. I'd really like to see a full example, how the overall picture looks like? The bindings describe a single port with a single endpoint. Where is it supposed to be connected to? Could you please provide an example of the overall system (including USB controller, DP controller, USB-C connector, etc.). I think one of the systems had muxes on the SBU lines, how are they supposed to be defined? Also, do we need to define the thunderbolt AltMode inside usb-connector.yaml? > > Describe the block, as present on the X1E family of SoCs, where it > implements the USB4v1 standard. > > Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > --- > Hello! > > This is our stab at USB4/Thunderbolt dt-bindings. > > This submission, as stated in the commit message, describes our USB4 > Host Router block, which is roughly the same class of hardware that you > can find on add-in PCIe cards aimed at x86 machines. > > This specific patch is NOT supposed to be merged, since the bindings > may still ever so slightly change, as we continue work on the driver > (i.e. it's still possible that we omitted some resource). > > It is however published early to create grounds for a discussion. > This is the first bring-up of USB4/TBT3 on a DT platform, so this > binding is likely going to influence all subsequent submissions. I've > added various DT and TBT folks to the recipient list to make everyone > aware of any decisions we settle on. > > Comments very welcome! > > P.S. > The driver part (which has quite some dependencies) is not yet 100% > ready to share and will be published at a later date. > --- > .../bindings/thunderbolt/qcom,usb4-hr.yaml | 263 +++++++++++++++++++++ > MAINTAINERS | 1 + > 2 files changed, 264 insertions(+) > > diff --git a/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml b/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml > new file mode 100644 > index 0000000000000000000000000000000000000000..1cf3d083c6129a492010a4b98fea0e8dec9746cf > --- /dev/null > +++ b/Documentation/devicetree/bindings/thunderbolt/qcom,usb4-hr.yaml > @@ -0,0 +1,263 @@ > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/thunderbolt/qcom,usb4-hr.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Qualcomm USB4 Host Router > + > +maintainers: > + - Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > + > +description: > + The Qualcomm USB4 Host Router IP block implements the NHI standard > + as described in the USB4 specification. > + > +properties: > + compatible: > + items: > + - enum: > + - qcom,x1e80100-usb4-hr # USB4v1 > + - const: qcom,usb4-hr > + > + reg: > + maxItems: 17 > + > + reg-names: > + items: > + - const: router > + - const: router_config > + - const: tmu_config > + - const: port_group > + - const: sideband > + - const: uc_ram > + - const: uc_per > + - const: uc_mbox > + - const: nhi > + - const: cfg > + - const: debug > + - const: usbap_config > + - const: pcieap_config > + - const: dpap0_aux > + - const: dpap0_config > + - const: dpap1_aux > + - const: dpap1_config > + > + interrupts: > + items: > + - description: Combined event interrupt for all three rings > + - description: OOB Firmware interrupt > + > + interrupt-names: > + items: > + - const: ring > + - const: fw > + > + clocks: > + maxItems: 10 > + > + clock-names: > + items: > + - const: sys > + - const: tmu > + - const: ahb > + - const: axi > + - const: master > + - const: phy_rx0 > + - const: phy_rx1 > + - const: sb > + - const: dp0 > + - const: dp1 > + > + resets: > + maxItems: 13 > + > + reset-names: > + items: > + - const: core > + - const: phy_nocsr > + - const: sys > + - const: rx0 > + - const: rx1 > + - const: usb_pipe > + - const: pcie_pipe > + - const: tmu > + - const: sideband_iface > + - const: hia_master > + - const: ahb > + - const: dp0 > + - const: dp1 > + > + power-domains: > + maxItems: 1 > + > + required-opps: > + maxItems: 1 > + > + phys: > + maxItems: 1 > + > + phy-names: > + const: usb4 > + > + iommus: > + maxItems: 1 > + > + interconnects: > + maxItems: 2 > + > + interconnect-names: > + items: > + - const: usb4-ddr > + - const: apps-usb4 > + > + mode-switch: true > + > + wakeup-source: true > + > +allOf: > + - $ref: /schemas/usb/usb-switch.yaml# I don't think this should be including usb-switch.yaml (pretty much like QMP PHY isn't a usb-switch). > + > +required: > + - compatible > + - reg > + - reg-names > + - interrupts > + - interrupt-names > + - clocks > + - clock-names > + - resets > + - reset-names > + - power-domains > + - phys > + - phy-names > + - iommus > + - interconnects > + - interconnect-names > + - mode-switch > + - port > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/interrupt-controller/irq.h> > + > + soc { > + #address-cells = <2>; > + #size-cells = <2>; > + > + usb4_router0: usb4-host-router@15600000 { > + compatible = "qcom,x1e80100-usb4-hr", > + "qcom,usb4-hr"; > + reg = <0x0 0x15600000 0x0 0x8000>, > + <0x0 0x15608000 0x0 0x70>, > + <0x0 0x15608070 0x0 0x500>, > + <0x0 0x1560d000 0x0 0x1000>, > + <0x0 0x15612000 0x0 0x1000>, > + <0x0 0x15613000 0x0 0xe000>, > + <0x0 0x15621000 0x0 0x2000>, > + <0x0 0x15623000 0x0 0x2000>, > + <0x0 0x1563f000 0x0 0x40000>, > + <0x0 0x1567f000 0x0 0x1000>, > + <0x0 0x15680000 0x0 0x1000>, > + <0x0 0x15681000 0x0 0x1000>, > + <0x0 0x15682000 0x0 0x1000>, > + <0x0 0x15683000 0x0 0x1000>, > + <0x0 0x15685000 0x0 0x1000>, > + <0x0 0x15686000 0x0 0x1000>, > + <0x0 0x15688000 0x0 0x1000>; > + reg-names = "router", > + "router_config", > + "tmu_config", > + "port_group", > + "sideband", > + "uc_ram", > + "uc_per", > + "uc_mbox", > + "nhi", > + "cfg", > + "debug", > + "usbap_config", > + "pcieap_config", > + "dpap0_aux", > + "dpap0_config", > + "dpap1_aux", > + "dpap1_config"; > + > + interrupts = <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, > + <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>; > + interrupt-names = "ring", > + "fw"; > + > + clocks = <&gcc_usb4_0_sys_clk>, > + <&gcc_usb4_0_tmu_clk>, > + <&gcc_usb4_0_cfg_ahb_clk>, > + <&gcc_aggre_usb4_0_axi_clk>, > + <&gcc_usb4_0_master_clk>, > + <&gcc_usb4_0_phy_rx0_clk>, > + <&gcc_usb4_0_phy_rx1_clk>, > + <&gcc_usb4_0_sb_if_clk>, > + <&gcc_usb4_0_dp0_clk>, > + <&gcc_usb4_0_dp1_clk>; > + clock-names = "sys", > + "tmu", > + "ahb", > + "axi", > + "master", > + "phy_rx0", > + "phy_rx1", > + "sb", > + "dp0", > + "dp1"; > + > + resets = <&gcc_usb4_0_bcr>, > + <&gcc_usb4phy_phy_prim_bcr>, > + <&gcc_usb4_0_misc_usb4_sys_bcr>, > + <&gcc_usb4_0_misc_rx_clk_0_bcr>, > + <&gcc_usb4_0_misc_rx_clk_1_bcr>, > + <&gcc_usb4_0_misc_usb_pipe_bcr>, > + <&gcc_usb4_0_misc_pcie_pipe_bcr>, > + <&gcc_usb4_0_misc_tmu_bcr>, > + <&gcc_usb4_0_misc_sb_if_bcr>, > + <&gcc_usb4_0_misc_hia_mstr_bcr>, > + <&gcc_usb4_0_misc_ahb_bcr>, > + <&gcc_usb4_0_misc_dp0_max_pclk_bcr>, > + <&gcc_usb4_0_misc_dp1_max_pclk_bcr>; > + reset-names = "core", > + "phy_nocsr", > + "sys", > + "rx0", > + "rx1", > + "usb_pipe", > + "pcie_pipe", > + "tmu", > + "sideband_iface", > + "hia_master", > + "ahb", > + "dp0", > + "dp1"; > + > + power-domains = <&gcc GCC_USB4_0_GDSC>; > + > + phys = <&usb4_phy>; > + phy-names = "usb4"; > + > + iommus = <&apps_smmu 0x1440 0x0>; > + > + interconnects = <&icc0 &icc1>, > + <&icc2 &icc3>; > + interconnect-names = "usb4-ddr", > + "apps-usb4"; > + > + mode-switch; > + > + port { > + usb4_0_mode_in: endpoint { > + }; > + }; > + }; > + }; > +... > diff --git a/MAINTAINERS b/MAINTAINERS > index 9da37c8dee69de9421d4f70906b4e623a442d171..b607f0a66f953fb1ea72e3405820288850004dfe 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -25428,6 +25428,7 @@ L: linux-usb@vger.kernel.org > S: Maintained > T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git > F: Documentation/admin-guide/thunderbolt.rst > +F: Documentation/devicetree/bindings/thunderbolt/ > F: drivers/thunderbolt/ > F: include/linux/thunderbolt.h > > > --- > base-commit: 05af764719214d6568adb55c8749dec295228da8 > change-id: 20250916-topic-qcom_usb4_bindings-3e83e2209e1e > > Best regards, > -- > Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> > -- With best wishes Dmitry
© 2016 - 2025 Red Hat, Inc.