drivers/power/supply/ltc2941-battery-gauge.c

Source file repositories/reference/linux-study-clean/drivers/power/supply/ltc2941-battery-gauge.c

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/ltc2941-battery-gauge.c
Extension
.c
Size
16810 bytes
Lines
648
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 ltc294x_info {
	struct i2c_client *client;	/* I2C Client pointer */
	struct power_supply *supply;	/* Supply pointer */
	struct power_supply_desc supply_desc;	/* Supply description */
	struct delayed_work work;	/* Work scheduler */
	enum ltc294x_id id;		/* Chip type */
	int charge;	/* Last charge register content */
	int r_sense;	/* mOhm */
	int Qlsb;	/* nAh */
};

static inline int convert_bin_to_uAh(
	const struct ltc294x_info *info, int Q)
{
	return ((Q * (info->Qlsb / 10))) / 100;
}

static inline int convert_uAh_to_bin(
	const struct ltc294x_info *info, int uAh)
{
	int Q;

	Q = (uAh * 100) / (info->Qlsb/10);
	return (Q < LTC294X_MAX_VALUE) ? Q : LTC294X_MAX_VALUE;
}

static int ltc294x_read_regs(struct i2c_client *client,
	enum ltc294x_reg reg, u8 *buf, int num_regs)
{
	int ret;
	struct i2c_msg msgs[2] = { };
	u8 reg_start = reg;

	msgs[0].addr	= client->addr;
	msgs[0].len	= 1;
	msgs[0].buf	= &reg_start;

	msgs[1].addr	= client->addr;
	msgs[1].len	= num_regs;
	msgs[1].buf	= buf;
	msgs[1].flags	= I2C_M_RD;

	ret = i2c_transfer(client->adapter, &msgs[0], 2);
	if (ret < 0) {
		dev_err(&client->dev, "ltc2941 read_reg(0x%x[%d]) failed: %pe\n",
			reg, num_regs, ERR_PTR(ret));
		return ret;
	}

	dev_dbg(&client->dev, "%s (%#x, %d) -> %#x\n",
		__func__, reg, num_regs, *buf);

	return 0;
}

static int ltc294x_write_regs(struct i2c_client *client,
	enum ltc294x_reg reg, const u8 *buf, int num_regs)
{
	int ret;
	u8 reg_start = reg;

	ret = i2c_smbus_write_i2c_block_data(client, reg_start, num_regs, buf);
	if (ret < 0) {
		dev_err(&client->dev, "ltc2941 write_reg(0x%x[%d]) failed: %pe\n",
			reg, num_regs, ERR_PTR(ret));
		return ret;
	}

	dev_dbg(&client->dev, "%s (%#x, %d) -> %#x\n",
		__func__, reg, num_regs, *buf);

	return 0;
}

static int ltc294x_reset(const struct ltc294x_info *info, int prescaler_exp)
{
	int ret;
	u8 value;
	u8 control;

	/* Read status and control registers */
	ret = ltc294x_read_regs(info->client, LTC294X_REG_CONTROL, &value, 1);
	if (ret < 0)
		return ret;

	control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) |
				LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED;
	/* Put device into "monitor" mode */
	switch (info->id) {
	case LTC2942_ID:	/* 2942 measures every 2 sec */

Annotation

Implementation Notes