Re: [PATCH 1/2] dt-bindings: chrome: Add cros-ec-typec mux props

From: Prashant Malani
Date: Tue Jun 09 2020 - 19:57:47 EST


Hi Rob,

Thanks again for the comments and feedback. Kindly see responses inline:

(Trimming unrelated text from thread):

On Tue, Jun 09, 2020 at 02:30:11PM -0600, Rob Herring wrote:
> On Fri, May 29, 2020 at 5:30 PM Prashant Malani <pmalani@xxxxxxxxxxxx> wrote:
> >
> > Nodes truncated and unrelated fields omitted in the interest of brevity:
> >
> > // Chrome OS EC Type C Port Manager.
> > typec {
> > compatible = "google,cros-ec-typec";
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > connector@0 {
> > compatible = "usb-c-connector";
> > reg = <0>;
> > power-role = "dual";
> > data-role = "dual";
> > try-power-role = "source";
> > mode-switch = <&foo_mux>;
> > // Other switches can point to the same mux.
> > ....
>
> The connector is supposed to have 'ports' for USB2, USB3, and Aux
> unless the parent is the USB controller.
Understood; so, coupled with Heikki's explanation (see below for where
I've pasted it), would it be something like so? (adding inline to the connector
node definition):

ports {
            #address-cells = <1>;
            #size-cells = <0>;

            port@0 {
                reg = <0>;
                usb_con_hs: endpoint {
                    remote-endpoint = <&foo_usb_hs_controller>;
                };
            };

            port@1 {
                reg = <1>;
                usb_con0_ss: endpoint@0 {
                    remote-endpoint = <&mode_mux_in>;
                };
            };

            port@2 {
                reg = <2>;
                usb_con_sbu: endpoint {
                    remote-endpoint = <&foo_dp_aux>;
                };
            };
        };

>
> > };
> > };
> >
> > // Mux switch
> > // TODO: Can possibly embed this in the PHY controller node itself?
> > foo_mux {
> > compatible = "vendor,typec-mux";
> > mux-gpios = <&gpio_controller 23 GPIO_ACTIVE_HIGH>;
> >
> > ports {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > port@0 {
> > reg = <0>;
> > mux_dp_in: endpoint {
> > remote-endpoint = <&dp_phy_out>;
> > };
> > };
> >
> > port@1 {
> > reg = <1>;
> > mux_usb_in: endpoint1 {
> > remote-endpoint = <&usb3_phy_out>;
> > };
> > };
>
> This all goes away if you have ports in the connector node. More below.

I think I my earlier example may have been a bit incorrect. Per Heikki's
explanation of who the consumer of the mux-control bindings is, the
foo_mux definition would now be like so:

foo_mux {
compatible = "typec-mux-consumer";
// This can be expanded to add more mux-controls for orientation,
// data role etc.
mux-controls = <&mode_mux_controller>;
mux-control-names = "mode";
#address-cells = <1>;
#size-cells = <0>;

    port@0 {
    reg = <0>;
       mode_mux_in: endpoint {
  remote-endpoint = <&usb_con0_ss>
        };
    };

    port@1 {
        reg = <1>;
        mode_mux_out_usb3: endpoint {
  remote-endpoint = <&usb3_0_ep>
        };
    };

    port@2 {
        reg = <2>;
        mode_mux_out_dp: endpoint {
  remote-endpoint = <&dp0_out_ep>
        };
    };
};

and we add the definition for the mux-controller, where the mux-gpio
control actually resides:

mode_mux_controller: mux-controller {
    compatible = "vendor,typec-mode-mux";
    mux-gpios = <&gpio_controller 23 GPIO_ACTIVE_HIGH>;
};

>
> > };
> > };
> >
> > // Type C PHY Controller.
> > tcphy0: phy@ff7c0000 {
> > compatible = "rockchip,rk3399-typec-phy";
> > reg = <0x0 0xff7c0000 0x0 0x40000>;
> > ...
> > tcphy0_dp: phy@dc00000 {
> > compatible = "soc,dp-phy";
> > reg = <0xdc00000 0x1000>;
> > ports {
> > port@0 {
> > reg = <0>;
> > dp_phy_out: endpoint {
> > remote-endpoint = <&mux_dp_in>;
> > };
> > };
>
> This is wrong in that 'phys' are not part of the graph. It's the DP
> and USB controllers that should be part of the graph. Any phys are
> referenced with the phys binding and are not part of the graph.

Got it. So the new PHY definition would be just the same, but no
"ports".

>
> > };
> > };
> >
> > tcphy0_usb3: phy@db00000 {
> > compatible = "soc,usb3-phy";
> > reg = <0xdb00000 0x1000>;
> > ports {
> > port@0 {
> > reg = <0>;
> > usb3_phy_out: endpoint {
> > remote-endpoint = <&mux_usb3_in>;
> > };
> > };
> > };
> > };
> > };
> >
> >
> > // USB3 Host controller
> > usbdrd3_0: usb@fe800000 {
> > compatible = "rockchip,rk3399-dwc3";
> > #address-cells = <2>;
> > #size-cells = <2>;
> > clocks = ...;
> > clock-names = ...;
> > status = "disabled";
> >
> > usbdrd_dwc3_0: usb@fe800000 {
> > compatible = "snps,dwc3";
> > reg = <0x0 0xfe800000 0x0 0x100000>;
> > interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>;
> > clocks = ...;
> > clock-names = ...;
> > dr_mode = "otg";
> > phys = <&tcphy0_usb3>;
> > phy-names = "usb3-phy";
> > phy_type = "utmi_wide";
> > power-domains = <&power RK3399_PD_USB3>;
> > status = "disabled";

This means a port definition here:
ports {
            #address-cells = <1>;
            #size-cells = <0>;

            port@0 {
                reg = <0>;
                usb3_0_ep: endpoint {
                    remote-endpoint = <&mode_mux_out_usb3>;
                };
            };
          };

> > };
> > };
> >
> > // DP controller
> > cdn_dp: dp@fec00000 {
> > compatible = "rockchip,rk3399-cdn-dp";
> > reg = <0x0 0xfec00000 0x0 0x100000>;
> > interrupts = ...;
> > clocks = ...;
> > clock-names = ...;
> > phys = <&tcphy0_dp>;
> > ...
> > ports {
> > dp_in: port {
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > dp_in_vopb: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&vopb_out_dp>;
> > };
> >
> > dp_in_vopl: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&vopl_out_dp>;
> > };
> > };
>
> This should have an output port and then that is connected to the USB
> connector. Given that DP is muxed with the USB SS signals, port@1
> (defined as USB SS) should then have 2 endpoints.

