usb: misc: nb7vpq904m: allow USB control connect and disconnect

add redriver_notify_connect() and redriver_notify_disconnect().

Change-Id: I48b2198df2a2257b13946fd8fcd7517f51073d45
Signed-off-by: Linyu Yuan <linyyuan@codeaurora.org>
This commit is contained in:
Linyu Yuan 2020-11-29 10:50:20 +08:00
commit 1362aa149f
2 changed files with 113 additions and 7 deletions

View file

@ -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;
};
@ -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;
@ -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,
@ -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;
}
@ -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;
@ -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_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 -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;
if (redriver->op_mode == OP_MODE_DP)
return 0;
@ -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,

View file

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