--- zzzz-none-000/linux-4.9.279/drivers/usb/host/xhci-ring.c 2021-08-08 06:38:54.000000000 +0000 +++ puma7-atom-6591-750/linux-4.9.279/drivers/usb/host/xhci-ring.c 2023-02-08 11:43:42.000000000 +0000 @@ -71,6 +71,16 @@ #include "xhci-trace.h" #include "xhci-mtk.h" +#if defined (CONFIG_AVM_KERNEL) +/* 20180719 AVM/VGJ USB3 ports switchable */ +extern int usb3port_config; + +#define HUB_DEBOUNCE_TIMEOUT 2000 +#define HUB_DEBOUNCE_STEP 25 +#define HUB_DEBOUNCE_STABLE 100 +#endif + + /* * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA * address of the TRB. @@ -1609,6 +1619,51 @@ port_id); temp = readl(port_array[faked_port_index]); + +#if defined (CONFIG_AVM_KERNEL) + /* 20180719 AVM/VGJ Disable USB3 if necessary when a device is connected */ + if ((hcd->speed == HCD_USB3) && (temp & PORT_CONNECT)) { + if (!(usb3port_config & faked_port_index)) { + int total_time; + + /* Disable Port as in xhci_hub_control */ + xhci_warn(xhci, "Disable port %d\n", faked_port_index); + temp = xhci_port_state_to_neutral(temp); + /* + * Clear all change bits, so that we get a new + * connection event. + */ + temp |= PORT_CSC | PORT_PEC | PORT_WRC | + PORT_OCC | PORT_RC | PORT_PLC | + PORT_CEC; + writel(temp | PORT_PE, + port_array[faked_port_index]); + temp = readl(port_array[faked_port_index]); + + /* Wait for the link to enter the disabled state as in hub_usb3_port_disable */ + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { + temp = readl(port_array[faked_port_index]); + xhci_warn(xhci, "waiting for port %d to disable, status = 0x%x\n", faked_port_index, temp); + + if ((temp & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_DISABLED) + break; + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + break; + msleep(HUB_DEBOUNCE_STEP); + } + } + } + + /* 20180719 AVM/VGJ Enable USB3 if necessary when a device is disconnected */ + if ((hcd->speed != HCD_USB3) && (temp & PORT_CSC) && !(temp & PORT_CONNECT)) { + if (!(usb3port_config & faked_port_index)) { + /* Enable port */ + xhci_warn(xhci, "Enable port %d\n", faked_port_index); + xhci_set_link_state(xhci, xhci->usb3_ports, faked_port_index, USB_SS_PORT_LS_RX_DETECT); + } + } +#endif if (hcd->state == HC_STATE_SUSPENDED) { xhci_dbg(xhci, "resume root hub\n"); usb_hcd_resume_root_hub(hcd);