f5219334fd3a56cf68fe8e3a28e55905d43a93a7
[platform/kernel/linux-starfive.git] / drivers / firmware / arm_scmi / base.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * System Control and Management Interface (SCMI) Base Protocol
4  *
5  * Copyright (C) 2018-2021 ARM Ltd.
6  */
7
8 #define pr_fmt(fmt) "SCMI Notifications BASE - " fmt
9
10 #include <linux/module.h>
11 #include <linux/scmi_protocol.h>
12
13 #include "common.h"
14 #include "notify.h"
15
16 #define SCMI_BASE_NUM_SOURCES           1
17 #define SCMI_BASE_MAX_CMD_ERR_COUNT     1024
18
19 enum scmi_base_protocol_cmd {
20         BASE_DISCOVER_VENDOR = 0x3,
21         BASE_DISCOVER_SUB_VENDOR = 0x4,
22         BASE_DISCOVER_IMPLEMENT_VERSION = 0x5,
23         BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
24         BASE_DISCOVER_AGENT = 0x7,
25         BASE_NOTIFY_ERRORS = 0x8,
26         BASE_SET_DEVICE_PERMISSIONS = 0x9,
27         BASE_SET_PROTOCOL_PERMISSIONS = 0xa,
28         BASE_RESET_AGENT_CONFIGURATION = 0xb,
29 };
30
31 struct scmi_msg_resp_base_attributes {
32         u8 num_protocols;
33         u8 num_agents;
34         __le16 reserved;
35 };
36
37 struct scmi_msg_resp_base_discover_agent {
38         __le32 agent_id;
39         u8 name[SCMI_MAX_STR_SIZE];
40 };
41
42
43 struct scmi_msg_base_error_notify {
44         __le32 event_control;
45 #define BASE_TP_NOTIFY_ALL      BIT(0)
46 };
47
48 struct scmi_base_error_notify_payld {
49         __le32 agent_id;
50         __le32 error_status;
51 #define IS_FATAL_ERROR(x)       ((x) & BIT(31))
52 #define ERROR_CMD_COUNT(x)      FIELD_GET(GENMASK(9, 0), (x))
53         __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT];
54 };
55
56 /**
57  * scmi_base_attributes_get() - gets the implementation details
58  *      that are associated with the base protocol.
59  *
60  * @ph: SCMI protocol handle
61  *
62  * Return: 0 on success, else appropriate SCMI error.
63  */
64 static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph)
65 {
66         int ret;
67         struct scmi_xfer *t;
68         struct scmi_msg_resp_base_attributes *attr_info;
69         struct scmi_revision_info *rev = ph->get_priv(ph);
70
71         ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
72                                       0, sizeof(*attr_info), &t);
73         if (ret)
74                 return ret;
75
76         ret = ph->xops->do_xfer(ph, t);
77         if (!ret) {
78                 attr_info = t->rx.buf;
79                 rev->num_protocols = attr_info->num_protocols;
80                 rev->num_agents = attr_info->num_agents;
81         }
82
83         ph->xops->xfer_put(ph, t);
84
85         return ret;
86 }
87
88 /**
89  * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
90  *
91  * @ph: SCMI protocol handle
92  * @sub_vendor: specify true if sub-vendor ID is needed
93  *
94  * Return: 0 on success, else appropriate SCMI error.
95  */
96 static int
97 scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor)
98 {
99         u8 cmd;
100         int ret, size;
101         char *vendor_id;
102         struct scmi_xfer *t;
103         struct scmi_revision_info *rev = ph->get_priv(ph);
104
105
106         if (sub_vendor) {
107                 cmd = BASE_DISCOVER_SUB_VENDOR;
108                 vendor_id = rev->sub_vendor_id;
109                 size = ARRAY_SIZE(rev->sub_vendor_id);
110         } else {
111                 cmd = BASE_DISCOVER_VENDOR;
112                 vendor_id = rev->vendor_id;
113                 size = ARRAY_SIZE(rev->vendor_id);
114         }
115
116         ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t);
117         if (ret)
118                 return ret;
119
120         ret = ph->xops->do_xfer(ph, t);
121         if (!ret)
122                 memcpy(vendor_id, t->rx.buf, size);
123
124         ph->xops->xfer_put(ph, t);
125
126         return ret;
127 }
128
129 /**
130  * scmi_base_implementation_version_get() - gets a vendor-specific
131  *      implementation 32-bit version. The format of the version number is
132  *      vendor-specific
133  *
134  * @ph: SCMI protocol handle
135  *
136  * Return: 0 on success, else appropriate SCMI error.
137  */
138 static int
139 scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph)
140 {
141         int ret;
142         __le32 *impl_ver;
143         struct scmi_xfer *t;
144         struct scmi_revision_info *rev = ph->get_priv(ph);
145
146         ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION,
147                                       0, sizeof(*impl_ver), &t);
148         if (ret)
149                 return ret;
150
151         ret = ph->xops->do_xfer(ph, t);
152         if (!ret) {
153                 impl_ver = t->rx.buf;
154                 rev->impl_ver = le32_to_cpu(*impl_ver);
155         }
156
157         ph->xops->xfer_put(ph, t);
158
159         return ret;
160 }
161
162 /**
163  * scmi_base_implementation_list_get() - gets the list of protocols it is
164  *      OSPM is allowed to access
165  *
166  * @ph: SCMI protocol handle
167  * @protocols_imp: pointer to hold the list of protocol identifiers
168  *
169  * Return: 0 on success, else appropriate SCMI error.
170  */
171 static int
172 scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
173                                   u8 *protocols_imp)
174 {
175         u8 *list;
176         int ret, loop;
177         struct scmi_xfer *t;
178         __le32 *num_skip, *num_ret;
179         u32 tot_num_ret = 0, loop_num_ret;
180         struct device *dev = ph->dev;
181
182         ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS,
183                                       sizeof(*num_skip), 0, &t);
184         if (ret)
185                 return ret;
186
187         num_skip = t->tx.buf;
188         num_ret = t->rx.buf;
189         list = t->rx.buf + sizeof(*num_ret);
190
191         do {
192                 /* Set the number of protocols to be skipped/already read */
193                 *num_skip = cpu_to_le32(tot_num_ret);
194
195                 ret = ph->xops->do_xfer(ph, t);
196                 if (ret)
197                         break;
198
199                 loop_num_ret = le32_to_cpu(*num_ret);
200                 if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
201                         dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
202                         break;
203                 }
204
205                 for (loop = 0; loop < loop_num_ret; loop++)
206                         protocols_imp[tot_num_ret + loop] = *(list + loop);
207
208                 tot_num_ret += loop_num_ret;
209
210                 ph->xops->reset_rx_to_maxsz(ph, t);
211         } while (loop_num_ret);
212
213         ph->xops->xfer_put(ph, t);
214
215         return ret;
216 }
217
218 /**
219  * scmi_base_discover_agent_get() - discover the name of an agent
220  *
221  * @ph: SCMI protocol handle
222  * @id: Agent identifier
223  * @name: Agent identifier ASCII string
224  *
225  * An agent id of 0 is reserved to identify the platform itself.
226  * Generally operating system is represented as "OSPM"
227  *
228  * Return: 0 on success, else appropriate SCMI error.
229  */
230 static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph,
231                                         int id, char *name)
232 {
233         int ret;
234         struct scmi_msg_resp_base_discover_agent *agent_info;
235         struct scmi_xfer *t;
236
237         ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT,
238                                       sizeof(__le32), sizeof(*agent_info), &t);
239         if (ret)
240                 return ret;
241
242         put_unaligned_le32(id, t->tx.buf);
243
244         ret = ph->xops->do_xfer(ph, t);
245         if (!ret) {
246                 agent_info = t->rx.buf;
247                 strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE);
248         }
249
250         ph->xops->xfer_put(ph, t);
251
252         return ret;
253 }
254
255 static int scmi_base_error_notify(const struct scmi_protocol_handle *ph,
256                                   bool enable)
257 {
258         int ret;
259         u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0;
260         struct scmi_xfer *t;
261         struct scmi_msg_base_error_notify *cfg;
262
263         ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS,
264                                       sizeof(*cfg), 0, &t);
265         if (ret)
266                 return ret;
267
268         cfg = t->tx.buf;
269         cfg->event_control = cpu_to_le32(evt_cntl);
270
271         ret = ph->xops->do_xfer(ph, t);
272
273         ph->xops->xfer_put(ph, t);
274         return ret;
275 }
276
277 static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle *ph,
278                                         u8 evt_id, u32 src_id, bool enable)
279 {
280         int ret;
281
282         ret = scmi_base_error_notify(ph, enable);
283         if (ret)
284                 pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret);
285
286         return ret;
287 }
288
289 static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph,
290                                           u8 evt_id, ktime_t timestamp,
291                                           const void *payld, size_t payld_sz,
292                                           void *report, u32 *src_id)
293 {
294         int i;
295         const struct scmi_base_error_notify_payld *p = payld;
296         struct scmi_base_error_report *r = report;
297
298         /*
299          * BaseError notification payload is variable in size but
300          * up to a maximum length determined by the struct ponted by p.
301          * Instead payld_sz is the effective length of this notification
302          * payload so cannot be greater of the maximum allowed size as
303          * pointed by p.
304          */
305         if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz)
306                 return NULL;
307
308         r->timestamp = timestamp;
309         r->agent_id = le32_to_cpu(p->agent_id);
310         r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status));
311         r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status));
312         for (i = 0; i < r->cmd_count; i++)
313                 r->reports[i] = le64_to_cpu(p->msg_reports[i]);
314         *src_id = 0;
315
316         return r;
317 }
318
319 static const struct scmi_event base_events[] = {
320         {
321                 .id = SCMI_EVENT_BASE_ERROR_EVENT,
322                 .max_payld_sz = sizeof(struct scmi_base_error_notify_payld),
323                 .max_report_sz = sizeof(struct scmi_base_error_report) +
324                                   SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64),
325         },
326 };
327
328 static const struct scmi_event_ops base_event_ops = {
329         .set_notify_enabled = scmi_base_set_notify_enabled,
330         .fill_custom_report = scmi_base_fill_custom_report,
331 };
332
333 static const struct scmi_protocol_events base_protocol_events = {
334         .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ,
335         .ops = &base_event_ops,
336         .evts = base_events,
337         .num_events = ARRAY_SIZE(base_events),
338         .num_sources = SCMI_BASE_NUM_SOURCES,
339 };
340
341 static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
342 {
343         int id, ret;
344         u8 *prot_imp;
345         u32 version;
346         char name[SCMI_MAX_STR_SIZE];
347         struct device *dev = ph->dev;
348         struct scmi_revision_info *rev = scmi_revision_area_get(ph);
349
350         ret = ph->xops->version_get(ph, &version);
351         if (ret)
352                 return ret;
353
354         prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
355         if (!prot_imp)
356                 return -ENOMEM;
357
358         rev->major_ver = PROTOCOL_REV_MAJOR(version),
359         rev->minor_ver = PROTOCOL_REV_MINOR(version);
360         ph->set_priv(ph, rev);
361
362         scmi_base_attributes_get(ph);
363         scmi_base_vendor_id_get(ph, false);
364         scmi_base_vendor_id_get(ph, true);
365         scmi_base_implementation_version_get(ph);
366         scmi_base_implementation_list_get(ph, prot_imp);
367
368         scmi_setup_protocol_implemented(ph, prot_imp);
369
370         dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
371                  rev->major_ver, rev->minor_ver, rev->vendor_id,
372                  rev->sub_vendor_id, rev->impl_ver);
373         dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols,
374                 rev->num_agents);
375
376         for (id = 0; id < rev->num_agents; id++) {
377                 scmi_base_discover_agent_get(ph, id, name);
378                 dev_dbg(dev, "Agent %d: %s\n", id, name);
379         }
380
381         return 0;
382 }
383
384 static const struct scmi_protocol scmi_base = {
385         .id = SCMI_PROTOCOL_BASE,
386         .owner = NULL,
387         .instance_init = &scmi_base_protocol_init,
388         .ops = NULL,
389         .events = &base_protocol_events,
390 };
391
392 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base)