drivers/usb/typec/mux/tusb1046.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/typec/mux/tusb1046.c
Extension
.c
Size
4818 bytes
Lines
197
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 tusb1046_priv {
	struct i2c_client *client;
	struct typec_switch_dev *sw;
	struct typec_mux_dev *mux;

	/* Lock General register during accesses */
	struct mutex general_reg_lock;
};

static int tusb1046_mux_set(struct typec_mux_dev *mux,
			    struct typec_mux_state *state)
{
	struct tusb1046_priv *priv = typec_mux_get_drvdata(mux);
	struct i2c_client *client = priv->client;
	struct device *dev = &client->dev;
	int mode, val, ret = 0;

	if (state->mode >= TYPEC_STATE_MODAL &&
	    state->alt->svid != USB_TYPEC_DP_SID)
		return -EINVAL;

	dev_dbg(dev, "mux mode requested: %lu\n", state->mode);

	mutex_lock(&priv->general_reg_lock);

	val = i2c_smbus_read_byte_data(client, TUSB1046_REG_GENERAL);
	if (val < 0) {
		dev_err(dev, "failed to read ctlsel status, err %d\n", val);
		ret = val;
		goto out_unlock;
	}

	switch (state->mode) {
	case TYPEC_STATE_USB:
		mode = TUSB1046_CTLSEL_USB3;
		break;
	case TYPEC_DP_STATE_C:
	case TYPEC_DP_STATE_E:
		mode = TUSB1046_CTLSEL_4LANE_DP;
		break;
	case TYPEC_DP_STATE_D:
		mode = TUSB1046_CTLSEL_USB3_AND_2LANE_DP;
		break;
	case TYPEC_STATE_SAFE:
	default:
		mode = TUSB1046_CTLSEL_DISABLED;
		break;
	}

	val &= ~TUSB1046_GENERAL_CTLSEL;
	val |= mode;

	ret = i2c_smbus_write_byte_data(client, TUSB1046_REG_GENERAL, val);

out_unlock:
	mutex_unlock(&priv->general_reg_lock);
	return ret;
}

static int tusb1046_switch_set(struct typec_switch_dev *sw,
			       enum typec_orientation orientation)
{
	struct tusb1046_priv *priv = typec_switch_get_drvdata(sw);
	struct i2c_client *client = priv->client;
	struct device *dev = &client->dev;
	int val, ret = 0;

	dev_dbg(dev, "setting USB3.0 lane flip for orientation %d\n", orientation);

	mutex_lock(&priv->general_reg_lock);

	val = i2c_smbus_read_byte_data(client, TUSB1046_REG_GENERAL);
	if (val < 0) {
		dev_err(dev, "failed to read flipsel status, err %d\n", val);
		ret = val;
		goto out_unlock;
	}

	if (orientation == TYPEC_ORIENTATION_REVERSE)
		val |= TUSB1046_GENERAL_FLIPSEL;
	else
		val &= ~TUSB1046_GENERAL_FLIPSEL;

	ret = i2c_smbus_write_byte_data(client, TUSB1046_REG_GENERAL, val);

out_unlock:
	mutex_unlock(&priv->general_reg_lock);
	return ret;
}

Annotation

Implementation Notes