drivers/power/supply/cros_charge-control.c

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

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/cros_charge-control.c
Extension
.c
Size
9708 bytes
Lines
338
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 cros_chctl_priv {
	struct device *dev;
	struct cros_ec_device *cros_ec;
	struct acpi_battery_hook battery_hook;
	struct power_supply *hooked_battery;
	u8 cmd_version;

	const struct power_supply_ext *psy_ext;

	struct mutex lock; /* protects fields below and cros_ec */
	enum power_supply_charge_behaviour current_behaviour;
	u8 current_start_threshold, current_end_threshold;
};

static int cros_chctl_send_charge_control_cmd(struct cros_ec_device *cros_ec,
					      u8 cmd_version, struct ec_params_charge_control *req)
{
	int ret;
	static const u8 outsizes[] = {
		[1] = offsetof(struct ec_params_charge_control, cmd),
		[2] = sizeof(struct ec_params_charge_control),
		[3] = sizeof(struct ec_params_charge_control),
	};

	ret = cros_ec_cmd(cros_ec, cmd_version, EC_CMD_CHARGE_CONTROL, req,
			  outsizes[cmd_version], NULL, 0);

	if (ret < 0)
		return ret;

	return 0;
}

static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
{
	struct ec_params_charge_control req = {};

	lockdep_assert_held(&priv->lock);

	req.cmd = EC_CHARGE_CONTROL_CMD_SET;

	switch (priv->current_behaviour) {
	case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
		req.mode = CHARGE_CONTROL_NORMAL;
		break;
	case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
		req.mode = CHARGE_CONTROL_IDLE;
		break;
	case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE:
		req.mode = CHARGE_CONTROL_DISCHARGE;
		break;
	default:
		return -EINVAL;
	}

	if (priv->current_behaviour == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO &&
	    !(priv->current_start_threshold == 0 && priv->current_end_threshold == 100)) {
		req.sustain_soc.lower = priv->current_start_threshold;
		req.sustain_soc.upper = priv->current_end_threshold;
	} else {
		/* Disable charging limits */
		req.sustain_soc.lower = -1;
		req.sustain_soc.upper = -1;
	}

	return cros_chctl_send_charge_control_cmd(priv->cros_ec, priv->cmd_version, &req);
}

static int cros_chctl_psy_ext_get_prop(struct power_supply *psy,
				       const struct power_supply_ext *ext,
				       void *data,
				       enum power_supply_property psp,
				       union power_supply_propval *val)
{
	struct cros_chctl_priv *priv = data;

	switch (psp) {
	case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
		val->intval = priv->current_start_threshold;
		return 0;
	case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
		val->intval = priv->current_end_threshold;
		return 0;
	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
		val->intval = priv->current_behaviour;
		return 0;
	default:
		return -EINVAL;
	}
}

Annotation

Implementation Notes