drivers/power/supply/adc-battery-helper.c

Source file repositories/reference/linux-study-clean/drivers/power/supply/adc-battery-helper.c

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/adc-battery-helper.c
Extension
.c
Size
10389 bytes
Lines
328
Domain
Driver Families
Bucket
drivers/power
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

// SPDX-License-Identifier: GPL-2.0+
/*
 * Helper for batteries with accurate current and voltage measurement, but
 * without temperature measurement or without a "resistance-temp-table".
 *
 * Some fuel-gauges are not full-featured autonomous fuel-gauges.
 * These fuel-gauges offer accurate current and voltage measurements but
 * their coulomb-counters are intended to work together with an always on
 * micro-controller monitoring the fuel-gauge.
 *
 * This adc-battery-helper code offers open-circuit-voltage (ocv) and through
 * that capacity estimation for devices where such limited functionality
 * fuel-gauges are exposed directly to Linux.
 *
 * This helper requires the hw to provide accurate battery current_now and
 * voltage_now measurement and this helper the provides the following properties
 * based on top of those readings:
 *
 *	POWER_SUPPLY_PROP_STATUS
 *	POWER_SUPPLY_PROP_VOLTAGE_OCV
 *	POWER_SUPPLY_PROP_VOLTAGE_NOW
 *	POWER_SUPPLY_PROP_CURRENT_NOW
 *	POWER_SUPPLY_PROP_CAPACITY
 *
 * As well as optional the following properties assuming an always present
 * system-scope battery, allowing direct use of adc_battery_helper_get_prop()
 * in this common case:
 *	POWER_SUPPLY_PROP_PRESENT
 *	POWER_SUPPLY_PROP_SCOPE
 *
 * Using this helper is as simple as:
 *
 * 1. Embed a struct adc_battery_helper this MUST be the first member of
 *    the battery driver's data struct.
 * 2. Use adc_battery_helper_props[] or add the above properties to
 *    the list of properties in power_supply_desc
 * 3. Call adc_battery_helper_init() after registering the power_supply and
 *    before returning from the probe() function
 * 4. Use adc_battery_helper_get_prop() as the power-supply's get_property()
 *    method, or call it for the above properties.
 * 5. Use adc_battery_helper_external_power_changed() as the power-supply's
 *    external_power_changed() method or call it from that method.
 * 6. Use adc_battery_helper_[suspend|resume]() as suspend-resume methods or
 *    call them from the driver's suspend-resume methods.
 *
 * The provided get_voltage_and_current_now() method will be called by this
 * helper at adc_battery_helper_init() time and later.
 *
 * Copyright (c) 2021-2025 Hans de Goede <hansg@kernel.org>
 */

#include <linux/cleanup.h>
#include <linux/devm-helpers.h>
#include <linux/gpio/consumer.h>
#include <linux/mutex.h>
#include <linux/power_supply.h>
#include <linux/workqueue.h>

#include "adc-battery-helper.h"

#define MOV_AVG_WINDOW_SIZE			ADC_BAT_HELPER_MOV_AVG_WINDOW_SIZE
#define INIT_POLL_TIME				(5 * HZ)
#define POLL_TIME				(30 * HZ)
#define SETTLE_TIME				(1 * HZ)

#define INIT_POLL_COUNT				30

#define CURR_HYST_UA				65000

#define LOW_BAT_UV				3700000
#define FULL_BAT_HYST_UV			38000

#define AMBIENT_TEMP_CELSIUS			25

static int adc_battery_helper_get_status(struct adc_battery_helper *help)
{
	int full_uv =
		help->psy->battery_info->constant_charge_voltage_max_uv - FULL_BAT_HYST_UV;

	if (help->curr_ua > CURR_HYST_UA)
		return POWER_SUPPLY_STATUS_CHARGING;

	if (help->curr_ua < -CURR_HYST_UA)
		return POWER_SUPPLY_STATUS_DISCHARGING;

	if (help->supplied) {
		bool full;

		if (help->charge_finished)
			full = gpiod_get_value_cansleep(help->charge_finished);

Annotation

Implementation Notes