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