1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Reset Protocol
5 * Copyright (C) 2019-2021 ARM Ltd.
8 #define pr_fmt(fmt) "SCMI Notifications RESET - " fmt
10 #include <linux/scmi_protocol.h>
15 enum scmi_reset_protocol_cmd {
16 RESET_DOMAIN_ATTRIBUTES = 0x3,
21 #define NUM_RESET_DOMAIN_MASK 0xffff
22 #define RESET_NOTIFY_ENABLE BIT(0)
24 struct scmi_msg_resp_reset_domain_attributes {
26 #define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31))
27 #define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30))
29 u8 name[SCMI_MAX_STR_SIZE];
32 struct scmi_msg_reset_domain_reset {
35 #define AUTONOMOUS_RESET BIT(0)
36 #define EXPLICIT_RESET_ASSERT BIT(1)
37 #define ASYNCHRONOUS_RESET BIT(2)
39 #define ARCH_COLD_RESET 0
42 struct scmi_msg_reset_notify {
45 #define RESET_TP_NOTIFY_ALL BIT(0)
48 struct scmi_reset_issued_notify_payld {
54 struct reset_dom_info {
58 char name[SCMI_MAX_STR_SIZE];
61 struct scmi_reset_info {
64 struct reset_dom_info *dom_info;
67 static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
68 struct scmi_reset_info *pi)
74 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
79 ret = ph->xops->do_xfer(ph, t);
81 attr = get_unaligned_le32(t->rx.buf);
82 pi->num_domains = attr & NUM_RESET_DOMAIN_MASK;
85 ph->xops->xfer_put(ph, t);
90 scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
91 u32 domain, struct reset_dom_info *dom_info)
95 struct scmi_msg_resp_reset_domain_attributes *attr;
97 ret = ph->xops->xfer_get_init(ph, RESET_DOMAIN_ATTRIBUTES,
98 sizeof(domain), sizeof(*attr), &t);
102 put_unaligned_le32(domain, t->tx.buf);
105 ret = ph->xops->do_xfer(ph, t);
107 u32 attributes = le32_to_cpu(attr->attributes);
109 dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes);
110 dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes);
111 dom_info->latency_us = le32_to_cpu(attr->latency);
112 if (dom_info->latency_us == U32_MAX)
113 dom_info->latency_us = 0;
114 strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
117 ph->xops->xfer_put(ph, t);
121 static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph)
123 struct scmi_reset_info *pi = ph->get_priv(ph);
125 return pi->num_domains;
128 static char *scmi_reset_name_get(const struct scmi_protocol_handle *ph,
131 struct scmi_reset_info *pi = ph->get_priv(ph);
133 struct reset_dom_info *dom = pi->dom_info + domain;
138 static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
141 struct scmi_reset_info *pi = ph->get_priv(ph);
142 struct reset_dom_info *dom = pi->dom_info + domain;
144 return dom->latency_us;
147 static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
148 u32 flags, u32 state)
152 struct scmi_msg_reset_domain_reset *dom;
153 struct scmi_reset_info *pi = ph->get_priv(ph);
154 struct reset_dom_info *rdom = pi->dom_info + domain;
156 if (rdom->async_reset)
157 flags |= ASYNCHRONOUS_RESET;
159 ret = ph->xops->xfer_get_init(ph, RESET, sizeof(*dom), 0, &t);
164 dom->domain_id = cpu_to_le32(domain);
165 dom->flags = cpu_to_le32(flags);
166 dom->reset_state = cpu_to_le32(state);
168 if (rdom->async_reset)
169 ret = ph->xops->do_xfer_with_response(ph, t);
171 ret = ph->xops->do_xfer(ph, t);
173 ph->xops->xfer_put(ph, t);
177 static int scmi_reset_domain_reset(const struct scmi_protocol_handle *ph,
180 return scmi_domain_reset(ph, domain, AUTONOMOUS_RESET,
185 scmi_reset_domain_assert(const struct scmi_protocol_handle *ph, u32 domain)
187 return scmi_domain_reset(ph, domain, EXPLICIT_RESET_ASSERT,
192 scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
194 return scmi_domain_reset(ph, domain, 0, ARCH_COLD_RESET);
197 static const struct scmi_reset_proto_ops reset_proto_ops = {
198 .num_domains_get = scmi_reset_num_domains_get,
199 .name_get = scmi_reset_name_get,
200 .latency_get = scmi_reset_latency_get,
201 .reset = scmi_reset_domain_reset,
202 .assert = scmi_reset_domain_assert,
203 .deassert = scmi_reset_domain_deassert,
206 static int scmi_reset_notify(const struct scmi_protocol_handle *ph,
207 u32 domain_id, bool enable)
210 u32 evt_cntl = enable ? RESET_TP_NOTIFY_ALL : 0;
212 struct scmi_msg_reset_notify *cfg;
214 ret = ph->xops->xfer_get_init(ph, RESET_NOTIFY, sizeof(*cfg), 0, &t);
219 cfg->id = cpu_to_le32(domain_id);
220 cfg->event_control = cpu_to_le32(evt_cntl);
222 ret = ph->xops->do_xfer(ph, t);
224 ph->xops->xfer_put(ph, t);
228 static int scmi_reset_set_notify_enabled(const void *ph,
229 u8 evt_id, u32 src_id, bool enable)
233 ret = scmi_reset_notify(ph, src_id, enable);
235 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
236 evt_id, src_id, ret);
241 static void *scmi_reset_fill_custom_report(const void *ph,
242 u8 evt_id, ktime_t timestamp,
243 const void *payld, size_t payld_sz,
244 void *report, u32 *src_id)
246 const struct scmi_reset_issued_notify_payld *p = payld;
247 struct scmi_reset_issued_report *r = report;
249 if (evt_id != SCMI_EVENT_RESET_ISSUED || sizeof(*p) != payld_sz)
252 r->timestamp = timestamp;
253 r->agent_id = le32_to_cpu(p->agent_id);
254 r->domain_id = le32_to_cpu(p->domain_id);
255 r->reset_state = le32_to_cpu(p->reset_state);
256 *src_id = r->domain_id;
261 static int scmi_reset_get_num_sources(const void *ph)
263 struct scmi_reset_info *pinfo =
264 ((const struct scmi_protocol_handle *)ph)->get_priv(ph);
269 return pinfo->num_domains;
272 static const struct scmi_event reset_events[] = {
274 .id = SCMI_EVENT_RESET_ISSUED,
275 .max_payld_sz = sizeof(struct scmi_reset_issued_notify_payld),
276 .max_report_sz = sizeof(struct scmi_reset_issued_report),
280 static const struct scmi_event_ops reset_event_ops = {
281 .get_num_sources = scmi_reset_get_num_sources,
282 .set_notify_enabled = scmi_reset_set_notify_enabled,
283 .fill_custom_report = scmi_reset_fill_custom_report,
286 static const struct scmi_protocol_events reset_protocol_events = {
287 .queue_sz = SCMI_PROTO_QUEUE_SZ,
288 .ops = &reset_event_ops,
289 .evts = reset_events,
290 .num_events = ARRAY_SIZE(reset_events),
293 static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
297 struct scmi_reset_info *pinfo;
299 ph->xops->version_get(ph, &version);
301 dev_dbg(ph->dev, "Reset Version %d.%d\n",
302 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
304 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
308 scmi_reset_attributes_get(ph, pinfo);
310 pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
311 sizeof(*pinfo->dom_info), GFP_KERNEL);
312 if (!pinfo->dom_info)
315 for (domain = 0; domain < pinfo->num_domains; domain++) {
316 struct reset_dom_info *dom = pinfo->dom_info + domain;
318 scmi_reset_domain_attributes_get(ph, domain, dom);
321 pinfo->version = version;
322 return ph->set_priv(ph, pinfo);
325 static const struct scmi_protocol scmi_reset = {
326 .id = SCMI_PROTOCOL_RESET,
327 .instance_init = &scmi_reset_protocol_init,
328 .ops = &reset_proto_ops,
329 .events = &reset_protocol_events,
332 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(reset, scmi_reset)