Jump to content

RockPi 4(A/B/C) - USB OTG mode in current/mainline kernels?


amcduffee

Recommended Posts

I know that not all features of legacy vendor kernels can be supported in mainline kernels.  However, has anyone considered and/or attempted to get the OTG capability working in a current/mainline kernel?

 

I have a couple different projects where I need to have OTG working so I can have the RockPi 4 be a USB device (e.g. mass storage, ethernet, etc.).  For the time being this means I can only use the legacy kernels, but I am hoping that might change in the future.

 

There are a number of different RK3399 boards with DWC3 controllers that could benefit from such a feature being available, right?  Since I don't understand the kernel/driver/platform glue layers well enough to make an attempt myself,  I am hoping someone who knows more about this might have some extra info?  Is it planned for the future?  Too complex? Something else?

 

Link to comment
Share on other sites

8 hours ago, amcduffee said:

Is it planned for the future?

 

In the future we plan to provide some sort of bounty to cover this, but for now, we can do nothing but skip. Current short term plan is to remove support (unless someone will join and pick it up) since we are already working more then possible and users contribution is barely enough to cover the bill for their download habits. There is already a big bill for the features that we have ported, working fine and nobody complains for but also nobody wants to cover. Board support is expensive and public share in that cost management is below 1% ... Anyone can try to hire someone to fix / port / support this - we really don't need more work on our expense - we have plenty of ... When / if this is fixed, send a patch. To mainline kernel https://www.kernel.org/  mailing list or to https://docs.armbian.com/Process_Contribute/, which will be far easier & cheaper.

Link to comment
Share on other sites

I've spent around 10 hours on this issue. I used the most recent rockpi image for Armbian (Armbian_21.08.1_Rockpi-4b_hirsute_edge_5.13.12_xfce_desktop.img.xz) 

 

I managed to finally make it work by adding this dts file:

/dts-v1/;
/plugin/;

/ {
        compatible = "rockchip,rk3399";

        fragment@0 {
                target = <&usbdrd_dwc3_0>;
                __overlay__ {
                        dr_mode = "peripheral";
                        compatible = "snps,dwc3";
                        reg = <0x0 0xfe800000 0x0 0x100000>;
                        phys = <&tcphy0_usb3>;
                        phy-names = "usb3-phy";
                        phy_type = "utmi_wide";
                        snps,dis_enblslpm_quirk;
                        snps,dis-u2-freeclk-exists-quirk;
                        snps,dis_u2_susphy_quirk;
                        snps,dis-del-phy-power-chg-quirk;
                        snps,xhci-slow-suspend-quirk;
                };
        };
};


So, write the above to dwc3-0-device.dts and then run:

sudo armbian-add-overlay dwc3-0-device.dts


After this, loading g_ether or g_mass_storage worked fine.

Edited by Terry Hardie
Link to comment
Share on other sites

I've been working this problem for quite some time for an rk3399 based board we're developing.  I need peripheral mode at SS for video/audio gadgets but also need Host mode (probably at any speed) for factory work though we can probably live without host mode.  The fix you have above appears to be just a slight variation of what already exists for default rk3399.dtsi.  Only the "snps,xhci-slow-suspend-quirk" seems to be new.  It didn't have an affect on my testing.

 

My use case requires USB3 OTG or peripheral mode over Type-C.  The existing type-c driver, fusb302, does not work at all, as far as I can tell.  I've have had no luck getting it to work with either the stock dwc3-of-simple driver of a the (see below) ported rockchip dwc driver.

 

I forward ported both the fusb302.c driver and the associated dwc3-rockchip.c driver from Rockchip's BSP to 5.15.14..  These act better but still don't work.  More importantly, you can't set the mode to OTG in the DTS and then try to switch between host and peripheral modes.  There are bugs in the dwc3-rockhip.c driver that cause the workqueue to timeout and the system to reboot.  I haven't figured out why that is - possibly the workqueue takes too long or, more likely, there is some kind of memory stomping going on.  The best you can do is set the mode to peripheral and just stay there.  But even that doesn't seem to work to allow the rk3399 to act as a storage device (which is what I use to test this because it's the easiest to setup).  At least not consistently.

 

