drivers/usb/typec/mux/ps883x.c

Source file repositories/reference/linux-study-clean/drivers/usb/typec/mux/ps883x.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/typec/mux/ps883x.c
Extension
.c
Size
13163 bytes
Lines
501
Domain
Driver Families
Bucket
drivers/usb
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 ps883x_retimer {
	struct i2c_client *client;
	struct gpio_desc *reset_gpio;
	struct regmap *regmap;
	struct typec_switch_dev *sw;
	struct typec_retimer *retimer;
	struct clk *xo_clk;
	struct regulator *vdd_supply;
	struct regulator *vdd33_supply;
	struct regulator *vdd33_cap_supply;
	struct regulator *vddat_supply;
	struct regulator *vddar_supply;
	struct regulator *vddio_supply;

	struct typec_switch *typec_switch;
	struct typec_mux *typec_mux;

	struct mutex lock; /* protect non-concurrent retimer & switch */

	enum typec_orientation orientation;
	u8 cfg0;
	u8 cfg1;
	u8 cfg2;
};

static int ps883x_configure(struct ps883x_retimer *retimer, int cfg0,
			    int cfg1, int cfg2)
{
	struct device *dev = &retimer->client->dev;
	int ret;

	if (retimer->cfg0 == cfg0 && retimer->cfg1 == cfg1 && retimer->cfg2 == cfg2)
		return 0;

	ret = regmap_write(retimer->regmap, REG_USB_PORT_CONN_STATUS_0, cfg0);
	if (ret) {
		dev_err(dev, "failed to write conn_status_0: %d\n", ret);
		return ret;
	}

	ret = regmap_write(retimer->regmap, REG_USB_PORT_CONN_STATUS_1, cfg1);
	if (ret) {
		dev_err(dev, "failed to write conn_status_1: %d\n", ret);
		return ret;
	}

	ret = regmap_write(retimer->regmap, REG_USB_PORT_CONN_STATUS_2, cfg2);
	if (ret) {
		dev_err(dev, "failed to write conn_status_2: %d\n", ret);
		return ret;
	}

	retimer->cfg0 = cfg0;
	retimer->cfg1 = cfg1;
	retimer->cfg2 = cfg2;

	return 0;
}

static int ps883x_set(struct ps883x_retimer *retimer, struct typec_retimer_state *state)
{
	struct typec_thunderbolt_data *tb_data;
	const struct enter_usb_data *eudo_data;
	int cfg0 = CONN_STATUS_0_CONNECTION_PRESENT;
	int cfg1 = 0x00;
	int cfg2 = 0x00;

	if (retimer->orientation == TYPEC_ORIENTATION_REVERSE)
		cfg0 |= CONN_STATUS_0_ORIENTATION_REVERSED;

	if (state->alt) {
		switch (state->alt->svid) {
		case USB_TYPEC_DP_SID:
			cfg1 |= CONN_STATUS_1_DP_CONNECTED |
				CONN_STATUS_1_DP_HPD_LEVEL;

			switch (state->mode)  {
			case TYPEC_DP_STATE_C:
				cfg1 |= CONN_STATUS_1_DP_SINK_REQUESTED |
					CONN_STATUS_1_DP_PIN_ASSIGNMENT_C_D;
				fallthrough;
			case TYPEC_DP_STATE_D:
				cfg1 |= CONN_STATUS_0_USB_3_1_CONNECTED;
				break;
			default: /* MODE_E */
				break;
			}
			break;
		case USB_TYPEC_TBT_SID:
			tb_data = state->data;

Annotation

Implementation Notes