Skip to content

Commit 8e3fee3

Browse files
committed
drivers: firmware: scmi: add event registration and core dispatcher
Add support for protocol-level registration of notification events during static registration. Each protocol declares the notifications it needs at static init time. In the SCMI core layer, upon receiving a P2A notification, the core iterates over all registered protocols to locate the matching event and dispatches it to the appropriate protocol handler. Signed-off-by: Yongxu Wang <[email protected]>
1 parent e8aa209 commit 8e3fee3

File tree

7 files changed

+79
-16
lines changed

7 files changed

+79
-16
lines changed

drivers/clock_control/clock_control_arm_scmi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,4 @@ static struct scmi_clock_data data;
121121

122122
DT_INST_SCMI_PROTOCOL_DEFINE(0, &scmi_clock_init, NULL, &data, NULL,
123123
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
124-
&scmi_clock_api);
124+
&scmi_clock_api, NULL);

drivers/firmware/scmi/core.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,37 @@ int scmi_status_to_errno(int scmi_status)
4343
}
4444
}
4545

46+
static int scmi_core_handle_notification(int hdr)
47+
{
48+
uint32_t protocol_id, msg_id;
49+
struct scmi_protocol_event *events;
50+
51+
protocol_id = SCMI_MESSAGE_HDR_TAKE_PROTOCOL(hdr);
52+
msg_id = SCMI_MESSAGE_HDR_TAKE_MSGID(hdr);
53+
54+
STRUCT_SECTION_FOREACH(scmi_protocol, it) {
55+
events = it->events;
56+
if (!events || !events->cb) {
57+
continue;
58+
}
59+
60+
if (protocol_id == it->id) {
61+
for (uint32_t num = 0; num < events->num_events; num++) {
62+
if (msg_id == events->evts[num]) {
63+
events->cb(msg_id);
64+
return 0;
65+
}
66+
}
67+
}
68+
}
69+
70+
return -ENOENT;
71+
}
72+
4673
static void scmi_core_reply_cb(struct scmi_channel *chan, int hdr)
4774
{
4875
int msg_type;
76+
int status;
4977

5078
msg_type = SCMI_MESSAGE_HDR_TAKE_TYPE(hdr);
5179

@@ -55,6 +83,10 @@ static void scmi_core_reply_cb(struct scmi_channel *chan, int hdr)
5583
case SCMI_DELAYED_REPLY:
5684
break;
5785
case SCMI_NOTIFICATION:
86+
status = scmi_core_handle_notification(hdr);
87+
if (status) {
88+
LOG_WRN("Scmi notification event not found");
89+
}
5890
break;
5991
default:
6092
LOG_WRN("Unexpected message type %u", msg_type);

drivers/firmware/scmi/nxp/cpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <zephyr/drivers/firmware/scmi/nxp/cpu.h>
99
#include <zephyr/kernel.h>
1010

11-
DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, nxp_scmi_cpu), NULL);
11+
DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, nxp_scmi_cpu), NULL, NULL);
1212

1313
int scmi_cpu_sleep_mode_set(struct scmi_cpu_sleep_mode_config *cfg)
1414
{

drivers/firmware/scmi/pinctrl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <zephyr/drivers/firmware/scmi/pinctrl.h>
88
#include <zephyr/kernel.h>
99

10-
DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, arm_scmi_pinctrl), NULL);
10+
DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, arm_scmi_pinctrl), NULL, NULL);
1111

1212
int scmi_pinctrl_settings_configure(struct scmi_pinctrl_settings *settings)
1313
{

drivers/firmware/scmi/power.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <string.h>
99
#include <zephyr/kernel.h>
1010

11-
DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, arm_scmi_power), NULL);
11+
DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, arm_scmi_power), NULL, NULL);
1212