So, completing the example, another port here:

dp_out: port@1 {
            reg = <1>;
            dp0_out_ep: endpoint {
                remote-endpoint = <&mode_mux_out_dp>;
            };
};

>
> Then the only new thing here is how to represent the GPIO line
> controlling the mux. Normally, I'd expect this to be in the parent of
> the connector (the type-C controller), but since you have multiple
> connectors, that doesn't work so well. So you can put 'mux-gpios' in
> the port@1 node. (Or maybe it should be 'mux-controls' with a gpio mux
> defined elsewhere).

I think the updated example better helps delineate what we're trying to
achieve. Per Heikki's earlier explanation (re-quoting here) :

"
> > > > The mode-switch here would actually represent the "consumer" part in
> > > > the mux-control bindings. So the mux-controls would describe the
> > > > relationship between the "mode-switch" and the mux controller(s),
> > > > while the mode-switch property describes the relationship between
> > > > something like USB Type-C Port Manager (or this cros_ec function) and
> > > > the "mux consumer".
"

So the device that "mode-switch" points to (in this case, foo_mux) is the "consumer" of
the mux-control direct consumer). Heikki, does this example better
demonstrate what the Type C connector class expects?

Also, I think it might be better to move these *-switch properties into the
usb-connector.yaml binding in the event that we decide to take this route,
since the "Chrome EC Type C port driver" isn't expected to use them directly.
Rob, kindly LMK if you'd prefer that, and I can make the change in the
next patch version.

I can re-write this example in a non-inline form if that would be easier
to interpret. Kindly LMK, and also LMK if this graph connection scheme
example is acceptable.

Thanks again, and best regards,

-Prashant

>
> Rob