drivers/extcon/extcon-ptn5150.c

Source file repositories/reference/linux-study-clean/drivers/extcon/extcon-ptn5150.c

File Facts

System
Linux kernel
Corpus path
drivers/extcon/extcon-ptn5150.c
Extension
.c
Size
10929 bytes
Lines
416
Domain
Driver Families
Bucket
drivers/extcon
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 ptn5150_info {
	struct device *dev;
	struct extcon_dev *edev;
	struct i2c_client *i2c;
	struct regmap *regmap;
	struct gpio_desc *int_gpiod;
	struct gpio_desc *vbus_gpiod;
	int irq;
	struct work_struct irq_work;
	struct mutex mutex;
	struct typec_switch *orient_sw;
	struct usb_role_switch *role_sw;
};

/* List of detectable cables */
static const unsigned int ptn5150_extcon_cable[] = {
	EXTCON_USB,
	EXTCON_USB_HOST,
	EXTCON_NONE,
};

static const struct regmap_config ptn5150_regmap_config = {
	.reg_bits	= 8,
	.val_bits	= 8,
	.max_register	= PTN5150_REG_END,
};

static void ptn5150_check_state(struct ptn5150_info *info)
{
	enum typec_orientation orient = TYPEC_ORIENTATION_NONE;
	unsigned int port_status, reg_data, vbus;
	enum usb_role usb_role = USB_ROLE_NONE;
	int ret;

	ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
	if (ret) {
		dev_err(info->dev, "failed to read CC STATUS %d\n", ret);
		return;
	}

	orient = FIELD_GET(PTN5150_REG_CC_POLARITY, reg_data);
	switch (orient) {
	case PTN5150_POLARITY_CC1:
		orient = TYPEC_ORIENTATION_NORMAL;
		break;
	case PTN5150_POLARITY_CC2:
		orient = TYPEC_ORIENTATION_REVERSE;
		break;
	default:
		orient = TYPEC_ORIENTATION_NONE;
		break;
	}

	ret = typec_switch_set(info->orient_sw, orient);
	if (ret)
		dev_err(info->dev, "failed to set orientation: %d\n", ret);

	port_status = FIELD_GET(PTN5150_REG_CC_PORT_ATTACHMENT, reg_data);

	switch (port_status) {
	case PTN5150_DFP_ATTACHED:
		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);
		gpiod_set_value_cansleep(info->vbus_gpiod, 0);
		extcon_set_state_sync(info->edev, EXTCON_USB, true);
		usb_role = USB_ROLE_DEVICE;
		break;
	case PTN5150_UFP_ATTACHED:
		extcon_set_state_sync(info->edev, EXTCON_USB, false);
		vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION, reg_data);
		if (vbus)
			gpiod_set_value_cansleep(info->vbus_gpiod, 0);
		else
			gpiod_set_value_cansleep(info->vbus_gpiod, 1);

		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
		usb_role = USB_ROLE_HOST;
		break;
	default:
		break;
	}

	if (usb_role) {
		ret = usb_role_switch_set_role(info->role_sw, usb_role);
		if (ret)
			dev_err(info->dev, "failed to set %s role: %d\n",
				usb_role_string(usb_role), ret);
	}
}

static void ptn5150_irq_work(struct work_struct *work)

Annotation

Implementation Notes