drivers/platform/chrome/cros_typec_switch.c

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

File Facts

System
Linux kernel
Corpus path
drivers/platform/chrome/cros_typec_switch.c
Extension
.c
Size
8355 bytes
Lines
320
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_port {
	int port_num;
	struct typec_mux_dev *mode_switch;
	struct typec_retimer *retimer;
	struct cros_typec_switch_data *sdata;
};

/* Driver-specific data. */
struct cros_typec_switch_data {
	struct device *dev;
	struct cros_ec_device *ec;
	struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
};

static int cros_typec_cmd_mux_set(struct cros_typec_switch_data *sdata, int port_num, u8 index,
				  u8 state)
{
	struct ec_params_typec_control req = {
		.port = port_num,
		.command = TYPEC_CONTROL_COMMAND_USB_MUX_SET,
		.mux_params = {
			.mux_index = index,
			.mux_flags = state,
		},
	};

	return cros_ec_cmd(sdata->ec, 0, EC_CMD_TYPEC_CONTROL, &req, sizeof(req), NULL, 0);
}

static int cros_typec_get_mux_state(unsigned long mode, struct typec_altmode *alt)
{
	int ret = -EOPNOTSUPP;
	u8 pin_assign;

	if (mode == TYPEC_STATE_SAFE) {
		ret = USB_PD_MUX_SAFE_MODE;
	} else if (mode == TYPEC_STATE_USB) {
		ret = USB_PD_MUX_USB_ENABLED;
	} else if (alt && alt->svid == USB_TYPEC_DP_SID) {
		ret = USB_PD_MUX_DP_ENABLED;
		pin_assign = mode - TYPEC_STATE_MODAL;
		if (pin_assign & DP_PIN_ASSIGN_D)
			ret |= USB_PD_MUX_USB_ENABLED;
	}

	return ret;
}

static int cros_typec_send_clear_event(struct cros_typec_switch_data *sdata, int port_num,
				       u32 events_mask)
{
	struct ec_params_typec_control req = {
		.port = port_num,
		.command = TYPEC_CONTROL_COMMAND_CLEAR_EVENTS,
		.clear_events_mask = events_mask,
	};

	return cros_ec_cmd(sdata->ec, 0, EC_CMD_TYPEC_CONTROL, &req, sizeof(req), NULL, 0);
}

static bool cros_typec_check_event(struct cros_typec_switch_data *sdata, int port_num, u32 mask)
{
	struct ec_response_typec_status resp;
	struct ec_params_typec_status req = {
		.port = port_num,
	};
	int ret;

	ret = cros_ec_cmd(sdata->ec, 0, EC_CMD_TYPEC_STATUS, &req, sizeof(req),
			  &resp, sizeof(resp));
	if (ret < 0) {
		dev_warn(sdata->dev, "EC_CMD_TYPEC_STATUS failed for port: %d\n", port_num);
		return false;
	}

	if (resp.events & mask)
		return true;

	return false;
}

/*
 * The ChromeOS EC treats both mode-switches and retimers as "muxes" for the purposes of the
 * host command API. This common function configures and verifies the retimer/mode-switch
 * according to the provided setting.
 */
static int cros_typec_configure_mux(struct cros_typec_switch_data *sdata, int port_num, int index,
				    unsigned long mode, struct typec_altmode *alt)
{
	unsigned long end;

Annotation

Implementation Notes