MLK-23753 imx8: Implement bus active check on OTG port
authorYe Li <ye.li@nxp.com>
Fri, 27 Mar 2020 03:45:17 +0000 (20:45 -0700)
committerYe Li <ye.li@nxp.com>
Thu, 29 Apr 2021 10:25:56 +0000 (03:25 -0700)
Using this way to check if OTG bus active, not depending on checking
OTG register. Because checking OTG register only working for first
cold boot from ROM. While doing partition reboot, SCFW will turn off
the entire conn SS, so that way won't work.

Signed-off-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
(cherry picked from commit ae746dcdb19914b5aa10ca8e8e9e9d5de854cdeb)
(cherry picked from commit a31720a8614e929ff4aff6ed12a4b065502437c8)

arch/arm/mach-imx/imx8/cpu.c
drivers/usb/gadget/ci_udc.c
include/usb/ci_udc.h

index 698e79f..e64925b 100644 (file)
@@ -31,6 +31,7 @@
 #include <spl.h>
 #include <env.h>
 #include <asm/mach-imx/imx_vservice.h>
+#include <usb/ci_udc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -1038,8 +1039,6 @@ int board_imx_lpi2c_bind(struct udevice *dev)
 }
 
 #ifdef CONFIG_USB_PORT_AUTO
-int usb_boot_index = 0xf;
-
 static int usb_port_auto_check(void)
 {
        int ret;
@@ -1065,7 +1064,7 @@ static int usb_port_auto_check(void)
                }
 
                enable_usboh3_clk(1);
-               usb2_data = readl(USB_BASE_ADDR + 0x154);
+               usb2_data = ci_udc_check_bus_active(USB_BASE_ADDR, USB_PHY0_BASE_ADDR, 0);
 
                ret = power_domain_off(&phy_pd);
                if (ret) {
@@ -1086,18 +1085,15 @@ static int usb_port_auto_check(void)
        return -1;
 }
 
-static void usb_port_record_index(void)
+int board_usb_gadget_port_auto(void)
 {
+    int usb_boot_index;
        usb_boot_index = usb_port_auto_check();
+
        if (usb_boot_index < 0)
                usb_boot_index = 0;
-}
 
-int board_usb_gadget_port_auto(void)
-{
-#if defined(CONFIG_SPL_BUILD)
-       usb_port_record_index();
-#endif
+       printf("auto usb %d\n", usb_boot_index);
 
        return usb_boot_index;
 }
@@ -1106,9 +1102,6 @@ int board_usb_gadget_port_auto(void)
 static void power_off_all_usb(void)
 {
        if (is_usb_boot()) {
-#ifdef CONFIG_USB_PORT_AUTO
-               usb_port_record_index();
-#endif
                /* Turn off all usb resource to let conn SS power down */
                sc_pm_set_resource_power_mode(-1, SC_R_USB_0_PHY, SC_PM_PW_MODE_OFF);
                sc_pm_set_resource_power_mode(-1, SC_R_USB_1_PHY, SC_PM_PW_MODE_OFF);
index 0dfb0c0..441e43c 100644 (file)
@@ -1037,6 +1037,99 @@ bool dfu_usb_get_reset(void)
        return !!(readl(&udc->usbsts) & STS_URI);
 }
 
+static int ci_udc_otg_phy_mode2(ulong phy_addr)
+{
+       void *__iomem phy_ctrl, *__iomem phy_status;
+       void *__iomem phy_base = (void *__iomem)phy_addr;
+       u32 val;
+
+       if (is_mx6() || is_mx7ulp() || is_imx8()) {
+               phy_ctrl = (void __iomem *)(phy_base + USBPHY_CTRL);
+               val = readl(phy_ctrl);
+               if (val & USBPHY_CTRL_OTG_ID)
+                       return USB_INIT_DEVICE;
+               else
+                       return USB_INIT_HOST;
+       } else if (is_mx7() || is_imx8mm() || is_imx8mn()) {
+               phy_status = (void __iomem *)(phy_base +
+                                             USBNC_PHY_STATUS_OFFSET);
+               val = readl(phy_status);
+               if (val & USBNC_PHYSTATUS_ID_DIG)
+                       return USB_INIT_DEVICE;
+               else
+                       return USB_INIT_HOST;
+       } else {
+               return -EINVAL;
+       }
+}
+
+bool udc_irq_reset(void)
+{
+       struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+       unsigned n = readl(&udc->usbsts);
+       writel(n, &udc->usbsts);
+
+       n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI);
+       if (n == 0)
+               return false;
+
+       if (n & STS_URI) {
+               DBG("-- reset --\n");
+               return true;
+       }
+
+       if (n & STS_SLI)
+               DBG("-- suspend --\n");
+
+       return false;
+}
+
+bool ci_udc_check_bus_active(ulong ehci_addr, ulong phy_addr, int index)
+{
+       struct usb_ehci *ehci = (struct usb_ehci *)ehci_addr;
+       struct ehci_ctrl ctrl;
+       int ret;
+       bool active = false;
+
+       ret = ehci_mx6_common_init(ehci, index);
+       if (ret)
+               return false;
+
+       if (ci_udc_otg_phy_mode2(phy_addr) != USB_INIT_DEVICE)
+               return false;
+
+       ctrl.hccr = (struct ehci_hccr *)((ulong)&ehci->caplength);
+       ctrl.hcor = (struct ehci_hcor *)((ulong)ctrl.hccr +
+                       HC_LENGTH(ehci_readl(&(ctrl.hccr)->cr_capbase)));
+       controller.ctrl = &ctrl;
+
+       ret = ci_udc_probe();
+       if (ret) {
+               return false;
+       }
+
+       ci_pullup(NULL, 1);
+
+       int count = 100;
+       while (count > 0) {
+               if (udc_irq_reset()) {
+                       active = true;
+                       break;
+               }
+               mdelay(10);
+               count--;
+       }
+
+       ci_pullup(NULL, 0);
+
+       ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req);
+       free(controller.items_mem);
+       free(controller.epts);
+
+       return active;
+}
+
+
 #if !CONFIG_IS_ENABLED(DM_USB_GADGET)
 int usb_gadget_handle_interrupts(int index)
 {
index f72f688..3e10f81 100644 (file)
@@ -12,4 +12,6 @@
 #define EP_MAX_PACKET_SIZE     0x200
 #define EP0_MAX_PACKET_SIZE    64
 
+bool ci_udc_check_bus_active(ulong ehci_addr, ulong phy_addr, int index);
+
 #endif /* __CI_UDC_H__ */