Loading drivers/usb/misc/ssusb-redriver-nb7vpq904m.c +101 −7 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ struct ssusb_redriver { u8 flat_gain[CHAN_MODE_NUM][CHANNEL_NUM]; u8 gen_dev_val; int ucsi_i2c_write_err; struct dentry *debug_root; }; Loading Loading @@ -132,7 +133,7 @@ static int redriver_i2c_reg_set(struct ssusb_redriver *redriver, return 0; } static void ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) static int ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) { u8 val = 0; Loading Loading @@ -192,7 +193,7 @@ static void ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) redriver->gen_dev_val = val; redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); return redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); } static int ssusb_redriver_param_config(struct ssusb_redriver *redriver, Loading Loading @@ -352,7 +353,7 @@ static int ssusb_redriver_channel_update(struct ssusb_redriver *redriver) return 0; err: dev_err(redriver->dev, "channel parameters update failure.\n"); dev_err(redriver->dev, "channel parameters update failure(%d).\n", ret); return ret; } Loading Loading @@ -458,6 +459,7 @@ static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, container_of(nb, struct ssusb_redriver, ucsi_nb); struct ucsi_glink_constat_info *info = data; enum operation_mode op_mode; int ret; if (info->connect && !info->partner_change) return NOTIFY_DONE; Loading Loading @@ -501,25 +503,115 @@ static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, "CC1" : "CC2"); } ssusb_redriver_channel_update(redriver); ret = ssusb_redriver_channel_update(redriver); if (ret) { dev_dbg(redriver->dev, "i2c bus may not resume(%d)\n", ret); redriver->ucsi_i2c_write_err = ret; return NOTIFY_DONE; } ssusb_redriver_gen_dev_set(redriver); return NOTIFY_OK; } int redriver_release_usb_lanes(struct device_node *node) int redriver_notify_connect(struct device_node *node) { struct ssusb_redriver *redriver; struct i2c_client *client; if (!node) return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; /* 1. no operation in recovery mode. * 2. needed when usb related mode set. * 3. currently ucsi notification arrive to redriver earlier than usb, * in ucsi notification callback, save mode even i2c write failed, * but add ucsi_i2c_write_err to indicate i2c write error, * this allow usb trigger i2c write again by check it. * !!! if future remove ucsi, ucsi_i2c_write_err can be removed, * and this function also need update !!!. */ if ((redriver->op_mode == OP_MODE_DEFAULT) || ((redriver->op_mode != OP_MODE_USB) && (redriver->op_mode != OP_MODE_USB_AND_DP)) || (!redriver->ucsi_i2c_write_err)) return 0; dev_dbg(redriver->dev, "op mode %s\n", OPMODESTR(redriver->op_mode)); /* !!! assume i2c resume complete here !!! */ ssusb_redriver_channel_update(redriver); ssusb_redriver_gen_dev_set(redriver); redriver->ucsi_i2c_write_err = 0; return 0; } EXPORT_SYMBOL(redriver_notify_connect); int redriver_notify_disconnect(struct device_node *node) { struct ssusb_redriver *redriver; struct i2c_client *client; if (!node) return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; /* 1. no operation in recovery mode. * 2. there is case for 4 lane display, first report usb mode, * second call usb release super speed lanes, * then stop usb host and call this disconnect, * it should not disable chip. * 3. if already disabled, no need to disable again. */ if ((redriver->op_mode == OP_MODE_DEFAULT) || (redriver->op_mode == OP_MODE_DP) || (redriver->op_mode == OP_MODE_NONE)) return 0; dev_dbg(redriver->dev, "op mode %s -> %s\n", OPMODESTR(redriver->op_mode), OPMODESTR(OP_MODE_NONE)); redriver->op_mode = OP_MODE_NONE; ssusb_redriver_gen_dev_set(redriver); return 0; } EXPORT_SYMBOL(redriver_notify_disconnect); int redriver_release_usb_lanes(struct device_node *node) { struct ssusb_redriver *redriver; struct i2c_client *client; if (!node) return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; if (redriver->op_mode == OP_MODE_DP) return 0; Loading @@ -542,13 +634,15 @@ int redriver_gadget_pullup(struct device_node *node, int is_on) u8 val; if (!node) return -EINVAL; return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -EINVAL; return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; /* * when redriver connect to a USB hub, and do adb root operation, Loading include/linux/usb/redriver.h +12 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ int redriver_release_usb_lanes(struct device_node *node); int redriver_gadget_pullup(struct device_node *node, int is_on); int redriver_notify_connect(struct device_node *node); int redriver_notify_disconnect(struct device_node *node); #else Loading @@ -23,6 +25,16 @@ static inline int redriver_gadget_pullup(struct device_node *node, int is_on) return 0; } static inline int redriver_notify_connect(struct device_node *node) { return 0; } static inline int redriver_notify_disconnect(struct device_node *node) { return 0; } #endif #endif /*__LINUX_USB_REDRIVER_H */ Loading
drivers/usb/misc/ssusb-redriver-nb7vpq904m.c +101 −7 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ struct ssusb_redriver { u8 flat_gain[CHAN_MODE_NUM][CHANNEL_NUM]; u8 gen_dev_val; int ucsi_i2c_write_err; struct dentry *debug_root; }; Loading Loading @@ -132,7 +133,7 @@ static int redriver_i2c_reg_set(struct ssusb_redriver *redriver, return 0; } static void ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) static int ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) { u8 val = 0; Loading Loading @@ -192,7 +193,7 @@ static void ssusb_redriver_gen_dev_set(struct ssusb_redriver *redriver) redriver->gen_dev_val = val; redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); return redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); } static int ssusb_redriver_param_config(struct ssusb_redriver *redriver, Loading Loading @@ -352,7 +353,7 @@ static int ssusb_redriver_channel_update(struct ssusb_redriver *redriver) return 0; err: dev_err(redriver->dev, "channel parameters update failure.\n"); dev_err(redriver->dev, "channel parameters update failure(%d).\n", ret); return ret; } Loading Loading @@ -458,6 +459,7 @@ static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, container_of(nb, struct ssusb_redriver, ucsi_nb); struct ucsi_glink_constat_info *info = data; enum operation_mode op_mode; int ret; if (info->connect && !info->partner_change) return NOTIFY_DONE; Loading Loading @@ -501,25 +503,115 @@ static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, "CC1" : "CC2"); } ssusb_redriver_channel_update(redriver); ret = ssusb_redriver_channel_update(redriver); if (ret) { dev_dbg(redriver->dev, "i2c bus may not resume(%d)\n", ret); redriver->ucsi_i2c_write_err = ret; return NOTIFY_DONE; } ssusb_redriver_gen_dev_set(redriver); return NOTIFY_OK; } int redriver_release_usb_lanes(struct device_node *node) int redriver_notify_connect(struct device_node *node) { struct ssusb_redriver *redriver; struct i2c_client *client; if (!node) return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; /* 1. no operation in recovery mode. * 2. needed when usb related mode set. * 3. currently ucsi notification arrive to redriver earlier than usb, * in ucsi notification callback, save mode even i2c write failed, * but add ucsi_i2c_write_err to indicate i2c write error, * this allow usb trigger i2c write again by check it. * !!! if future remove ucsi, ucsi_i2c_write_err can be removed, * and this function also need update !!!. */ if ((redriver->op_mode == OP_MODE_DEFAULT) || ((redriver->op_mode != OP_MODE_USB) && (redriver->op_mode != OP_MODE_USB_AND_DP)) || (!redriver->ucsi_i2c_write_err)) return 0; dev_dbg(redriver->dev, "op mode %s\n", OPMODESTR(redriver->op_mode)); /* !!! assume i2c resume complete here !!! */ ssusb_redriver_channel_update(redriver); ssusb_redriver_gen_dev_set(redriver); redriver->ucsi_i2c_write_err = 0; return 0; } EXPORT_SYMBOL(redriver_notify_connect); int redriver_notify_disconnect(struct device_node *node) { struct ssusb_redriver *redriver; struct i2c_client *client; if (!node) return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; /* 1. no operation in recovery mode. * 2. there is case for 4 lane display, first report usb mode, * second call usb release super speed lanes, * then stop usb host and call this disconnect, * it should not disable chip. * 3. if already disabled, no need to disable again. */ if ((redriver->op_mode == OP_MODE_DEFAULT) || (redriver->op_mode == OP_MODE_DP) || (redriver->op_mode == OP_MODE_NONE)) return 0; dev_dbg(redriver->dev, "op mode %s -> %s\n", OPMODESTR(redriver->op_mode), OPMODESTR(OP_MODE_NONE)); redriver->op_mode = OP_MODE_NONE; ssusb_redriver_gen_dev_set(redriver); return 0; } EXPORT_SYMBOL(redriver_notify_disconnect); int redriver_release_usb_lanes(struct device_node *node) { struct ssusb_redriver *redriver; struct i2c_client *client; if (!node) return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; if (redriver->op_mode == OP_MODE_DP) return 0; Loading @@ -542,13 +634,15 @@ int redriver_gadget_pullup(struct device_node *node, int is_on) u8 val; if (!node) return -EINVAL; return -ENODEV; client = of_find_i2c_device_by_node(node); if (!client) return -EINVAL; return -ENODEV; redriver = i2c_get_clientdata(client); if (!redriver) return -EINVAL; /* * when redriver connect to a USB hub, and do adb root operation, Loading
include/linux/usb/redriver.h +12 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ int redriver_release_usb_lanes(struct device_node *node); int redriver_gadget_pullup(struct device_node *node, int is_on); int redriver_notify_connect(struct device_node *node); int redriver_notify_disconnect(struct device_node *node); #else Loading @@ -23,6 +25,16 @@ static inline int redriver_gadget_pullup(struct device_node *node, int is_on) return 0; } static inline int redriver_notify_connect(struct device_node *node) { return 0; } static inline int redriver_notify_disconnect(struct device_node *node) { return 0; } #endif #endif /*__LINUX_USB_REDRIVER_H */