Re: [PATCH] arm64: dts: qcom: monaco-evk: Enable primary USB controller in host mode

From: Dmitry Baryshkov

Date: Wed Apr 22 2026 - 16:02:18 EST


On Wed, Apr 22, 2026 at 12:45:22PM +0530, Swati Agarwal wrote:
> On Sat, Apr 18, 2026 at 4:10 AM Dmitry Baryshkov
> <dmitry.baryshkov@xxxxxxxxxxxxxxxx> wrote:
> >
> > On Fri, Apr 17, 2026 at 08:50:14PM +0530, Swati Agarwal wrote:
> > > Enable primary USB controller in host mode on monaco EVK Platform.
> > >
> > > Primary USB controller is connected to a Genesys Logic USB HUB GL3590
> > > having 4 ports. The ports of hub that are present on lemans EVK standalone
> > > board are used as follows:-
> > > 1) port-1 is connected to HD3SS3220 Type-C port controller.
> > > 2) port-4 is used for the M.2 E key on corekit. Standard core kit uses UART
> > > for Bluetooth. This port is to be used only if user optionally replaces the
> > > WiFi card with the NFA765 chip which uses USB for Bluetooth.
> > >
> > > Remaining 2 ports will become functional when the interface plus mezzanine
> > > board is stacked on top of corekit:
> > >
> > > 3) port-2 is connected to another hub which is present on the mezz through
> > > which 4 type-A ports are connected.
> > > 4) port-3 is used for the M.2 B key for a 5G card when the mezz is
> > > connected.
> > >
> > > Primary USB Controller
> > > ↓
> > > GL3590 USB Hub (4 ports)
> > > |
> > > |-- Port 1 → HD3SS3220 Type‑C Port Controller → USB‑C Connector
> > > |
> > > |-- Port 2 → Mezzanine USB Hub (when mezz attached)
> > > |
> > > |-- Port 3 → M.2 B‑Key Slot (when mezz attached)
> > > |
> > > |-- Port 4 → M.2 E‑Key Slot
> > > (Default: BT via UART;
> > > USB only if NFA765 module is installed)
> > >
> > > Mark the primary USB controller as host only capable and add the HD3SS3220
> > > Type-C port controller along with Type-c connector for controlling vbus
> > > supply.
> > >
> > > In hardware, there are dip switches provided to operate between USB1 port 0
> > > and port 1 for primary Type-C USB controller. By default, switches will be
> > > off operating at USB0 port. After bootup to HLOS, it will be operated in
> > > USB1 port.
> >
> > Why did you choose this configuration?
> Hi Dmitry,
>
> Thanks for the review.
>
> This configuration follows the Monaco RB4 hardware design and intended
> usage model:
>
> The primary USB controller (USB1) exposes two Type‑C ports: USB0 and USB1.
>
> USB0 is intended exclusively for software download and recovery use
> cases (EDL, ramdump, fastboot).
> USB1 is intended for normal runtime operation after booting into HLOS.
>
> The hardware provides DIP switches to select between USB0 and USB1 for
> the primary controller. These switches default to the USB0 position to
> support software download mode.
>
> To avoid manual intervention, the board also provides GPIO‑controlled
> equivalents of these DIP switches. After booting into HLOS, software
> switches the configuration to USB1, which is the intended runtime
> port.

I assume this behaviour is documented in the board documentation?

My main concern is that with this approach it is not possible to enforce
any other mode of operation, even if the user wants to keep USB0 to
continue to function even after booting.

>
> The external USB hub (Genesys Logic GL3590) connected to USB1 is held
> in reset during download mode and is enabled only after the system
> transitions to runtime mode via software‑controlled GPIOs.
>
> In normal operation:
>
> The secondary USB controller (Micro‑USB / USB2) is used for ADB.
> USB0 of the primary controller is reserved for recovery and debug use cases.
> USB1 of the primary controller operates in host‑only mode to support
> downstream devices via the USB hub.

Is the USB0 suitable for OTG? Is it possible to connect USB devices to
that port or is it peripheral-only?

