Ar7240 (wa801-v1, wr741) usb patches (for v23.05.2)

Hi there!
I have two devices with ar7240 SoC. And it was so sad to see that usb gets bad while switching from ar71xx to ath79 arch. For that time I had no skills to do something with it. Someone told about it somewhere on this forum in that period, but no replies.
The behavior became like this

[    6.949330] ohci-platform 1b000000.usb: Generic Platform OHCI controller
[    6.956173] ohci-platform 1b000000.usb: new USB bus registered, assigned bus number 1
[    6.964114] ohci-platform 1b000000.usb: irq 3, io mem 0x1b000000
[    8.744853] usb 1-1: new full-speed USB device number 2 using ohci-platform
[    9.056825] ohci-platform 1b000000.usb: frame counter not updating; disabled
[    9.063907] ohci-platform 1b000000.usb: HC died; cleaning up
[   13.824989] usb usb1-port1: attempt power cycle

Recently I found fresh topic about this problem here
https://forum.openwrt.org/t/wr741nd-no-usb-on-recent-versions-21-02-5/154807
and there
https://github.com/openwrt/openwrt/issues/12224

and TS help me to find out missing lines of code and their new places.

I understand, that it's old usb, just 1.1, and there no devices in world and openwrt device tree on this SoC with soldered USB port. So I do not expect to see my patches in openwrt sources, though it will be nice.

But let it be here for modders like me, who just want do do something with hw/sw until it works better or became totally unrepairable...

So, the root or problem: in old arch ar71xx usb phy drivers was added to kernel by patches. One line of code writes to usb settings register with comment about this bug:

/* WAR for HW bug. Here it adjusts the duration between two SOFS */
__raw_writel(0x3, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ);

such corrections was also for ar7100 and thats lines was not vanished with drop-out patches, so I just compare the code for ar7100 and ar7200 (phy-ar7100-usb.c and phy-ar7200-usb.c) and get missing lines from there

patch for phy-ar7200-usb.c:

--- a/drivers/phy/phy-ar7200-usb.c
+++ b/drivers/phy/phy-ar7200-usb.c
@@ -10,13 +10,18 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
+#include <linux/delay.h>
 #include <linux/reset.h>
 #include <linux/of_gpio.h>
 
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+
 struct ar7200_usb_phy {
 	struct reset_control	*rst_phy;
 	struct reset_control	*rst_phy_analog;
 	struct reset_control	*suspend_override;
+        void __iomem            *io_base;
 	struct phy		*phy;
 	int			gpio;
 };
@@ -32,6 +37,10 @@ static int ar7200_usb_phy_power_on(struc
 		err |= reset_control_deassert(priv->rst_phy);
 	if (priv->rst_phy_analog)
 		err |= reset_control_deassert(priv->rst_phy_analog);
+        
+	mdelay(500);
+	/* WAR for HW bug. Here it adjusts the duration between two SOFS */
+	iowrite32(0x3, priv->io_base + AR71XX_USB_CTRL_REG_FLADJ);
 
 	return err;
 }
@@ -60,12 +69,18 @@ static const struct phy_ops ar7200_usb_p
 static int ar7200_usb_phy_probe(struct platform_device *pdev)
 {
 	struct phy_provider *phy_provider;
+        struct resource *res;
 	struct ar7200_usb_phy *priv;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+        priv->io_base = devm_ioremap_resource(&pdev->dev, res);
+        if (IS_ERR(priv->io_base))
+                return PTR_ERR(priv->io_base);
+
 	priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy");
 	if (IS_ERR(priv->rst_phy)) {
 		if (PTR_ERR(priv->rst_phy) != -EPROBE_DEFER)

it must not work without adding reg data to ar7240.dtsi like this:

--- old/ar7240.dtsi	2024-01-14 00:09:49.226689977 +0200
+++ new/ar7240.dtsi	2024-01-28 16:20:49.120573588 +0200
@@ -5,6 +5,7 @@
 / {
 	usb_phy: usb-phy {
 		compatible = "qca,ar7200-usb-phy";
+		reg = <0x18030000 0x10>;
 
 		reset-names = "usb-phy", "usb-ohci-dll";
 		resets = <&rst 4>, <&rst 3>;

now it works on wa801nd-v1:

[    6.190479] ehci-platform: EHCI generic platform driver
[    6.204488] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    6.213130] ohci-platform: OHCI generic platform driver
[    6.717512] ohci-platform 1b000000.usb: Generic Platform OHCI controller
[    6.724352] ohci-platform 1b000000.usb: new USB bus registered, assigned bus number 1
[    6.732418] ohci-platform 1b000000.usb: irq 3, io mem 0x1b000000
[    6.804868] hub 1-0:1.0: USB hub found
[    6.810124] hub 1-0:1.0: 1 port detected
[    6.826586] usbcore: registered new interface driver usb-storage
[    7.189521] usb 1-1: new full-speed USB device number 2 using ohci-platform
[    7.653507] usb-storage 1-1:1.0: USB Mass Storage device detected
[    7.671780] scsi host0: usb-storage 1-1:1.0
[    8.746585] scsi 0:0:0:0: Direct-Access     Wilk     GOODRAM 4GB      PMAP PQ: 0 ANSI: 6
[   11.713543] sd 0:0:0:0: [sda] 7815168 512-byte logical blocks: (4.00 GB/3.73 GiB)
[   11.726542] sd 0:0:0:0: [sda] Write Protect is off
[   11.737958] sd 0:0:0:0: [sda] No Caching mode page found
[   11.743412] sd 0:0:0:0: [sda] Assuming drive cache: write through
[   11.804094]  sda: sda1 sda2
[   11.830135] sd 0:0:0:0: [sda] Attached SCSI removable disk

Of course usb must be enabled somewhere in device dts like this

&usb_phy {
    status = "okay";
};

&usb {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";

    hub_port: port@1 {
        reg = <1>;
        #trigger-source-cells = <0>;
    };
};

and appropriate packages must be builded along the kernel too.

once more thans to user https://forum.openwrt.org/u/dossalab for his post.

2 Likes

I'm glad that there's still some interest in this mod, considering the router's age and the overall insanity of it...

At some point, I figured that finding a better router with USB would be more robust so I never bothered to fix this issue upstream. I've also created a patch, but as I said in the OP I had no idea if somebody will be willing to work on it.

Even though this router is garbage a lot of them were deployed over CIS countries, and I understand why people may want to find some use for the aging hardware.

Thanks, @taras.filatov & @dossalab,
With help of your investigation i updated the source and built OpenWrt 21 for dir-615 E4 (usb, spi flash 16mb and ddr 64mb mod).
usb 3g modems and external usb disk work fine with this old router on the OpenWrt.