I have seen the ported drivers work in USB2 HS mode and at one point I managed to get the storage device to be seen at SS, but I don't know how I did it, it didn't stay stable on the host side, and I have not been able to repeat it.

 

The BSP driver was rejected by the upstream USB developers back in 2016, so this path is just to make it work.  It would never make into the upstream.

 

I've noticed there is a hw switch on the RockPi4 for OTG vs Host mode.  I suspect they use that to load a different overlay at boot time.  It's a neat trick.  I don't know what drivers or DTS config they're using.

 

If anyone has additional information that might help getting the stock drivers or the ported drivers working, at a minimum as a peripheral at SS speed, let me know.

Thanks.

Link to comment
Share on other sites

30 minutes ago, mjhammel said:

I've noticed there is a hw switch on the RockPi4 for OTG vs Host mode.  I suspect they use that to load a different overlay at boot time.  It's a neat trick.  I don't know what drivers or DTS config they're using.

 

I recall looking into how the switch worked in the past.  It is a live switch and can be used after boot to switch between modes.  I remember coming across the driver callback (GPIO based ISR?) that is registered to handle whenever the switch is flipped.  The callback itself doesn't effect the mode change immediately but rather schedules a work item to make it happen later on another thread.  I don't think the switch plays a role in DTB overlays at boot, but I could be wrong on that point.

 

I am not a kernel/driver developer myself so my understanding of the lower level driver details is fuzzy at best.  I am fairly good at finding my way around the kernel layers and associating what parts/drivers are responsible for the actions I am interested in and/or troubleshooting.  I suspect the issue you are encountering with the driver not working and work queue items hanging will require the attention of a driver developer that is familiar enough with the DWC3 controller, its registers, transition timing sensitivities, etc.  Once things hit the level that requires understanding the datasheets on the controllers and ICs I can't help much, unfortunately.

 

Do you have a link to the upstream BSP patch that was rejected?  I would like to read up on that.  It certainly helps to explain the lackluster support for RK3399 OTG on mainline kernels.  A shame really because I find the RK3399 platform to be very capable otherwise...

Link to comment
Share on other sites

55 minutes ago, amcduffee said:

I recall looking into how the switch worked in the past.  It is a live switch and can be used after boot to switch between modes.  I remember coming across the driver callback (GPIO based ISR?) that is registered to handle whenever the switch is flipped.  The callback itself doesn't effect the mode change immediately but rather schedules a work item to make it happen later on another thread.  I don't think the switch plays a role in DTB overlays at boot, but I could be wrong on that point.

 

I am not a kernel/driver developer myself so my understanding of the lower level driver details is fuzzy at best.  I am fairly good at finding my way around the kernel layers and associating what parts/drivers are responsible for the actions I am interested in and/or troubleshooting.  I suspect the issue you are encountering with the driver not working and work queue items hanging will require the attention of a driver developer that is familiar enough with the DWC3 controller, its registers, transition timing sensitivities, etc.  Once things hit the level that requires understanding the datasheets on the controllers and ICs I can't help much, unfortunately.

 

Do you have a link to the upstream BSP patch that was rejected?  I would like to read up on that.  It certainly helps to explain the lackluster support for RK3399 OTG on mainline kernels.  A shame really because I find the RK3399 platform to be very capable otherwise...

The one I found is here:  https://patchwork.kernel.org/project/linux-rockchip/patch/1471251284-1804-1-git-send-email-william.wu@rock-chips.com/

 

I can probably handle the data sheets but I don't have them, nor do I have the understanding of how the usb upstream expects drivers to be written.  The GPIO ISR you mention might use a debugfs/sysfs interface to switch modes.  I don't know of a way to do it via sysfs, but the dwc3 drivers have some debugfs mode files that allow it.  That said, when I tried using those the system locked and/or rebooted.  The issue seems to be with the workqueue item (from the ported BSP driver) that handles the switching - it needs to reset the dwc3 controller and (I think) restart everything.  But that seems not to work or maybe it works partly but takes too long while trying to run in a workqueue item.  I can tell roughly where the problem is but not why it's happening.

 

