aboutsummaryrefslogtreecommitdiff
path: root/module/scmi/include/mod_scmi.h
blob: 510846cb98a26a6eb0a9a24c05dc916d4601fcc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
/*
 * Arm SCP/MCP Software
 * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Description:
 *      System Control and Management Interface (SCMI) support.
 */

#ifndef MOD_SCMI_H
#define MOD_SCMI_H

#include <internal/scmi.h>
#include <mod_scmi_std.h>

#include <fwk_id.h>
#include <fwk_module_idx.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

/*!
 * \addtogroup GroupModules Modules
 * \{
 */

/*!
 * \defgroup GroupSCMI System Control & Management Interface (SCMI)
 * \{
 */

/*!
 * \brief Index of the interfaces exposed by the SCMI module.
 */
enum mod_scmi_api_idx {
    MOD_SCMI_API_IDX_PROTOCOL,
    MOD_SCMI_API_IDX_TRANSPORT,
#ifdef BUILD_HAS_SCMI_NOTIFICATIONS
    MOD_SCMI_API_IDX_NOTIFICATION,
#endif
    MOD_SCMI_API_IDX_COUNT,
};

/*!
 * \brief Agent descriptor
 */
struct mod_scmi_agent {
    /*! \brief Type of the agent. */
    enum scmi_agent_type type;

    /*!
     *  \brief Pointer to the agent's name. This pointer may be equal to NULL.
     *       In that case, the agent will be assigned a default name based on
     *       its type: "PSCI", "MANAGEMENT", "OSPM", or "OTHER".
     *
     *  \details The agent name of the BASE_DISCOVER_AGENT command can be at
     *       most 16 bytes in length (null terminator included). If the value
     *       assigned to this variable is longer than the limit then the agents
     *       in the system will be provided with a truncated version of it.
     */
    const char *name;
};

/*!
 * \brief SCMI module configuration data.
 */
struct mod_scmi_config {
    /*!
     *  \brief Maximum number of SCMI protocol modules that can bind to the
     *       SCMI module.
     */
    unsigned int protocol_count_max;

    /*!
     *  \brief Number of agents in the system. Must be smaller than or equal to
     *       SCMI_AGENT_ID_MAX.
     */
    unsigned int agent_count;

    /*!
     *  \brief Table of descriptors of the agents in the system.
     *
     *  \details Entry 'i' in the table contains the descriptor of the agent
     *       with identifier 'i'. The agent identifiers are sequential and start
     *       from one, with the identifier 0 being reserved to identify the
     *       platform. The table must therefore have space for 'agent_count + 1'
     *       entries. The first entry is ignored.
     */
    const struct mod_scmi_agent *agent_table;

    /*!
     *  \brief Pointer to the vendor identifier.
     *
     *  \note The vendor identifier in the BASE_DISCOVER_VENDOR command is
     *       up to 16 bytes in length (null terminator included). The vendor
     *       identifier provided to agents will be truncated if it exceeds
     *       this limit.
     */
    const char *vendor_identifier;

    /*!
     *  \brief Pointer to the sub-vendor identifier.
     *
     *  \note The sub-vendor identifier in the BASE_DISCOVER_SUB_VENDOR
     *       command is up to 16 bytes in length (null terminator included).
     *       The sub-vendor identifier provided to agents will be truncated
     *       if it exceeds this limit.
     */
    const char *sub_vendor_identifier;
};

/*!
 * \brief Service configuration data.
 */
struct mod_scmi_service_config {
    /*!
     * \brief Identifier of the transport entity.
     */
    fwk_id_t transport_id;

    /*!
     * \brief Identifier of the API of the transport entity.
     */
    fwk_id_t transport_api_id;

    /*!
     * \brief Identifier of the notification indicating the transport has been
     *      initialized.
     */
    fwk_id_t transport_notification_init_id;

    /*!
     *  \brief Identifier of the agent.
     *
     *  \details An SCMI channel is the communication channel between an agent
     *        and the platform. This is the identifier assigned in the system
     *        to the agent using the transport channel identified by
     *        'scmi_channel_id'. The agent identifier must be greater than or
     *        equal to one (the identifier 0 is assigned to the platform) and
     *        lower than or equal to the number of agents declared in SCMI
     *        module configuration data.
     */
    unsigned int scmi_agent_id;

