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_PSU_H
9 #define MOD_PSU_H
10 
11 #include <fwk_id.h>
12 #include <fwk_module_idx.h>
13 #include <fwk_status.h>
14 
15 #include <stdbool.h>
16 #include <stdint.h>
17 
18 /*!
19  * \ingroup GroupModules
20  * \defgroup GroupPsu Power Supply Unit (PSU)
21  *
22  * \details The `psu` module represents an abstract interface through which
23  *      power supply units can be used. It provides functions for manipulating
24  *      the voltage as well as enabling/disabling the supply.
25  *
26  *      Users of the HAL interact with the individual power supply units through
27  *      the [device API](::mod_psu_device_api). This is the primary interface
28  *      that this module exposes and implements.
29  *
30  *      Separate to this is the [driver API](::mod_psu_driver_api), through
31  *      which the HAL will communicate with various driver implementations.
32  *      Driver implementations that need it may also utilise the [driver
33  *      response API](::mod_psu_driver_response_api), which allows power supply
34  *      units to pend requests and respond on-demand.
35  *
36  * \{
37  */
38 
39 /*!
40  * \brief API indices.
41  */
42 enum mod_psu_api_idx {
43     /*!
44      * \brief Device API.
45      *
46      * \note This API identifier implements the ::mod_psu_device_api interface.
47      *
48      * \warning Binding to this API must occur through an element of this
49      *      module.
50      */
51     MOD_PSU_API_IDX_DEVICE,
52 
53     /*!
54      * \brief Driver response API index.
55      *
56      * \note This API identifier implements the ::mod_psu_driver_response_api
57      *      interface.
58      *
59      * \warning Binding to this API must occur through an element of this
60      *      module.
61      */
62     MOD_PSU_API_IDX_DRIVER_RESPONSE,
63 
64     /*!
65      * \brief Number of defined APIs.
66      */
67     MOD_PSU_API_IDX_COUNT
68 };
69 
70 /*!
71  * \brief Event indices.
72  */
73 enum mod_psu_event_idx {
74     /*!
75      * \brief Response event to a ::mod_psu_device_api::get_enabled call.
76      *
77      * \note This event identifier uses the ::mod_psu_response structure as its
78      *      event parameters. The ::mod_psu_response::enabled field is active.
79      */
80     MOD_PSU_EVENT_IDX_GET_ENABLED,
81 
82     /*!
83      * \brief Response event to a ::mod_psu_device_api::set_enabled call.
84      *
85      * \note This event identifier uses the ::mod_psu_response structure as its
86      *      event parameters.
87      */
88     MOD_PSU_EVENT_IDX_SET_ENABLED,
89 
90     /*!
91      * \brief Response event to a ::mod_psu_device_api::get_voltage call.
92      *
93      * \note This event identifier uses the ::mod_psu_response structure as its
94      *      event parameters. The ::mod_psu_response::voltage field is active.
95      */
96     MOD_PSU_EVENT_IDX_GET_VOLTAGE,
97 
98     /*!
99      * \brief Response event to a ::mod_psu_device_api::set_voltage call.
100      *
101      * \note This event identifier uses the ::mod_psu_response structure as its
102      *      event parameters.
103      */
104     MOD_PSU_EVENT_IDX_SET_VOLTAGE,
105 
106     /*!
107      * \brief Number of defined events.
108      */
109     MOD_PSU_EVENT_IDX_COUNT,
110 };
111 
112 /*!
113  * \brief Device API.
114  *
115  * \details The PSU device API represents the abstract interface used to control
116  *      individual power supplies.
117  *
118  *      This is the primary interface through which users of the HAL will
119  *      interact with individual power supply units.
120  */
121 struct mod_psu_device_api {
122     /*!
123      * \brief Get whether the device is enabled or not.
124      *
125      * \param[in] device_id Identifier of the device to get the state of.
126      * \param[out] enabled `true` if the device is enabled, otherwise `false`.
127      *
128      * \retval ::FWK_E_HANDLER An error occurred in the device driver.
129      * \retval ::FWK_E_PARAM One or more parameters were invalid.
130      * \retval ::FWK_E_STATE The device cannot currently accept the request.
131      * \retval ::FWK_SUCCESS The operation succeeded.
132      *
133      * \return Status code representing the result of the operation.
134      */
135     int (*get_enabled)(fwk_id_t device_id, bool *enabled);
136 
137     /*!
138      * \brief Enable or disable the device.
139      *
140      * \param[in] device_id Identifier of the device to set the state of.
141      * \param[in] enable `true` to enable the device, or `false` to disable it.
142      *
143      * \retval ::FWK_E_HANDLER An error occurred in the device driver.
144      * \retval ::FWK_E_PARAM One or more parameters were invalid.
145      * \retval ::FWK_E_STATE The device cannot currently accept the request.
146      * \retval ::FWK_SUCCESS The operation succeeded.
147      *
148      * \return Status code representing the result of the operation.
149      */
150     int (*set_enabled)(fwk_id_t device_id, bool enable);
151 
152     /*!
153      * \brief Get the voltage of a device.
154      *
155      * \param[in] device_id Identifier of the device to get the voltage of.
156      * \param[out] voltage Voltage in millivolts (mV).
157      *
158      * \retval ::FWK_E_HANDLER An error occurred in the device driver.
159      * \retval ::FWK_E_PARAM One or more parameters were invalid.
160      * \retval ::FWK_E_STATE The device cannot currently accept the request.
161      * \retval ::FWK_SUCCESS The operation succeeded.
162      *
163      * \return Status code representing the result of the operation.
164      */
165     int (*get_voltage)(fwk_id_t device_id, uint32_t *voltage);
166 
167     /*!
168      * \brief Set the voltage of a device.
169      *
170      * \param[in] device_id Identifier of the device to set the voltage of.
171      * \param[in] voltage New voltage in millivolts (mV).
172      *
173      * \retval ::FWK_E_HANDLER An error occurred in the device driver.
174      * \retval ::FWK_E_PARAM One or more parameters were invalid.
175      * \retval ::FWK_E_STATE The device cannot currently accept the request.
176      * \retval ::FWK_SUCCESS The operation succeeded.
177      *
178      * \return Status code representing the result of the operation.
179      */
180     int (*set_voltage)(fwk_id_t device_id, uint32_t voltage);
181 };
182 
183 /*!
184  * \brief Device API identifier.
185  *
186  * \note This identifier corresponds to the ::MOD_PSU_API_IDX_DEVICE API index.
187  */
188 static const fwk_id_t mod_psu_api_id_device =
189     FWK_ID_API_INIT(FWK_MODULE_IDX_PSU, MOD_PSU_API_IDX_DEVICE);
190 
191 /*!
192  * \brief Response parameters.
193  *
194  * \details This structure is passed as the parameters to a response event
195  *      dispatched by the `psu` module.
196  */
197 struct mod_psu_response {
198     /*!
199      * \brief Status code representing the result of the operation.
200      */
201     int status;
202 
203     /*!
204      * \brief Response fields.
205      *
206      * \details These fields are used if the module is responding with extra
207      *      information. The activated field, if there is one, is based on the
208      *      event identifier of the response.
209      */
210     union {
211         /*!
212          * \brief `true` if the device is enabled, otherwise `false`.
213          *
214          * \warning Used only in response to a ::mod_psu_device_api::get_enabled
215          *      call.
216          */
217         bool enabled;
218 
219         /*!
220          * \brief Voltage in millivolts (mV).
221          *
222          * \warning Used only in response to a ::mod_psu_device_api::get_voltage
223          *      call.
224          */
225         uint32_t voltage;
226     };
227 };
228 
229 /*!
230  * \brief Identifier for a ::mod_psu_device_api::get_enabled call response
231  *      event.
232  *
233  * \note This identifier corresponds to the
234  *      ::MOD_PSU_EVENT_IDX_GET_ENABLED event index.
235  */
236 static const fwk_id_t mod_psu_event_id_get_enabled = FWK_ID_EVENT_INIT(
237     FWK_MODULE_IDX_PSU, MOD_PSU_EVENT_IDX_GET_ENABLED);
238 
239 /*!
240  * \brief Identifier for a ::mod_psu_device_api::set_enabled call response
241  *      event.
242  *
243  * \note This identifier corresponds to the
244  *      ::MOD_PSU_EVENT_IDX_SET_ENABLED event index.
245  */
246 static const fwk_id_t mod_psu_event_id_set_enabled = FWK_ID_EVENT_INIT(
247     FWK_MODULE_IDX_PSU, MOD_PSU_EVENT_IDX_SET_ENABLED);
248 
249 /*!
250  * \brief Identifier for a ::mod_psu_device_api::get_voltage call response
251  *      event.
252  *
253  * \note This identifier corresponds to the
254  *      ::MOD_PSU_EVENT_IDX_GET_VOLTAGE event index.
255  */
256 static const fwk_id_t mod_psu_event_id_get_voltage = FWK_ID_EVENT_INIT(
257     FWK_MODULE_IDX_PSU, MOD_PSU_EVENT_IDX_GET_VOLTAGE);
258 
259 /*!
260  * \brief Identifier for a ::mod_psu_device_api::set_voltage call response
261  *      event.
262  *
263  * \note This identifier corresponds to the
264  *      ::MOD_PSU_EVENT_IDX_SET_VOLTAGE event index.
265  */
266 static const fwk_id_t mod_psu_event_id_set_voltage = FWK_ID_EVENT_INIT(
267     FWK_MODULE_IDX_PSU, MOD_PSU_EVENT_IDX_SET_VOLTAGE);
268 
269 /*!
270  * \brief Driver API.
271  *
272  * \details The PSU driver API represents the abstract interface that power
273  *      supply drivers must implement in order for the PSU module to interact
274  *      with them.
275  */
276 struct mod_psu_driver_api {
277     /*!
278      * \brief Get whether the device is enabled or not.
279      *
280      * \param[in] id Identifier of the device to get the state of.
281      * \param[out] enabled `true` if the device is enabled, or `false` it is
282      *      disabled.
283      *
284      * \retval ::FWK_E_HANDLER The operation failed.
285      * \retval ::FWK_PENDING The result of the operation is pending.
286      * \retval ::FWK_SUCCESS The operation succeeded.
287      *
288      * \return Status code representing the result of the operation.
289      */
290     int (*get_enabled)(fwk_id_t id, bool *enabled);
291 
292     /*!
293      * \brief Enable or disable the device.
294      *
295      * \param[in] id Identifier of the device to set the state of.
296      * \param[in] enable `true` to enable the device, or `false` to disable it.
297      *
298      * \retval ::FWK_E_HANDLER The operation failed.
299      * \retval ::FWK_PENDING The result of the operation is pending.
300      * \retval ::FWK_SUCCESS The operation succeeded.
301      *
302      * \return Status code representing the result of the operation.
303      */
304     int (*set_enabled)(fwk_id_t id, bool enable);
305 
306     /*!
307      * \brief Get the voltage of a device.
308      *
309      * \param[in] id Identifier of the device to get the voltage of.
310      * \param[out] voltage Voltage in millivolts (mV).
311      *
312      * \retval ::FWK_E_HANDLER The operation failed.
313      * \retval ::FWK_PENDING The result of the operation is pending.
314      * \retval ::FWK_SUCCESS The operation succeeded.
315      *
316      * \return Status code representing the result of the operation.
317      */
318     int (*get_voltage)(fwk_id_t id, uint32_t *voltage);
319 
320     /*!
321      * \brief Set the voltage of a device.
322      *
323      * \param[in] id Identifier of the device to set the voltage of.
324      * \param[in] voltage New voltage in millivolts (mV).
325      *
326      * \retval ::FWK_E_HANDLER The operation failed.
327      * \retval ::FWK_PENDING The result of the operation is pending.
328      * \retval ::FWK_SUCCESS The operation succeeded.
329      *
330      * \return Status code representing the result of the operation.
331      */
332     int (*set_voltage)(fwk_id_t id, uint32_t voltage);
333 };
334 
335 /*!
336  * \brief Driver response.
337  *
338  * \details This structure is passed to the `psu` module through the [driver
339  *      response API](::mod_psu_driver_response_api::respond).
340  */
341 struct mod_psu_driver_response {
342     /*!
343      * \brief Status code representing the result of the operation.
344      */
345     int status;
346 
347     /*!
348      * \brief Response fields.
349      *
350      * \details These fields are used if the driver is responding with extra
351      *      information. The activated field, if there is one, is based on the
352      *      event type of the response.
353      */
354     union {
355         /*!
356          * \brief `true` if the device is enabled, otherwise `false`.
357          *
358          * \warning Used only in response to a
359          *      ::mod_psu_driver_api::get_enabled call.
360          */
361         bool enabled;
362 
363         /*!
364          * \brief Voltage in millivolts (mV).
365          *
366          * \warning Used only in response to a
367          *      ::mod_psu_driver_api::get_voltage call.
368          */
369         uint32_t voltage;
370     };
371 };
372 
373 /*!
374  * \brief Driver response API.
375  *
376  * \details The driver response API is the API used by drivers to communicate
377  *      the result of a previously-pended operation.
378  */
379 struct mod_psu_driver_response_api {
380     /*!
381      * \brief Respond to a previous driver request.
382      *
383      * \param element_id Identifier of the power supply element which submitted
384      *      the request to the driver.
385      * \param response Driver operation response.
386      */
387     void (*respond)(
388         fwk_id_t element_id,
389         struct mod_psu_driver_response response);
390 };
391 
392 /*!
393  * \brief Driver response API identifier.
394  *
395  * \note This identifier corresponds to the ::MOD_PSU_API_IDX_DRIVER_RESPONSE
396  *      API index.
397  */
398 static const fwk_id_t mod_psu_api_id_driver_response =
399     FWK_ID_API_INIT(FWK_MODULE_IDX_PSU, MOD_PSU_API_IDX_DRIVER_RESPONSE);
400 
401 /*!
402  * \brief Device configuration.
403  *
404  * \details This structure describes configuration parameters for power supply
405  *      devices, which are represented as elements of the PSU module.
406  */
407 struct mod_psu_element_cfg {
408     /*!
409      * \brief Driver entity identifier.
410      *
411      * \details This identifies the entity of the driver, which must implement
412      *      ::mod_psu_driver_api.
413      */
414     fwk_id_t driver_id;
415 
416     /*!
417      * \brief Driver API identifier.
418      *
419      * \details This identifies the API of the driver, which must implement
420      *      ::mod_psu_driver_api.
421      */
422     fwk_id_t driver_api_id;
423 };
424 
425 /*!
426  * \}
427  */
428 
429 #endif /* MOD_PSU_H */
430