drivers/power/supply/cw2015_battery.c

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

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/cw2015_battery.c
Extension
.c
Size
19516 bytes
Lines
762
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 cw_battery {
	struct device *dev;
	struct workqueue_struct *battery_workqueue;
	struct delayed_work battery_delay_work;
	struct regmap *regmap;
	struct power_supply *rk_bat;
	struct power_supply_battery_info *battery;
	u8 *bat_profile;

	bool charger_attached;
	bool battery_changed;

	int soc;
	int voltage_mv;
	int status;
	int time_to_empty;
	int charge_count;

	u32 poll_interval_ms;
	u8 alert_level;

	unsigned int read_errors;
	unsigned int charge_stuck_cnt;
};

static int cw_read_word(struct cw_battery *cw_bat, u8 reg, u16 *val)
{
	__be16 value;
	int ret;

	ret = regmap_bulk_read(cw_bat->regmap, reg, &value, sizeof(value));
	if (ret)
		return ret;

	*val = be16_to_cpu(value);
	return 0;
}

static int cw_update_profile(struct cw_battery *cw_bat)
{
	int ret;
	unsigned int reg_val;
	u8 reset_val;

	/* make sure gauge is not in sleep mode */
	ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val);
	if (ret)
		return ret;

	reset_val = reg_val;
	if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) {
		dev_err(cw_bat->dev,
			"Gauge is in sleep mode, can't update battery info\n");
		return -EINVAL;
	}

	/* write new battery info */
	ret = regmap_raw_write(cw_bat->regmap, CW2015_REG_BATINFO,
			       cw_bat->bat_profile,
			       CW2015_SIZE_BATINFO);
	if (ret)
		return ret;

	/* set config update flag  */
	reg_val |= CW2015_CONFIG_UPDATE_FLG;
	reg_val &= ~CW2015_MASK_ATHD;
	reg_val |= CW2015_ATHD(cw_bat->alert_level);
	ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val);
	if (ret)
		return ret;

	/* reset gauge to apply new battery profile */
	reset_val &= ~CW2015_MODE_RESTART;
	reg_val = reset_val | CW2015_MODE_RESTART;
	ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val);
	if (ret)
		return ret;

	/* wait for gauge to reset */
	msleep(20);

	/* clear reset flag */
	ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val);
	if (ret)
		return ret;

	/* wait for gauge to become ready */
	ret = regmap_read_poll_timeout(cw_bat->regmap, CW2015_REG_SOC,
				       reg_val, reg_val <= 100,
				       10 * USEC_PER_MSEC, 10 * USEC_PER_SEC);

Annotation

Implementation Notes