The stock dwc3 driver (dwc3-of-simple) doesn't do any of that and thus doesn't seem to support dynamic mode switching.  At least as far as I can tell.  I'm still experimenting with it.

 

Right now I'm just trying to get back to USB2 HS gadget-devices working.  It's a magic incantation of DTS and driver selection whose page is missing from my book of spells.  Oh, one thing I do seem to remember from when it worked was: don't over use the DTS.  There are lots of possible configurations you can add to the tcphy0 and usbdrd properties but, if I recall correctly, it was best not to use them.  So that's what I'm working on now.

 

Link to comment
Share on other sites

2 hours ago, mjhammel said:

Thanks for sharing the link, that was an interesting read.

 

2 hours ago, mjhammel said:

I can probably handle the data sheets but I don't have them, nor do I have the understanding of how the usb upstream expects drivers to be written.  The GPIO ISR you mention might use a debugfs/sysfs interface to switch modes.  I don't know of a way to do it via sysfs, but the dwc3 drivers have some debugfs mode files that allow it.  That said, when I tried using those the system locked and/or rebooted.  The issue seems to be with the workqueue item (from the ported BSP driver) that handles the switching - it needs to reset the dwc3 controller and (I think) restart everything.  But that seems not to work or maybe it works partly but takes too long while trying to run in a workqueue item.  I can tell roughly where the problem is but not why it's happening.

 

Seeing the patches jogged my memory a bit.  The 'dwc3_rockchip_otg_extcon_evt_work' function is what handles the actual mode switching.  Its execution is scheduled using a work queue via the dwc3_rockchip_*_notifier functions which are based on some extcon notifier.  I have almost no understanding of what extcon is nor how the notifiers work and how they are ultimately connected to the physical switch.  It is possible the physical switch manipulates a basic resistance circuit to force the CC pin resistance to the required amount to force UFP/DFP modes.  Once the resistance is forced the dwc3 controller generates IRQs that inform the driver via notifiers?  I am guessing here, but it makes sense because the OTG port is wired to a type-A connector which means the physical switch could control the CC pin resistances without interfering since CC pin can't be wired to a type-A connector.

 

You are right about the dwc3 controller needing to be reset at the same time, the patch thread discusses this requirement.  In fact, I think it was this very requirement that led to them stripping the 'static' keyword from the 'dwc3_phy_setup' function in dwc3/core.c so it could be called from their new dwc3/dwc3-rockchip.c driver.  It was this change in particular that caused the immediate NAK for upstream.

 

I presume that if your port attempts lack the required logic to reset the dwc3 controller managed in core.c that is likely why the work queue item is hanging or locking up the system?  What kernel version and from what source did you port the driver?  If it isn't from the 'legacy' branch repo used by Armbian it might be worth trying again with the following version which I can confirm has functioning mode switch logic:

   https://github.com/ayufan-rock64/linux-kernel

   tag:4.4.202-1237-rockchip-ayufan

 

2 hours ago, mjhammel said:

Right now I'm just trying to get back to USB2 HS gadget-devices working.  It's a magic incantation of DTS and driver selection whose page is missing from my book of spells.  Oh, one thing I do seem to remember from when it worked was: don't over use the DTS.  There are lots of possible configurations you can add to the tcphy0 and usbdrd properties but, if I recall correctly, it was best not to use them.  So that's what I'm working on now.

 

Are you possibly running into issues getting back to USB2 HS peripheral mode because you still have ported code compiled in?  I ask because I took Terry's DTS patch from above and integrated it into the Armbian build for a linux-5.10.y 'current' branch kernel (specifically 5.10.92-rockchip64) and have the peripheral mode operational as long as 'dr_mode = "peripheral"' is set in the built DTB as shown in the patch.  I have tested it with mass storage, hid and ncm gadgets, all working as expected.