    /*!
     *  \brief Identifier of SCMI P2A service asssociated with this A2P service.
     *
     *  \details If a request for notifications is received on this service
     *        channel the notifications will be sent on the channel identified
     *        here.
     */
    fwk_id_t scmi_p2a_id;
};

/*!
 * \brief SCMI module to transport entity API.
 */
struct mod_scmi_to_transport_api {
    /*!
     * \brief Check whether a channel is secure or non-secure.
     *
     * \param channel_id Channel identifier.
     * \param[out] secure Channel security state. True if the channel
     *      is secure, or false if it is non-secure.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The `secure` parameter was a null pointer value.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*get_secure)(fwk_id_t channel_id, bool *secure);

    /*!
     * \brief Get the maximum permitted payload size of a channel.
     *
     * \param channel_id Channel identifier.
     * \param[out] size Maximum payload size in bytes.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The `size` parameter was a null pointer value.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*get_max_payload_size)(fwk_id_t channel_id, size_t *size);

    /*!
     * \brief Get the SCMI message header from a channel.
     *
     * \param channel_id Channel identifier.
     * \param[out] message_header SCMI message header.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The `message_header` parameter was a null pointer value.
     * \retval ::FWK_E_ACCESS No message is available to read.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*get_message_header)(fwk_id_t channel_id, uint32_t *message_header);

    /*!
     * \brief Get the SCMI payload from a channel.
     *
     * \param channel_id Channel identifier.
     * \param[out] payload Pointer to the payload.
     * \param[out] size Payload size. May be NULL, in which case the
     *      parameter should be ignored.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The `payload` parameter was a null pointer value.
     *      - The `size` parameter was a null pointer value.
     * \retval ::FWK_E_ACCESS No message is available to read.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*get_payload)(fwk_id_t channel_id, const void **payload,
                       size_t *size);

    /*!
     * \brief Write part of a payload to a channel.
     *
     * \param channel_id Channel identifier.
     * \param offset Offset to begin writing at.
     * \param payload Payload data to write.
     * \param size Size of the payload data.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The `payload` parameter was a null pointer value.
     *      - The offset and size provided are not within the bounds of the
     *        payload area.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*write_payload)(fwk_id_t channel_id, size_t offset,
                         const void *payload, size_t size);

    /*!
     * \brief Respond to an SCMI message on a channel.
     *
     * \param channel_id Channel identifier.
     * \param payload Payload data to write, or NULL if a payload has already
     *      been written.
     * \param size Size of the payload source.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The size given is less than the size of one paylout entry.
     * \retval ::FWK_E_ACCESS No message is available to respond to.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*respond)(fwk_id_t channel_id, const void *payload, size_t size);

    /*!
     * \brief Send a message on a channel.
     *
     * \param channel_id Channel identifier.
     * \param message_header Message ID.
     * \param payload Payload data to write.
     * \param size Size of the payload source.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `channel_id` parameter was not a valid system entity
     *        identifier.
     *      - The size given is less than the size of one paylout entry.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*transmit)(fwk_id_t channel_id, uint32_t message_header,
        const void *payload, size_t size);
};

/*!
 * \brief Transport entity API to SCMI module API.
 */
struct mod_scmi_from_transport_api {
    /*!
     * \brief Signal to a SCMI service that a incoming message for it has
     *      incorrect length and payload size and so the incoming message has
     *      been dropped.
     *
     * \note Subscribed SCMI service should call the respond API to free the
     *       channel.
     *
     * \param service_id service identifier.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM The service_id parameter is invalid.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*signal_error)(fwk_id_t service_id);

    /*!
     * \brief Signal to a service that a message is incoming.
     *
     * \param service_id SCMI service identifier.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM The `service_id` parameter was not a valid system
     *      entity identifier.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*signal_message)(fwk_id_t service_id);
};

/*!
 * \brief SCMI protocol message handler prototype.
 *
 * \details Prototype of a message handler called by the SCMI module when it
 *      receives a message for a SCMI protocol module.
 *
 * \note A return value of FWK_SUCCESS indicates only that no internal error
 *      was encountered, not that the SCMI command has returned a successful
 *      result to the SCMI agent. In the case where the return value indicates
 *      an internal failure, the SCMI command is expected to return the status
 *      code SCMI_GENERIC_ERROR per the specification.
 *
 * \param protocol_id Identifier of the protocol module.
 * \param service_id Identifer of the SCMI service which received the message.
 * \param payload Pointer to the message payload.
 * \param payload_size Size in number of bytes of the message payload.
 * \param message_id Identifier of the message to be handled by the protocol
 *      handler.
 *
 * \retval ::FWK_SUCCESS The operation succeeded.
 * \return One of the standard error codes for implementation-defined errors.
 *
 */
typedef int mod_scmi_message_handler_t(fwk_id_t protocol_id,
    fwk_id_t service_id, const uint32_t *payload, size_t payload_size,
    unsigned int message_id);

/*!
 * \brief SCMI module to SCMI protocol module API.
 */
struct mod_scmi_to_protocol_api {
    /*!
     * \brief Get the SCMI protocol identifier of the SCMI protocol implemented
     *      by the SCMI protocol module implementing this API.
     *
     * \param protocol_id Identifier of the protocol module.
     * \param scmi_protocol_id SCMI protocol identifier.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     *
     */
    int (*get_scmi_protocol_id)(fwk_id_t protocol_id,
                                uint8_t *scmi_protocol_id);

