drivers/pwm/pwm-cros-ec.c

Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-cros-ec.c

File Facts

System
Linux kernel
Corpus path
drivers/pwm/pwm-cros-ec.c
Extension
.c
Size
7182 bytes
Lines
287
Domain
Driver Families
Bucket
drivers/pwm
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_pwm_device {
	struct cros_ec_device *ec;
	bool use_pwm_type;
};

static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *chip)
{
	return pwmchip_get_drvdata(chip);
}

static int cros_ec_dt_type_to_pwm_type(u8 dt_index, u8 *pwm_type)
{
	switch (dt_index) {
	case CROS_EC_PWM_DT_KB_LIGHT:
		*pwm_type = EC_PWM_TYPE_KB_LIGHT;
		return 0;
	case CROS_EC_PWM_DT_DISPLAY_LIGHT:
		*pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT;
		return 0;
	default:
		return -EINVAL;
	}
}

static int cros_ec_pwm_set_duty(struct cros_ec_pwm_device *ec_pwm, u8 index,
				u16 duty)
{
	struct cros_ec_device *ec = ec_pwm->ec;
	TRAILING_OVERLAP(struct cros_ec_command, msg, data,
		struct ec_params_pwm_set_duty params;
	) __packed buf;
	struct ec_params_pwm_set_duty *params = &buf.params;
	struct cros_ec_command *msg = &buf.msg;
	int ret;

	memset(&buf, 0, sizeof(buf));

	msg->version = 0;
	msg->command = EC_CMD_PWM_SET_DUTY;
	msg->insize = 0;
	msg->outsize = sizeof(*params);

	params->duty = duty;

	if (ec_pwm->use_pwm_type) {
		ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
		if (ret) {
			dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
			return ret;
		}
		params->index = 0;
	} else {
		params->pwm_type = EC_PWM_TYPE_GENERIC;
		params->index = index;
	}

	return cros_ec_cmd_xfer_status(ec, msg);
}

static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, bool use_pwm_type, u8 index)
{
	TRAILING_OVERLAP(struct cros_ec_command, msg, data,
		union {
			struct ec_params_pwm_get_duty params;
			struct ec_response_pwm_get_duty resp;
		};
	) __packed buf;
	struct ec_params_pwm_get_duty *params = &buf.params;
	struct ec_response_pwm_get_duty *resp = &buf.resp;
	struct cros_ec_command *msg = &buf.msg;
	int ret;

	memset(&buf, 0, sizeof(buf));

	msg->version = 0;
	msg->command = EC_CMD_PWM_GET_DUTY;
	msg->insize = sizeof(*resp);
	msg->outsize = sizeof(*params);

	if (use_pwm_type) {
		ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
		if (ret) {
			dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
			return ret;
		}
		params->index = 0;
	} else {
		params->pwm_type = EC_PWM_TYPE_GENERIC;
		params->index = index;
	}

Annotation

Implementation Notes