Link to comment
Share on other sites

First, thanks for the tips.  It's good to have someone to boune ideas off of.

 

Quote

Seeing the patches jogged my memory a bit.  The 'dwc3_rockchip_otg_extcon_evt_work' function is what handles the actual mode switching.  Its execution is scheduled using a work queue via the dwc3_rockchip_*_notifier functions which are based on some extcon notifier.  I have almost no understanding of what extcon is nor how the notifiers work and how they are ultimately connected to the physical switch.  It is possible the physical switch manipulates a basic resistance circuit to force the CC pin resistance to the required amount to force UFP/DFP modes.  Once the resistance is forced the dwc3 controller generates IRQs that inform the driver via notifiers?  I am guessing here, but it makes sense because the OTG port is wired to a type-A connector which means the physical switch could control the CC pin resistances without interfering since CC pin can't be wired to a type-A connector.

The extcon is the physical port (re: "external connection"), in this case a Typc-C connector on our board.  It notifies the phy core that then initiates the callback to the workqueue in the dwc3-rockchip driver.  At least that's my understanding.  You have to reference the extcon in the usbdrd3 proprerty, which is the rockchip dwc3 driver (the dwc3-simple driver doesn't directly reference an extcon), so it can attach the extcon to the phy.  But apparently you also need to attach it to the tcphy0 property, or so it seems based on some other DTS examples.  It's very confusing.

 

The extcon driver in this case is fusb302.  There is one of those under drivers/usb/typec/tcpm that comes from Google.  But that doesn't seem to work no matter what I do with its dts config.  So I forward ported the fusb302 driver from the BSP, which comes from rockchip.  With some added debug I can see connection events and the callback to the workqueue function. 

 

Quote

You are right about the dwc3 controller needing to be reset at the same time, the patch thread discusses this requirement.  In fact, I think it was this very requirement that led to them stripping the 'static' keyword from the 'dwc3_phy_setup' function in dwc3/core.c so it could be called from their new dwc3/dwc3-rockchip.c driver.  It was this change in particular that caused the immediate NAK for upstream.

Turns out my version of that patch came later and does not have the call to dwc3_phy_setup() - which is why my port compiled without the core.c/h patch.  Of course, that may also be the reason it doesn't work.

 

Quote

I presume that if your port attempts lack the required logic to reset the dwc3 controller managed in core.c that is likely why the work queue item is hanging or locking up the system?  What kernel version and from what source did you port the driver?  If it isn't from the 'legacy' branch repo used by Armbian it might be worth trying again with the following version which I can confirm has functioning mode switch logic:

  https://github.com/ayufan-rock64/linux-kernel

   tag:4.4.202-1237-rockchip-ayufan

I ported it from a 4.4 kernel.   The ayufan-rock64 kernel is not something I can drop on this device.  We're bumped to 5.15.14 (upstream release + custom patches, most if not all are from the net) at the moment and it's tied to the specific u-boot we have.  It also probably wouldn't support our display, though I have a serial console so maybe that doesn't matter.

 

Quote

Are you possibly running into issues getting back to USB2 HS peripheral mode because you still have ported code compiled in?  I ask because I took Terry's DTS patch from above and integrated it into the Armbian build for a linux-5.10.y 'current' branch kernel (specifically 5.10.92-rockchip64) and have the peripheral mode operational as long as 'dr_mode = "peripheral"' is set in the built DTB as shown in the patch.  I have tested it with mass storage, hid and ncm gadgets, all working as expected.

