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

Commit a1d126aa authored by Mayank Rana's avatar Mayank Rana
Browse files

ucsi: Add usage of USB role switch functionality



This change adds usage of USB role switch framework to notify
USB role to start USB host/device stack to USB driver.

Change-Id: I9778e0e3d2db2aaccf2f19c6dfd2482dad6acbfc
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 0390237b
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -473,15 +473,19 @@ static void ucsi_unregister_partner(struct ucsi_connector *con)
static void ucsi_partner_change(struct ucsi_connector *con)
{
	int ret;
	struct ucsi *ucsi = con->ucsi;
	enum usb_role u_role = USB_ROLE_NONE;

	if (!con->partner)
		return;

	switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
	case UCSI_CONSTAT_PARTNER_TYPE_UFP:
		u_role = USB_ROLE_HOST;
		typec_set_data_role(con->port, TYPEC_HOST);
		break;
	case UCSI_CONSTAT_PARTNER_TYPE_DFP:
		u_role = USB_ROLE_DEVICE;
		typec_set_data_role(con->port, TYPEC_DEVICE);
		break;
	default:
@@ -492,6 +496,11 @@ static void ucsi_partner_change(struct ucsi_connector *con)
	if (!completion_done(&con->complete))
		complete(&con->complete);

	ret = usb_role_switch_set_role(ucsi->usb_role_sw, u_role);
	if (ret)
		dev_err(ucsi->dev, "%s(): failed to set role(%d):%d\n",
						__func__, u_role, ret);

	/* Can't rely on Partner Flags field. Always checking the alt modes. */
	ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP);
	if (ret)
@@ -510,6 +519,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
	enum typec_role role;
	u64 command;
	int ret;
	enum usb_role u_role = USB_ROLE_NONE;

	mutex_lock(&con->lock);

@@ -540,9 +550,11 @@ static void ucsi_handle_connector_change(struct work_struct *work)

		switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
		case UCSI_CONSTAT_PARTNER_TYPE_UFP:
			u_role = USB_ROLE_HOST;
			typec_set_data_role(con->port, TYPEC_HOST);
			break;
		case UCSI_CONSTAT_PARTNER_TYPE_DFP:
			u_role = USB_ROLE_DEVICE;
			typec_set_data_role(con->port, TYPEC_DEVICE);
			break;
		default:
@@ -553,6 +565,11 @@ static void ucsi_handle_connector_change(struct work_struct *work)
			ucsi_register_partner(con);
		else
			ucsi_unregister_partner(con);

		ret = usb_role_switch_set_role(ucsi->usb_role_sw, u_role);
		if (ret)
			dev_err(ucsi->dev, "%s(): failed to set role(%d):%d\n",
							__func__, u_role, ret);
	}

	if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) {
@@ -776,6 +793,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
	enum typec_accessory *accessory = cap->accessory;
	u64 command;
	int ret;
	enum usb_role role = USB_ROLE_NONE;

	INIT_WORK(&con->work, ucsi_handle_connector_change);
	init_completion(&con->complete);
@@ -840,9 +858,11 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)

	switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
	case UCSI_CONSTAT_PARTNER_TYPE_UFP:
		role = USB_ROLE_HOST;
		typec_set_data_role(con->port, TYPEC_HOST);
		break;
	case UCSI_CONSTAT_PARTNER_TYPE_DFP:
		role = USB_ROLE_DEVICE;
		typec_set_data_role(con->port, TYPEC_DEVICE);
		break;
	default:
@@ -857,6 +877,11 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
		ucsi_register_partner(con);
	}

	ret = usb_role_switch_set_role(ucsi->usb_role_sw, role);
	if (ret)
		dev_err(ucsi->dev, "%s(): failed to set role(%d):%d\n",
						__func__, role, ret);

	if (con->partner) {
		ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP);
		if (ret)
@@ -920,6 +945,13 @@ int ucsi_init(struct ucsi *ucsi)
		goto err_reset;
	}

	ucsi->usb_role_sw = fwnode_usb_role_switch_get(dev_fwnode(ucsi->dev));
	if (IS_ERR_OR_NULL(ucsi->usb_role_sw)) {
		dev_err(ucsi->dev, "%s(): Unable to find usb role switch\n",
								__func__);
		ucsi->usb_role_sw = NULL;
	}

	/* Register all connectors */
	for (i = 0; i < ucsi->cap.num_connectors; i++) {
		ret = ucsi_register_port(ucsi, i);
+3 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/types.h>
#include <linux/usb/typec.h>
#include <linux/usb/role.h>

/* -------------------------------------------------------------------------- */

@@ -277,6 +278,8 @@ struct ucsi {
#define EVENT_PENDING	0
#define COMMAND_PENDING	1
#define ACK_PENDING	2

	struct usb_role_switch *usb_role_sw;
};

#define UCSI_MAX_SVID		5