System designTroubleshooting

USB3 port dead on a custom board: the device tree phy-names mismatch

Fix a USB3 lane that never enumerates: the device tree phy-names mismatch, how to count phandles, map usb2/usb3 lanes to connectors, and verify with lsusb.

LumaSpec Vision11 min read Share on LinkedIn

On this page 8 sections
  1. 01Why is one USB3 port dead while its neighbors work?
  2. 02How do I count phys against phy-names?
  3. 03Which connector owns which usb3 lane?
  4. 04What does lsusb -t tell me about the port?
  5. 05How much bandwidth do I lose at 480M?
  6. 06What else keeps a lane down after the counts match?
  7. 07How do I prove the port before the board ships?
  8. 08Questions

You built a carrier board with three USB3 interfaces, two of them pass, and the third sees nothing at all, or a camera on it crawls at USB2 speed. Before you reach for the oscilloscope, count strings in the device tree: the commonest single fault is a controller node whose phys list holds one more phandle than phy-names holds names, which silently disables exactly one SuperSpeed lane. This guide walks that check on a real three-port bring-up, maps connectors to usb2/usb3 lane pairs, separates "nothing detected" from "detected at 480M", and sizes the bandwidth you lose while the fault is live. It is written for engineers bringing up their own board with USB3 machine vision cameras. If your camera misbehaves on a known-good host instead, start with USB3 camera negotiated USB2 speed: why lsusb -t shows 480M and come back here for the board side.

Why is one USB3 port dead while its neighbors work?

In the bring-up this guide dissects, the controller node carried six phandles in phys and five names in phy-names, so the lane usb3-2 was never requested and the port on it reported no attach at all. Two of the board's three USB3 interfaces passed; the third failed. Every lane node in the pad controller was enabled and set to the xusb pad function, every port node had its mode and supply, and none of that was the fault. The defect sat one node away, in the USB controller's PHY lists:

phys = <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-0}>,
       <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-1}>,
       <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-2}>,
       <&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-0}>,
       <&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-1}>,
       <&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-2}>;
phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1";

Six phandles, five strings. The kernel pairs the two lists by index, the first name belongs to the first phandle, the fifth to the fifth, so the sixth phandle has no name, no lookup, and no code path that ever initializes it. The lane stays down, and the connector it feeds loses SuperSpeed; had the nameless lane been a usb2 lane, the port would be dead outright. Nothing warns you: the tree compiles, the bootloader accepts it, and the boot log stays quiet.

How do I count phys against phy-names?

Count the phandles in phys and the strings in phy-names and force the counts equal: the Nth string must name the Nth phandle, so this board needs usb3-2 added as a sixth entry. You can do the whole check on the running board, without reflashing, because the live tree is exposed under /proc/device-tree:

tr '\0' '\n' < /proc/device-tree/<usb-controller>/phy-names | nl

<usb-controller> stands for your controller's node path. nl numbers the strings, one per line, which is your name count. The phandle side comes from the decompiled blob:

dtc -I dtb -O dts <boot-dtb> | grep -A 10 phy-names

<boot-dtb> is your board's compiled device tree blob. Count the phandles in the printed phys list, compare, and fix the shorter list where they differ. Here the fix is one string:

phy-names = "usb2-0", "usb2-1", "usb2-2",
            "usb3-0", "usb3-1", "usb3-2";

Rebuild the blob, flash it, reboot, and replug. Keep the order paired as you edit: shuffling phys while leaving phy-names alone binds lanes to the wrong connectors, which shows up later as devices appearing on the wrong jack. The same index pairing governs every controller that uses the generic PHY binding, so the counting check is portable across SoC vendors and carrier boards.

Which connector owns which usb3 lane?

The schematic owns the answer, and you prove it empirically: plug one known SuperSpeed device into each jack in turn and note which root hub gains a device, because that jack owns a live lane pair. Lane numbering follows the module's pinout, never the order of connectors on your front panel, so take the pairing from the reference carrier schematic and confirm it on the bench. Watch dmesg while you plug: each attach prints the hub port the kernel saw, which pins the mapping in seconds.