>
> This setup ensures reliable access to download and recovery paths
> while allowing the runtime USB topology to be switched automatically
> by software in accordance with the board design.
>
> >
> > > @@ -742,6 +822,28 @@ expander5_int: expander5-int-state {
> > > bias-pull-up;
> > > };
> > >
> > > + usb1_hub_reset: usb1-hub-reset-state {
> > > + pins = "gpio7";
> > > + function = "gpio";
> > > + output-enable;
> > > + output-high;
> > > + bias-disable;
> > > + };
> > > +
> > > + usb1_id: usb1-id-state {
> > > + pins = "gpio13";
> > > + function = "gpio";
> > > + bias-pull-up;
> > > + };
> > > +
> > > + usb1_hs_sel_switch: usb1-hs-sel-switch-state {
> > > + pins = "gpio14";
> > > + function = "gpio";
> > > + output-enable;
> > > + output-high;
> > > + bias-disable;
> > > + };
> >
> > Why do you use gpio-hog for SS switch, but then you use pinctrl for HS
> > switch?
> Initially, I attempted to model both HS and SS select signals (as well
> as the USB hub reset) uniformly using gpio-hog.
>
> gpio7_hog: gpio7-hog {
> gpio-hog;
> gpios = <7 GPIO_ACTIVE_HIGH>;
> output-high;
> line-name = "bootup-high-gpio7";
> };
>
> gpio14_hog: gpio14-hog {
> gpio-hog;
> gpios = <14 GPIO_ACTIVE_HIGH>;
> output-high;
> line-name = "usb1-hs-high-gpio14";
> };
>
> However, placing gpio-hog nodes for HS select and hub reset under the
> TLMM node caused dtbs_check failures, This resulted in schema errors
> such as:
>
> make LLVM=-15 ARCH=arm64 -j99 CHECK_DTBS=1 qcom/monaco-evk.dtb
> DTC [C] arch/arm64/boot/dts/qcom/monaco-evk.dtb
> /local/mnt/workspace/swatagar/upstream/linux-next/arch/arm64/boot/dts/qcom/monaco-evk.dtb:
> pinctrl@f100000 (qcom,qcs8300-tlmm): Unevaluated properties are not
> allowed ('gpio14-hog', 'gpio7-hog' were unexpected)
> from schema $id:
> http://devicetree.org/schemas/pinctrl/qcom,qcs8300-tlmm.yaml

See how it's handled in the qcom,sdm845-tlmm.yaml and patch the bindings
accordingly (ideally move it to qcom,tlmm-common.yaml).

>
> To resolve this in a binding‑compliant way:
>
> HS select and USB hub reset GPIOs, which are TLMM‑controlled SoC pins,
> are configured using pinctrl, which is the supported and
> schema‑compliant mechanism for TLMM.
> The SS select GPIO resides on a TCA9538 GPIO expander, which does not
> support pinctrl. For this signal, gpio-hog is a binding‑compliant
> mechanism.
>
>
> Regards,
> Swati
> >
> > > +
> > > expander1_int: expander1-int-state {
> > > pins = "gpio16";
> > > function = "gpio";
> > > @@ -784,6 +886,12 @@ expander3_int: expander3-int-state {
> > > bias-pull-up;
> > > };
> > >
> > > + usb1_intr: usb1-intr-state {
> > > + pins = "gpio45";
> > > + function = "gpio";
> > > + bias-pull-up;
> > > + };
> > > +
> > > expander6_int: expander6-int-state {
> > > pins = "gpio52";
> > > function = "gpio";
> > > @@ -863,9 +971,72 @@ &ufs_mem_phy {
> > > };
> > >
> > > &usb_1 {
> > > - dr_mode = "peripheral";
> > > + dr_mode = "host";
> > > +
> > > + #address-cells = <1>;
> > > + #size-cells = <0>;
> > > +
> > > + pinctrl-names = "default";
> > > + pinctrl-0 = <&usb1_hub_reset &usb1_hs_sel_switch>;
> > >
> > > status = "okay";
> > > +
> > > + usb_hub_2_x: hub@1 {
> > > + compatible = "usb5e3,610";
> > > + reg = <1>;
> > > +
> > > + peer-hub = <&usb_hub_3_x>;
> > > +
> > > + ports {
> > > + #address-cells = <1>;
> > > + #size-cells = <0>;
> > > +
> > > + port@1 {
> > > + reg = <1>;
> > > +
> > > + usb_hub_2_1: endpoint {
> > > + remote-endpoint = <&usb1_con_hs_ep>;
> > > + };
> > > + };
> > > +
> > > + /*
> > > + * Port-4 is connected to M.2 E key connector on corekit.
> > > + */
> > > + port@4 {
> > > + reg = <4>;
> > > +
> > > + usb_hub_2_4: endpoint {
> > > + };
> > > + };
> > > + };
> > > + };
> > > +
> > > + usb_hub_3_x: hub@2 {
> > > + compatible = "usb5e3,625";
> > > + reg = <2>;
> > > +
> > > + peer-hub = <&usb_hub_2_x>;
> > > +
> > > + ports {
> > > + #address-cells = <1>;
> > > + #size-cells = <0>;
> > > +
> > > + port@1 {
> > > + reg = <1>;
> > > +
> > > + usb_hub_3_1: endpoint {
> > > + remote-endpoint = <&hd3ss3220_1_out_ep>;
> > > + };
> > > + };
> > > +
> > > + port@4 {
> > > + reg = <4>;
> > > +
> > > + usb_hub_3_4: endpoint {
> > > + };
> > > + };
> > > + };
> > > + };
> > > };
> > >
> > > &usb_1_hsphy {
> > > --
> > > 2.34.1
> > >
> >
> > --
> > With best wishes
> > Dmitry

--
With best wishes
Dmitry