1313
struct scmi_power_state_get_reply {
1414
int32_t status;

include/zephyr/drivers/firmware/scmi/protocol.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,36 @@ struct scmi_protocol {
108108
const struct device *transport;
109109
/** protocol private data */
110110
void *data;
111+
/** protocol event */
112+
struct scmi_protocol_event *events;
113+
};
114+
115+
/**
116+
* @typedef scmi_protocol_event_callback
117+
* @brief Per‑protocol notification callback invoked by the SCMI core.
118+
*
119+
* Define event-specific information during the static registration phase
120+
* of each SCMI protocol. When a P2A notification/interrupt is received,
121+
* the SCMI core decodes the message and dispatches it to the corresponding
122+
* protocol's callback.
123+
*
124+
* @param msg_id is the protocol specific message index.
125+
* @return int 0 on success, negative error code on failure
126+
*/
127+
typedef int (*scmi_protocol_event_callback)(int32_t msg_id);
128+
129+
/**
130+
* @struct scmi_protocol_event
131+
*
132+
* @brief SCMI protocol event structure
133+
*/
134+
struct scmi_protocol_event {
135+
/** events ids */
136+
uint32_t *evts;
137+
/** Number of supported protocol's events **/
138+
uint32_t num_events;
139+
/** protocol private event call back **/
140+
scmi_protocol_event_callback cb;
111141
};
112142

113143
/**

include/zephyr/drivers/firmware/scmi/util.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,14 @@
186186
* @param proto protocol ID in decimal format
187187
* @param pdata protocol private data
188188
*/
189-
#define DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, proto, pdata) \
189+
#define DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, proto, pdata, pevents) \
190190
STRUCT_SECTION_ITERABLE(scmi_protocol, SCMI_PROTOCOL_NAME(proto)) = \
191191
{ \
192192
.id = proto, \
193193
.tx = DT_SCMI_TRANSPORT_TX_CHAN(node_id), \
194194
.rx = DT_SCMI_TRANSPORT_RX_CHAN(node_id), \
195195
.data = pdata, \
196+
.events = pevents, \
196197
}
197198

198199
#else /* CONFIG_ARM_SCMI_TRANSPORT_HAS_STATIC_CHANNELS */
@@ -249,12 +250,12 @@
249250
* @param level protocol initialization level
250251
* @param prio protocol's priority within its initialization level
251252
*/
252-
#define DT_SCMI_PROTOCOL_DEFINE(node_id, init_fn, pm, data, config, \
253-
level, prio, api) \
254-
DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id) \
255-
DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, DT_REG_ADDR_RAW(node_id), data); \
256-
DEVICE_DT_DEFINE(node_id, init_fn, pm, \
257-
&SCMI_PROTOCOL_NAME(DT_REG_ADDR_RAW(node_id)), \
253+
#define DT_SCMI_PROTOCOL_DEFINE(node_id, init_fn, pm, data, config, \
254+
level, prio, api, events) \
255+
DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id) \
256+
DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, DT_REG_ADDR_RAW(node_id), data, events); \
257+
DEVICE_DT_DEFINE(node_id, init_fn, pm, \
258+
&SCMI_PROTOCOL_NAME(DT_REG_ADDR_RAW(node_id)), \
258259
config, level, prio, api)
259260

260261
/**
@@ -271,9 +272,9 @@
271272
* @param prio protocol's priority within its initialization level
272273
*/
273274
#define DT_INST_SCMI_PROTOCOL_DEFINE(inst, init_fn, pm, data, config, \
274-
level, prio, api) \
275+
level, prio, api, events) \
275276
DT_SCMI_PROTOCOL_DEFINE(DT_INST(inst, DT_DRV_COMPAT), init_fn, pm, \
276-
data, config, level, prio, api)
277+
data, config, level, prio, api, events)
277278

278279
/**
279280
* @brief Define an SCMI protocol with no device
@@ -286,9 +287,9 @@
286287
* @param node_id protocol node identifier
287288
* @param data protocol private data
288289
*/
289-
#define DT_SCMI_PROTOCOL_DEFINE_NODEV(node_id, data) \
290-
DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id) \
291-
DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, DT_REG_ADDR_RAW(node_id), data)
290+
#define DT_SCMI_PROTOCOL_DEFINE_NODEV(node_id, data, events_ptr) \
291+
DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id) \
292+
DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, DT_REG_ADDR_RAW(node_id), data, events_ptr)
292293

293294
/**
294295
* @brief Create an SCMI message field

0 commit comments

Comments
 (0)