drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.c
Extension
.c
Size
7483 bytes
Lines
262
Domain
Driver Families
Bucket
drivers/platform
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 atla10_ec_battery_state {
	u8 status;			/* Using ACPI Battery spec status bits */
	u8 capacity;			/* Percent */
	__le16 charge_now_mAh;
	__le16 voltage_now_mV;
	__le16 current_now_mA;
	__le16 charge_full_mAh;
	__le16 temp;			/* centi degrees Celsius */
} __packed;

struct atla10_ec_battery_info {
	__le16 charge_full_design_mAh;
	__le16 voltage_now_mV;		/* Should be design voltage, but is not ? */
	__le16 charge_full_design2_mAh;
} __packed;

struct atla10_ec_data {
	struct i2c_client *client;
	struct power_supply *psy;
	struct delayed_work work;
	struct mutex update_lock;
	struct atla10_ec_battery_info info;
	struct atla10_ec_battery_state state;
	bool valid;			/* true if state is valid */
	unsigned long last_update;	/* In jiffies */
};

static int atla10_ec_cmd(struct atla10_ec_data *data, u8 cmd, u8 len, u8 *values)
{
	struct device *dev = &data->client->dev;
	u8 buf[I2C_SMBUS_BLOCK_MAX];
	int ret;

	ret = i2c_smbus_read_block_data(data->client, cmd, buf);
	if (ret != len) {
		dev_err(dev, "I2C command 0x%02x error: %d\n", cmd, ret);
		return -EIO;
	}

	memcpy(values, buf, len);
	return 0;
}

static int atla10_ec_update(struct atla10_ec_data *data)
{
	int ret;

	if (data->valid && time_before(jiffies, data->last_update + UPDATE_INTERVAL_JIFFIES))
		return 0;

	ret = atla10_ec_cmd(data, ATLA10_EC_BATTERY_STATE_COMMAND,
			    sizeof(data->state), (u8 *)&data->state);
	if (ret)
		return ret;

	data->last_update = jiffies;
	data->valid = true;
	return 0;
}

static int atla10_ec_psy_get_property(struct power_supply *psy,
				      enum power_supply_property psp,
				      union power_supply_propval *val)
{
	struct atla10_ec_data *data = power_supply_get_drvdata(psy);
	int charge_now_mAh, charge_full_mAh, ret;

	guard(mutex)(&data->update_lock);

	ret = atla10_ec_update(data);
	if (ret)
		return ret;

	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		if (data->state.status & ACPI_BATTERY_STATE_DISCHARGING)
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
		else if (data->state.status & ACPI_BATTERY_STATE_CHARGING)
			val->intval = POWER_SUPPLY_STATUS_CHARGING;
		else if (data->state.capacity == 100)
			val->intval = POWER_SUPPLY_STATUS_FULL;
		else
			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
		break;
	case POWER_SUPPLY_PROP_CAPACITY:
		val->intval = data->state.capacity;
		break;
	case POWER_SUPPLY_PROP_CHARGE_NOW:
		/*
		 * The EC has a bug where it reports charge-full-design as

Annotation

Implementation Notes