Commit 226ff2e6 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman
Browse files

usb: typec: ucsi: Convert connector specific commands to bitmaps



That allows the fields in those command data structures to
be easily validated. If an unsupported field is accessed, a
warning is generated.

This will not force UCSI version checks to be made in every
place where these data structures are accessed, but it will
make it easier to pinpoint issues that are caused by the
unconditional accesses to those fields, and perhaps more
importantly, allow those issues to be noticed immediately.

Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20241106150605.1017744-1-heikki.krogerus@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 474538b8
Loading
Loading
Loading
Loading
+12 −16
Original line number Diff line number Diff line
@@ -55,8 +55,8 @@ static int ucsi_psy_get_online(struct ucsi_connector *con,
			       union power_supply_propval *val)
{
	val->intval = UCSI_PSY_OFFLINE;
	if (con->status.flags & UCSI_CONSTAT_CONNECTED &&
	    (con->status.flags & UCSI_CONSTAT_PWR_DIR) == TYPEC_SINK)
	if (UCSI_CONSTAT(con, CONNECTED) &&
	    (UCSI_CONSTAT(con, PWR_DIR) == TYPEC_SINK))
		val->intval = UCSI_PSY_FIXED_ONLINE;
	return 0;
}
@@ -66,7 +66,7 @@ static int ucsi_psy_get_voltage_min(struct ucsi_connector *con,
{
	u32 pdo;

	switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
	case UCSI_CONSTAT_PWR_OPMODE_PD:
		pdo = con->src_pdos[0];
		val->intval = pdo_fixed_voltage(pdo) * 1000;
@@ -89,7 +89,7 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connector *con,
{
	u32 pdo;

	switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
	case UCSI_CONSTAT_PWR_OPMODE_PD:
		if (con->num_pdos > 0) {
			pdo = con->src_pdos[con->num_pdos - 1];
@@ -117,7 +117,7 @@ static int ucsi_psy_get_voltage_now(struct ucsi_connector *con,
	int index;
	u32 pdo;

	switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
	case UCSI_CONSTAT_PWR_OPMODE_PD:
		index = rdo_index(con->rdo);
		if (index > 0) {
@@ -145,7 +145,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
{
	u32 pdo;

	switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
	case UCSI_CONSTAT_PWR_OPMODE_PD:
		if (con->num_pdos > 0) {
			pdo = con->src_pdos[con->num_pdos - 1];
@@ -173,9 +173,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
static int ucsi_psy_get_current_now(struct ucsi_connector *con,
				    union power_supply_propval *val)
{
	u16 flags = con->status.flags;

	if (UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD)
	if (UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD)
		val->intval = rdo_op_current(con->rdo) * 1000;
	else
		val->intval = 0;
@@ -185,11 +183,9 @@ static int ucsi_psy_get_current_now(struct ucsi_connector *con,
static int ucsi_psy_get_usb_type(struct ucsi_connector *con,
				 union power_supply_propval *val)
{
	u16 flags = con->status.flags;

	val->intval = POWER_SUPPLY_USB_TYPE_C;
	if (flags & UCSI_CONSTAT_CONNECTED &&
	    UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD)
	if (UCSI_CONSTAT(con, CONNECTED) &&
	    UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD)
		val->intval = POWER_SUPPLY_USB_TYPE_PD;

	return 0;
@@ -197,18 +193,18 @@ static int ucsi_psy_get_usb_type(struct ucsi_connector *con,

static int ucsi_psy_get_charge_type(struct ucsi_connector *con, union power_supply_propval *val)
{
	if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) {
	if (!(UCSI_CONSTAT(con, CONNECTED))) {
		val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
		return 0;
	}

	/* The Battery Charging Cabability Status field is only valid in sink role. */
	if ((con->status.flags & UCSI_CONSTAT_PWR_DIR) != TYPEC_SINK) {
	if (UCSI_CONSTAT(con, PWR_DIR) != TYPEC_SINK) {
		val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
		return 0;
	}

	switch (UCSI_CONSTAT_BC_STATUS(con->status.pwr_status)) {
	switch (UCSI_CONSTAT(con, BC_STATUS)) {
	case UCSI_CONSTAT_BC_NOMINAL_CHARGING:
		val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
		break;
+14 −14
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ DEFINE_EVENT(ucsi_log_command, ucsi_reset_ppm,
);

DECLARE_EVENT_CLASS(ucsi_log_connector_status,
	TP_PROTO(int port, struct ucsi_connector_status *status),
	TP_ARGS(port, status),
	TP_PROTO(int port, struct ucsi_connector *con),
	TP_ARGS(port, con),
	TP_STRUCT__entry(
		__field(int, port)
		__field(u16, change)
@@ -55,14 +55,14 @@ DECLARE_EVENT_CLASS(ucsi_log_connector_status,
	),
	TP_fast_assign(
		__entry->port = port - 1;
		__entry->change = status->change;
		__entry->opmode = UCSI_CONSTAT_PWR_OPMODE(status->flags);
		__entry->connected = !!(status->flags & UCSI_CONSTAT_CONNECTED);
		__entry->pwr_dir = !!(status->flags & UCSI_CONSTAT_PWR_DIR);
		__entry->partner_flags = UCSI_CONSTAT_PARTNER_FLAGS(status->flags);
		__entry->partner_type = UCSI_CONSTAT_PARTNER_TYPE(status->flags);
		__entry->request_data_obj = status->request_data_obj;
		__entry->bc_status = UCSI_CONSTAT_BC_STATUS(status->pwr_status);
		__entry->change = UCSI_CONSTAT(con, CHANGE);
		__entry->opmode = UCSI_CONSTAT(con, PWR_OPMODE);
		__entry->connected = UCSI_CONSTAT(con, CONNECTED);
		__entry->pwr_dir = UCSI_CONSTAT(con, PWR_DIR);
		__entry->partner_flags = UCSI_CONSTAT(con, PARTNER_FLAGS);
		__entry->partner_type = UCSI_CONSTAT(con, PARTNER_TYPE);
		__entry->request_data_obj = UCSI_CONSTAT(con, RDO);
		__entry->bc_status = UCSI_CONSTAT(con, BC_STATUS);
	),
	TP_printk("port%d status: change=%04x, opmode=%x, connected=%d, "
		"sourcing=%d, partner_flags=%x, partner_type=%x, "
@@ -73,13 +73,13 @@ DECLARE_EVENT_CLASS(ucsi_log_connector_status,
);

DEFINE_EVENT(ucsi_log_connector_status, ucsi_connector_change,
	TP_PROTO(int port, struct ucsi_connector_status *status),
	TP_ARGS(port, status)
	TP_PROTO(int port, struct ucsi_connector *con),
	TP_ARGS(port, con)
);

DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port,
	TP_PROTO(int port, struct ucsi_connector_status *status),
	TP_ARGS(port, status)
	TP_PROTO(int port, struct ucsi_connector *con),
	TP_ARGS(port, con)
);

DECLARE_EVENT_CLASS(ucsi_log_register_altmode,
+59 −62
Original line number Diff line number Diff line
@@ -651,10 +651,11 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
{
	u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
	struct ucsi *ucsi = con->ucsi;
	size_t size = min(UCSI_GET_CONNECTOR_STATUS_SIZE, UCSI_MAX_DATA_LENGTH(con->ucsi));
	int ret;

	ret = ucsi_send_command_common(ucsi, command, &con->status, sizeof(con->status), conn_ack);
	ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);

	return ret < 0 ? ret : 0;
}

@@ -668,8 +669,7 @@ static int ucsi_read_pdos(struct ucsi_connector *con,

	if (is_partner &&
	    ucsi->quirks & UCSI_NO_PARTNER_PDOS &&
	    ((con->status.flags & UCSI_CONSTAT_PWR_DIR) ||
	     !is_source(role)))
	    (UCSI_CONSTAT(con, PWR_DIR) || !is_source(role)))
		return 0;

	command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num);
@@ -983,6 +983,7 @@ static void ucsi_unregister_cable(struct ucsi_connector *con)

static int ucsi_check_connector_capability(struct ucsi_connector *con)
{
	u64 pd_revision;
	u64 command;
	int ret;

@@ -996,17 +997,17 @@ static int ucsi_check_connector_capability(struct ucsi_connector *con)
		return ret;
	}

	typec_partner_set_pd_revision(con->partner,
		UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
	pd_revision = UCSI_CONCAP(con, PARTNER_PD_REVISION_V2_1);
	typec_partner_set_pd_revision(con->partner, UCSI_SPEC_REVISION_TO_BCD(pd_revision));

	return ret;
}

static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
{
	switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
	case UCSI_CONSTAT_PWR_OPMODE_PD:
		con->rdo = con->status.request_data_obj;
		con->rdo = UCSI_CONSTAT(con, RDO);
		typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
		ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0);
		ucsi_partner_task(con, ucsi_check_altmodes, 30, HZ);
@@ -1030,7 +1031,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con)

static int ucsi_register_partner(struct ucsi_connector *con)
{
	u8 pwr_opmode = UCSI_CONSTAT_PWR_OPMODE(con->status.flags);
	u8 pwr_opmode = UCSI_CONSTAT(con, PWR_OPMODE);
	struct typec_partner_desc desc;
	struct typec_partner *partner;

@@ -1039,7 +1040,7 @@ static int ucsi_register_partner(struct ucsi_connector *con)

	memset(&desc, 0, sizeof(desc));

	switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
	case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
		desc.accessory = TYPEC_ACCESSORY_DEBUG;
		break;
@@ -1057,6 +1058,11 @@ static int ucsi_register_partner(struct ucsi_connector *con)
		desc.identity = &con->partner_identity;
	desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;

	if (con->ucsi->version >= UCSI_VERSION_2_1) {
		u64 pd_revision = UCSI_CONCAP(con, PARTNER_PD_REVISION_V2_1);
		desc.pd_revision = UCSI_SPEC_REVISION_TO_BCD(pd_revision);
	}

	partner = typec_register_partner(con->port, &desc);
	if (IS_ERR(partner)) {
		dev_err(con->ucsi->dev,
@@ -1067,13 +1073,11 @@ static int ucsi_register_partner(struct ucsi_connector *con)

	con->partner = partner;

	if ((con->ucsi->version >= UCSI_VERSION_3_0) &&
	    (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) &
	     UCSI_CONSTAT_PARTNER_FLAG_USB4_GEN4))
	if (con->ucsi->version >= UCSI_VERSION_3_0 &&
	    UCSI_CONSTAT(con, PARTNER_FLAG_USB4_GEN4))
		typec_partner_set_usb_mode(partner, USB_MODE_USB4);
	else if ((con->ucsi->version >= UCSI_VERSION_2_0) &&
		 (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) &
		  UCSI_CONSTAT_PARTNER_FLAG_USB4_GEN3))
	else if (con->ucsi->version >= UCSI_VERSION_2_0 &&
		 UCSI_CONSTAT(con, PARTNER_FLAG_USB4_GEN3))
		typec_partner_set_usb_mode(partner, USB_MODE_USB4);

	return 0;
@@ -1100,7 +1104,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)
	enum usb_role u_role = USB_ROLE_NONE;
	int ret;

	switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
	case UCSI_CONSTAT_PARTNER_TYPE_UFP:
	case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
		u_role = USB_ROLE_HOST;
@@ -1116,8 +1120,8 @@ static void ucsi_partner_change(struct ucsi_connector *con)
		break;
	}

	if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
		switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
	if (UCSI_CONSTAT(con, CONNECTED)) {
		switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
		case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
			typec_set_mode(con->port, TYPEC_MODE_DEBUG);
			break;
@@ -1125,14 +1129,13 @@ static void ucsi_partner_change(struct ucsi_connector *con)
			typec_set_mode(con->port, TYPEC_MODE_AUDIO);
			break;
		default:
			if (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) ==
					UCSI_CONSTAT_PARTNER_FLAG_USB)
			if (UCSI_CONSTAT(con, PARTNER_FLAG_USB))
				typec_set_mode(con->port, TYPEC_STATE_USB);
		}
	}

	/* Only notify USB controller if partner supports USB data */
	if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
	if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
		u_role = USB_ROLE_NONE;

	ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
@@ -1143,7 +1146,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)

static int ucsi_check_connection(struct ucsi_connector *con)
{
	u8 prev_flags = con->status.flags;
	u8 prev_state = UCSI_CONSTAT(con, CONNECTED);
	int ret;

	ret = ucsi_get_connector_status(con, false);
@@ -1152,10 +1155,9 @@ static int ucsi_check_connection(struct ucsi_connector *con)
		return ret;
	}

	if (con->status.flags == prev_flags)
	if (UCSI_CONSTAT(con, CONNECTED)) {
		if (prev_state)
			return 0;

	if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
		ucsi_register_partner(con);
		ucsi_pwr_opmode_change(con);
		ucsi_partner_change(con);
@@ -1211,6 +1213,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
						  work);
	struct ucsi *ucsi = con->ucsi;
	enum typec_role role;
	u16 change;
	int ret;

	mutex_lock(&con->lock);
@@ -1227,14 +1230,15 @@ static void ucsi_handle_connector_change(struct work_struct *work)
		goto out_unlock;
	}

	trace_ucsi_connector_change(con->num, &con->status);
	trace_ucsi_connector_change(con->num, con);

	if (ucsi->ops->connector_status)
		ucsi->ops->connector_status(con);

	role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
	change = UCSI_CONSTAT(con, CHANGE);
	role = UCSI_CONSTAT(con, PWR_DIR);

	if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
	if (change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
		typec_set_pwr_role(con->port, role);

		/* Complete pending power role swap */
@@ -1242,12 +1246,12 @@ static void ucsi_handle_connector_change(struct work_struct *work)
			complete(&con->complete);
	}

	if (con->status.change & UCSI_CONSTAT_CONNECT_CHANGE) {
	if (change & UCSI_CONSTAT_CONNECT_CHANGE) {
		typec_set_pwr_role(con->port, role);
		ucsi_port_psy_changed(con);
		ucsi_partner_change(con);

		if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
		if (UCSI_CONSTAT(con, CONNECTED)) {
			ucsi_register_partner(con);
			ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
			if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
@@ -1255,8 +1259,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
			if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
				ucsi_partner_task(con, ucsi_check_cable, 1, HZ);

			if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
			    UCSI_CONSTAT_PWR_OPMODE_PD) {
			if (UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
				ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
				ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
			}
@@ -1265,11 +1268,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
		}
	}

	if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE ||
	    con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE)
	if (change & (UCSI_CONSTAT_POWER_OPMODE_CHANGE | UCSI_CONSTAT_POWER_LEVEL_CHANGE))
		ucsi_pwr_opmode_change(con);

	if (con->partner && con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) {
	if (con->partner && (change & UCSI_CONSTAT_PARTNER_CHANGE)) {
		ucsi_partner_change(con);

		/* Complete pending data role swap */
@@ -1277,10 +1279,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
			complete(&con->complete);
	}

	if (con->status.change & UCSI_CONSTAT_CAM_CHANGE)
	if (change & UCSI_CONSTAT_CAM_CHANGE)
		ucsi_partner_task(con, ucsi_check_altmodes, 1, HZ);

	if (con->status.change & UCSI_CONSTAT_BC_CHANGE)
	if (change & UCSI_CONSTAT_BC_CHANGE)
		ucsi_port_psy_changed(con);

out_unlock:
@@ -1440,7 +1442,7 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role)
		goto out_unlock;
	}

	partner_type = UCSI_CONSTAT_PARTNER_TYPE(con->status.flags);
	partner_type = UCSI_CONSTAT(con, PARTNER_TYPE);
	if ((partner_type == UCSI_CONSTAT_PARTNER_TYPE_DFP &&
	     role == TYPEC_DEVICE) ||
	    (partner_type == UCSI_CONSTAT_PARTNER_TYPE_UFP &&
@@ -1484,7 +1486,7 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
		goto out_unlock;
	}

	cur_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
	cur_role = UCSI_CONSTAT(con, PWR_DIR);

	if (cur_role == role)
		goto out_unlock;
@@ -1507,8 +1509,7 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
	mutex_lock(&con->lock);

	/* Something has gone wrong while swapping the role */
	if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) !=
	    UCSI_CONSTAT_PWR_OPMODE_PD) {
	if (UCSI_CONSTAT(con, PWR_OPMODE) != UCSI_CONSTAT_PWR_OPMODE_PD) {
		ucsi_reset_connector(con, true);
		ret = -EPROTO;
	}
@@ -1576,19 +1577,18 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
	if (ret < 0)
		goto out_unlock;

	if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
	if (UCSI_CONCAP(con, OPMODE_DRP))
		cap->data = TYPEC_PORT_DRD;
	else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
	else if (UCSI_CONCAP(con, OPMODE_DFP))
		cap->data = TYPEC_PORT_DFP;
	else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
	else if (UCSI_CONCAP(con, OPMODE_UFP))
		cap->data = TYPEC_PORT_UFP;

	if ((con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER) &&
	    (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER))
	if (UCSI_CONCAP(con, PROVIDER) && UCSI_CONCAP(con, CONSUMER))
		cap->type = TYPEC_PORT_DRP;
	else if (con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER)
	else if (UCSI_CONCAP(con, PROVIDER))
		cap->type = TYPEC_PORT_SRC;
	else if (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER)
	else if (UCSI_CONCAP(con, CONSUMER))
		cap->type = TYPEC_PORT_SNK;

	cap->revision = ucsi->cap.typec_version;
@@ -1596,9 +1596,9 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
	cap->svdm_version = SVDM_VER_2_0;
	cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;

	if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY)
	if (UCSI_CONCAP(con, OPMODE_AUDIO_ACCESSORY))
		*accessory++ = TYPEC_ACCESSORY_AUDIO;
	if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
	if (UCSI_CONCAP(con, OPMODE_DEBUG_ACCESSORY))
		*accessory = TYPEC_ACCESSORY_DEBUG;

	if (UCSI_CONCAP_USB2_SUPPORT(con))
@@ -1646,7 +1646,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
	if (ucsi->ops->connector_status)
		ucsi->ops->connector_status(con);

	switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
	switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
	case UCSI_CONSTAT_PARTNER_TYPE_UFP:
	case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
		u_role = USB_ROLE_HOST;
@@ -1663,9 +1663,8 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
	}

	/* Check if there is already something connected */
	if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
		typec_set_pwr_role(con->port,
				  !!(con->status.flags & UCSI_CONSTAT_PWR_DIR));
	if (UCSI_CONSTAT(con, CONNECTED)) {
		typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR));
		ucsi_register_partner(con);
		ucsi_pwr_opmode_change(con);
		ucsi_port_psy_changed(con);
@@ -1676,7 +1675,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
	}

	/* Only notify USB controller if partner supports USB data */
	if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
	if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
		u_role = USB_ROLE_NONE;

	ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
@@ -1686,16 +1685,14 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
		ret = 0;
	}

	if (con->partner &&
	    UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
	    UCSI_CONSTAT_PWR_OPMODE_PD) {
	if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
		ucsi_register_device_pdos(con);
		ucsi_get_src_pdos(con);
		ucsi_check_altmodes(con);
		ucsi_check_connector_capability(con);
	}

	trace_ucsi_register_port(con->num, &con->status);
	trace_ucsi_register_port(con->num, con);

out:
	fwnode_handle_put(cap->fwnode);
@@ -1778,7 +1775,7 @@ static int ucsi_init(struct ucsi *ucsi)

	/* Get PPM capabilities */
	command = UCSI_GET_CAPABILITY;
	ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap));
	ret = ucsi_send_command(ucsi, command, &ucsi->cap, UCSI_GET_CAPABILITY_SIZE);
	if (ret < 0)
		goto err_reset;

+153 −99

File changed.

Preview size limit exceeded, changes collapsed.

+2 −5
Original line number Diff line number Diff line
@@ -104,7 +104,6 @@ static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_le
	u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE |
			   UCSI_CONSTAT_PDOS_CHANGE;
	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
	struct ucsi_connector_status *status;
	int ret;

	ret = ucsi_acpi_read_message_in(ucsi, val, val_len);
@@ -113,11 +112,9 @@ static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_le

	if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS &&
	    ua->check_bogus_event) {
		status = (struct ucsi_connector_status *)val;

		/* Clear the bogus change */
		if (status->change == bogus_change)
			status->change = 0;
		if (*(u16 *)val == bogus_change)
			*(u16 *)val = 0;

		ua->check_bogus_event = false;
	}