1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Description: 8 * System Control and Management Interface (SCMI) support. 9 */ 10 11 #ifndef MOD_SCMI_H 12 #define MOD_SCMI_H 13 14 #include <internal/scmi.h> 15 #include <mod_scmi_std.h> 16 17 #include <fwk_id.h> 18 #include <fwk_module_idx.h> 19 20 #include <stdbool.h> 21 #include <stddef.h> 22 #include <stdint.h> 23 24 /*! 25 * \addtogroup GroupModules Modules 26 * \{ 27 */ 28 29 /*! 30 * \defgroup GroupSCMI System Control & Management Interface (SCMI) 31 * \{ 32 */ 33 34 /*! 35 * \brief Index of the interfaces exposed by the SCMI module. 36 */ 37 enum mod_scmi_api_idx { 38 MOD_SCMI_API_IDX_PROTOCOL, 39 MOD_SCMI_API_IDX_PROTOCOL_REQ, 40 MOD_SCMI_API_IDX_TRANSPORT, 41 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS 42 MOD_SCMI_API_IDX_NOTIFICATION, 43 #endif 44 MOD_SCMI_API_IDX_COUNT, 45 }; 46 47 /*! 48 * \brief Entity role. 49 */ 50 enum mod_scmi_entity_role { MOD_SCMI_ROLE_PLATFORM, MOD_SCMI_ROLE_AGENT }; 51 52 /*! 53 * \brief Agent descriptor 54 */ 55 struct mod_scmi_agent { 56 /*! \brief Type of the agent. */ 57 enum scmi_agent_type type; 58 59 /*! 60 * \brief Pointer to the agent's name. This pointer may be equal to NULL. 61 * In that case, the agent will be assigned a default name based on 62 * its type: "PSCI", "MANAGEMENT", "OSPM", or "OTHER". 63 * 64 * \details The agent name of the BASE_DISCOVER_AGENT command can be at 65 * most 16 bytes in length (null terminator included). If the value 66 * assigned to this variable is longer than the limit then the agents 67 * in the system will be provided with a truncated version of it. 68 */ 69 const char *name; 70 }; 71 72 /*! 73 * \brief SCMI module configuration data. 74 */ 75 struct mod_scmi_config { 76 /*! 77 * \brief Maximum number of SCMI protocol modules that can bind to the 78 * SCMI module. 79 */ 80 unsigned int protocol_count_max; 81 82 /*! 83 * \brief Maximum number of SCMI protocol requester modules that can 84 * bind to the SCMI module. 85 */ 86 unsigned int protocol_requester_count_max; 87 88 #ifndef BUILD_HAS_MOD_RESOURCE_PERMS 89 /*! 90 * \brief Number of the disabled SCMI protocols for the PSCI agent. 91 * If set to zero then all protocols are allowed for a PSCI agent. 92 */ 93 unsigned int dis_protocol_count_psci; 94 95 /*! 96 * \brief list protocols disabled for the PSCI agent , limited 97 * by protocol_count_psci 98 */ 99 const uint32_t *dis_protocol_list_psci; 100 #endif 101 102 /*! 103 * \brief Number of agents in the system. Must be smaller than or equal to 104 * SCMI_AGENT_ID_MAX. 105 */ 106 unsigned int agent_count; 107 108 /*! 109 * \brief Table of descriptors of the agents in the system. 110 * 111 * \details Entry 'i' in the table contains the descriptor of the agent 112 * with identifier 'i'. The agent identifiers are sequential and start 113 * from one, with the identifier 0 being reserved to identify the 114 * platform. The table must therefore have space for 'agent_count + 1' 115 * entries. The first entry is ignored. 116 */ 117 const struct mod_scmi_agent *agent_table; 118 119 /*! 120 * \brief Pointer to the vendor identifier. 121 * 122 * \note The vendor identifier in the BASE_DISCOVER_VENDOR command is 123 * up to 16 bytes in length (null terminator included). The vendor 124 * identifier provided to agents will be truncated if it exceeds 125 * this limit. 126 */ 127 const char *vendor_identifier; 128 129 /*! 130 * \brief Pointer to the sub-vendor identifier. 131 * 132 * \note The sub-vendor identifier in the BASE_DISCOVER_SUB_VENDOR 133 * command is up to 16 bytes in length (null terminator included). 134 * The sub-vendor identifier provided to agents will be truncated 135 * if it exceeds this limit. 136 */ 137 const char *sub_vendor_identifier; 138 }; 139 140 /*! 141 * \brief Service configuration data. 142 */ 143 struct mod_scmi_service_config { 144 /*! 145 * \brief Identifier of the transport entity. 146 */ 147 fwk_id_t transport_id; 148 149 /*! 150 * \brief Identifier of the API of the transport entity. 151 */ 152 fwk_id_t transport_api_id; 153 154 /*! 155 * \brief Identifier of the notification indicating the transport has been 156 * initialized. 157 */ 158 fwk_id_t transport_notification_init_id; 159 160 /*! 161 * \brief Identifier of the agent. 162 * 163 * \details An SCMI channel is the communication channel between an agent 164 * and the platform. This is the identifier assigned in the system 165 * to the agent using the transport channel identified by 166 * 'scmi_channel_id'. The agent identifier must be greater than or 167 * equal to one (the identifier 0 is assigned to the platform) and 168 * lower than or equal to the number of agents declared in SCMI 169 * module configuration data. 170 */ 171 unsigned int scmi_agent_id; 172 173 /*! 174 * \brief Identifier of SCMI P2A service asssociated with this A2P service. 175 * 176 * \details If a request for notifications is received on this service 177 * channel the notifications will be sent on the channel identified 178 * here. 179 */ 180 fwk_id_t scmi_p2a_id; 181 182 /*! 183 * \brief Entity role. 184 * 185 * \details Determine if this entity is an agent or a platform. 186 */ 187 enum mod_scmi_entity_role scmi_entity_role; 188 }; 189 190 /*! 191 * \brief SCMI module to transport entity API. 192 */ 193 struct mod_scmi_to_transport_api { 194 /*! 195 * \brief Check whether a channel is secure or non-secure. 196 * 197 * \param channel_id Channel identifier. 198 * \param[out] secure Channel security state. True if the channel 199 * is secure, or false if it is non-secure. 200 * 201 * \retval ::FWK_SUCCESS The operation succeeded. 202 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 203 * - The `channel_id` parameter was not a valid system entity 204 * identifier. 205 * - The `secure` parameter was a null pointer value. 206 * \return One of the standard error codes for implementation-defined 207 * errors. 208 */ 209 int (*get_secure)(fwk_id_t channel_id, bool *secure); 210 211 /*! 212 * \brief Get the maximum permitted payload size of a channel. 213 * 214 * \param channel_id Channel identifier. 215 * \param[out] size Maximum payload size in bytes. 216 * 217 * \retval ::FWK_SUCCESS The operation succeeded. 218 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 219 * - The `channel_id` parameter was not a valid system entity 220 * identifier. 221 * - The `size` parameter was a null pointer value. 222 * \return One of the standard error codes for implementation-defined 223 * errors. 224 */ 225 int (*get_max_payload_size)(fwk_id_t channel_id, size_t *size); 226 227 /*! 228 * \brief Get the SCMI message header from a channel. 229 * 230 * \param channel_id Channel identifier. 231 * \param[out] message_header SCMI message header. 232 * 233 * \retval ::FWK_SUCCESS The operation succeeded. 234 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 235 * - The `channel_id` parameter was not a valid system entity 236 * identifier. 237 * - The `message_header` parameter was a null pointer value. 238 * \retval ::FWK_E_ACCESS No message is available to read. 239 * \return One of the standard error codes for implementation-defined 240 * errors. 241 */ 242 int (*get_message_header)(fwk_id_t channel_id, uint32_t *message_header); 243 244 /*! 245 * \brief Get the SCMI payload from a channel. 246 * 247 * \param channel_id Channel identifier. 248 * \param[out] payload Pointer to the payload. 249 * \param[out] size Payload size. May be NULL, in which case the 250 * parameter should be ignored. 251 * 252 * \retval ::FWK_SUCCESS The operation succeeded. 253 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 254 * - The `channel_id` parameter was not a valid system entity 255 * identifier. 256 * - The `payload` parameter was a null pointer value. 257 * - The `size` parameter was a null pointer value. 258 * \retval ::FWK_E_ACCESS No message is available to read. 259 * \return One of the standard error codes for implementation-defined 260 * errors. 261 */ 262 int (*get_payload)(fwk_id_t channel_id, const void **payload, 263 size_t *size); 264 265 /*! 266 * \brief Write part of a payload to a channel. 267 * 268 * \param channel_id Channel identifier. 269 * \param offset Offset to begin writing at. 270 * \param payload Payload data to write. 271 * \param size Size of the payload data. 272 * 273 * \retval ::FWK_SUCCESS The operation succeeded. 274 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 275 * - The `channel_id` parameter was not a valid system entity 276 * identifier. 277 * - The `payload` parameter was a null pointer value. 278 * - The offset and size provided are not within the bounds of the 279 * payload area. 280 * \return One of the standard error codes for implementation-defined 281 * errors. 282 */ 283 int (*write_payload)(fwk_id_t channel_id, size_t offset, 284 const void *payload, size_t size); 285 286 /*! 287 * \brief Respond to an SCMI message on a channel. 288 * 289 * \param channel_id Channel identifier. 290 * \param payload Payload data to write, or NULL if a payload has already 291 * been written. 292 * \param size Size of the payload source. 293 * 294 * \retval ::FWK_SUCCESS The operation succeeded. 295 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 296 * - The `channel_id` parameter was not a valid system entity 297 * identifier. 298 * - The size given is less than the size of one paylout entry. 299 * \retval ::FWK_E_ACCESS No message is available to respond to. 300 * \return One of the standard error codes for implementation-defined 301 * errors. 302 */ 303 int (*respond)(fwk_id_t channel_id, const void *payload, size_t size); 304 305 /*! 306 * \brief Send a message on a channel. 307 * 308 * \param channel_id Channel identifier. 309 * \param message_header Message ID. 310 * \param payload Payload data to write. 311 * \param size Size of the payload source. 312 * \param request_ack_by_interrupt flag to select whether acknowledgement 313 * interrupt is required for this message. 314 * 315 * \retval ::FWK_SUCCESS The operation succeeded. 316 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 317 * - The `channel_id` parameter was not a valid system entity 318 * identifier. 319 * - The size given is less than the size of one paylout entry. 320 * \return One of the standard error codes for implementation-defined 321 * errors. 322 */ 323 int (*transmit)( 324 fwk_id_t channel_id, 325 uint32_t message_header, 326 const void *payload, 327 size_t size, 328 bool request_ack_by_interrupt); 329 330 /*! 331 * \brief Release the transport channel context lock. 332 * 333 * \param channel_id Transport channel identifier. 334 * 335 * \retval ::FWK_SUCCESS The operation succeeded. 336 */ 337 int (*release_transport_channel_lock)(fwk_id_t channel_id); 338 }; 339 340 /*! 341 * \brief Transport entity API to SCMI module API. 342 */ 343 struct mod_scmi_from_transport_api { 344 /*! 345 * \brief Signal to a SCMI service that a incoming message for it has 346 * incorrect length and payload size and so the incoming message has 347 * been dropped. 348 * 349 * \note Subscribed SCMI service should call the respond API to free the 350 * channel. 351 * 352 * \param service_id service identifier. 353 * 354 * \retval ::FWK_SUCCESS The operation succeeded. 355 * \retval ::FWK_E_PARAM The service_id parameter is invalid. 356 * \return One of the standard error codes for implementation-defined 357 * errors. 358 */ 359 int (*signal_error)(fwk_id_t service_id); 360 361 /*! 362 * \brief Signal to a service that a message is incoming. 363 * 364 * \param service_id SCMI service identifier. 365 * 366 * \retval ::FWK_SUCCESS The operation succeeded. 367 * \retval ::FWK_E_PARAM The `service_id` parameter was not a valid system 368 * entity identifier. 369 * \return One of the standard error codes for implementation-defined 370 * errors. 371 */ 372 int (*signal_message)(fwk_id_t service_id); 373 }; 374 375 /*! 376 * \brief SCMI protocol message handler prototype. 377 * 378 * \details Prototype of a message handler called by the SCMI module when it 379 * receives a message for a SCMI protocol module. 380 * 381 * \note A return value of FWK_SUCCESS indicates only that no internal error 382 * was encountered, not that the SCMI command has returned a successful 383 * result to the SCMI agent. In the case where the return value indicates 384 * an internal failure, the SCMI command is expected to return the status 385 * code SCMI_GENERIC_ERROR per the specification. 386 * 387 * \param protocol_id Identifier of the protocol module. 388 * \param service_id Identifer of the SCMI service which received the message. 389 * \param payload Pointer to the message payload. 390 * \param payload_size Size in number of bytes of the message payload. 391 * \param message_id Identifier of the message to be handled by the protocol 392 * handler. 393 * 394 * \retval ::FWK_SUCCESS The operation succeeded. 395 * \return One of the standard error codes for implementation-defined errors. 396 * 397 */ 398 typedef int mod_scmi_message_handler_t(fwk_id_t protocol_id, 399 fwk_id_t service_id, const uint32_t *payload, size_t payload_size, 400 unsigned int message_id); 401 402 /*! 403 * \brief SCMI module to SCMI protocol module API. 404 */ 405 struct mod_scmi_to_protocol_api { 406 /*! 407 * \brief Get the SCMI protocol identifier of the SCMI protocol implemented 408 * by the SCMI protocol module implementing this API. 409 * 410 * \param protocol_id Identifier of the protocol module. 411 * \param scmi_protocol_id SCMI protocol identifier. 412 * 413 * \retval ::FWK_SUCCESS The operation succeeded. 414 * \return One of the standard error codes for implementation-defined 415 * errors. 416 * 417 */ 418 int (*get_scmi_protocol_id)(fwk_id_t protocol_id, 419 uint8_t *scmi_protocol_id); 420 421 /*! Protocol message handler. */ 422 mod_scmi_message_handler_t *message_handler; 423 }; 424 425 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS 426 /*! 427 * \brief SCMI protocol SCMI module SCMI notification API. 428 */ 429 struct mod_scmi_notification_api { 430 /*! 431 * \brief Initialize notification context for a protocol. 432 * 433 * \param protocol_id Identifier of the protocol. 434 * \param agent_count Number of agents supported by the protocol. 435 * \param element_count Number of elements that support notification. 436 * \param operation_count Number of notification SCMI messages supported. 437 * 438 * \retval ::FWK_SUCCESS Initialization successful. 439 * \retval One of the standard error codes for implementation-defined 440 * errors. 441 */ 442 int (*scmi_notification_init)( 443 unsigned int protocol_id, 444 unsigned int agent_count, 445 unsigned int element_count, 446 unsigned int operation_count); 447 448 /*! 449 * \brief Add an agent to subscriber list that requested a notification. 450 * 451 * \param protocol_id Identifier of the protocol. 452 * \param element_idx Index of the element within specified protocol 453 * context. 454 * \param operation_id Identifier of the operation. 455 * \param service_id Identifier of the agent's SCMI service context. 456 * 457 * \retval ::FWK_SUCCESS Adding of subscriber agent to the list is 458 * successful. 459 * \retval One of the standard error codes for implementation-defined 460 * errors. 461 */ 462 int (*scmi_notification_add_subscriber)( 463 unsigned int protocol_id, 464 unsigned int element_idx, 465 unsigned int operation_id, 466 fwk_id_t service_id); 467 468 /*! 469 * \brief Remove an agent from subscriber list. 470 * 471 * \param protocol_id Identifier of the protocol. 472 * \param agent_idx Index of the agent within specified protocol context. 473 * \param element_idx Index of the element within specified protocol 474 * context. 475 * \param operation_id Identifier of the operation. 476 * 477 * \retval ::FWK_SUCCESS Removing of subscriber agent from the list is 478 * successful. 479 * \retval One of the standard error codes for implementation-defined 480 * errors. 481 */ 482 int (*scmi_notification_remove_subscriber)( 483 unsigned int protocol_id, 484 unsigned int agent_idx, 485 unsigned int element_idx, 486 unsigned int operation_id); 487 488 /*! 489 * \brief Notifiy all agents which requested a specific notification. 490 * 491 * \param protocol_id Identifier of the protocol. 492 * \param operation_id Identifier of the operation. 493 * \param scmi_response_message_id SCMI message identifier that is sent as 494 * as a part of the notification. 495 * \param payload_p2a Notification message payload from platform to 496 * agent. 497 * \param payload_size Size of the message. 498 * 499 * \retval ::FWK_SUCCESS Notification to agents is successful. 500 * \retval One of the standard error codes for implementation-defined 501 * errors. 502 */ 503 int (*scmi_notification_notify)( 504 unsigned int protocol_id, 505 unsigned int operation_id, 506 unsigned int scmi_response_message_id, 507 void *payload_p2a, 508 size_t payload_size); 509 }; 510 #endif 511 512 /*! 513 * \brief SCMI protocol module to SCMI module API. 514 */ 515 struct mod_scmi_from_protocol_api { 516 /*! 517 * \brief Get the number of active agents. 518 * 519 * \param[out] agent_count Number of active agents. 520 * 521 * \retval ::FWK_SUCCESS The agent count was returned. 522 * \retval ::FWK_E_PARAM The parameter `agent_count` is equal to `NULL`. 523 */ 524 int (*get_agent_count)(unsigned int *agent_count); 525 526 /*! 527 * \brief Get the identifier of the agent associated with a service 528 * 529 * \param service_id Identifier of the service. 530 * \param[out] agent_id Agent identifier. 531 * 532 * \retval ::FWK_SUCCESS The agent identifier was returned. 533 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 534 * - The `service_id` parameter was not a valid system entity 535 * identifier. 536 * - The `agent_id` parameter was a null pointer value. 537 * \retval ::FWK_E_INIT The service is not initialized. 538 * \retval ::FWK_E_STATE The service is in an invalid state. 539 */ 540 int (*get_agent_id)(fwk_id_t service_id, unsigned int *agent_id); 541 542 /*! 543 * \brief Get the type of the agent given its identifier. 544 * 545 * \details This API can be used by SCMI protocols to check the validity 546 * of an agent identifier. 547 * 548 * \param agent_id Identifier of the agent. 549 * \param[out] agent_type Agent type. 550 * 551 * \retval ::FWK_SUCCESS The agent identifier was returned. 552 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 553 * - The `agent_id` parameter was not a valid system entity 554 * identifier. 555 * - The `agent_type` parameter was a null pointer value. 556 */ 557 int (*get_agent_type)(uint32_t agent_id, enum scmi_agent_type *agent_type); 558 559 /*! 560 * \brief Get the maximum permitted payload size of a channel associated 561 * with a service. 562 * 563 * \param service_id Service identifier. 564 * \param[out] size Maximum payload size in bytes. 565 * 566 * \retval ::FWK_SUCCESS The operation succeeded. 567 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 568 * - The `service_id` parameter was not a valid system entity 569 * identifier. 570 * - The `size` parameter was a null pointer value. 571 * \retval ::FWK_E_INIT The service is not initialized. 572 * \retval ::FWK_E_STATE The service is in an invalid sate. 573 * \return One of the standard error codes for implementation-defined 574 * errors. 575 */ 576 int (*get_max_payload_size)(fwk_id_t service_id, size_t *size); 577 578 /*! 579 * \brief Write part of a payload through a service. 580 * 581 * \param service_id Service identifier. 582 * \param offset Offset to begin writing at. 583 * \param payload Payload data to write. 584 * \param size Size of the payload data. 585 * 586 * \retval ::FWK_SUCCESS The operation succeeded. 587 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 588 * - The `service_id` parameter was not a valid system entity 589 * identifier. 590 * - The offset and size given were not within the bounds of the 591 * payload area. 592 * \return One of the standard error codes for implementation-defined 593 * errors. 594 */ 595 int (*write_payload)(fwk_id_t service_id, size_t offset, 596 const void *payload, size_t size); 597 598 /*! 599 * \brief Respond to an SCMI message on a service. 600 * 601 * \param service_id Service identifier. 602 * \param payload Payload data to write, or NULL if a payload has already 603 * been written. 604 * \param size Size of the payload. 605 * 606 * \retval ::FWK_SUCCESS The operation succeeded. 607 * \retval ::FWK_E_SUPPORT Transport-specific message not supported. 608 * \return One of the standard error codes for implementation-defined 609 * errors. 610 */ 611 int (*respond)(fwk_id_t service_id, const void *payload, size_t size); 612 613 /*! 614 * \brief Send a notification to the agent on behalf on an SCMI service. 615 * 616 * \param service_id Service identifier. 617 * \param protocol_id Protocol identifier. 618 * \param message_id Message identifier. 619 * \param payload Payload data to write, or NULL if a payload has already 620 * been written. 621 * \param size Size of the payload in bytes. 622 */ 623 void (*notify)(fwk_id_t service_id, int protocol_id, int message_id, 624 const void *payload, size_t size); 625 }; 626 627 /*! 628 * \brief SCMI protocol requester module to SCMI module API. 629 */ 630 struct mod_scmi_from_protocol_req_api { 631 /*! 632 * \brief Send an SCMI message 633 * 634 * \param scmi_message_id SCMI message identifier. 635 * \param scmi_protocol_id SCMI message protocol identifier. 636 * \param token SCMI message token. 637 * \param service_id SCMI service identifier. 638 * \param payload Payload data to write 639 * \param payload_size size of the payload in bytes. 640 * \param request_ack_by_interrupt flag to select whether acknowledgement 641 * interrupt is required for this message. 642 */ 643 int (*scmi_send_message)( 644 uint8_t scmi_message_id, 645 uint8_t scmi_protocol_id, 646 uint8_t token, 647 fwk_id_t service_id, 648 const void *payload, 649 size_t payload_size, 650 bool request_ack_by_interrupt); 651 652 /*! 653 * \brief Handle response SCMI message 654 * 655 * \param service_id Service identifier. 656 * 657 * \retval ::FWK_SUCCESS The operation succeeded. 658 */ 659 int (*response_message_handler)(fwk_id_t service_id); 660 }; 661 662 /*! 663 * \brief SCMI notification indices. 664 */ 665 enum mod_scmi_notification_idx { 666 /*! The SCMI service has been initialized */ 667 MOD_SCMI_NOTIFICATION_IDX_INITIALIZED, 668 669 /*! Number of defined notifications */ 670 MOD_SCMI_NOTIFICATION_IDX_COUNT 671 }; 672 673 /*! 674 * \brief Identifier for the MOD_SCMI_NOTIFICATION_IDX_INITIALIZED 675 * notification. 676 */ 677 static const fwk_id_t mod_scmi_notification_id_initialized = 678 FWK_ID_NOTIFICATION_INIT( 679 FWK_MODULE_IDX_SCMI, 680 MOD_SCMI_NOTIFICATION_IDX_INITIALIZED); 681 682 /*! 683 * \} 684 */ 685 686 /*! 687 * \} 688 */ 689 690 #endif /* MOD_SCMI_H */ 691