drivers/hwmon/cros_ec_hwmon.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/cros_ec_hwmon.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/cros_ec_hwmon.c
Extension
.c
Size
18626 bytes
Lines
674
Domain
Driver Families
Bucket
drivers/hwmon
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_ec_hwmon_priv {
	struct cros_ec_device *cros_ec;
	const char *temp_sensor_names[EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES];
	u8 usable_fans;
	bool fan_control_supported;
	bool temp_threshold_supported;
	u8 manual_fans; /* bits to indicate whether the fan is set to manual */
	u8 manual_fan_pwm[EC_FAN_SPEED_ENTRIES];
};

struct cros_ec_hwmon_cooling_priv {
	struct cros_ec_hwmon_priv *hwmon_priv;
	u8 index;
};

static int cros_ec_hwmon_read_fan_speed(struct cros_ec_device *cros_ec, u8 index, u16 *speed)
{
	int ret;
	__le16 __speed;

	ret = cros_ec_cmd_readmem(cros_ec, EC_MEMMAP_FAN + index * 2, 2, &__speed);
	if (ret < 0)
		return ret;

	*speed = le16_to_cpu(__speed);
	return 0;
}

static int cros_ec_hwmon_read_pwm_value(struct cros_ec_device *cros_ec, u8 index, u8 *pwm_value)
{
	struct ec_params_pwm_get_fan_duty req = {
		.fan_idx = index,
	};
	struct ec_response_pwm_get_fan_duty resp;
	int ret;

	ret = cros_ec_cmd(cros_ec, CROS_EC_HWMON_PWM_GET_FAN_DUTY_CMD_VERSION,
			  EC_CMD_PWM_GET_FAN_DUTY, &req, sizeof(req), &resp, sizeof(resp));
	if (ret < 0)
		return ret;

	*pwm_value = (u8)DIV_ROUND_CLOSEST(le32_to_cpu(resp.percent) * 255, 100);
	return 0;
}

static int cros_ec_hwmon_read_pwm_enable(struct cros_ec_device *cros_ec, u8 index,
					 u8 *control_method)
{
	struct ec_params_auto_fan_ctrl_v2 req = {
		.cmd = EC_AUTO_FAN_CONTROL_CMD_GET,
		.fan_idx = index,
	};
	struct ec_response_auto_fan_control resp;
	int ret;

	ret = cros_ec_cmd(cros_ec, CROS_EC_HWMON_THERMAL_AUTO_FAN_CTRL_CMD_VERSION,
			  EC_CMD_THERMAL_AUTO_FAN_CTRL, &req, sizeof(req), &resp, sizeof(resp));
	if (ret < 0)
		return ret;

	*control_method = resp.is_auto ? 2 : 1;
	return 0;
}

static int cros_ec_hwmon_read_fan_target(struct cros_ec_device *cros_ec, u16 *speed)
{
	struct ec_response_pwm_get_fan_rpm resp;
	int ret;

	ret = cros_ec_cmd(cros_ec, 0, EC_CMD_PWM_GET_FAN_TARGET_RPM,
			  NULL, 0, &resp, sizeof(resp));
	if (ret < 0)
		return ret;

	*speed = resp.rpm;
	return 0;
}

static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 *temp)
{
	unsigned int offset;
	int ret;

	if (index < EC_TEMP_SENSOR_ENTRIES)
		offset = EC_MEMMAP_TEMP_SENSOR + index;
	else
		offset = EC_MEMMAP_TEMP_SENSOR_B + index - EC_TEMP_SENSOR_ENTRIES;

	ret = cros_ec_cmd_readmem(cros_ec, offset, 1, temp);
	if (ret < 0)

Annotation

Implementation Notes