Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1362aa14 authored by Linyu Yuan's avatar Linyu Yuan
Browse files

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



add redriver_notify_connect() and redriver_notify_disconnect().

Change-Id: I48b2198df2a2257b13946fd8fcd7517f51073d45
Signed-off-by: default avatarLinyu Yuan <linyyuan@codeaurora.org>
parent aa860b5b
Loading
Loading
Loading
Loading
+101 −7
Original line number Diff line number Diff line
@@ -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_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;
@@ -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,
+12 −0
Original line number Diff line number Diff line
@@ -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 */