1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Description: 8 * Transport HAL module 9 */ 10 11 #ifndef MOD_TRANSPORT_H 12 #define MOD_TRANSPORT_H 13 14 #include <fwk_assert.h> 15 #include <fwk_element.h> 16 #include <fwk_event.h> 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 GroupTransport Transport 31 * 32 * \brief HAL Module used to provide transport for inter-processor messages 33 * 34 * 35 * \details This module can bind to different transport driver modules like i2c, 36 * mhu2, mhu3, etc and provides a transport agnostic HAL for the other modules 37 * to send and receive messages. 38 * @{ 39 */ 40 41 /*! 42 * \brief structure used for sending & receiving messages 43 */ 44 struct mod_transport_buffer { 45 /*! Reserved field, must be zero */ 46 uint32_t reserved0; 47 /*! Channel status */ 48 volatile uint32_t status; 49 /*! Implementation defined field */ 50 uint64_t reserved1; 51 /*! Channel flags */ 52 uint32_t flags; 53 /*! Length in bytes of the message header and payload */ 54 volatile uint32_t length; 55 /*! Message header field */ 56 uint32_t message_header; 57 /*! Message payload */ 58 uint32_t payload[]; 59 }; 60 61 /*! Interrupt mode enable flag position */ 62 #define MOD_TRANSPORT_FLAGS_IENABLED_POS 0 63 /*! Interrupt mode enable bit mask */ 64 #define MOD_TRANSPORT_FLAGS_IENABLED_MASK \ 65 (UINT32_C(0x1) << MOD_TRANSPORT_FLAGS_IENABLED_POS) 66 67 /*! 68 * \name Channel policies 69 * 70 * \details These policies define attributes that affect how the channel is 71 * treated 72 * 73 * @{ 74 */ 75 76 /*! No policies */ 77 #define MOD_TRANSPORT_POLICY_NONE ((uint32_t)0) 78 79 /*! This channel is secure */ 80 #define MOD_TRANSPORT_POLICY_SECURE ((uint32_t)(1U << 0)) 81 82 /*! 83 * The mailbox for this channel requires initialization. Only relevant for 84 * out-band type transport channels. 85 */ 86 #define MOD_TRANSPORT_POLICY_INIT_MAILBOX ((uint32_t)(1U << 1)) 87 88 /*! 89 * @} 90 */ 91 92 /*! 93 * \brief Channel type 94 * 95 * \details Defines the role of an entity in a channel 96 */ 97 enum mod_transport_channel_type { 98 /*! Requester channel */ 99 MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER, 100 101 /*! Completer channel */ 102 MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, 103 104 /*! Channel type count */ 105 MOD_TRANSPORT_CHANNEL_TYPE_COUNT, 106 }; 107 108 /*! 109 * \brief Channel transport type 110 * 111 * \details Defines the type of transport used by the channel 112 */ 113 enum mod_transport_channel_transport_type { 114 /*! Out-band transport - SMT */ 115 MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, 116 117 #ifdef BUILD_HAS_INBAND_MSG_SUPPORT 118 /*! In-band transport - MHUv2, MHUv3, I2C, etc*/ 119 MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND, 120 #endif 121 122 /*! Trigger interrupt only */ 123 MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, 124 125 #ifdef BUILD_HAS_FAST_CHANNELS 126 /*! Fast Channel transport */ 127 MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_FAST_CHANNELS, 128 #endif 129 130 /*! Channel transport type count */ 131 MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_COUNT, 132 }; 133 134 /*! 135 * \brief Channel config. 136 */ 137 struct mod_transport_channel_config { 138 /*! Channel transport type (In-band, Out-band, etc.) */ 139 enum mod_transport_channel_transport_type transport_type; 140 141 /*! Channel role (requester or completer) */ 142 enum mod_transport_channel_type channel_type; 143 144 /*! 145 * Out-band shared mailbox address. Only relevant for out-band 146 * transport type. 147 */ 148 uintptr_t out_band_mailbox_address; 149 150 /*! 151 * Out-band shared mailbox size in bytes. Only relevant for out-band 152 * transport type. 153 */ 154 size_t out_band_mailbox_size; 155 156 /*! 157 * Internal read & write mailbox size in bytes. Only relevant for 158 * in-band transport type. 159 */ 160 size_t in_band_mailbox_size; 161 162 /*! 163 * Identifier of the power domain that this channel depends on. 164 * Applicable for out-band transport channels only. 165 */ 166 fwk_id_t pd_source_id; 167 168 /*! 169 * Identifier of the API to bind to signal message/error for Firmware 170 * channels. This field is irrelevant for channels that are used for 171 * SCMI messages. 172 */ 173 fwk_id_t signal_api_id; 174 175 /*! Channel policies */ 176 uint32_t policies; 177 178 /*! Identifier of the driver */ 179 fwk_id_t driver_id; 180 181 /*! Identifier of the driver API to bind to */ 182 fwk_id_t driver_api_id; 183 }; 184 185 #ifdef BUILD_HAS_FAST_CHANNELS 186 /*! 187 * \brief Data structure encapsulating address(es) and length of a fast channel 188 * between two components 189 */ 190 struct fast_channel_addr { 191 /*! Address as seen by the firmware running on current processor */ 192 uintptr_t local_view_address; 193 /*! Address as seen by the firmware/OS running on target processor */ 194 uintptr_t target_view_address; 195 /*! Length of the fast channel in bytes */ 196 size_t length; 197 }; 198 #endif 199 200 /*! 201 * \brief Driver API (Implemented by the driver) 202 * 203 * \details Interface used for Transport -> driver communication 204 */ 205 206 struct mod_transport_driver_api { 207 #ifdef BUILD_HAS_INBAND_MSG_SUPPORT 208 /*! 209 * \brief Send in-band message using the driver 210 * 211 * \param message Pointer to the message struct 212 * \param device_id Device identifier 213 * 214 * \retval ::FWK_SUCCESS The operation succeeded 215 * \return One of the standard error codes for implementation-defined 216 * errors 217 */ 218 int (*send_message)( 219 struct mod_transport_buffer *message, 220 fwk_id_t device_id); 221 222 /*! 223 * \brief Retrieve the in-band message from the driver 224 * 225 * \param[out] message Pointer to the message struct 226 * \param device_id Device identifier 227 * 228 * \retval ::FWK_SUCCESS The operation succeeded 229 * \return One of the standard error codes for implementation-defined 230 * errors 231 */ 232 int ( 233 *get_message)(struct mod_transport_buffer *message, fwk_id_t device_id); 234 #endif 235 236 /*! 237 * \brief Raise an interrupt on the receiver 238 * 239 * \param device_id Device identifier 240 * 241 * \retval ::FWK_SUCCESS The operation succeeded 242 * \return One of the standard error codes for implementation-defined 243 * errors 244 */ 245 int (*trigger_event)(fwk_id_t device_id); 246 247 #ifdef BUILD_HAS_FAST_CHANNELS 248 /*! 249 * \brief Get fast channel. 250 * 251 * \param fch_id fast channel identifier 252 * \param[out] fch Pointer to the requested fast channel 253 * 254 * \retval ::FWK_SUCCESS The operation succeeded. 255 */ 256 int (*get_fch)(fwk_id_t fch_id, struct fast_channel_addr *fch); 257 258 /*! 259 * \brief Register a callback function in the driver 260 * 261 * \param fch_id fast channel identifier 262 * \param param Context-specific value 263 * \param fch_callback Pointer to the callback function 264 * 265 * \retval ::FWK_SUCCESS The operation succeeded. 266 */ 267 int (*fch_register_callback)( 268 fwk_id_t fch_id, 269 uintptr_t param, 270 void (*fch_callback)(uintptr_t param)); 271 #endif 272 }; 273 274 /*! 275 * \brief Driver input API (Implemented by the transport module) 276 * 277 * \details Interface used for driver -> Transport communication. 278 */ 279 struct mod_transport_driver_input_api { 280 /*! 281 * \brief Signal an incoming message 282 * 283 * \param channel_id Channel identifier 284 * 285 * \retval ::FWK_SUCCESS The operation succeeded. 286 * \return One of the standard error codes for implementation-defined 287 * errors. 288 */ 289 int (*signal_message)(fwk_id_t channel_id); 290 }; 291 292 /*! 293 * \brief Firmware transport API 294 * 295 * \details Interface used for Firmware messages. 296 */ 297 struct mod_transport_firmware_api { 298 /*! 299 * \brief Check whether a channel is secure or non-secure. 300 * 301 * \param channel_id Channel identifier. 302 * \param[out] secure Channel security state. True if the channel 303 * is secure, or false if it is non-secure. 304 * 305 * \retval ::FWK_SUCCESS The operation succeeded. 306 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 307 * - The `secure` parameter was a null pointer value. 308 * \return One of the standard error codes for implementation-defined 309 * errors. 310 */ 311 int (*get_secure)(fwk_id_t channel_id, bool *secure); 312 313 /*! 314 * \brief Get the maximum permitted payload size of a channel. 315 * 316 * \param channel_id Channel identifier. 317 * \param[out] size Maximum payload size in bytes. 318 * 319 * \retval ::FWK_SUCCESS The operation succeeded. 320 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 321 * - The `size` parameter was a null pointer value. 322 * \return One of the standard error codes for implementation-defined 323 * errors. 324 */ 325 326 int (*get_max_payload_size)(fwk_id_t channel_id, size_t *size); 327 328 /*! 329 * \brief Get the message header from a channel. 330 * 331 * \param channel_id Channel identifier. 332 * \param[out] message_header message header. 333 * 334 * \retval ::FWK_SUCCESS The operation succeeded. 335 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 336 * - The `message_header` parameter was a null pointer value. 337 * \retval ::FWK_E_ACCESS No message is available to read. 338 * \return One of the standard error codes for implementation-defined 339 * errors. 340 */ 341 int (*get_message_header)(fwk_id_t channel_id, uint32_t *message_header); 342 343 /*! 344 * \brief Get the payload from a channel. 345 * 346 * \param channel_id Channel identifier. 347 * \param[out] payload Pointer to the payload. 348 * \param[out] size Payload size. May be NULL, in which case the 349 * parameter should be ignored. 350 * 351 * \retval ::FWK_SUCCESS The operation succeeded. 352 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 353 * - The `payload` parameter was a null pointer value. 354 * - The `size` parameter was a null pointer value. 355 * \retval ::FWK_E_ACCESS No message is available to read. 356 * \return One of the standard error codes for implementation-defined 357 * errors. 358 */ 359 int (*get_payload)(fwk_id_t channel_id, const void **payload, size_t *size); 360 361 /*! 362 * \brief Write part of a payload to a channel. 363 * 364 * \param channel_id Channel identifier. 365 * \param offset Offset to begin writing at. 366 * \param payload Payload data to write. 367 * \param size Size of the payload data. 368 * 369 * \retval ::FWK_SUCCESS The operation succeeded. 370 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 371 * - The `payload` parameter was a null pointer value. 372 * - The offset and size provided are not within the bounds of the 373 * payload area. 374 * \retval ::FWK_E_ACCESS No message available to respond to. 375 * \return One of the standard error codes for implementation-defined 376 * errors. 377 */ 378 int (*write_payload)( 379 fwk_id_t channel_id, 380 size_t offset, 381 const void *payload, 382 size_t size); 383 384 /*! 385 * \brief Respond to message on a channel. 386 * 387 * \param channel_id Channel identifier. 388 * \param payload Payload data to write, or NULL if a payload has already 389 * been written. 390 * \param size Size of the payload source. 391 * 392 * \retval ::FWK_SUCCESS The operation succeeded. 393 * \retval ::FWK_E_SUPPORT In-band message not supported. 394 * \return One of the standard error codes for implementation-defined 395 * errors. 396 */ 397 int (*respond)(fwk_id_t channel_id, const void *payload, size_t size); 398 399 /*! 400 * \brief Send a message on a channel. 401 * 402 * \param channel_id Channel identifier. 403 * \param message_header Message header. 404 * \param payload Payload data to write. 405 * \param size Size of the payload source. 406 * \param request_ack_by_interrupt flag to select whether acknowledgement 407 * interrupt is required for this message. 408 * 409 * \retval ::FWK_SUCCESS The operation succeeded. 410 * \retval ::FWK_E_BUSY Previous message was not read by agent/platform 411 * \retval ::FWK_E_SUPPORT In-band message not supported. 412 * \return One of the standard error codes for implementation-defined 413 * errors. 414 */ 415 int (*transmit)( 416 fwk_id_t channel_id, 417 uint32_t message_header, 418 const void *payload, 419 size_t size, 420 bool request_ack_by_interrupt); 421 422 /*! 423 * \brief Release the transport channel context lock. 424 * 425 * \param channel_id Transport channel identifier. 426 * 427 * \retval ::FWK_SUCCESS The operation succeeded. 428 */ 429 int (*release_transport_channel_lock)(fwk_id_t channel_id); 430 431 /*! 432 * \brief Trigger interrupt on receiver using the driver. 433 * 434 * \param channel_id Transport channel identifier. 435 * 436 * \retval ::FWK_SUCCESS The operation succeeded. 437 * \return One of the standard error codes for implementation-defined 438 * errors 439 */ 440 int (*trigger_interrupt)(fwk_id_t channel_id); 441 }; 442 443 /*! 444 * \brief Firmware Signal API 445 * 446 * \details Interface used to signal Firmware messages/errors. 447 */ 448 struct mod_transport_firmware_signal_api { 449 /*! 450 * \brief Signal to a service that a incoming message for it has 451 * incorrect length and payload size and so the incoming message has 452 * been dropped. 453 * 454 * \note Subscribed service should call the release_transport_channel_lock() 455 * to free the channel. 456 * 457 * \param service_id service identifier. 458 * 459 * \retval ::FWK_SUCCESS The operation succeeded. 460 * \retval ::FWK_E_PARAM The service_id parameter is invalid. 461 * \return One of the standard error codes for implementation-defined 462 * errors. 463 */ 464 int (*signal_error)(fwk_id_t service_id); 465 466 /*! 467 * \brief Signal to a service that a message is incoming. 468 * 469 * \param service_id Service identifier. 470 * 471 * \retval ::FWK_SUCCESS The operation succeeded. 472 * \retval ::FWK_E_PARAM The `service_id` parameter was not a valid system 473 * entity identifier. 474 * \return One of the standard error codes for implementation-defined 475 * errors. 476 */ 477 int (*signal_message)(fwk_id_t service_id); 478 }; 479 480 #ifdef BUILD_HAS_FAST_CHANNELS 481 /*! 482 * \brief Fast Channels API 483 * 484 * \details Interface used for Fast Channels 485 */ 486 struct mod_transport_fast_channels_api { 487 /*! 488 * \brief Get fast channel. 489 * 490 * \param fch_id Fast channel identifier 491 * \param[out] fch Pointer to the requested fast channel 492 * 493 * \retval ::FWK_SUCCESS The operation succeeded. 494 */ 495 int (*transport_get_fch)(fwk_id_t fch_id, struct fast_channel_addr *fch); 496 497 /*! 498 * \brief Register a callback function. 499 * 500 * \param fch_id Fast channel identifier 501 * \param param Context-specific value 502 * \param fch_callback Pointer to the callback function 503 * 504 * \retval ::FWK_SUCCESS The operation succeeded. 505 */ 506 int (*transport_fch_register_callback)( 507 fwk_id_t fch_id, 508 uintptr_t param, 509 void (*fch_callback)(uintptr_t param)); 510 }; 511 #endif 512 513 /*! 514 * \brief Type of the interfaces exposed by the transport module. 515 */ 516 enum mod_transport_api_idx { 517 /*! Interface for driver module */ 518 MOD_TRANSPORT_API_IDX_DRIVER_INPUT, 519 #ifdef BUILD_HAS_MOD_SCMI 520 /*! Interface for scmi module */ 521 MOD_TRANSPORT_API_IDX_SCMI_TO_TRANSPORT, 522 #endif 523 /*! Interface for MSCP Firmware communication */ 524 MOD_TRANSPORT_API_IDX_FIRMWARE, 525 #ifdef BUILD_HAS_FAST_CHANNELS 526 /*! Interface for scmi protocol modules that use SCMI Fast Channels */ 527 MOD_TRANSPORT_API_IDX_FAST_CHANNELS, 528 #endif 529 /*! Number of defined interfaces */ 530 MOD_TRANSPORT_API_IDX_COUNT, 531 }; 532 533 /*! 534 * \brief Transport notification indices. 535 */ 536 enum mod_transport_notification_idx { 537 /*! The out_band mailbox/channel has been initialized */ 538 MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED, 539 540 /*! Number of defined notifications */ 541 MOD_TRANSPORT_NOTIFICATION_IDX_COUNT 542 }; 543 544 /*! 545 * \brief Identifier for the MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED 546 * notification. 547 */ 548 static const fwk_id_t mod_transport_notification_id_initialized = 549 FWK_ID_NOTIFICATION_INIT( 550 FWK_MODULE_IDX_TRANSPORT, 551 MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED); 552 553 /*! 554 * @} 555 */ 556 557 /*! 558 * @} 559 */ 560 561 #endif /* MOD_TRANSPORT_H */ 562