    /*! Protocol message handler. */
    mod_scmi_message_handler_t *message_handler;
};

#ifdef BUILD_HAS_SCMI_NOTIFICATIONS
/*!
 * \brief SCMI protocol SCMI module SCMI notification API.
 */
struct mod_scmi_notification_api {
    /*!
     * \brief Initialize notification context for a protocol.
     *
     * \param protocol_id Identifier of the protocol.
     * \param agent_count Number of agents supported by the protocol.
     * \param element_count Number of elements that support notification.
     * \param operation_count Number of notification SCMI messages supported.
     *
     * \retval ::FWK_SUCCESS Initialization successful.
     * \retval One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*scmi_notification_init)(
        unsigned int protocol_id,
        unsigned int agent_count,
        unsigned int element_count,
        unsigned int operation_count);

    /*!
     * \brief Add an agent to subscriber list that requested a notification.
     *
     * \param protocol_id Identifier of the protocol.
     * \param element_idx Index of the element within specified protocol
     *     context.
     * \param operation_id Identifier of the operation.
     * \param service_id  Identifier of the agent's SCMI service context.
     *
     * \retval ::FWK_SUCCESS Adding of subscriber agent to the list is
     *      successful.
     * \retval One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*scmi_notification_add_subscriber)(
        unsigned int protocol_id,
        unsigned int element_idx,
        unsigned int operation_id,
        fwk_id_t service_id);

    /*!
     * \brief Remove an agent from subscriber list.
     *
     * \param protocol_id Identifier of the protocol.
     * \param agent_idx Index of the agent within specified protocol context.
     * \param element_idx Index of the element within specified protocol
     *     context.
     * \param operation_id Identifier of the operation.
     *
     * \retval ::FWK_SUCCESS Removing of subscriber agent from the list is
     *     successful.
     * \retval One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*scmi_notification_remove_subscriber)(
        unsigned int protocol_id,
        unsigned int agent_idx,
        unsigned int element_idx,
        unsigned int operation_id);

    /*!
     * \brief Notifiy all agents which requested a specific notification.
     *
     * \param protocol_id Identifier of the protocol.
     * \param operation_id Identifier of the operation.
     * \param scmi_response_message_id SCMI message identifier that is sent as
     *     as a part of the notification.
     * \param payload_p2a Notification message payload from platform to
     *     agent.
     * \param payload_size Size of the message.
     *
     * \retval ::FWK_SUCCESS Notification to agents is successful.
     * \retval One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*scmi_notification_notify)(
        unsigned int protocol_id,
        unsigned int operation_id,
        unsigned int scmi_response_message_id,
        void *payload_p2a,
        size_t payload_size);
};
#endif

/*!
 * \brief SCMI protocol module to SCMI module API.
 */
struct mod_scmi_from_protocol_api {
    /*!
     * \brief Get the number of active agents.
     *
     * \param[out] agent_count Number of active agents.
     *
     * \retval ::FWK_SUCCESS The agent count was returned.
     * \retval ::FWK_E_PARAM The parameter `agent_count` is equal to `NULL`.
     */
    int (*get_agent_count)(int *agent_count);

    /*!
     * \brief Get the identifier of the agent associated with a service
     *
     * \param service_id Identifier of the service.
     * \param[out] agent_id Agent identifier.
     *
     * \retval ::FWK_SUCCESS The agent identifier was returned.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `service_id` parameter was not a valid system entity
     *        identifier.
     *      - The `agent_id` parameter was a null pointer value.
     * \retval ::FWK_E_INIT The service is not initialized.
     * \retval ::FWK_E_STATE The service is in an invalid state.
     */
    int (*get_agent_id)(fwk_id_t service_id, unsigned int *agent_id);

