1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "config_sensor.h"
9 #include "juno_id.h"
10 
11 #if (PLATFORM_VARIANT == JUNO_VARIANT_BOARD)
12 #    include <mod_juno_adc.h>
13 #    include <mod_juno_pvt.h>
14 #    include <mod_juno_xrp7724.h>
15 #endif
16 
17 #include <mod_scmi_sensor.h>
18 #include <mod_sensor.h>
19 
20 #include <fwk_assert.h>
21 #include <fwk_element.h>
22 #include <fwk_id.h>
23 #include <fwk_macros.h>
24 #include <fwk_mm.h>
25 #include <fwk_module.h>
26 #include <fwk_module_idx.h>
27 #include <fwk_status.h>
28 #include <fwk_string.h>
29 
30 #include <string.h>
31 
32 #if (PLATFORM_VARIANT == JUNO_VARIANT_BOARD)
33 static const struct fwk_element sensor_element_table_r0[] = {
34     /*
35      * PMIC Sensor
36      */
37     [MOD_JUNO_SENSOR_XRP7724_PMIC_TEMP_IDX] = {
38         .name = "TEMP_PMIC",
39         .data = &(struct mod_sensor_dev_config) {
40             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_XRP7724, 0),
41             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_XRP7724,
42                 MOD_JUNO_XRP7724_API_IDX_SENSOR),
43 
44         },
45     },
46 
47     /*
48      * PVT Sensors
49      */
50     [MOD_JUNO_PVT_SENSOR_VOLT_BIG] = {
51         .name = "VOLT_BIG",
52         .data = (&(struct mod_sensor_dev_config) {
53             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
54                                                  JUNO_PVT_GROUP_BIG,
55                                                  0),
56             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
57         }),
58     },
59     [MOD_JUNO_PVT_SENSOR_VOLT_LITTLE] = {
60         .name = "VOLT_LITTLE",
61         .data = (&(struct mod_sensor_dev_config) {
62             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
63                                                  JUNO_PVT_GROUP_LITTLE,
64                                                  0),
65             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
66         }),
67     },
68     [MOD_JUNO_PVT_SENSOR_TEMP_SOC] = {
69         .name = "TEMP_SOC",
70         .data = (&(struct mod_sensor_dev_config) {
71             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
72                                                  JUNO_PVT_GROUP_SOC,
73                                                  0),
74             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
75         }),
76     },
77     [MOD_JUNO_PVT_SENSOR_VOLT_SYS] = {
78         .name = "VOLT_SYS",
79         .data = (&(struct mod_sensor_dev_config) {
80             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
81                                                  JUNO_PVT_GROUP_STDCELL,
82                                                  0),
83             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
84         }),
85     },
86 
87     /*
88      * ADC Sensors
89      */
90     [MOD_JUNO_SENSOR_VOLT_SYS_IDX] = {
91         .name = "BRD_VOLT_SYS",
92         .data = &((struct mod_sensor_dev_config) {
93             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
94                                                  ADC_TYPE_VOLT,
95                                                  ADC_DEV_SYS),
96             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
97                                              MOD_JUNO_ADC_API_IDX_DRIVER),
98         }),
99     },
100     [MOD_JUNO_SENSOR_VOLT_BIG_IDX] = {
101         .name = "BRD_VOLT_BIG",
102         .data = &((struct mod_sensor_dev_config) {
103             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
104                                                  ADC_TYPE_VOLT,
105                                                  ADC_DEV_BIG),
106             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
107                                              MOD_JUNO_ADC_API_IDX_DRIVER),
108         }),
109     },
110     [MOD_JUNO_SENSOR_VOLT_LITTLE_IDX] = {
111         .name = "BRD_VOLT_LITTLE",
112         .data = &((struct mod_sensor_dev_config) {
113             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
114                                                  ADC_TYPE_VOLT,
115                                                  ADC_DEV_LITTLE),
116             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
117                                              MOD_JUNO_ADC_API_IDX_DRIVER),
118         }),
119     },
120     [MOD_JUNO_SENSOR_VOLT_GPU_IDX] = {
121         .name = "BRD_VOLT_GPU",
122         .data = &((struct mod_sensor_dev_config) {
123             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
124                                                  ADC_TYPE_VOLT,
125                                                  ADC_DEV_GPU),
126             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
127                                              MOD_JUNO_ADC_API_IDX_DRIVER),
128         }),
129     },
130 
131 #    if USE_FULL_SET_SENSORS
132     [MOD_JUNO_SENSOR_AMPS_SYS_IDX] = {
133         .name = "BRD_CURR_SYS",
134         .data = &((struct mod_sensor_dev_config) {
135             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
136                                                  ADC_TYPE_CURRENT,
137                                                  ADC_DEV_SYS),
138             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
139                                              MOD_JUNO_ADC_API_IDX_DRIVER),
140         }),
141     },
142     [MOD_JUNO_SENSOR_AMPS_BIG_IDX] = {
143         .name = "BRD_CURR_BIG",
144         .data = &((struct mod_sensor_dev_config) {
145             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
146                                                  ADC_TYPE_CURRENT,
147                                                  ADC_DEV_BIG),
148             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
149                                              MOD_JUNO_ADC_API_IDX_DRIVER),
150         }),
151     },
152     [MOD_JUNO_SENSOR_AMPS_LITTLE_IDX] = {
153         .name = "BRD_CURR_LITTLE",
154         .data = &((struct mod_sensor_dev_config) {
155             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
156                                                  ADC_TYPE_CURRENT,
157                                                  ADC_DEV_LITTLE),
158             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
159                                              MOD_JUNO_ADC_API_IDX_DRIVER),
160         }),
161     },
162     [MOD_JUNO_SENSOR_AMPS_GPU_IDX] = {
163         .name = "BRD_CURR_GPU",
164         .data = &((struct mod_sensor_dev_config) {
165             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
166                                                  ADC_TYPE_CURRENT,
167                                                  ADC_DEV_GPU),
168             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
169                                              MOD_JUNO_ADC_API_IDX_DRIVER),
170         }),
171     },
172     [MOD_JUNO_SENSOR_WATT_SYS_IDX] = {
173         .name = "BRD_PWR_SYS",
174         .data = &((struct mod_sensor_dev_config) {
175             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
176                                                  ADC_TYPE_POWER,
177                                                  ADC_DEV_SYS),
178             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
179                                              MOD_JUNO_ADC_API_IDX_DRIVER),
180         }),
181     },
182     [MOD_JUNO_SENSOR_WATT_BIG_IDX] = {
183         .name = "BRD_PWR_BIG",
184         .data = &((struct mod_sensor_dev_config) {
185             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
186                                                  ADC_TYPE_POWER,
187                                                  ADC_DEV_BIG),
188             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
189                                              MOD_JUNO_ADC_API_IDX_DRIVER),
190         }),
191     },
192     [MOD_JUNO_SENSOR_WATT_LITTLE_IDX] = {
193         .name = "BRD_PWR_LITTLE",
194         .data = &((struct mod_sensor_dev_config) {
195             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
196                                                  ADC_TYPE_POWER,
197                                                  ADC_DEV_LITTLE),
198             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
199                                              MOD_JUNO_ADC_API_IDX_DRIVER),
200         }),
201     },
202     [MOD_JUNO_SENSOR_WATT_GPU_IDX] = {
203         .name = "BRD_PWR_GPU",
204         .data = &((struct mod_sensor_dev_config) {
205             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
206                                                  ADC_TYPE_POWER,
207                                                  ADC_DEV_GPU),
208             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
209                                              MOD_JUNO_ADC_API_IDX_DRIVER),
210         }),
211     },
212     [MOD_JUNO_SENSOR_JOULE_SYS_IDX] = {
213         .name = "BRD_ENRG_SYS",
214         .data = &((struct mod_sensor_dev_config) {
215             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
216                                                  ADC_TYPE_ENERGY,
217                                                  ADC_DEV_SYS),
218             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
219                                              MOD_JUNO_ADC_API_IDX_DRIVER),
220         }),
221     },
222     [MOD_JUNO_SENSOR_JOULE_BIG_IDX] = {
223         .name = "BRD_ENRG_BIG",
224         .data = &((struct mod_sensor_dev_config) {
225             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
226                                                  ADC_TYPE_ENERGY,
227                                                  ADC_DEV_BIG),
228             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
229                                              MOD_JUNO_ADC_API_IDX_DRIVER),
230         }),
231     },
232     [MOD_JUNO_SENSOR_JOULE_LITTLE_IDX] = {
233         .name = "BRD_ENRG_LITTLE",
234         .data = &((struct mod_sensor_dev_config) {
235             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
236                                                  ADC_TYPE_ENERGY,
237                                                  ADC_DEV_LITTLE),
238             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
239                                              MOD_JUNO_ADC_API_IDX_DRIVER),
240         }),
241     },
242     [MOD_JUNO_SENSOR_JOULE_GPU_IDX] = {
243         .name = "BRD_ENRG_GPU",
244         .data = &((struct mod_sensor_dev_config) {
245             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC,
246                                                  ADC_TYPE_ENERGY,
247                                                  ADC_DEV_GPU),
248             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC,
249                                              MOD_JUNO_ADC_API_IDX_DRIVER),
250         }),
251     },
252 #    endif
253 
254     /* The termination description is added at runtime */
255 };
256 
257 #    if USE_FULL_SET_SENSORS
258 /* The following table lists PVT sensors available on juno R1 & R2 */
259 static const struct fwk_element pvt_sensors_juno_r1_r2_elem_table[] = {
260     [0] = {
261         .name = "TEMP_BIG",
262         .data = (&(struct mod_sensor_dev_config) {
263             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
264                                                  JUNO_PVT_GROUP_BIG,
265                                                  1),
266             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
267         }),
268     },
269     [1] = {
270         .name = "TEMP_LITTLE",
271         .data = (&(struct mod_sensor_dev_config) {
272             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
273                                                  JUNO_PVT_GROUP_LITTLE,
274                                                  1),
275             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
276         }),
277     },
278     [2] = {
279         .name = "TEMP_GPU_0",
280         .data = (&(struct mod_sensor_dev_config) {
281             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
282                                                  JUNO_PVT_GROUP_GPU,
283                                                  0),
284             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
285         }),
286     },
287     [3] = {
288         .name = "TEMP_GPU_1",
289         .data = (&(struct mod_sensor_dev_config) {
290             .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PVT,
291                                                  JUNO_PVT_GROUP_GPU,
292                                                  1),
293             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_PVT, 0),
294         }),
295     },
296     /* The termination description is added at runtime */
297 };
298 #endif
299 
300 #elif (PLATFORM_VARIANT == JUNO_VARIANT_FVP)
301 
302 /*
303  * When running on a model at least one fake sensor is required to register in
304  * order to properly initialize scmi sensor management.
305  */
306 static const struct fwk_element sensor_element_table_fvp[] = {
307     [0] = {
308         .name = "Fake sensor",
309         .data = &((struct mod_sensor_dev_config) {
310             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, 0),
311             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0),
312         }),
313     },
314 
315     [1] = { 0 } /* Termination description */
316 };
317 
318 #endif
319 
get_sensor_element_table(fwk_id_t module_id)320 static const struct fwk_element *get_sensor_element_table(fwk_id_t module_id)
321 {
322     #if USE_FULL_SET_SENSORS
323     enum juno_idx_revision rev;
324     size_t pvt_sensor_elem_table_size;
325     #endif
326 
327 #if (PLATFORM_VARIANT == JUNO_VARIANT_FVP)
328     return sensor_element_table_fvp;
329 #elif (PLATFORM_VARIANT == JUNO_VARIANT_BOARD)
330     size_t sensor_elem_table_size;
331     struct fwk_element *element_table;
332     sensor_elem_table_size = FWK_ARRAY_SIZE(sensor_element_table_r0);
333 
334 #    if USE_FULL_SET_SENSORS
335     status = juno_id_get_revision(&rev);
336     if (status != FWK_SUCCESS)
337         return NULL;
338 
339     if (rev == JUNO_IDX_REVISION_R0) {
340         /* Just add the termination description */
341         element_table = fwk_mm_calloc(
342             (sensor_elem_table_size + 1), sizeof(struct fwk_element));
343 
344         memcpy(
345             element_table,
346             sensor_element_table_r0,
347             sizeof(sensor_element_table_r0));
348     } else {
349         pvt_sensor_elem_table_size =
350             FWK_ARRAY_SIZE(pvt_sensors_juno_r1_r2_elem_table);
351 
352         /*
353          * Add additional sensors available on Juno R1 & R2 and the
354          * termination description.
355          */
356         element_table = fwk_mm_calloc(
357             (sensor_elem_table_size + pvt_sensor_elem_table_size + 1),
358             sizeof(struct fwk_element));
359 
360         memcpy(
361             element_table,
362             sensor_element_table_r0,
363             sizeof(sensor_element_table_r0));
364 
365         memcpy(
366             element_table + sensor_elem_table_size,
367             pvt_sensors_juno_r1_r2_elem_table,
368             sizeof(pvt_sensors_juno_r1_r2_elem_table));
369     }
370 #    else
371     /* Just add the termination description */
372     element_table =
373         fwk_mm_calloc((sensor_elem_table_size + 1), sizeof(struct fwk_element));
374     if (element_table == NULL) {
375         return NULL;
376     }
377 
378     fwk_str_memcpy(
379         element_table,
380         sensor_element_table_r0,
381         sizeof(sensor_element_table_r0));
382 #    endif
383 
384     return element_table;
385 #endif
386 }
387 
388 struct fwk_module_config config_sensor = {
389     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_sensor_element_table),
390 };
391