From f3872ee37a1a50f9e6ec4eff70518c348ac908c2 Mon Sep 17 00:00:00 2001 From: Linyu Yuan Date: Mon, 16 Nov 2020 18:35:45 +0800 Subject: [PATCH] usb: misc: nb7vpq904m: fix issue when connect USB hub when redriver connect to a USB hub, and do adb root operation, due to redriver rx termination detection issue, hub will not detct device logical removal. workaround to temp disable/enable redriver when usb pullup operation. Change-Id: Ia3b0c99a28dd7d0601e7c5bcc612c4c48447c165 Signed-off-by: Linyu Yuan --- drivers/usb/misc/ssusb-redriver-nb7vpq904m.c | 39 ++++++++++++++++++++ include/linux/usb/redriver.h | 6 +++ 2 files changed, 45 insertions(+) diff --git a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c index f597879b9fdb..7b6d3d0fc76a 100644 --- a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c +++ b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c @@ -98,6 +98,8 @@ struct ssusb_redriver { u8 loss_match[CHAN_MODE_NUM][CHANNEL_NUM]; u8 flat_gain[CHAN_MODE_NUM][CHANNEL_NUM]; + u8 gen_dev_val; + struct dentry *debug_root; }; @@ -188,6 +190,8 @@ static void ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) break; } + redriver->gen_dev_val = val; + redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); } @@ -530,6 +534,41 @@ int redriver_release_usb_lanes(struct device_node *node) } EXPORT_SYMBOL(redriver_release_usb_lanes); +/* NOTE: DO NOT change mode in this funciton */ +int redriver_gadget_pullup(struct device_node *node, int is_on) +{ + struct ssusb_redriver *redriver; + struct i2c_client *client; + u8 val; + + if (!node) + return -EINVAL; + + client = of_find_i2c_device_by_node(node); + if (!client) + return -EINVAL; + + redriver = i2c_get_clientdata(client); + + /* + * when redriver connect to a USB hub, and do adb root operation, + * due to redriver rx termination detection issue, + * hub will not detct device logical removal. + * workaround to temp disable/enable redriver when usb pullup operation. + */ + if (redriver->op_mode != OP_MODE_USB) + return 0; + + val = redriver->gen_dev_val; + if (!is_on) + val &= ~CHIP_EN; + + redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); + + return 0; +} +EXPORT_SYMBOL(redriver_gadget_pullup); + static void ssusb_redriver_orientation_gpio_init( struct ssusb_redriver *redriver) { diff --git a/include/linux/usb/redriver.h b/include/linux/usb/redriver.h index 7b49225820ae..13fb97a97b54 100644 --- a/include/linux/usb/redriver.h +++ b/include/linux/usb/redriver.h @@ -9,6 +9,7 @@ #ifdef CONFIG_USB_REDRIVER int redriver_release_usb_lanes(struct device_node *node); +int redriver_gadget_pullup(struct device_node *node, int is_on); #else @@ -17,6 +18,11 @@ static inline int redriver_release_usb_lanes(struct device_node *node) return 0; } +static inline int redriver_gadget_pullup(struct device_node *node, int is_on) +{ + return 0; +} + #endif #endif /*__LINUX_USB_REDRIVER_H */