    /*!
     * \brief Get the type of the agent given its identifier.
     *
     * \details This API can be used by SCMI protocols to check the validity
     *          of an agent identifier.
     *
     * \param agent_id Identifier of the agent.
     * \param[out] agent_type Agent type.
     *
     * \retval ::FWK_SUCCESS The agent identifier was returned.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `agent_id` parameter was not a valid system entity
     *        identifier.
     *      - The `agent_type` parameter was a null pointer value.
     */
    int (*get_agent_type)(uint32_t agent_id, enum scmi_agent_type *agent_type);

    /*!
     * \brief Get the maximum permitted payload size of a channel associated
     *        with a service.
     *
     * \param service_id Service identifier.
     * \param[out] size Maximum payload size in bytes.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `service_id` parameter was not a valid system entity
     *        identifier.
     *      - The `size` parameter was a null pointer value.
     * \retval ::FWK_E_INIT The service is not initialized.
     * \retval ::FWK_E_STATE The service is in an invalid sate.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*get_max_payload_size)(fwk_id_t service_id, size_t *size);

    /*!
     * \brief Write part of a payload through a service.
     *
     * \param service_id Service identifier.
     * \param offset Offset to begin writing at.
     * \param payload Payload data to write.
     * \param size Size of the payload data.
     *
     * \retval ::FWK_SUCCESS The operation succeeded.
     * \retval ::FWK_E_PARAM An invalid parameter was encountered:
     *      - The `service_id` parameter was not a valid system entity
     *        identifier.
     *      - The offset and size given were not within the bounds of the
     *        payload area.
     * \return One of the standard error codes for implementation-defined
     *      errors.
     */
    int (*write_payload)(fwk_id_t service_id, size_t offset,
                         const void *payload, size_t size);

    /*!
     * \brief Respond to an SCMI message on a service.
     *
     * \param service_id Service identifier.
     * \param payload Payload data to write, or NULL if a payload has already
     *      been written.
     * \param size Size of the payload.
     */
    void (*respond)(fwk_id_t service_id, const void *payload, size_t size);

    /*!
     * \brief Send a notification to the agent on behalf on an SCMI service.
     *
     * \param service_id Service identifier.
     * \param protocol_id Protocol identifier.
     * \param message_id Message identifier.
     * \param payload Payload data to write, or NULL if a payload has already
     *         been written.
     * \param size Size of the payload in bytes.
     */
    void (*notify)(fwk_id_t service_id, int protocol_id, int message_id,
        const void *payload, size_t size);
};

/*!
 * \brief Identify if an SCMI entity is the communications master for a given
 *      channel type.
 *
 * \param type Channel type.
 * \param role Entity role.
 *
 * \retval true The entity is the communications master of the channel.
 * \retval false The entity is the communications slave of the channel.
 */
static inline bool mod_scmi_is_master(enum scmi_channel_type type,
                                      enum scmi_role role)
{
    return (int)type == (int)role;
}

/*!
 * \brief Identify if an SCMI entity is the communications slave for a given
 *      channel type.
 *
 * \param type Channel type.
 * \param role Entity role.
 *
 * \retval true The entity is the communications slave of the channel.
 * \retval false The entity is the communications master of the channel.
 */
static inline bool mod_scmi_is_slave(enum scmi_channel_type type,
                                     enum scmi_role role)
{
    return (int)type != (int)role;
}

/*!
 * \brief SCMI notification indices.
 */
enum mod_scmi_notification_idx {
    /*! The SCMI service has been initialized */
    MOD_SCMI_NOTIFICATION_IDX_INITIALIZED,

    /*! Number of defined notifications */
    MOD_SCMI_NOTIFICATION_IDX_COUNT
};

/*!
 * \brief Identifier for the MOD_SCMI_NOTIFICATION_IDX_INITIALIZED
 *     notification.
 */
static const fwk_id_t mod_scmi_notification_id_initialized =
    FWK_ID_NOTIFICATION_INIT(
        FWK_MODULE_IDX_SCMI,
        MOD_SCMI_NOTIFICATION_IDX_INITIALIZED);

/*!
 * \}
 */

/*!
 * \}
 */

#endif /* MOD_SCMI_H */