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.