My changes are simple, really.  They consist of choosing

  • a fusb302 driver:  Google's (CONFIG_TYPEC_FUSB302, plus some other typec drivers which I think are required) or Rockchips (CONFIG_FUSB_30X, which is part of my port and is standalone)
  • a dwc3-* driver: dwc3-of-simple (aka CONFIG_USB_DWC3_OF_SIMPLE) or dwc3-rockchip (CONFIG_USB_DWC3_ROCKCHIP, which I've added to the Kconfig). 

We run as an embedded board so nearly everything is statically compiled, but I make the fusb driver a module and manually load it after boot.  This way if any of the drivers lock up it won't happen until the fusb is loaded and I plug something in (or left something plugged in from the last test).  Then the DTS is updated to match those selections.  There are a few places that this matters.  Note that what follows is what I have, but it obviously isn't working.

 

When using the stock drivers (Google fusb302, dwc3-of-simple), it looks like this:

 

&i2c4 {
    status = "okay";
    fusb0: fusb30x@22 {
        // Google fusb
        compatible = "fcs,fusb302";
        fcs,int_n = <&gpio1 2 GPIO_ACTIVE_HIGH>;
        interrupt-parent = <&gpio1>;
        interrupts = <RK_PA2 IRQ_TYPE_LEVEL_LOW>;
        pinctrl-names = "default";
        pinctrl-0 = <&fusb0_int>;
        vbus-supply = <&vcc5v0_typec0>;
        status = "okay";

        connector {
            compatible = "usb-c-connector";
            data-role = "dual";
            label = "USB-C";
            op-sink-microwatt = <1000000>;
            power-role = "dual";
            sink-pdos =
                <PDO_FIXED(5000, 2500, PDO_FIXED_USB_COMM)>;
            source-pdos =
                <PDO_FIXED(5000, 1400, PDO_FIXED_USB_COMM)>;
            try-power-role = "sink";

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

                port@0 {
                    reg = <0>;

                    usbc_hs: endpoint {
                        remote-endpoint =
                            <&u2phy0_typec_hs>;
                    };
                };

                port@1 {
                    reg = <1>;

                    usbc_ss: endpoint {
                        remote-endpoint =
                            <&tcphy0_typec_ss>;
                    };
                };
            };
        };
    };
};
&u2phy0 {
    status = "okay";
    extcon = <&fusb0>;

    // otg-vbus-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
    u2phy0_otg: otg-port {
        // phy-supply = <&vcc5v0_typec0>;
        status = "okay";
    };
    u2phy0_host: host-port {
        phy-supply = <&vcc5v0_typec0>;
        status = "okay";
    };

    port {
        u2phy0_typec_hs: endpoint {
            remote-endpoint = <&usbc_hs>;
        };
    };
};
&usbdrd3_0 {
    status = "okay";
};
&usbdrd_dwc3_0 {
    status = "okay";
    dr_mode = "peripheral";
};
&tcphy0 {
    status = "okay";
    extcon = <&fusb0>;
};

&tcphy0_usb3 {
    status = "okay";
    extcon = <&fusb0>;
    port {
        tcphy0_typec_ss: endpoint {
            remote-endpoint = <&usbc_ss>;
        };
    };
};

 

When using the Rockchip fusb302 and dwc3 driver it looks like this:

&i2c4 {
    status = "okay";
    fusb0: fusb30x@22 {
        compatible = "fairchild,fusb302";
        vbus-5v-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
        int-n-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
        fusb302,role = "ROLE_MODE_DRP";
        fusb302,try_role = "ROLE_MODE_DRP";

        reg = <0x22>;
        pinctrl-names = "default";
        pinctrl-0 = <&fusb0_int>;
        status = "okay";
    };
};
&u2phy0 {
    status = "okay";

    otg-vbus-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
    u2phy0_otg: otg-port {
        status = "okay";
    };
    u2phy0_host: host-port {
        phy-supply = <&vcc5v0_typec0>;
        status = "disabled";
    };
};
&usbdrd3_0 {
    status = "okay";
    extcon = <&fusb0>;
};
&usbdrd_dwc3_0 {
    status = "okay";
    extcon = <&fusb0>;
    dr_mode = "otg";

    /* USB 3.0 */
    maximum-speed = "super-speed";
    phys = <&tcphy0_usb3>;
    phy-names = "usb3-phy";
};
&tcphy0 {
    status = "okay";
    extcon = <&fusb0>;
    resets = <&cru SRST_UPHY0>,
             <&cru SRST_UPHY0_PIPE_L00>,
             <&cru SRST_P_UPHY0_TCPHY>,
             <&cru SRST_A_USB3_OTG0>;
    reset-names = "uphy", "uphy-pipe", "uphy-tcphy", "usb3-otg";
};
&tcphy0_usb3 {
    status = "okay";
};

