WIP FPC-III support
[linux/fpc-iii.git] / drivers / firmware / arm_scmi / system.c
blob283e12d5f24b7364a4c08103a40c2c46ac0f0065
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * System Control and Management Interface (SCMI) System Power Protocol
5 * Copyright (C) 2020 ARM Ltd.
6 */
8 #define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt
10 #include <linux/scmi_protocol.h>
12 #include "common.h"
13 #include "notify.h"
15 #define SCMI_SYSTEM_NUM_SOURCES 1
17 enum scmi_system_protocol_cmd {
18 SYSTEM_POWER_STATE_NOTIFY = 0x5,
21 struct scmi_system_power_state_notify {
22 __le32 notify_enable;
25 struct scmi_system_power_state_notifier_payld {
26 __le32 agent_id;
27 __le32 flags;
28 __le32 system_state;
31 struct scmi_system_info {
32 u32 version;
35 static int scmi_system_request_notify(const struct scmi_handle *handle,
36 bool enable)
38 int ret;
39 struct scmi_xfer *t;
40 struct scmi_system_power_state_notify *notify;
42 ret = scmi_xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY,
43 SCMI_PROTOCOL_SYSTEM, sizeof(*notify), 0, &t);
44 if (ret)
45 return ret;
47 notify = t->tx.buf;
48 notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;
50 ret = scmi_do_xfer(handle, t);
52 scmi_xfer_put(handle, t);
53 return ret;
56 static int scmi_system_set_notify_enabled(const struct scmi_handle *handle,
57 u8 evt_id, u32 src_id, bool enable)
59 int ret;
61 ret = scmi_system_request_notify(handle, enable);
62 if (ret)
63 pr_debug("FAIL_ENABLE - evt[%X] - ret:%d\n", evt_id, ret);
65 return ret;
68 static void *scmi_system_fill_custom_report(const struct scmi_handle *handle,
69 u8 evt_id, ktime_t timestamp,
70 const void *payld, size_t payld_sz,
71 void *report, u32 *src_id)
73 const struct scmi_system_power_state_notifier_payld *p = payld;
74 struct scmi_system_power_state_notifier_report *r = report;
76 if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER ||
77 sizeof(*p) != payld_sz)
78 return NULL;
80 r->timestamp = timestamp;
81 r->agent_id = le32_to_cpu(p->agent_id);
82 r->flags = le32_to_cpu(p->flags);
83 r->system_state = le32_to_cpu(p->system_state);
84 *src_id = 0;
86 return r;
89 static const struct scmi_event system_events[] = {
91 .id = SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER,
92 .max_payld_sz =
93 sizeof(struct scmi_system_power_state_notifier_payld),
94 .max_report_sz =
95 sizeof(struct scmi_system_power_state_notifier_report),
99 static const struct scmi_event_ops system_event_ops = {
100 .set_notify_enabled = scmi_system_set_notify_enabled,
101 .fill_custom_report = scmi_system_fill_custom_report,
104 static int scmi_system_protocol_init(struct scmi_handle *handle)
106 u32 version;
107 struct scmi_system_info *pinfo;
109 scmi_version_get(handle, SCMI_PROTOCOL_SYSTEM, &version);
111 dev_dbg(handle->dev, "System Power Version %d.%d\n",
112 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
114 pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
115 if (!pinfo)
116 return -ENOMEM;
118 scmi_register_protocol_events(handle,
119 SCMI_PROTOCOL_SYSTEM, SCMI_PROTO_QUEUE_SZ,
120 &system_event_ops,
121 system_events,
122 ARRAY_SIZE(system_events),
123 SCMI_SYSTEM_NUM_SOURCES);
125 pinfo->version = version;
126 handle->system_priv = pinfo;
128 return 0;
131 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SYSTEM, system)