drivers/power/supply/sbs-charger.c

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

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/sbs-charger.c
Extension
.c
Size
6637 bytes
Lines
265
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 sbs_info {
	struct i2c_client		*client;
	struct power_supply		*power_supply;
	struct regmap			*regmap;
	struct delayed_work		work;
	unsigned int			last_state;
};

static int sbs_get_property(struct power_supply *psy,
			    enum power_supply_property psp,
			    union power_supply_propval *val)
{
	struct sbs_info *chip = power_supply_get_drvdata(psy);
	unsigned int reg;

	reg = chip->last_state;

	switch (psp) {
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = !!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT);
		break;

	case POWER_SUPPLY_PROP_ONLINE:
		val->intval = !!(reg & SBS_CHARGER_STATUS_AC_PRESENT);
		break;

	case POWER_SUPPLY_PROP_STATUS:
		val->intval = POWER_SUPPLY_STATUS_UNKNOWN;

		if (!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT))
			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
		else if (reg & SBS_CHARGER_STATUS_AC_PRESENT &&
			 !(reg & SBS_CHARGER_STATUS_CHARGE_INHIBITED))
			val->intval = POWER_SUPPLY_STATUS_CHARGING;
		else
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;

		break;

	case POWER_SUPPLY_PROP_HEALTH:
		if (reg & SBS_CHARGER_STATUS_RES_COLD)
			val->intval = POWER_SUPPLY_HEALTH_COLD;
		if (reg & SBS_CHARGER_STATUS_RES_HOT)
			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
		else
			val->intval = POWER_SUPPLY_HEALTH_GOOD;

		break;

	default:
		return -EINVAL;
	}

	return 0;
}

static int sbs_check_state(struct sbs_info *chip)
{
	unsigned int reg;
	int ret;

	ret = regmap_read(chip->regmap, SBS_CHARGER_REG_STATUS, &reg);
	if (!ret && reg != chip->last_state) {
		chip->last_state = reg;
		power_supply_changed(chip->power_supply);
		return 1;
	}

	return 0;
}

static void sbs_delayed_work(struct work_struct *work)
{
	struct sbs_info *chip = container_of(work, struct sbs_info, work.work);

	sbs_check_state(chip);

	schedule_delayed_work(&chip->work,
			      msecs_to_jiffies(SBS_CHARGER_POLL_TIME));
}

static irqreturn_t sbs_irq_thread(int irq, void *data)
{
	struct sbs_info *chip = data;
	int ret;

	ret = sbs_check_state(chip);

	return ret ? IRQ_HANDLED : IRQ_NONE;
}

Annotation

Implementation Notes