drivers/power/supply/sbs-battery.c

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

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/sbs-battery.c
Extension
.c
Size
33489 bytes
Lines
1296
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;
	bool				is_present;
	struct gpio_desc		*gpio_detect;
	bool				charger_broadcasts;
	int				last_state;
	int				poll_time;
	u32				i2c_retry_count;
	u32				poll_retry_count;
	struct delayed_work		work;
	struct mutex			mode_lock;
	u32				flags;
	int				technology;
	char				strings[NR_STRING_BUFFERS][I2C_SMBUS_BLOCK_MAX + 1];
};

static char *sbs_get_string_buf(struct sbs_info *chip,
				enum power_supply_property psp)
{
	int i = 0;

	for (i = 0; i < NR_STRING_BUFFERS; i++)
		if (string_properties[i] == psp)
			return chip->strings[i];

	return ERR_PTR(-EINVAL);
}

static void sbs_invalidate_cached_props(struct sbs_info *chip)
{
	int i = 0;

	chip->technology = -1;

	for (i = 0; i < NR_STRING_BUFFERS; i++)
		chip->strings[i][0] = 0;
}

static bool force_load;

static int sbs_read_word_data(struct i2c_client *client, u8 address);
static int sbs_write_word_data(struct i2c_client *client, u8 address, u16 value);

static void sbs_disable_charger_broadcasts(struct sbs_info *chip)
{
	int val = sbs_read_word_data(chip->client, BATTERY_MODE_OFFSET);
	if (val < 0)
		goto exit;

	val |= BATTERY_MODE_CHARGER_MASK;

	val = sbs_write_word_data(chip->client, BATTERY_MODE_OFFSET, val);

exit:
	if (val < 0)
		dev_err(&chip->client->dev,
			"Failed to disable charger broadcasting: %d\n", val);
	else
		dev_dbg(&chip->client->dev, "%s\n", __func__);
}

static int sbs_update_presence(struct sbs_info *chip, bool is_present)
{
	struct i2c_client *client = chip->client;
	int retries = chip->i2c_retry_count;
	s32 ret = 0;
	u8 version;

	if (chip->is_present == is_present)
		return 0;

	if (!is_present) {
		chip->is_present = false;
		/* Disable PEC when no device is present */
		client->flags &= ~I2C_CLIENT_PEC;
		sbs_invalidate_cached_props(chip);
		return 0;
	}

	/* Check if device supports packet error checking and use it */
	while (retries > 0) {
		ret = i2c_smbus_read_word_data(client, REG_ADDR_SPEC_INFO);
		if (ret >= 0)
			break;

		/*
		 * Some batteries trigger the detection pin before the
		 * I2C bus is properly connected. This works around the
		 * issue.

Annotation

Implementation Notes