drivers/usb/typec/tcpm/tcpci.c

Source file repositories/reference/linux-study-clean/drivers/usb/typec/tcpm/tcpci.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/typec/tcpm/tcpci.c
Extension
.c
Size
27975 bytes
Lines
1051
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 tcpci {
	struct device *dev;

	struct tcpm_port *port;

	struct regmap *regmap;
	unsigned int alert_mask;

	bool controls_vbus;

	struct tcpc_dev tcpc;
	struct tcpci_data *data;
	struct gpio_desc *orientation_gpio;
};

struct tcpci_chip {
	struct tcpci *tcpci;
	struct tcpci_data data;
};

struct tcpm_port *tcpci_get_tcpm_port(struct tcpci *tcpci)
{
	return tcpci->port;
}
EXPORT_SYMBOL_GPL(tcpci_get_tcpm_port);

static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
{
	return container_of(tcpc, struct tcpci, tcpc);
}

static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, u16 *val)
{
	return regmap_raw_read(tcpci->regmap, reg, val, sizeof(u16));
}

static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
{
	return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16));
}

static int tcpci_check_std_output_cap(struct regmap *regmap, u8 mask)
{
	unsigned int reg;
	int ret;

	ret = regmap_read(regmap, TCPC_STD_OUTPUT_CAP, &reg);
	if (ret < 0)
		return ret;

	return (reg & mask) == mask;
}

static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
{
	struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
	bool vconn_pres;
	enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1;
	unsigned int reg;
	int ret;

	ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, &reg);
	if (ret < 0)
		return ret;

	vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES);
	if (vconn_pres) {
		ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, &reg);
		if (ret < 0)
			return ret;

		if (reg & TCPC_TCPC_CTRL_ORIENTATION)
			polarity = TYPEC_POLARITY_CC2;
	}

	switch (cc) {
	case TYPEC_CC_RA:
		reg = (FIELD_PREP(TCPC_ROLE_CTRL_CC1, TCPC_ROLE_CTRL_CC_RA)
		       | FIELD_PREP(TCPC_ROLE_CTRL_CC2, TCPC_ROLE_CTRL_CC_RA));
		break;
	case TYPEC_CC_RD:
		reg = (FIELD_PREP(TCPC_ROLE_CTRL_CC1, TCPC_ROLE_CTRL_CC_RD)
		       | FIELD_PREP(TCPC_ROLE_CTRL_CC2, TCPC_ROLE_CTRL_CC_RD));
		break;
	case TYPEC_CC_RP_DEF:
		reg = (FIELD_PREP(TCPC_ROLE_CTRL_CC1, TCPC_ROLE_CTRL_CC_RP)
		       | FIELD_PREP(TCPC_ROLE_CTRL_CC2, TCPC_ROLE_CTRL_CC_RP)
		       | FIELD_PREP(TCPC_ROLE_CTRL_RP_VAL,
				    TCPC_ROLE_CTRL_RP_VAL_DEF));
		break;

Annotation

Implementation Notes