In the failed bring-up, debugging stalled because the board's own designer could not say which physical jack was the third interface. Close that gap before anything else, and write the proven map onto the schematic sheet so the next person inherits it. One subtlety from the same board: the on-board hub enumerated twice, once under the 2.0 root hub on bus 001 and once under the 3.0 root hub on bus 002, because a SuperSpeed hub carries a companion high-speed controller. Seeing the hub's second instance is not evidence that your problem lane works, since the hub sits on whichever pair the designer chose, and here that was the first interface.

What does lsusb -t tell me about the port?

lsusb -t prints the negotiated speed of every device: 5000M means the SuperSpeed link trained, 480M means the device fell back to high speed, and no new line at all means the port never saw an attach. Plain lsusb shows the bus layout behind that: on the failed board, bus 001 hung off the 2.0 root hub and carried the keyboard plus the hub's high-speed half, while bus 002 hung off the 3.0 root hub and carried the hub's SuperSpeed half, and nothing else. That is how "the camera is only detected as USB2" turned out to be wrong: nothing was detected at all. Split the two symptoms before you touch anything:

Readout on the jack Likely cause Test Fix
No device appears Lane never bound: nameless phandle, disabled lane, dead VBUS Count the lists; meter 5 V on VBUS Add the name, enable the lane, fix the rail
Device shows 480M SuperSpeed link will not train: pair polarity, coupling parts, cable, plug-at-boot Swap in a known-good 3 m cable, replug after boot Rework the pair or shorten the run
Device on the wrong jack Lists shuffled, lanes bound to the wrong names Plug into each jack, watch dmesg Restore index-paired order

Replug while watching dmesg | tail; over-current messages and disconnect storms point at wiring, not at the tree. And if the same camera misbehaves on a known-good PC, the fault is host-side: a camera enumerating as USB 2.0 on a USB 3.0 port covers those link-level causes.

How much bandwidth do I lose at 480M?

A high-speed fallback delivers about 40 MB/s of usable payload against roughly 400 MB/s on a trained SuperSpeed link, so a camera needing 372 MB/s falls from 120 fps to about 13 fps while the fault is live. The arithmetic is one line:

payload = pixels per frame × bytes per pixel × fps fallback fps = usable MB/s ÷ (pixels per frame × bytes per pixel)

Run it on a real board camera from the catalogue: the LS-BCM-0003, 3.1 MP global shutter, 120 fps over USB3.

Board-level cameras3.1 MP USB3 board-level camera, IMX252, 1/1.8" global shutter, 120 fps (LS-BCM-0003)LS-BCM-0003
Sensor format
1/1.8"
Lens mount
C-mount
Interface
USB3
Resolution
5 MP
$690.00View partBuild a system with it

Call the frame 3.1 million pixels. At one byte per pixel, the payload is 3.1 × 120 = 372 MB/s, which is 372 × 8 = 2,976 Mbps, comfortably inside a 5 Gbps link, which after 8b/10b encoding and protocol overhead plans out at about 400 MB/s usable. On a 480 Mbps fallback with 40 MB/s usable, the same camera tops out at 40 ÷ 3.1 = 12.9, call it 13 fps. At 12 bits per pixel the stream would be 372 × 1.5 = 558 MB/s, above what one SuperSpeed link delivers, which is why such cameras pack bits or cap fps. If several cameras share the controller, how many USB cameras one controller can feed before drops sizes the total.

Treat 480M as a fault to fix, never a mode to live with: inspection timing tuned at 120 fps does not survive 13, and a line-rate trigger will starve.

What else keeps a lane down after the counts match?

With the lists equal, the next faults in order of likelihood are a usb3 port node the pad controller never received, a VBUS rail that never rises, a device that was already plugged in at boot, and SuperSpeed pairs that cannot train. Work them in that order:

  1. Missing usb3 port node. The pad controller's ports section needs a node for the SuperSpeed lane as well as the usb2 lane sharing the connector, with status = "okay", its mode, and its vbus-supply. Decompile and look; if only the usb2 node is there, add the usb3 one.
  2. VBUS never rises. Meter the jack's VBUS pin: 5 V, board idle, nothing attached. The regulator named in vbus-supply must exist and be enabled; wiring the jack straight to the 5 V rail, as many carrier boards do, is fine during bring-up and removes one variable.
  3. Plugged in at power-up. A SuperSpeed device present at boot on the recovery or flashing port can be seen by the firmware and then dropped by the kernel. Replug after boot and retest on a second jack before suspecting the tree again.
  4. Pairs that will not train. USB2 has two wires and forgives a lot; SuperSpeed pairs do not. A polarity swap or a missing coupling part on a transmit pair leaves the device at 480M permanently, so compare the schematic against the connector's drawing and budget a rework if they disagree.
  5. Cable beyond its reach. A passive SuperSpeed run degrades past about 3 m. Put the known-good short cable between board and camera for the fault-finding pass, then test the final length.