I'll try adding that dwc3_phy_setup() call just for grins to see what happens.  But I'm not sure it matters if I try to boot in peripheral mode to start with.  I think it only matters if I'm trying to use OTG.  I'm trying to use peripheral mode only right now just to get device mode working in any way possible (but preferrably at least at HS).

Link to comment
Share on other sites

1 hour ago, mjhammel said:

First, thanks for the tips.  It's good to have someone to boune ideas off of.

Yw and likewise.  I am still hoping to find someone who can help puzzle through what is missing to get OTG switching fully functional on Armbian 'current' branch kernels for the RockPi 4b.  I have at least realized through our discussion that the 'dwc3-rockchip' driver is entirely absent in the 5.10.y current kernels, so that almost certainly needs to be patched in for there to be any shot at getting it to work.  It is also clear why it is absent based on the upstream NAK link you provided.

 

1 hour ago, mjhammel said:

The extcon is the physical port (re: "external connection"), in this case a Typc-C connector on our board.  It notifies the phy core that then initiates the callback to the workqueue in the dwc3-rockchip driver.  At least that's my understanding.  You have to reference the extcon in the usbdrd3 proprerty, which is the rockchip dwc3 driver (the dwc3-simple driver doesn't directly reference an extcon), so it can attach the extcon to the phy.  But apparently you also need to attach it to the tcphy0 property, or so it seems based on some other DTS examples.  It's very confusing.

 

The extcon driver in this case is fusb302.  There is one of those under drivers/usb/typec/tcpm that comes from Google.  But that doesn't seem to work no matter what I do with its dts config.  So I forward ported the fusb302 driver from the BSP, which comes from rockchip.  With some added debug I can see connection events and the callback to the workqueue function. 

 

These past couple days are the first time I have ever ventured to understand what extcon is and what it is used for.  It is still vague, but I am guessing it is meant to be an abstraction between drivers that need some awareness of each others events?  So, in your case the dwc3-rockchip driver for the dwc3 controller needs a way to be aware of the UFP/DFP mode switch events generated by the fusb302 driver?

 

1 hour ago, mjhammel said:

Turns out my version of that patch came later and does not have the call to dwc3_phy_setup() - which is why my port compiled without the core.c/h patch.  Of course, that may also be the reason it doesn't work.

 

Does the later version of the patch provide the controller reset using a different approach?  Based on the patch thread it is mandatory to reset the dwc3 controller, so if the newer patch doesn't have equivalent behavior, implemented a different way, then it is very likely an issue.

 

After closer examination of the dwc3-rockchip driver in the Ayufan kernel I can now see that the dwc3_rockchip_otg_extcon_evt_work callback seems to use an OTG reset to force the dwc controller into P2 power state.  Upon resuming the PM runtime in core.c re-initializes the dwc3 controller.  I guess this is their workaround to not being able to remove 'static' and call dwc3_phy_setup() directly.

 

1 hour ago, mjhammel said:

I ported it from a 4.4 kernel.   The ayufan-rock64 kernel is not something I can drop on this device.  We're bumped to 5.15.14 (upstream release + custom patches, most if not all are from the net) at the moment and it's tied to the specific u-boot we have.  It also probably wouldn't support our display, though I have a serial console so maybe that doesn't matter.

 

I understand, but I was more suggesting that you could use the Ayufan kernel as a point of reference to see how the drivers differ.  In other words, does the Ayufan version have logic that your ported driver doesn't? If so, it could be the missing piece.  For example, the PM trick I pointed out above.

 

Also, it may be worth a shot to try porting the drivers, as is, from the Ayufan kernel to see if they work when compiled into your kernel?

 

1 hour ago, mjhammel said:

