drivers/power/supply/max8997_charger.c

Source file repositories/reference/linux-study-clean/drivers/power/supply/max8997_charger.c

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/max8997_charger.c
Extension
.c
Size
8030 bytes
Lines
288
Domain
Driver Families
Bucket
drivers/power
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 charger_data {
	struct device *dev;
	struct max8997_dev *iodev;
	struct power_supply *battery;
	struct regulator *reg;
	struct extcon_dev *edev;
	struct notifier_block extcon_nb;
	struct work_struct extcon_work;
};

static enum power_supply_property max8997_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS, /* "FULL", "CHARGING" or "DISCHARGING". */
	POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */
	POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */
};

/* Note that the charger control is done by a current regulator "CHARGER" */
static int max8997_battery_get_property(struct power_supply *psy,
		enum power_supply_property psp,
		union power_supply_propval *val)
{
	struct charger_data *charger = power_supply_get_drvdata(psy);
	struct i2c_client *i2c = charger->iodev->i2c;
	int ret;
	u8 reg;

	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		val->intval = 0;
		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
		if (ret)
			return ret;
		if ((reg & (1 << 0)) == 0x1)
			val->intval = POWER_SUPPLY_STATUS_FULL;
		else if ((reg & DCINOK_MASK))
			val->intval = POWER_SUPPLY_STATUS_CHARGING;
		else
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;

		break;
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = 0;
		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
		if (ret)
			return ret;
		if ((reg & DETBAT_MASK) == 0x0)
			val->intval = 1;

		break;
	case POWER_SUPPLY_PROP_ONLINE:
		val->intval = 0;
		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
		if (ret)
			return ret;
		if (reg & DCINOK_MASK)
			val->intval = 1;

		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static void max8997_battery_extcon_evt_worker(struct work_struct *work)
{
	struct charger_data *charger =
	    container_of(work, struct charger_data, extcon_work);
	struct extcon_dev *edev = charger->edev;
	int current_limit;

	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
		dev_dbg(charger->dev, "USB SDP charger is connected\n");
		current_limit = 450000;
	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
		dev_dbg(charger->dev, "USB DCP charger is connected\n");
		current_limit = 650000;
	} else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {
		dev_dbg(charger->dev, "USB FAST charger is connected\n");
		current_limit = 650000;
	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {
		dev_dbg(charger->dev, "USB SLOW charger is connected\n");
		current_limit = 650000;
	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
		dev_dbg(charger->dev, "USB CDP charger is connected\n");
		current_limit = 650000;
	} else {
		dev_dbg(charger->dev, "USB charger is disconnected\n");
		current_limit = -1;

Annotation

Implementation Notes