--- zzzz-none-000/linux-4.9.279/drivers/usb/host/xhci.c 2021-08-08 06:38:54.000000000 +0000 +++ puma7-atom-6591-750/linux-4.9.279/drivers/usb/host/xhci.c 2023-02-08 11:43:42.000000000 +0000 @@ -30,6 +30,14 @@ #include #include +#if defined (CONFIG_AVM_KERNEL) +#include +#include + +static struct delayed_work xhci_vbus_work; + +#endif + #include "xhci.h" #include "xhci-trace.h" #include "xhci-mtk.h" @@ -39,6 +47,13 @@ #define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) +#if defined (CONFIG_AVM_KERNEL) +/* 20160219 AVM/VGJ USB3 ports switchable */ +int usb3port_config = 0; //default USB2 only +module_param(usb3port_config, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(usb3port_config, "Bitmask of allowed USB3 ports"); +#endif + /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ static int link_quirk; module_param(link_quirk, int, S_IRUGO | S_IWUSR); @@ -48,6 +63,29 @@ module_param(quirks, uint, S_IRUGO); MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); +#if IS_ENABLED(CONFIG_AVM_KERNEL) +int gpio_avm_usb30_power(bool enable) +{ + enum _avm_hw_param param; + int gpio_enable; + int gpio_inv; + int gpio_pin; + int retval; + + retval = avm_get_hw_config(AVM_HW_CONFIG_VERSION, + "gpio_avm_usb30_pwr_en", &gpio_pin, ¶m); + if (retval < 0) { + pr_err("Failed retrieving USB GPIO pin configuration\n"); + return retval; + } + + gpio_inv = (param == avm_hw_param_gpio_out_active_low); + gpio_enable = enable ^ gpio_inv; + + return avm_gpio_out_bit(gpio_pin, gpio_enable); +} +#endif + /* * xhci_handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read @@ -564,6 +602,17 @@ /*-------------------------------------------------------------------------*/ +/* 20180214 AVM/WKR delayed work for activation of VBUS power */ +#if IS_ENABLED(CONFIG_AVM_KERNEL) +static void xhci_vbus_work_func(struct work_struct *work) +{ + if (!gpio_avm_usb30_power(true)) + pr_info("xHCI: delayed VBUS POWER on\n"); + else + pr_err("xHCI: failed turning on delayed VBUS POWER\n"); +} +#endif + static int xhci_run_finished(struct xhci_hcd *xhci) { if (xhci_start(xhci)) { @@ -576,6 +625,13 @@ if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); +#if IS_ENABLED(CONFIG_AVM_KERNEL) + /* delay VBUS power after host initialization */ + cancel_delayed_work_sync(&xhci_vbus_work); + pr_info("xHCI: delay VBUS POWER on for 100 ms\n"); + schedule_delayed_work(&xhci_vbus_work, msecs_to_jiffies(100)); +#endif + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_run for USB3 roothub"); return 0; @@ -727,6 +783,16 @@ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_stop completed - status = %x", readl(&xhci->op_regs->status)); + +#if IS_ENABLED(CONFIG_AVM_KERNEL) + cancel_delayed_work_sync(&xhci_vbus_work); + + if (!gpio_avm_usb30_power(false)) + pr_info("xHCI: PORT POWER off"); + else + pr_err("xHCI: failed turning PORT POWER off"); +#endif + mutex_unlock(&xhci->mutex); } @@ -5115,6 +5181,11 @@ static int __init xhci_hcd_init(void) { +#if IS_ENABLED(CONFIG_AVM_KERNEL) + /* Delayed work for re-activation of VBUS power */ + INIT_DELAYED_WORK(&xhci_vbus_work, xhci_vbus_work_func); +#endif + /* * Check the compiler generated sizes of structures that must be laid * out in specific ways for hardware access.