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  *     I2C HAL
9  */
10 
11 #ifndef MOD_I2C_H
12 #define MOD_I2C_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 <stdint.h>
22 
23 /*!
24  * \addtogroup GroupModules Modules
25  * \{
26  */
27 
28 /*!
29  * \defgroup GroupI2C I2C HAL
30  *
31  * \details Support for transmitting and receiving data through I2C Bus
32  *     peripherals
33  * \{
34  */
35 
36 /*!
37  * \brief Configuration data for an I2C device.
38  */
39 struct mod_i2c_dev_config {
40     /*!
41      *  Identifier of the module or element providing the driver for the I2C
42      *  device.
43      */
44     fwk_id_t driver_id;
45 
46     /*! Identifier of the driver API. */
47     fwk_id_t api_id;
48 };
49 
50 /*!
51  * \brief Parameters of the event.
52  */
53 struct mod_i2c_event_param {
54     /*! Status of the I2C transaction. */
55     int status;
56 };
57 
58 /*!
59  * \brief  I2C transaction request parameters.
60  */
61 struct mod_i2c_request {
62     /*!
63      * \brief Number of data bytes to transmit.
64      */
65     uint8_t transmit_byte_count;
66 
67     /*!
68      * \brief Number of data bytes to receive.
69      */
70     uint8_t receive_byte_count;
71 
72     /*!
73      * \brief Address of the target on the I2C bus.
74      */
75     uint8_t target_address;
76 
77     /*!
78      * \brief Pointer to the data to transmit.
79      */
80     uint8_t *transmit_data;
81 
82     /*!
83      * \brief Pointer to the received data.
84      */
85     uint8_t *receive_data;
86 };
87 
88 static_assert(sizeof(struct mod_i2c_request) <= FWK_EVENT_PARAMETERS_SIZE,
89     "An I2C request should fit in the params field of an event\n");
90 
91 /*!
92  * \brief I2C driver interface.
93  *
94  * \details The interface the I2C HAL module relies on to perform actions on an
95  *      I2C device.
96  */
97 struct mod_i2c_driver_api {
98     /*!
99      * \brief Request transmission of data as Controller to a selected target.
100      *
101      * \details When the function returns the transmission may not be completed.
102      *      The driver can assume the integrity of the data during the
103      *      transmission. When the transmission operation has finished,
104      *      the driver shall report it through the I2C HAL module driver
105      *      response API.
106      *
107      * \param dev_id Identifier of the I2C device
108      * \param transmit_request Request information for the I2C transmission
109      *
110      * \retval ::FWK_PENDING The request was submitted.
111      * \retval ::FWK_SUCCESS The request was successfully completed.
112      * \retval ::FWK_E_PARAM One or more parameters were invalid.
113      * \return One of the standard framework status codes.
114      */
115     int (*transmit_as_controller)(
116         fwk_id_t dev_id,
117         struct mod_i2c_request *transmit_request);
118 
119     /*!
120      * \brief Request the reception of data as Controller from a selected
121      * target.
122      *
123      * \details When the function returns the reception may not be completed.
124      *      The driver can assume the integrity of the data pointer during the
125      *      reception. When the reception operation has finished, the driver
126      *      shall report it through the I2C HAL module driver response API.
127      *
128      * \param dev_id Identifier of the I2C device
129      * \param receive_request Request information for the I2C reception
130      *
131      * \retval ::FWK_PENDING The request was submitted.
132      * \retval ::FWK_SUCCESS The request was successfully completed.
133      * \retval ::FWK_E_PARAM One or more parameters were invalid.
134      * \return One of the standard framework status codes.
135      */
136     int (*receive_as_controller)(
137         fwk_id_t dev_id,
138         struct mod_i2c_request *receive_request);
139 };
140 
141 /*!
142  * \brief I2C HAL module interface.
143  */
144 struct mod_i2c_api {
145     /*!
146      * \brief Request transmission of data as Controller to a selected target.
147      *
148      * \details When the function returns the transmission is not completed,
149      *      possibly not even started. The data buffer must stay allocated
150      *      and its content must not be modified until the transmission is
151      *      completed or aborted. When the transmission operation has finished
152      *      a response event is sent to the client.
153      *
154      * \param dev_id Identifier of the I2C device
155      * \param target_address Address of the target on the I2C bus
156      * \param data Pointer to the data bytes to transmit to the target
157      * \param byte_count Number of data bytes to transmit
158      *
159      * \retval ::FWK_PENDING The request was submitted.
160      * \retval ::FWK_E_PARAM One or more parameters were invalid.
161      * \retval ::FWK_E_BUSY An I2C transaction is already on-going.
162      * \retval ::FWK_E_DEVICE The transmission is aborted due to a device error.
163      * \return One of the standard framework status codes.
164      */
165     int (*transmit_as_controller)(
166         fwk_id_t dev_id,
167         uint8_t target_address,
168         uint8_t *data,
169         uint8_t byte_count);
170 
171     /*!
172      * \brief Request reception of data as Controller from a selected target.
173      *
174      * \details When the function returns the reception is not completed,
175      *      possibly not even started. The data buffer must stay allocated
176      *      and its content must not be modified until the reception is
177      *      completed or aborted. When the reception operation has finished
178      *      a response event is sent to the client.
179      *
180      * \param dev_id Identifier of the I2C device
181      * \param target_address Address of the target on the I2C bus
182      * \param data Pointer to the buffer to receive data from the target
183      * \param byte_count Number of data bytes to receive
184      *
185      * \retval ::FWK_PENDING The request was submitted.
186      * \retval ::FWK_E_PARAM One or more parameters were invalid.
187      * \retval ::FWK_E_BUSY An I2C transaction is already on-going.
188      * \retval ::FWK_E_DEVICE The reception is aborted due to a device error.
189      * \return One of the standard framework status codes.
190      */
191     int (*receive_as_controller)(
192         fwk_id_t dev_id,
193         uint8_t target_address,
194         uint8_t *data,
195         uint8_t byte_count);
196 
197     /*!
198      * \brief Request the transmission followed by the reception of data as
199      *      Controller to/from a selected target.
200      *
201      * \details When the function returns the transaction is not completed,
202      *      possibly not even started. The data buffer must stay allocated
203      *      and its content must not be modified until the transaction is
204      *      completed or aborted. When the transaction operation has finished
205      *      a response event is sent to the client.
206      *
207      * \param dev_id Identifier of the I2C device
208      * \param target_address Address of the target on the I2C bus
209      * \param transmit_data Pointer to the buffer to transmit the data in the
210      *      first phase.
211      * \param receive_data Pointer to the buffer to receive the data in the
212      *      second phase.
213      * \param transmit_byte_count Number of data bytes to transmit in the first
214      *      phase.
215      * \param receive_byte_count Number of data bytes to receive in the second
216      *      phase.
217      *
218      * \retval ::FWK_PENDING The request was submitted.
219      * \retval ::FWK_E_PARAM One or more parameters were invalid.
220      * \retval ::FWK_E_BUSY An I2C transaction is already on-going.
221      * \retval ::FWK_E_DEVICE The reception is aborted due to a device error.
222      * \return One of the standard framework status codes.
223      */
224     int (*transmit_then_receive_as_controller)(
225         fwk_id_t dev_id,
226         uint8_t target_address,
227         uint8_t *transmit_data,
228         uint8_t *receive_data,
229         uint8_t transmit_byte_count,
230         uint8_t receive_byte_count);
231 };
232 
233 /*!
234  * \brief I2C HAL module driver response API.
235  *
236  * \details The interface the I2C HAL module exposes to its module drivers to
237  *      report transmission or reception completion following the occurrence of
238  *      interrupts.
239  */
240 struct mod_i2c_driver_response_api {
241     /*!
242      * \brief Function called back after the completion or abortion of an I2C
243      *      transaction request.
244      *
245      * \param dev_id Identifier of the I2C device
246      * \param i2c_status I2C transaction status
247      */
248     void (*transaction_completed)(fwk_id_t dev_id, int i2c_status);
249 };
250 
251 /*!
252  * \defgroup GroupI2CIds Identifiers
253  * \{
254  */
255 
256 /*!
257  * \brief API indices.
258  */
259 enum mod_i2c_api_idx {
260     MOD_I2C_API_IDX_I2C,
261     MOD_I2C_API_IDX_DRIVER_RESPONSE,
262     MOD_I2C_API_IDX_COUNT,
263 };
264 
265 /*! I2C API identifier */
266 static const fwk_id_t mod_i2c_api_id_i2c =
267     FWK_ID_API_INIT(FWK_MODULE_IDX_I2C, MOD_I2C_API_IDX_I2C);
268 
269 /*! Driver response API identifier */
270 static const fwk_id_t mod_i2c_api_id_driver_response =
271     FWK_ID_API_INIT(FWK_MODULE_IDX_I2C, MOD_I2C_API_IDX_DRIVER_RESPONSE);
272 
273 /*!
274  * \brief Event indices
275  */
276 enum mod_i2c_event_idx {
277     MOD_I2C_EVENT_IDX_REQUEST_TRANSMIT,
278     MOD_I2C_EVENT_IDX_REQUEST_RECEIVE,
279     MOD_I2C_EVENT_IDX_REQUEST_TRANSMIT_THEN_RECEIVE,
280     MOD_I2C_EVENT_IDX_COUNT,
281 };
282 
283 /*! Transmit request event identifier */
284 static const fwk_id_t mod_i2c_event_id_request_tx = FWK_ID_EVENT_INIT(
285     FWK_MODULE_IDX_I2C, MOD_I2C_EVENT_IDX_REQUEST_TRANSMIT);
286 
287 /*! Receive request event identifier */
288 static const fwk_id_t mod_i2c_event_id_request_rx = FWK_ID_EVENT_INIT(
289     FWK_MODULE_IDX_I2C, MOD_I2C_EVENT_IDX_REQUEST_RECEIVE);
290 
291 /*! Transmit then receive request event identifier */
292 static const fwk_id_t mod_i2c_event_id_request_tx_rx = FWK_ID_EVENT_INIT(
293     FWK_MODULE_IDX_I2C, MOD_I2C_EVENT_IDX_REQUEST_TRANSMIT_THEN_RECEIVE);
294 
295 /*!
296  * \}
297  */
298 
299 /*!
300  * \}
301  */
302 
303 /*!
304  * \}
305  */
306 
307 #endif /* MOD_I2C_H */
308