If the on-board hub is in the path, a USB3 hub that disconnects right after detection on the board's USB-C port walks that sub-tree.

How do I prove the port before the board ships?

Three passes close it: six names for six phandles in the decompiled tree, 5000M for a device on that jack in lsusb -t, and the camera holding its rated frame rate through a full shift. Write the results into the release notes for the board:

  • Counts 1:1 and index-paired for every controller node on the board.
  • Connector-to-lane map proven by plug-and-watch and written on the schematic.
  • 5000M readout with a SuperSpeed device on each USB3 jack.
  • dmesg clean: no over-current, no endless probe deferral.
  • Camera soaks at full frame rate for an hour, on the flexing cable if the axis moves.
  • Ten plug cycles on the new connector, enumeration every time.

Two bench parts cover the rest of the chain:

The LS-CBL-0219 is a 3 m USB3.0 camera cable built for drag-chain flex, the known-good cable for every fault-finding pass on a moving axis. The MV-GU2204 is a quad USB3.0 host adaptor, 4 ports on one card, for the controller PC while the board's third lane is in rework. More host-side interfaces sit in the frame grabbers category.

AccessoriesFrame grabbers

CoaXPress, Camera Link and GigE cards

58 models · from $189.00

Decisions by what you found:

  • Counts mismatched: add the missing string, reflash, done, a one-line fix.
  • Counts right, VBUS dead: fix the regulator node, an hour of work.
  • 480M with a good short cable: connector wiring; rework the pair, and move the camera to a proven jack or the host card until the rework lands.
  • Deadline this week: keep the quad adaptor in the host PC, or sidestep USB3 with a GigE board camera such as the LS-BCM-0020, a 6.3 MP module at 18 fps. GigE reaches 100 m on standard cable.

On the camera side, the board camera evaluation checklist for inspection systems and the guide to a board-level camera and USB3 bridge board pick up where this one ends. You can build the station step by step in the configurator, browse the machine vision camera finder and the accessories finder for cables and host cards, and find more bring-up write-ups on the systems topic page. If the lane still refuses to train after the counts match, send us the decompiled node and the lsusb -t capture through the contact page.

Questions

How long can a passive USB3 camera cable be?

Plan on 3 m for a passive SuperSpeed run inside a machine; past that the link trains erratically or drops to 480M. Longer reaches call for an active or optical USB3 cable, or for moving the camera to another interface on fixed stations. On a moving axis, use a cable rated for drag-chain flex and treat 3 m as the ceiling there too.

What does -517 beside the pad controller in dmesg mean?

-517 is EPROBE_DEFER: the pad controller's probe was postponed because a clock or regulator it depends on had not appeared yet. A handful of these lines during boot is normal. When the message repeats indefinitely, a supply or clock named in the pad controller node never comes up, and no lane on that pad binds until that dependency is fixed.

Can I test the USB3 lane without a camera?

Yes. Plug any SuperSpeed mass-storage stick into the jack and read lsusb -t: a 5000M line proves the lane trained. A USB2 stick proves only the usb2 half of the connector, exactly the half that keeps working when the SuperSpeed lane is down, so choose a device you know is SuperSpeed-capable.

How much current can a USB3 camera port supply?

A USB3 downstream port budgets 900 mA at 5 V, so 4.5 W, against 500 mA on a USB2 port. A board camera alone fits; a camera plus LED lighting on the same jack does not. Feed the lighting from its own controller and supply instead of the camera's VBUS, and the link stays stable.

Do I need phy-names when phys lists only one phandle?

With a single phandle the lookup is unambiguous, and several drivers accept phys without names, but keep a matching phy-names entry anyway. It costs one string, it documents which lane the phandle feeds, and the next engineer who adds a lane inherits an index-paired pattern instead of a silent mismatch.