[PATCH 2/2] dt-bindings: usb: snps,dwc3: Fix downstream port numbering
Chen-Yu Tsai
wenst at chromium.org
Thu Oct 15 02:00:14 PDT 2026
(Cc-ed Mathias, the xHCI driver maintainer in case I misunderstood xHCI.)
On Thu, Oct 15, 2026 at 4:44 PM Neil Armstrong
<neil.armstrong at linaro.org> wrote:
>
> On 10/14/26 18:36, Konrad Dybcio wrote:
> > On 10/14/26 11:44 AM, Neil Armstrong wrote:
> >> On 10/14/26 11:29, Chen-Yu Tsai wrote:
> >>> On Wed, Oct 14, 2026 at 5:28 PM Neil Armstrong
> >>> <neil.armstrong at linaro.org> wrote:
> >>>>
> >>>> On 10/14/26 10:20, Chen-Yu Tsai wrote:
> >>>>> The DWC3 controller can operate in host mode. It does so with a XHCI
> >>>>> compliant host controller. The XHCI has two downstream ports, one for
> >>>>> HS and one for SS. USB downstream ports start from 1, not 0.
> >
> > [...]
> >
> >
> >>> IMHO having consistent numbering across controller types would be
> >>> better. This avoids making the USB core and hub code deal with more
> >>> exceptions, and also easier to understand and write device trees.
> >>
> >> I was in the impression the port number not necessarily reflects
> >> an actual physical numbering, and can be a logical number we would
> >> then map in the kernel.
> >>
> >> I don't see any issue here having base 0 for the bindings and then
> >> converting it to base 1 for the XHCI port numbering.
> >
> > I thought base1 comes from the USB spec and not just XHCI?
>
> This is my question, is the spec says: each USB Host Controller root
> port shall be considered as a port of a Hub and numbered the same way,
> then fine, let's use the base1 numbering.
>
> As I understand how USB is architectured, all downstream ports of Hubs
> are numbered in base1, and the whole topology is based on that.
>
> But here, we are speaking of physically separate USB busses, one
> USB2.0 and one USB3.0, a controller could also have 10 USB2.0 ports
> and 5 USB3.0 ports, who knows. The way those will be numbered is not
> part of the specification because the specification only the defines
> the topology of an USB bus, like PCI(e) defines the topology on a PCI(e) bus.
No, the XHCI spec actually specifies how to identify the number of ports
and which port supports what version. See below.
> How we aggregate all those busses to abstract them to software is not
> part of the spec, we chose to declare a fake root Hub with a physical
> downstream port as a virtual port of the root Hub, fine but this is
> purely software abstraction.
As far as I understand the implementation in Linux and the XHCI spec,
the XHCI hardware registers give the "maximum number of ports" in
HCSPARAMS1. Then there is at least 1 "xHCI Supported Protocol Capability"
entry in the "Extended capabilities" section that describes a group of
ports (offset and number) and the USB protocol supported by that group.
Using the example given by the XHCI spec on page 330 as figure 4-35:
XHCI port 1: HS on physical port 1
XHCI port 2: HS on physical port 2
XHCI port 3: HS on physical port 3
XHCI port 4: HS on physical port 4
XHCI port 5: SS on physical port 3
XHCI port 6: SS on physical port 4
The DT would be something like:
xhci {
ports {
port at 1 { /* graph to HS EP on USB A connector 1 */ };
port at 2 { /* graph to HS EP on USB A connector 2 */ };
port at 3 { /* graph to HS EP on USB A connector 3 */ };
port at 4 { /* graph to HS EP on USB A connector 4 */ };
port at 5 { /* graph to SS EP on USB A connector 3 */ };
port at 6 { /* graph to SS EP on USB A connector 4 */ };
};
};
> We may only use the hardware IP port numbering in the bindings, not
> the software abstraction.
And we are using hardware port numbering. It's just the numbers used
are the physical port numbers from the XHCI registers, not the logical
port numbers on the root hubs.
In fact, we could say that the port numbers on the root hubs for XHCI
are made up.
> We could use the base1 to describe the DWC3 ports, but how to describe
> all the physical USB busses a controller can expose ? We may not limit
> the bindings to USB2.0 and USB3.0 ports only.
Technically, there is one bus for USB 2.0 and one bus for USB 3.0. But
currently for XHCI in DT, we describe the hardware ports directly,
regardless of the USB protocol they support.
I don't know why we don't describe the root hub, but maybe it's because
prior to XHCI the controller and root hub were the same entity? Even for
XHCI, the root hub is more of a logical entity.
And AFAICT, the hardware registers don't distinguish between ports on the
USB 2.0 root hub vs the USB 3.0 root hub. The port control registers are
just in an array, indexed from 1 to maxPorts, i.e. the physical index.
> How about the USB4, does it use the USB3.0 port ?
I'm not familiar with USB4. A quick search says that it can tunnel
USB 3.x, DP, and PCIe, and it doesn't have its own USB HCI defined.
So I'm thinking the USB4 controller would be more like a nexus node
or multiplexing node, or perhaps like a USB C connector. It has input
ports for all the protocols it can tunnel, connected to their respective
controllers (XHCI, DP, PCIe). The binding probably would be very messy
if one controller supported multiple outgoing ports, as each downstream
port has a 3-to-1 relationship with its respective upstream protocol
interfaces.
ChenYu
More information about the Linux-rockchip
mailing list