--- zzzz-none-000/linux-3.10.107/arch/mips/ath79/dev-usb.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/mips/ath79/dev-usb.c 2021-02-04 17:41:59.000000000 +0000 @@ -37,6 +37,8 @@ static struct usb_ehci_pdata ath79_ehci_pdata_v2 = { .caps_offset = 0x100, .has_tt = 1, + .qca_force_host_mode = 1, + .qca_force_16bit_ptw = 1, }; static void __init ath79_usb_register(const char *name, int id, @@ -159,6 +161,9 @@ ath79_device_reset_clear(AR913X_RESET_USB_PHY); mdelay(10); + ath79_ehci_pdata_v2.qca_force_host_mode = 0; + ath79_ehci_pdata_v2.qca_force_16bit_ptw = 0; + ath79_usb_register("ehci-platform", -1, AR913X_EHCI_BASE, AR913X_EHCI_SIZE, ATH79_CPU_IRQ(3), @@ -182,14 +187,34 @@ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } -static void __init ar934x_usb_setup(void) +static void enable_tx_tx_idp_violation_fix(unsigned base) { - u32 bootstrap; + void __iomem *phy_reg; + u32 t; + + phy_reg = ioremap(base, 4); + if (!phy_reg) + return; + + t = ioread32(phy_reg); + t &= ~0xff; + t |= 0x58; + iowrite32(t, phy_reg); + + iounmap(phy_reg); +} - bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); - if (bootstrap & AR934X_BOOTSTRAP_USB_MODE_DEVICE) +static void ar934x_usb_reset_notifier(struct platform_device *pdev) +{ + if (pdev->id != -1) return; + enable_tx_tx_idp_violation_fix(0x18116c94); + dev_info(&pdev->dev, "TX-TX IDP fix enabled\n"); +} + +static void __init ar934x_usb_setup(void) +{ ath79_device_reset_set(AR934X_RESET_USBSUS_OVERRIDE); udelay(1000); @@ -202,14 +227,64 @@ ath79_device_reset_clear(AR934X_RESET_USB_HOST); udelay(1000); + if (ath79_soc_rev >= 3) + ath79_ehci_pdata_v2.reset_notifier = ar934x_usb_reset_notifier; + ath79_usb_register("ehci-platform", -1, AR934X_EHCI_BASE, AR934X_EHCI_SIZE, ATH79_CPU_IRQ(3), &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } +static void __init qca953x_usb_setup(void) +{ + u32 bootstrap; + + bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); + + ath79_device_reset_set(QCA953X_RESET_USBSUS_OVERRIDE); + udelay(1000); + + ath79_device_reset_clear(QCA953X_RESET_USB_PHY); + udelay(1000); + + ath79_device_reset_clear(QCA953X_RESET_USB_PHY_ANALOG); + udelay(1000); + + ath79_device_reset_clear(QCA953X_RESET_USB_HOST); + udelay(1000); + + ath79_usb_register("ehci-platform", -1, + QCA953X_EHCI_BASE, QCA953X_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +} + +static void qca955x_usb_reset_notifier(struct platform_device *pdev) +{ + u32 base; + + switch (pdev->id) { + case 0: + base = 0x18116c94; + break; + + case 1: + base = 0x18116e54; + break; + + default: + return; + } + + enable_tx_tx_idp_violation_fix(base); + dev_info(&pdev->dev, "TX-TX IDP fix enabled\n"); +} + static void __init qca955x_usb_setup(void) { + ath79_ehci_pdata_v2.reset_notifier = qca955x_usb_reset_notifier; + ath79_usb_register("ehci-platform", 0, QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE, ATH79_IP3_IRQ(0), @@ -221,6 +296,27 @@ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } +static void __init qca956x_usb_setup(void) +{ + ath79_usb_register("ehci-platform", 0, + QCA956X_EHCI0_BASE, QCA956X_EHCI_SIZE, + ATH79_IP3_IRQ(0), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); + + ath79_usb_register("ehci-platform", 1, + QCA956X_EHCI1_BASE, QCA956X_EHCI_SIZE, + ATH79_IP3_IRQ(1), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +} + +static void __init qcn550x_usb_setup(void) +{ + ath79_usb_register("ehci-platform", 0, + QCN550X_EHCI0_BASE, QCN550X_EHCI_SIZE, + ATH79_IP3_IRQ(0), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +} + void __init ath79_register_usb(void) { if (soc_is_ar71xx()) @@ -235,8 +331,14 @@ ar933x_usb_setup(); else if (soc_is_ar934x()) ar934x_usb_setup(); + else if (soc_is_qca953x()) + qca953x_usb_setup(); else if (soc_is_qca955x()) qca955x_usb_setup(); + else if (soc_is_qca956x()) + qca956x_usb_setup(); + else if (soc_is_qcn550x()) + qcn550x_usb_setup(); else BUG(); }