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 <linyyuan@codeaurora.org>
This commit is contained in:
Linyu Yuan 2020-11-16 18:35:45 +08:00 • committed by Gerrit - the friendly Code Review server
commit f3872ee37a
2 changed files with 45 additions and 0 deletions

View file

@ -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)
{

View file

@ -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 */