drivers/firmware/arm_scmi/system.c

Source file repositories/reference/linux-study-clean/drivers/firmware/arm_scmi/system.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/arm_scmi/system.c
Extension
.c
Size
4457 bytes
Lines
171
Domain
Driver Families
Bucket
drivers/firmware
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 scmi_system_power_state_notify {
	__le32 notify_enable;
};

struct scmi_system_power_state_notifier_payld {
	__le32 agent_id;
	__le32 flags;
	__le32 system_state;
	__le32 timeout;
};

struct scmi_system_info {
	bool graceful_timeout_supported;
	bool power_state_notify_cmd;
};

static bool scmi_system_notify_supported(const struct scmi_protocol_handle *ph,
					 u8 evt_id, u32 src_id)
{
	struct scmi_system_info *pinfo = ph->get_priv(ph);

	if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER)
		return false;

	return pinfo->power_state_notify_cmd;
}

static int scmi_system_request_notify(const struct scmi_protocol_handle *ph,
				      bool enable)
{
	int ret;
	struct scmi_xfer *t;
	struct scmi_system_power_state_notify *notify;

	ret = ph->xops->xfer_get_init(ph, SYSTEM_POWER_STATE_NOTIFY,
				      sizeof(*notify), 0, &t);
	if (ret)
		return ret;

	notify = t->tx.buf;
	notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;

	ret = ph->xops->do_xfer(ph, t);

	ph->xops->xfer_put(ph, t);
	return ret;
}

static int scmi_system_set_notify_enabled(const struct scmi_protocol_handle *ph,
					  u8 evt_id, u32 src_id, bool enable)
{
	int ret;

	ret = scmi_system_request_notify(ph, enable);
	if (ret)
		pr_debug("FAIL_ENABLE - evt[%X] - ret:%d\n", evt_id, ret);

	return ret;
}

static void *
scmi_system_fill_custom_report(const struct scmi_protocol_handle *ph,
			       u8 evt_id, ktime_t timestamp,
			       const void *payld, size_t payld_sz,
			       void *report, u32 *src_id)
{
	size_t expected_sz;
	const struct scmi_system_power_state_notifier_payld *p = payld;
	struct scmi_system_power_state_notifier_report *r = report;
	struct scmi_system_info *pinfo = ph->get_priv(ph);

	expected_sz = pinfo->graceful_timeout_supported ?
			sizeof(*p) : sizeof(*p) - sizeof(__le32);
	if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER ||
	    payld_sz != expected_sz)
		return NULL;

	r->timestamp = timestamp;
	r->agent_id = le32_to_cpu(p->agent_id);
	r->flags = le32_to_cpu(p->flags);
	r->system_state = le32_to_cpu(p->system_state);
	if (pinfo->graceful_timeout_supported &&
	    r->system_state == SCMI_SYSTEM_SHUTDOWN &&
	    SCMI_SYSPOWER_IS_REQUEST_GRACEFUL(r->flags))
		r->timeout = le32_to_cpu(p->timeout);
	else
		r->timeout = 0x00;
	*src_id = 0;

	return r;

Annotation

Implementation Notes