1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Base Protocol
5 * Copyright (C) 2018-2021 ARM Ltd.
8 #define pr_fmt(fmt) "SCMI Notifications BASE - " fmt
10 #include <linux/module.h>
11 #include <linux/scmi_protocol.h>
16 /* Updated only after ALL the mandatory features for that version are merged */
17 #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001
19 #define SCMI_BASE_NUM_SOURCES 1
20 #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024
22 enum scmi_base_protocol_cmd
{
23 BASE_DISCOVER_VENDOR
= 0x3,
24 BASE_DISCOVER_SUB_VENDOR
= 0x4,
25 BASE_DISCOVER_IMPLEMENT_VERSION
= 0x5,
26 BASE_DISCOVER_LIST_PROTOCOLS
= 0x6,
27 BASE_DISCOVER_AGENT
= 0x7,
28 BASE_NOTIFY_ERRORS
= 0x8,
29 BASE_SET_DEVICE_PERMISSIONS
= 0x9,
30 BASE_SET_PROTOCOL_PERMISSIONS
= 0xa,
31 BASE_RESET_AGENT_CONFIGURATION
= 0xb,
34 struct scmi_msg_resp_base_attributes
{
40 struct scmi_msg_resp_base_discover_agent
{
42 u8 name
[SCMI_SHORT_NAME_MAX_SIZE
];
45 struct scmi_msg_base_error_notify
{
47 #define BASE_TP_NOTIFY_ALL BIT(0)
50 struct scmi_base_error_notify_payld
{
53 #define IS_FATAL_ERROR(x) ((x) & BIT(31))
54 #define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x))
55 __le64 msg_reports
[SCMI_BASE_MAX_CMD_ERR_COUNT
];
59 * scmi_base_attributes_get() - gets the implementation details
60 * that are associated with the base protocol.
62 * @ph: SCMI protocol handle
64 * Return: 0 on success, else appropriate SCMI error.
66 static int scmi_base_attributes_get(const struct scmi_protocol_handle
*ph
)
70 struct scmi_msg_resp_base_attributes
*attr_info
;
71 struct scmi_revision_info
*rev
= ph
->get_priv(ph
);
73 ret
= ph
->xops
->xfer_get_init(ph
, PROTOCOL_ATTRIBUTES
,
74 0, sizeof(*attr_info
), &t
);
78 ret
= ph
->xops
->do_xfer(ph
, t
);
80 attr_info
= t
->rx
.buf
;
81 rev
->num_protocols
= attr_info
->num_protocols
;
82 rev
->num_agents
= attr_info
->num_agents
;
85 ph
->xops
->xfer_put(ph
, t
);
91 * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
93 * @ph: SCMI protocol handle
94 * @sub_vendor: specify true if sub-vendor ID is needed
96 * Return: 0 on success, else appropriate SCMI error.
99 scmi_base_vendor_id_get(const struct scmi_protocol_handle
*ph
, bool sub_vendor
)
105 struct scmi_revision_info
*rev
= ph
->get_priv(ph
);
108 cmd
= BASE_DISCOVER_SUB_VENDOR
;
109 vendor_id
= rev
->sub_vendor_id
;
110 size
= ARRAY_SIZE(rev
->sub_vendor_id
);
112 cmd
= BASE_DISCOVER_VENDOR
;
113 vendor_id
= rev
->vendor_id
;
114 size
= ARRAY_SIZE(rev
->vendor_id
);
117 ret
= ph
->xops
->xfer_get_init(ph
, cmd
, 0, size
, &t
);
121 ret
= ph
->xops
->do_xfer(ph
, t
);
123 strscpy(vendor_id
, t
->rx
.buf
, size
);
125 ph
->xops
->xfer_put(ph
, t
);
131 * scmi_base_implementation_version_get() - gets a vendor-specific
132 * implementation 32-bit version. The format of the version number is
135 * @ph: SCMI protocol handle
137 * Return: 0 on success, else appropriate SCMI error.
140 scmi_base_implementation_version_get(const struct scmi_protocol_handle
*ph
)
145 struct scmi_revision_info
*rev
= ph
->get_priv(ph
);
147 ret
= ph
->xops
->xfer_get_init(ph
, BASE_DISCOVER_IMPLEMENT_VERSION
,
148 0, sizeof(*impl_ver
), &t
);
152 ret
= ph
->xops
->do_xfer(ph
, t
);
154 impl_ver
= t
->rx
.buf
;
155 rev
->impl_ver
= le32_to_cpu(*impl_ver
);
158 ph
->xops
->xfer_put(ph
, t
);
164 * scmi_base_implementation_list_get() - gets the list of protocols it is
165 * OSPM is allowed to access
167 * @ph: SCMI protocol handle
168 * @protocols_imp: pointer to hold the list of protocol identifiers
170 * Return: 0 on success, else appropriate SCMI error.
173 scmi_base_implementation_list_get(const struct scmi_protocol_handle
*ph
,
179 __le32
*num_skip
, *num_ret
;
180 u32 tot_num_ret
= 0, loop_num_ret
;
181 struct device
*dev
= ph
->dev
;
182 struct scmi_revision_info
*rev
= ph
->get_priv(ph
);
184 ret
= ph
->xops
->xfer_get_init(ph
, BASE_DISCOVER_LIST_PROTOCOLS
,
185 sizeof(*num_skip
), 0, &t
);
189 num_skip
= t
->tx
.buf
;
191 list
= t
->rx
.buf
+ sizeof(*num_ret
);
197 /* Set the number of protocols to be skipped/already read */
198 *num_skip
= cpu_to_le32(tot_num_ret
);
200 ret
= ph
->xops
->do_xfer(ph
, t
);
204 loop_num_ret
= le32_to_cpu(*num_ret
);
208 if (loop_num_ret
> rev
->num_protocols
- tot_num_ret
) {
210 "No. Returned protocols > Total protocols.\n");
214 if (t
->rx
.len
< (sizeof(u32
) * 2)) {
215 dev_err(dev
, "Truncated reply - rx.len:%zd\n",
221 real_list_sz
= t
->rx
.len
- sizeof(u32
);
222 calc_list_sz
= (1 + (loop_num_ret
- 1) / sizeof(u32
)) *
224 if (calc_list_sz
!= real_list_sz
) {
226 "Malformed reply - real_sz:%zd calc_sz:%u (loop_num_ret:%d)\n",
227 real_list_sz
, calc_list_sz
, loop_num_ret
);
229 * Bail out if the expected list size is bigger than the
230 * total payload size of the received reply.
232 if (calc_list_sz
> real_list_sz
) {
238 for (loop
= 0; loop
< loop_num_ret
; loop
++)
239 protocols_imp
[tot_num_ret
+ loop
] = *(list
+ loop
);
241 tot_num_ret
+= loop_num_ret
;
243 ph
->xops
->reset_rx_to_maxsz(ph
, t
);
244 } while (tot_num_ret
< rev
->num_protocols
);
246 ph
->xops
->xfer_put(ph
, t
);
252 * scmi_base_discover_agent_get() - discover the name of an agent
254 * @ph: SCMI protocol handle
255 * @id: Agent identifier
256 * @name: Agent identifier ASCII string
258 * An agent id of 0 is reserved to identify the platform itself.
259 * Generally operating system is represented as "OSPM"
261 * Return: 0 on success, else appropriate SCMI error.
263 static int scmi_base_discover_agent_get(const struct scmi_protocol_handle
*ph
,
267 struct scmi_msg_resp_base_discover_agent
*agent_info
;
270 ret
= ph
->xops
->xfer_get_init(ph
, BASE_DISCOVER_AGENT
,
271 sizeof(__le32
), sizeof(*agent_info
), &t
);
275 put_unaligned_le32(id
, t
->tx
.buf
);
277 ret
= ph
->xops
->do_xfer(ph
, t
);
279 agent_info
= t
->rx
.buf
;
280 strscpy(name
, agent_info
->name
, SCMI_SHORT_NAME_MAX_SIZE
);
283 ph
->xops
->xfer_put(ph
, t
);
288 static int scmi_base_error_notify(const struct scmi_protocol_handle
*ph
,
292 u32 evt_cntl
= enable
? BASE_TP_NOTIFY_ALL
: 0;
294 struct scmi_msg_base_error_notify
*cfg
;
296 ret
= ph
->xops
->xfer_get_init(ph
, BASE_NOTIFY_ERRORS
,
297 sizeof(*cfg
), 0, &t
);
302 cfg
->event_control
= cpu_to_le32(evt_cntl
);
304 ret
= ph
->xops
->do_xfer(ph
, t
);
306 ph
->xops
->xfer_put(ph
, t
);
310 static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle
*ph
,
311 u8 evt_id
, u32 src_id
, bool enable
)
315 ret
= scmi_base_error_notify(ph
, enable
);
317 pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id
, ret
);
322 static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle
*ph
,
323 u8 evt_id
, ktime_t timestamp
,
324 const void *payld
, size_t payld_sz
,
325 void *report
, u32
*src_id
)
328 const struct scmi_base_error_notify_payld
*p
= payld
;
329 struct scmi_base_error_report
*r
= report
;
332 * BaseError notification payload is variable in size but
333 * up to a maximum length determined by the struct ponted by p.
334 * Instead payld_sz is the effective length of this notification
335 * payload so cannot be greater of the maximum allowed size as
338 if (evt_id
!= SCMI_EVENT_BASE_ERROR_EVENT
|| sizeof(*p
) < payld_sz
)
341 r
->timestamp
= timestamp
;
342 r
->agent_id
= le32_to_cpu(p
->agent_id
);
343 r
->fatal
= IS_FATAL_ERROR(le32_to_cpu(p
->error_status
));
344 r
->cmd_count
= ERROR_CMD_COUNT(le32_to_cpu(p
->error_status
));
345 for (i
= 0; i
< r
->cmd_count
; i
++)
346 r
->reports
[i
] = le64_to_cpu(p
->msg_reports
[i
]);
352 static const struct scmi_event base_events
[] = {
354 .id
= SCMI_EVENT_BASE_ERROR_EVENT
,
355 .max_payld_sz
= sizeof(struct scmi_base_error_notify_payld
),
356 .max_report_sz
= sizeof(struct scmi_base_error_report
) +
357 SCMI_BASE_MAX_CMD_ERR_COUNT
* sizeof(u64
),
361 static const struct scmi_event_ops base_event_ops
= {
362 .set_notify_enabled
= scmi_base_set_notify_enabled
,
363 .fill_custom_report
= scmi_base_fill_custom_report
,
366 static const struct scmi_protocol_events base_protocol_events
= {
367 .queue_sz
= 4 * SCMI_PROTO_QUEUE_SZ
,
368 .ops
= &base_event_ops
,
370 .num_events
= ARRAY_SIZE(base_events
),
371 .num_sources
= SCMI_BASE_NUM_SOURCES
,
374 static int scmi_base_protocol_init(const struct scmi_protocol_handle
*ph
)
379 char name
[SCMI_SHORT_NAME_MAX_SIZE
];
380 struct device
*dev
= ph
->dev
;
381 struct scmi_revision_info
*rev
= scmi_revision_area_get(ph
);
383 ret
= ph
->xops
->version_get(ph
, &version
);
387 rev
->major_ver
= PROTOCOL_REV_MAJOR(version
);
388 rev
->minor_ver
= PROTOCOL_REV_MINOR(version
);
389 ph
->set_priv(ph
, rev
, version
);
391 ret
= scmi_base_attributes_get(ph
);
395 prot_imp
= devm_kcalloc(dev
, rev
->num_protocols
, sizeof(u8
),
400 scmi_base_vendor_id_get(ph
, false);
401 scmi_base_vendor_id_get(ph
, true);
402 scmi_base_implementation_version_get(ph
);
403 scmi_base_implementation_list_get(ph
, prot_imp
);
405 scmi_setup_protocol_implemented(ph
, prot_imp
);
407 dev_info(dev
, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
408 rev
->major_ver
, rev
->minor_ver
, rev
->vendor_id
,
409 rev
->sub_vendor_id
, rev
->impl_ver
);
410 dev_dbg(dev
, "Found %d protocol(s) %d agent(s)\n", rev
->num_protocols
,
413 for (id
= 0; id
< rev
->num_agents
; id
++) {
414 scmi_base_discover_agent_get(ph
, id
, name
);
415 dev_dbg(dev
, "Agent %d: %s\n", id
, name
);
421 static const struct scmi_protocol scmi_base
= {
422 .id
= SCMI_PROTOCOL_BASE
,
424 .instance_init
= &scmi_base_protocol_init
,
426 .events
= &base_protocol_events
,
427 .supported_version
= SCMI_PROTOCOL_SUPPORTED_VERSION
,
430 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base
, scmi_base
)