Commit 1ff5d97f authored by Prashant Malani's avatar Prashant Malani
Browse files

platform/chrome: cros_ec_typec: Register port altmodes



Instead of using manually managed altmode structs, register the port's
altmodes with the Type-C framework. This facilitates matching them to
partner altmodes later.

Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarPrashant Malani <pmalani@chromium.org>
Acked-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20220712210318.2671292-2-pmalani@chromium.org
parent a47bc5a0
Loading
Loading
Loading
Loading
+40 −11
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@

#define DRV_NAME "cros-ec-typec"

#define DP_PORT_VDO	(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D) | DP_CAP_DFP_D)

/* Supported alt modes. */
enum {
	CROS_EC_ALTMODE_DP = 0,
@@ -60,7 +62,7 @@ struct cros_typec_port {
	uint8_t mux_flags;
	uint8_t role;

	struct typec_altmode port_altmode[CROS_EC_ALTMODE_MAX];
	struct typec_altmode *port_altmode[CROS_EC_ALTMODE_MAX];

	/* Flag indicating that PD partner discovery data parsing is completed. */
	bool sop_disc_done;
@@ -253,6 +255,14 @@ static void cros_typec_remove_cable(struct cros_typec_data *typec,
	port->sop_prime_disc_done = false;
}

static void cros_typec_unregister_port_altmodes(struct cros_typec_port *port)
{
	int i;

	for (i = 0; i < CROS_EC_ALTMODE_MAX; i++)
		typec_unregister_altmode(port->port_altmode[i]);
}

static void cros_unregister_ports(struct cros_typec_data *typec)
{
	int i;
@@ -267,34 +277,49 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
		usb_role_switch_put(typec->ports[i]->role_sw);
		typec_switch_put(typec->ports[i]->ori_sw);
		typec_mux_put(typec->ports[i]->mux);
		cros_typec_unregister_port_altmodes(typec->ports[i]);
		typec_unregister_port(typec->ports[i]->port);
	}
}

/*
 * Fake the alt mode structs until we actually start registering Type C port
 * and partner alt modes.
 * Register port alt modes with known values till we start retrieving
 * port capabilities from the EC.
 */
static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
static int cros_typec_register_port_altmodes(struct cros_typec_data *typec,
					      int port_num)
{
	struct cros_typec_port *port = typec->ports[port_num];
	struct typec_altmode_desc desc;
	struct typec_altmode *amode;

	/* All PD capable CrOS devices are assumed to support DP altmode. */
	port->port_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
	port->port_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
	desc.svid = USB_TYPEC_DP_SID,
	desc.mode = USB_TYPEC_DP_MODE,
	desc.vdo = DP_PORT_VDO,
	amode = typec_port_register_altmode(port->port, &desc);
	if (IS_ERR(amode))
		return PTR_ERR(amode);
	port->port_altmode[CROS_EC_ALTMODE_DP] = amode;

	/*
	 * Register TBT compatibility alt mode. The EC will not enter the mode
	 * if it doesn't support it, so it's safe to register it unconditionally
	 * here for now.
	 */
	port->port_altmode[CROS_EC_ALTMODE_TBT].svid = USB_TYPEC_TBT_SID;
	port->port_altmode[CROS_EC_ALTMODE_TBT].mode = TYPEC_ANY_MODE;
	memset(&desc, 0, sizeof(desc));
	desc.svid = USB_TYPEC_TBT_SID,
	desc.mode = TYPEC_ANY_MODE,
	amode = typec_port_register_altmode(port->port, &desc);
	if (IS_ERR(amode))
		return PTR_ERR(amode);
	port->port_altmode[CROS_EC_ALTMODE_TBT] = amode;

	port->state.alt = NULL;
	port->state.mode = TYPEC_STATE_USB;
	port->state.data = NULL;

	return 0;
}

static int cros_typec_init_ports(struct cros_typec_data *typec)
@@ -361,7 +386,11 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
			dev_dbg(dev, "No switch control for port %d\n",
				port_num);

		cros_typec_register_port_altmodes(typec, port_num);
		ret = cros_typec_register_port_altmodes(typec, port_num);
		if (ret) {
			dev_err(dev, "Failed to register port altmodes\n");
			goto unregister_ports;
		}

		cros_port->disc_data = devm_kzalloc(dev, EC_PROTO2_MAX_RESPONSE_SIZE, GFP_KERNEL);
		if (!cros_port->disc_data) {
@@ -430,7 +459,7 @@ static int cros_typec_enable_tbt(struct cros_typec_data *typec,
		data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE;

	if (!port->state.alt) {
		port->state.alt = &port->port_altmode[CROS_EC_ALTMODE_TBT];
		port->state.alt = port->port_altmode[CROS_EC_ALTMODE_TBT];
		ret = cros_typec_usb_safe_state(port);
		if (ret)
			return ret;
@@ -472,7 +501,7 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec,
	/* Configuration VDO. */
	dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
	if (!port->state.alt) {
		port->state.alt = &port->port_altmode[CROS_EC_ALTMODE_DP];
		port->state.alt = port->port_altmode[CROS_EC_ALTMODE_DP];
		ret = cros_typec_usb_safe_state(port);
		if (ret)
			return ret;