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