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