drivers/extcon/extcon-max14526.c

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

File Facts

System
Linux kernel
Corpus path
drivers/extcon/extcon-max14526.c
Extension
.c
Size
7495 bytes
Lines
303
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 max14526_data {
	struct i2c_client *client;
	struct extcon_dev *edev;

	struct regmap *regmap;
	struct regmap_field *rfield[MAX14526_N_REGMAP_FIELDS];

	int last_state;
	int cable;
};

enum max14526_muic_modes {
	MAX14526_OTG     = MAX14526_GND, /* no power */
	MAX14526_MHL     = MAX14526_56KOHM, /* no power */
	MAX14526_OTG_Y   = MAX14526_GND | V_VBUS,
	MAX14526_MHL_CHG = MAX14526_GND | V_VBUS | CHGDET,
	MAX14526_NONE    = MAX14526_OPEN,
	MAX14526_USB     = MAX14526_OPEN | V_VBUS,
	MAX14526_CHG     = MAX14526_OPEN | V_VBUS | CHGDET,
};

static const unsigned int max14526_extcon_cable[] = {
	EXTCON_USB,
	EXTCON_USB_HOST,
	EXTCON_CHG_USB_FAST,
	EXTCON_DISP_MHL,
	EXTCON_NONE,
};

static int max14526_ap_usb_mode(struct max14526_data *priv)
{
	struct device *dev = &priv->client->dev;
	int ret;

	/* Enable USB Path */
	ret = regmap_field_write(priv->rfield[DM], SW_DATA);
	if (ret)
		return ret;

	ret = regmap_field_write(priv->rfield[DP], SW_DATA);
	if (ret)
		return ret;

	/* Enable 200K, Charger Pump and ADC */
	ret = regmap_write(priv->regmap, MAX14526_CONTROL_1,
			   ID_200 | ADC_EN | CP_EN);
	if (ret)
		return ret;

	dev_dbg(dev, "AP USB mode set\n");

	return 0;
}

static irqreturn_t max14526_interrupt(int irq, void *dev_id)
{
	struct max14526_data *priv = dev_id;
	struct device *dev = &priv->client->dev;
	int state, ret;

	/*
	 * Upon an MUIC IRQ (MUIC_INT_N falls), wait at least 70ms
	 * before reading INT_STAT and STATUS. After the reads,
	 * MUIC_INT_N returns to high (but the INT_STAT and STATUS
	 * contents will be held).
	 */
	msleep(100);

	ret = regmap_read(priv->regmap, MAX14526_INT_STAT, &state);
	if (ret)
		dev_err(dev, "failed to read MUIC state %d\n", ret);

	if (state == priv->last_state)
		return IRQ_HANDLED;

	/* Detach previous device */
	extcon_set_state_sync(priv->edev, priv->cable, false);

	switch (state) {
	case MAX14526_USB:
		priv->cable = EXTCON_USB;
		break;

	case MAX14526_CHG:
		priv->cable = EXTCON_CHG_USB_FAST;
		break;

	case MAX14526_OTG:
	case MAX14526_OTG_Y:
		priv->cable = EXTCON_USB_HOST;

Annotation

Implementation Notes