1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef MOD_SDS_H
9 #define MOD_SDS_H
10 
11 #include <fwk_element.h>
12 #include <fwk_id.h>
13 #include <fwk_module_idx.h>
14 
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <stdint.h>
18 
19 /*!
20  * \addtogroup GroupModules Modules
21  * \{
22  */
23 
24 /*!
25  * \defgroup GroupSDS Shared Data Storage
26  *
27  * \details Provides a framework for the structured storage of data that is
28  *      shared between the SCP Firmware and application processor firmware.
29  *
30  * \{
31  */
32 
33 /*
34  * Bit positions for the fields that make up a structure's unique,
35  * 32-bit identifier. This value consists of the 16-bit ID, an 8-bit major
36  * version number and an 8-bit minor version number.
37  */
38 
39 /*! Position of the identifier field. */
40 #define MOD_SDS_ID_IDENTIFIER_POS    0
41 /*! Position of the minor version field. */
42 #define MOD_SDS_ID_VERSION_MINOR_POS 16
43 /*! Position of the major version field. */
44 #define MOD_SDS_ID_VERSION_MAJOR_POS 24
45 
46 /*
47  * Masks for the structure identifier fields.
48  */
49 
50 /*! Mask for the identifier field. */
51 #define MOD_SDS_ID_IDENTIFIER_MASK    0x0000FFFF
52 /*! Mask for the minor version field. */
53 #define MOD_SDS_ID_VERSION_MINOR_MASK 0x00FF0000
54 /*! Mask for the major version field. */
55 #define MOD_SDS_ID_VERSION_MAJOR_MASK 0xFF000000
56 
57 /*!
58  * \brief Element descriptor that describes an SDS region that will be
59  *      automatically created during module initialization.
60  */
61 struct mod_sds_region_desc {
62     /*!
63      * \brief Base address of the SDS region.
64      */
65     void *base;
66 
67     /*!
68      * \brief Size in bytes of the SDS Memory Region.
69      *
70      * \note If the SDS module is initialized and a region already exists then
71      *       the region will be resized to match the size given here. The
72      *       existing region may be increased or shrunk, as required. In the
73      *       latter case the new size must be sufficient to hold the existing
74      *       contents and if it is not then the initialization process will
75      *       fail.
76      */
77     size_t size;
78 };
79 
80 /*!
81  * \brief Element descriptor that describes an SDS structure that will be
82  *      automatically created during element initialization.
83  */
84 struct mod_sds_structure_desc {
85     /*! Identifier of the structure to be created. */
86     uint32_t id;
87 
88     /*! Identifier of the SDS region containing the structure. */
89     uint32_t region_id;
90 
91     /*! Size, in bytes, of the structure. */
92     size_t size;
93 
94     /*!
95      *  Payload of the structure. If not equal to NULL, as part of the
96      *  initialization of the module's elements, the payload of the structure
97      *  identified by 'id' is initalized/updated to the value pointed to by
98      *  'payload'.
99      */
100     const void *payload;
101 
102     /*! Set the valid flag in the structure if true. */
103     bool finalize;
104 };
105 
106 /*!
107  * \brief Module configuration.
108  */
109 struct mod_sds_config {
110     /*!
111      * Descriptors of all the SDS regions the module will use.
112      */
113     const struct mod_sds_region_desc *regions;
114 
115     /*!
116      * Number of SDS regions managed by the module.
117      */
118     unsigned int region_count;
119 
120 #ifdef BUILD_HAS_MOD_CLOCK
121     /*! Identifier of the clock that this module depends on */
122     fwk_id_t clock_id;
123 #endif
124 };
125 
126 /*!
127  * \brief SDS notification indices.
128  */
129 enum mod_sds_notification_idx {
130     /*! The SDS region has been initialized */
131     MOD_SDS_NOTIFICATION_IDX_INITIALIZED,
132 
133     /*! Number of defined notifications */
134     MOD_SDS_NOTIFICATION_IDX_COUNT
135 };
136 
137 /*!
138  * \brief Identifier for the ::MOD_SDS_NOTIFICATION_IDX_INITIALIZED
139  *     notification.
140  */
141 static const fwk_id_t mod_sds_notification_id_initialized =
142     FWK_ID_NOTIFICATION_INIT(
143         FWK_MODULE_IDX_SDS,
144         MOD_SDS_NOTIFICATION_IDX_INITIALIZED);
145 
146 /*!
147  * \brief Module interface.
148  */
149 struct mod_sds_api {
150     /*!
151      * \brief Write data within a Shared Data Structure.
152      *
153      * \details Write data to a given offset within a Shared Data Structure. The
154      *      SDS module ensures that the data being written is properly
155      *      contained within the structure but it is the caller's responsibility
156      *      to ensure that the correct field or fields are being updated.
157      *
158      * \note A single write may update a portion of a field, a complete
159      *      field, or multiple fields, depending on the definition of the
160      *      structure and the size of the data being written.
161      *
162      * \param structure_id The identifier of the Shared Data Structure into
163      *      which data will be written.
164      *
165      * \param offset The offset, in bytes, of the field within the Shared Data
166      *      Structure.
167      *
168      * \param data Pointer to the data that will be written into the Shared Data
169      *      Structure's field.
170      *
171      * \param size Size, in bytes, of the data to be written.
172      *
173      * \retval ::FWK_SUCCESS Data was successfully written to the structure.
174      * \retval ::FWK_E_PARAM An invalid parameter was encountered:
175      *      - The `data` parameter was a null pointer value.
176      *      - An invalid structure identifier was provided.
177      * \retval ::FWK_E_RANGE The field extends outside of the structure bounds.
178      */
179     int (*struct_write)(uint32_t structure_id, unsigned int offset,
180                         const void *data, size_t size);
181 
182     /*!
183      * \brief Read data from within a Shared Data Structure.
184      *
185      * \details Read data from a given offset within a Shared Data Structure.
186      *      The SDS module ensures that the data being read is contained
187      *      completely within the structure but it is the caller's
188      *      responsibility to ensure that the correct field(s) are being read.
189      *
190      *      A single read may return only a portion of a field, a complete
191      *      field, or multiple fields, depending on the definition of the
192      *      structure and the value of the size parameter.
193      *
194      * \note Reading from a structure that has not been finalized is permitted
195      *      but discouraged.
196      *
197      * \param structure_id The identifier of the Shared Data Structure from
198      *      which data will be read.
199      *
200      * \param offset The offset, in bytes, of the field within the Shared Data
201      *      Structure.
202      *
203      * \param[out] data The field data that will be read.
204      *
205      * \param size Size, in bytes, of the storage pointed to by the data
206      *       parameter.
207      *
208      * \retval ::FWK_SUCCESS Data was successfully read from the structure.
209      * \retval ::FWK_E_PARAM An invalid parameter was encountered:
210      *      - The `data` parameter was a null pointer value.
211      *      - An invalid structure identifier was provided.
212      * \retval ::FWK_E_RANGE The field extends outside of the structure bounds.
213      */
214     int (*struct_read)(uint32_t structure_id, unsigned int offset, void *data,
215                        size_t size);
216 
217     /*!
218      * \brief Mark a Shared Data Structure as valid and ready for use by
219      *      application processor firmware.
220      *
221      * \param structure_id The identifier of the Shared Data Structure to
222      *      finalize.
223      *
224      * \retval ::FWK_SUCCESS The structure was successfully finalized.
225      * \retval ::FWK_E_PARAM An invalid structure identifier was provided.
226      * \retval ::FWK_E_STATE The structure has already been finalized.
227      */
228     int (*struct_finalize)(uint32_t structure_id);
229 };
230 
231 /*!
232  * \}
233  */
234 
235 /*!
236  * \}
237  */
238 
239 #endif /* MOD_SDS_H */
240