drivers/platform/chrome/cros_typec_altmode.c

Source file repositories/reference/linux-study-clean/drivers/platform/chrome/cros_typec_altmode.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/chrome/cros_typec_altmode.c
Extension
.c
Size
9102 bytes
Lines
375
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cros_typec_altmode_data {
	struct work_struct work;
	struct cros_typec_port *port;
	struct typec_altmode *alt;
	bool ap_mode_entry;

	struct mutex lock;
	u32 header;
	u32 *vdo_data;
	u8 vdo_size;

	u16 sid;
	u8 mode;
};

struct cros_typec_dp_data {
	struct cros_typec_altmode_data adata;
	struct typec_displayport_data data;
	bool configured;
	bool pending_status_update;
};

static void cros_typec_altmode_work(struct work_struct *work)
{
	struct cros_typec_altmode_data *data =
		container_of(work, struct cros_typec_altmode_data, work);

	mutex_lock(&data->lock);

	if (typec_altmode_vdm(data->alt, data->header, data->vdo_data,
			      data->vdo_size))
		dev_err(&data->alt->dev, "VDM 0x%x failed\n", data->header);

	data->header = 0;
	data->vdo_data = NULL;
	data->vdo_size = 0;

	mutex_unlock(&data->lock);
}

static int cros_typec_altmode_enter(struct typec_altmode *alt, u32 *vdo)
{
	struct cros_typec_altmode_data *adata = typec_altmode_get_drvdata(alt);
	struct ec_params_typec_control req = {
		.port = adata->port->port_num,
		.command = TYPEC_CONTROL_COMMAND_ENTER_MODE,
	};
	int svdm_version;
	int ret;

	if (!adata->ap_mode_entry) {
		dev_warn(&alt->dev,
			 "EC does not support AP driven mode entry\n");
		return -EOPNOTSUPP;
	}

	if (adata->sid == USB_TYPEC_DP_SID)
		req.mode_to_enter = CROS_EC_ALTMODE_DP;
	else if (adata->sid == USB_TYPEC_TBT_SID)
		req.mode_to_enter = CROS_EC_ALTMODE_TBT;
	else
		return -EOPNOTSUPP;

	ret = cros_ec_cmd(adata->port->typec_data->ec, 0, EC_CMD_TYPEC_CONTROL,
			  &req, sizeof(req), NULL, 0);
	if (ret < 0)
		return ret;

	svdm_version = typec_altmode_get_svdm_version(alt);
	if (svdm_version < 0)
		return svdm_version;

	mutex_lock(&adata->lock);

	adata->header = VDO(adata->sid, 1, svdm_version, CMD_ENTER_MODE);
	adata->header |= VDO_OPOS(adata->mode);
	adata->header |= VDO_CMDT(CMDT_RSP_ACK);
	adata->vdo_data = NULL;
	adata->vdo_size = 1;
	schedule_work(&adata->work);

	mutex_unlock(&adata->lock);
	return ret;
}

static int cros_typec_altmode_exit(struct typec_altmode *alt)
{
	struct cros_typec_altmode_data *adata = typec_altmode_get_drvdata(alt);
	struct ec_params_typec_control req = {
		.port = adata->port->port_num,

Annotation

Implementation Notes