My changes are simple, really.  They consist of choosing

  • a fusb302 driver:  Google's (CONFIG_TYPEC_FUSB302, plus some other typec drivers which I think are required) or Rockchips (CONFIG_FUSB_30X, which is part of my port and is standalone)
  • a dwc3-* driver: dwc3-of-simple (aka CONFIG_USB_DWC3_OF_SIMPLE) or dwc3-rockchip (CONFIG_USB_DWC3_ROCKCHIP, which I've added to the Kconfig). 

We run as an embedded board so nearly everything is statically compiled, but I make the fusb driver a module and manually load it after boot.  This way if any of the drivers lock up it won't happen until the fusb is loaded and I plug something in (or left something plugged in from the last test).  Then the DTS is updated to match those selections.  There are a few places that this matters.  Note that what follows is what I have, but it obviously isn't working.

 

The RockPi4 B I am working with is a bit interesting because although it does have a fusb302 chip and a type-C connector it is only used to power the board.  The dwc3 OTG port is wired to one of the type-A connectors.  So, although technically there is a fusb302 preset it isn't used for anything USB related (i.e. fusb302.ko is compiled but not loaded).  Both host and peripheral modes are fully working, on 5.10.y with Terry's DTS patch, as far as I have tested.  However, I can only switch between the modes by changing dr_mode in DT and rebooting.  The live switching doesn't work because I now realize the 'dwc3-of-simple' driver is being used which doesn't support OTG switching.

 

For clarity, since the RockPi4 B connects the OTG port to a type-A connector it can only accomplish mode switching using either a sysfs file (soft switch as I call it), or by reacting to the physical switch that Radxa put on their board underneath the USB ports (hard switch as I call it).  I don't care about the hard switch, so I don't plan to make that functional on 5.10.y.  I only need the soft switch via a sysfs file and the drivers that can effect the switch correctly on a running system.

 

I presume your problem is a missing interaction between the fusb302 UFP/DFP mode switch events and a correct dwc3 controller reset catalyzed by the dwc3-rockchip driver.  If this isn't happening then when you modprobe the fusb302 module you lock the system because nothing causes the requisite dwc3 controller reset so that both chips are synchronized on what mode they should be operating in?

 

I would definitely compare the dwc3-rockchip driver in the Ayufan kernel to the one you ported to see if any differences stand out.

Link to comment
Share on other sites

Quote

in your case the dwc3-rockchip driver for the dwc3 controller needs a way to be aware of the UFP/DFP mode switch events generated by the fusb302 driver?

I think so, but I'm not experienced with the callback/notification methods enough to be clear on that.

Quote

Does the later version of the patch provide the controller reset using a different approach? 

It uses pm_runtime_*() functions to deal with it, I believe.

 

Quote

I was more suggesting that you could use the Ayufan kernel as a point of reference to see how the drivers differ.

I did that this morning and, while dwc3-rockchip.c in both are very similar, there are many differences that are not just kernel version related.  The processing in various functions is different.  I'm going to try to port Ayufan's dwc3-rockchip.c to 5.15.14 and see if that works better - there are only a few API changes I think.  The drivers/mfd/fusb302.c is also similar, but very different.  These all have the same copyright block at the top but it doesn't tell me which is newer or where they might have a common ancestor.

Quote

I can only switch between the modes by changing dr_mode in DT and rebooting.

You could manage that in software with a UI that swaps a DT overlay.  But it's basically just a software solution to the hardware switch.  Also, with kexec, you could reboot with a new DT without a hardware reset, but it's still a kernel reboot.

Quote

I only need the soft switch via a sysfs file and the drivers that can effect the switch correctly on a running system.

I'm able to switch modes (not that the modes work, but I can switch them) using debugfs instead of sysfs.  It's unclear to me how bad it would be to have debugfs mounted on a production system.  Might expose things you don't want exposed.  I suspose you could move the mode debugfs file to sysfs - you're basically just exposing a function call but it would probably be the same (or the same with a different wrapper for the API) for both.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines