1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * SCMI sensor management protocol support.
9 */
10
11 #include <internal/scmi_sensor.h>
12
13 #include <mod_scmi.h>
14 #include <mod_scmi_sensor.h>
15 #include <mod_sensor.h>
16
17 #include <fwk_assert.h>
18 #include <fwk_core.h>
19 #include <fwk_event.h>
20 #include <fwk_id.h>
21 #include <fwk_log.h>
22 #include <fwk_macros.h>
23 #include <fwk_mm.h>
24 #include <fwk_module.h>
25 #include <fwk_module_idx.h>
26 #include <fwk_status.h>
27 #include <fwk_string.h>
28
29 #include <stdbool.h>
30 #include <stdint.h>
31
32 #define MOD_SCMI_SENSOR_NOTIFICATION_COUNT 1
33
34 #ifdef BUILD_HAS_MOD_RESOURCE_PERMS
35 # include <mod_resource_perms.h>
36 #endif
37
38 struct sensor_operations {
39 /*
40 * Service identifier currently requesting operation from this sensor.
41 * A 'none' value means that there is no pending request.
42 */
43 fwk_id_t service_id;
44 };
45
46 struct mod_scmi_sensor_ctx {
47 /* Number of sensors */
48 unsigned int sensor_count;
49
50 /* SCMI protocol module to SCMI module API */
51 const struct mod_scmi_from_protocol_api *scmi_api;
52
53 /* Sensor module API */
54 const struct mod_sensor_api *sensor_api;
55
56 /* Pointer to a table of sensor operations */
57 struct sensor_operations *sensor_ops_table;
58
59 /* Array of sensor values */
60 struct mod_sensor_data *sensor_values;
61
62 #ifdef BUILD_HAS_MOD_RESOURCE_PERMS
63 /* SCMI Resource Permissions API */
64 const struct mod_res_permissions_api *res_perms_api;
65 #endif
66
67 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS
68 /* Number of active agents */
69 unsigned int agent_count;
70
71 /* SCMI notification API */
72 const struct mod_scmi_notification_api *scmi_notification_api;
73 #endif
74 };
75
76 static int scmi_sensor_protocol_version_handler(fwk_id_t service_id,
77 const uint32_t *payload);
78 static int scmi_sensor_protocol_attributes_handler(fwk_id_t service_id,
79 const uint32_t *payload);
80 static int scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id,
81 const uint32_t *payload);
82 static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id,
83 const uint32_t *payload);
84 #ifdef BUILD_HAS_SCMI_SENSOR_EVENTS
85 static int scmi_sensor_trip_point_notify_handler(
86 fwk_id_t service_id,
87 const uint32_t *payload);
88 static int scmi_sensor_trip_point_config_handler(
89 fwk_id_t service_id,
90 const uint32_t *payload);
91 #endif
92 #ifdef BUILD_HAS_SCMI_SENSOR_V2
93 static int scmi_sensor_axis_desc_get_handler(
94 fwk_id_t service_id,
95 const uint32_t *payload);
96 #endif
97 static int scmi_sensor_reading_get_handler(fwk_id_t service_id,
98 const uint32_t *payload);
99
100 struct scmi_sensor_event_parameters {
101 fwk_id_t sensor_id;
102 };
103
104 static const fwk_id_t mod_scmi_sensor_event_id_get_request =
105 FWK_ID_EVENT_INIT(FWK_MODULE_IDX_SCMI_SENSOR,
106 SCMI_SENSOR_EVENT_IDX_REQUEST);
107
108 /*
109 * Internal variables.
110 */
111 static struct mod_scmi_sensor_ctx scmi_sensor_ctx;
112
113 static int (*handler_table[MOD_SCMI_SENSOR_COMMAND_COUNT])(
114 fwk_id_t,
115 const uint32_t *) = {
116 [MOD_SCMI_PROTOCOL_VERSION] = scmi_sensor_protocol_version_handler,
117 [MOD_SCMI_PROTOCOL_ATTRIBUTES] = scmi_sensor_protocol_attributes_handler,
118 [MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] =
119 scmi_sensor_protocol_msg_attributes_handler,
120 [MOD_SCMI_SENSOR_DESCRIPTION_GET] = scmi_sensor_protocol_desc_get_handler,
121 #ifdef BUILD_HAS_SCMI_SENSOR_EVENTS
122 [MOD_SCMI_SENSOR_TRIP_POINT_NOTIFY] = scmi_sensor_trip_point_notify_handler,
123 [MOD_SCMI_SENSOR_TRIP_POINT_CONFIG] = scmi_sensor_trip_point_config_handler,
124 #endif
125 #ifdef BUILD_HAS_SCMI_SENSOR_V2
126 [MOD_SCMI_SENSOR_AXIS_DESCRIPTION_GET] = scmi_sensor_axis_desc_get_handler,
127 #endif
128 [MOD_SCMI_SENSOR_READING_GET] = scmi_sensor_reading_get_handler
129 };
130
131 static unsigned int payload_size_table[MOD_SCMI_SENSOR_COMMAND_COUNT] = {
132 [MOD_SCMI_PROTOCOL_VERSION] = 0,
133 [MOD_SCMI_PROTOCOL_ATTRIBUTES] = 0,
134 [MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] =
135 (unsigned int)sizeof(struct scmi_protocol_message_attributes_a2p),
136 [MOD_SCMI_SENSOR_DESCRIPTION_GET] =
137 (unsigned int)sizeof(struct scmi_sensor_protocol_description_get_a2p),
138 #ifdef BUILD_HAS_SCMI_SENSOR_EVENTS
139 [MOD_SCMI_SENSOR_TRIP_POINT_NOTIFY] =
140 sizeof(struct scmi_sensor_trip_point_notify_a2p),
141 [MOD_SCMI_SENSOR_TRIP_POINT_CONFIG] =
142 sizeof(struct scmi_sensor_trip_point_config_a2p),
143 #endif
144 #ifdef BUILD_HAS_SCMI_SENSOR_V2
145 [MOD_SCMI_SENSOR_AXIS_DESCRIPTION_GET] =
146 (unsigned int)sizeof(struct scmi_sensor_axis_description_get_a2p),
147 #endif
148 [MOD_SCMI_SENSOR_READING_GET] =
149 (unsigned int)sizeof(struct scmi_sensor_protocol_reading_get_a2p),
150 };
151
152 /*
153 * Static helper for responding to SCMI a reading get request.
154 */
scmi_sensor_reading_respond(fwk_id_t sensor_id,const struct mod_sensor_data * sensor_data)155 static int scmi_sensor_reading_respond(
156 fwk_id_t sensor_id,
157 const struct mod_sensor_data *sensor_data)
158 {
159 struct scmi_sensor_protocol_reading_get_p2a return_values;
160 unsigned int payload_size;
161 const void *payload = NULL;
162 int status = FWK_SUCCESS;
163 int respond_status;
164 unsigned int sensor_idx;
165 fwk_id_t service_id;
166 #ifdef BUILD_HAS_SCMI_SENSOR_V2
167 struct scmi_sensor_protocol_reading_get_data axis_value;
168 unsigned int axis_idx, values_max, max_payload_size;
169 #endif
170
171 /*
172 * The service identifier used for the response is retrieved from the
173 * sensor operations table.
174 */
175 sensor_idx = fwk_id_get_element_idx(sensor_id);
176 service_id = scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id;
177
178 if (sensor_data->status != FWK_SUCCESS) {
179 return_values.status = (int32_t)SCMI_HARDWARE_ERROR;
180 goto exit_error;
181 }
182
183 #ifdef BUILD_HAS_SCMI_SENSOR_V2
184 payload_size = sizeof(return_values);
185 status = scmi_sensor_ctx.scmi_api->get_max_payload_size(
186 service_id, &max_payload_size);
187 if (status != FWK_SUCCESS) {
188 goto exit_unexpected;
189 }
190
191 values_max = SCMI_SENSOR_READ_GET_VALUES_MAX(max_payload_size);
192 if (values_max == 0 || values_max < sensor_data->axis_count) {
193 /* Can't fit sensor axis value in the payload */
194 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
195 goto exit_error;
196 }
197
198 for (axis_idx = 0; axis_idx < sensor_data->axis_count;
199 ++axis_idx, payload_size += sizeof(axis_value)) {
200 if (sensor_data->axis_count == 1) {
201 axis_value = (struct scmi_sensor_protocol_reading_get_data){
202 .sensor_value_low = (int32_t)sensor_data->value,
203 .sensor_value_high = (int32_t)(sensor_data->value >> 32),
204 .timestamp_low = (uint32_t)sensor_data->timestamp,
205 .timestamp_high = (uint32_t)(sensor_data->timestamp >> 32),
206 };
207 } else {
208 axis_value = (struct scmi_sensor_protocol_reading_get_data){
209 .sensor_value_low = (int32_t)sensor_data->axis_value[axis_idx],
210 .sensor_value_high =
211 (int32_t)(sensor_data->axis_value[axis_idx] >> 32),
212 .timestamp_low = (uint32_t)sensor_data->timestamp,
213 .timestamp_high = (uint32_t)(sensor_data->timestamp >> 32),
214 };
215 }
216
217 status = scmi_sensor_ctx.scmi_api->write_payload(
218 service_id,
219 payload_size,
220 &axis_value,
221 sizeof(struct scmi_sensor_protocol_reading_get_data));
222 if (status != FWK_SUCCESS) {
223 /* Failed to write sensor axis value into message payload */
224 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
225 goto exit_error;
226 }
227 }
228 return_values.status = (int32_t)SCMI_SUCCESS;
229
230 status = scmi_sensor_ctx.scmi_api->write_payload(
231 service_id, 0, &return_values, sizeof(return_values));
232 if (status != FWK_SUCCESS) {
233 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
234 goto exit_error;
235 }
236 goto exit;
237
238 #else
239 return_values = (struct scmi_sensor_protocol_reading_get_p2a){
240 .status = SCMI_SUCCESS,
241 .sensor_value_low = (uint32_t)sensor_data->value,
242 .sensor_value_high = (uint32_t)(sensor_data->value >> 32)
243 };
244 payload = &return_values;
245 payload_size = sizeof(return_values);
246 goto exit;
247 #endif
248
249 #ifdef BUILD_HAS_SCMI_SENSOR_V2
250 exit_unexpected:
251 fwk_unexpected();
252 #endif
253
254 exit_error:
255 payload_size = sizeof(return_values.status);
256 payload = &return_values;
257 status = FWK_E_PANIC;
258 exit:
259 respond_status =
260 scmi_sensor_ctx.scmi_api->respond(service_id, payload, payload_size);
261 if (respond_status != FWK_SUCCESS) {
262 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
263 }
264 /*
265 * Set the service identifier to 'none' to indicate the sensor is
266 * available again.
267 */
268 scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id = FWK_ID_NONE;
269 return status;
270 }
271
272 /*
273 * Sensor management protocol implementation
274 */
scmi_sensor_protocol_version_handler(fwk_id_t service_id,const uint32_t * payload)275 static int scmi_sensor_protocol_version_handler(fwk_id_t service_id,
276 const uint32_t *payload)
277 {
278 struct scmi_protocol_version_p2a return_values = {
279 .status = (int32_t)SCMI_SUCCESS,
280 .version = SCMI_PROTOCOL_VERSION_SENSOR,
281 };
282
283 return scmi_sensor_ctx.scmi_api->respond(
284 service_id, &return_values, sizeof(return_values));
285 }
286
scmi_sensor_protocol_attributes_handler(fwk_id_t service_id,const uint32_t * payload)287 static int scmi_sensor_protocol_attributes_handler(fwk_id_t service_id,
288 const uint32_t *payload)
289 {
290 struct scmi_sensor_protocol_attributes_p2a return_values = {
291 .status = (int32_t)SCMI_SUCCESS,
292 .attributes = scmi_sensor_ctx.sensor_count,
293 .sensor_reg_len = 0, /* Unsupported */
294 };
295
296 return scmi_sensor_ctx.scmi_api->respond(
297 service_id, &return_values, sizeof(return_values));
298 }
299
scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id,const uint32_t * payload)300 static int scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id,
301 const uint32_t *payload)
302 {
303 const struct scmi_protocol_message_attributes_a2p *parameters;
304 struct scmi_protocol_message_attributes_p2a return_values;
305
306 parameters = (const struct scmi_protocol_message_attributes_a2p *)
307 payload;
308
309 if ((parameters->message_id < FWK_ARRAY_SIZE(handler_table)) &&
310 (handler_table[parameters->message_id] != NULL)) {
311 return_values = (struct scmi_protocol_message_attributes_p2a) {
312 .status = SCMI_SUCCESS,
313 /* All commands have an attributes value of 0 */
314 .attributes = 0,
315 };
316 } else {
317 return_values.status = (int32_t)SCMI_NOT_FOUND;
318 }
319
320 return scmi_sensor_ctx.scmi_api->respond(
321 service_id,
322 &return_values,
323 (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) :
324 sizeof(return_values.status));
325 }
326
scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id,const uint32_t * payload)327 static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id,
328 const uint32_t *payload)
329 {
330 int status, respond_status;
331 size_t payload_size;
332 size_t max_payload_size;
333 const struct scmi_sensor_protocol_description_get_a2p *parameters =
334 (const struct scmi_sensor_protocol_description_get_a2p *)payload;
335 struct scmi_sensor_desc desc = { 0 };
336 unsigned int num_descs, desc_index, desc_index_max;
337 struct mod_sensor_complete_info sensor_info;
338 struct scmi_sensor_protocol_description_get_p2a return_values = {
339 .status = (int32_t)SCMI_GENERIC_ERROR,
340 };
341 fwk_id_t sensor_id;
342
343 payload_size = sizeof(return_values);
344
345 status = scmi_sensor_ctx.scmi_api->get_max_payload_size(service_id,
346 &max_payload_size);
347 if (status != FWK_SUCCESS) {
348 goto exit;
349 }
350
351 if (SCMI_SENSOR_DESCS_MAX(max_payload_size) == 0) {
352 /* Can't even fit one sensor description in the payload */
353 status = FWK_E_SIZE;
354 goto exit_unexpected;
355 }
356
357 parameters =
358 (const struct scmi_sensor_protocol_description_get_a2p *)payload;
359 desc_index = parameters->desc_index;
360
361 if (desc_index >= scmi_sensor_ctx.sensor_count) {
362 return_values.status = (int32_t)SCMI_INVALID_PARAMETERS;
363 goto exit;
364 }
365
366 num_descs = (unsigned int)FWK_MIN(
367 SCMI_SENSOR_DESCS_MAX(max_payload_size),
368 (scmi_sensor_ctx.sensor_count - desc_index));
369 desc_index_max = (desc_index + num_descs - 1);
370
371 for (; desc_index <= desc_index_max; ++desc_index,
372 payload_size += sizeof(desc)) {
373
374 desc = (struct scmi_sensor_desc) {
375 .sensor_id = desc_index,
376 .sensor_attributes_low = 0, /* None supported */
377 };
378
379 sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR, desc_index);
380 if (!fwk_module_is_valid_element_id(sensor_id)) {
381 /* domain_idx did not map to a sensor device */
382 return_values.status = (int32_t)SCMI_NOT_FOUND;
383 goto exit_unexpected;
384 }
385
386 status = scmi_sensor_ctx.sensor_api->get_info(sensor_id, &sensor_info);
387 if (status != FWK_SUCCESS) {
388 /* Unable to get sensor info */
389 goto exit_unexpected;
390 }
391
392 if (sensor_info.hal_info.type >= MOD_SENSOR_TYPE_COUNT) {
393 /* Invalid sensor type */
394 goto exit_unexpected;
395 }
396
397 if ((sensor_info.hal_info.unit_multiplier <
398 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MIN) ||
399 (sensor_info.hal_info.unit_multiplier >
400 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX)) {
401 /* Sensor unit multiplier out of range */
402 goto exit_unexpected;
403 }
404
405 if ((sensor_info.hal_info.update_interval_multiplier <
406 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MIN) ||
407 (sensor_info.hal_info.update_interval_multiplier >
408 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MAX)) {
409 /* Sensor update interval multiplier is out of range */
410 goto exit_unexpected;
411 }
412
413 if (sensor_info.hal_info.update_interval >=
414 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK) {
415 /* Update interval is too big to fit in its mask */
416 goto exit_unexpected;
417 }
418 if (sensor_info.trip_point.count >=
419 SCMI_SENSOR_DESC_ATTRS_LOW_SENSOR_NUM_TRIP_POINTS_MASK) {
420 /* Number of trip points is too big to fit in its mask */
421 goto exit_unexpected;
422 }
423
424 #ifdef BUILD_HAS_SCMI_SENSOR_V2
425 desc.sensor_attributes_low = SCMI_SENSOR_DESC_ATTRIBUTES_LOW(
426 0U, /* Asyncronous reading not-supported */
427 sensor_info.hal_info.ext_attributes,
428 (uint32_t)sensor_info.trip_point.count);
429 #else
430 desc.sensor_attributes_low = SCMI_SENSOR_DESC_ATTRIBUTES_LOW(
431 0U, /* Asyncronous reading not-supported */
432 (uint32_t)sensor_info.trip_point.count);
433 #endif
434
435 desc.sensor_attributes_high = SCMI_SENSOR_DESC_ATTRIBUTES_HIGH(
436 sensor_info.hal_info.type,
437 sensor_info.hal_info.unit_multiplier,
438 (uint32_t)sensor_info.hal_info.update_interval_multiplier,
439 (uint32_t)sensor_info.hal_info.update_interval);
440
441 #ifdef BUILD_HAS_SCMI_SENSOR_V2
442 scmi_sensor_prop_set(&sensor_info, &desc);
443 #endif
444
445 /*
446 * Copy sensor name into description struct. Copy n-1 chars to ensure a
447 * NULL terminator at the end. (struct has been zeroed out)
448 */
449 fwk_str_strncpy(
450 desc.sensor_name,
451 fwk_module_get_element_name(sensor_id),
452 sizeof(desc.sensor_name) - 1);
453
454 status = scmi_sensor_ctx.scmi_api->write_payload(service_id,
455 payload_size, &desc, sizeof(struct scmi_sensor_desc));
456 if (status != FWK_SUCCESS) {
457 /* Failed to write sensor description into message payload */
458 goto exit_unexpected;
459 }
460 }
461
462 return_values = (struct scmi_sensor_protocol_description_get_p2a) {
463 .status = SCMI_SUCCESS,
464 .num_sensor_flags = SCMI_SENSOR_NUM_SENSOR_FLAGS(num_descs,
465 (scmi_sensor_ctx.sensor_count - desc_index_max - 1))
466 };
467
468 status = scmi_sensor_ctx.scmi_api->write_payload(service_id, 0,
469 &return_values, sizeof(return_values));
470 if (status != FWK_SUCCESS) {
471 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
472 }
473 goto exit;
474
475 exit_unexpected:
476 fwk_unexpected();
477 exit:
478 respond_status = scmi_sensor_ctx.scmi_api->respond(
479 service_id,
480 (return_values.status == SCMI_SUCCESS) ? NULL : &return_values.status,
481 (return_values.status == SCMI_SUCCESS) ? payload_size :
482 sizeof(return_values.status));
483
484 if (respond_status != FWK_SUCCESS) {
485 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
486 }
487
488 return status;
489 }
490
491 #ifdef BUILD_HAS_SCMI_SENSOR_EVENTS
scmi_sensor_trip_point_notify_handler(fwk_id_t service_id,const uint32_t * payload)492 static int scmi_sensor_trip_point_notify_handler(
493 fwk_id_t service_id,
494 const uint32_t *payload)
495 {
496 uint32_t flags;
497 unsigned int agent_id;
498 int status, respond_status;
499 struct scmi_sensor_trip_point_notify_a2p *parameters;
500 struct scmi_sensor_trip_point_notify_p2a return_values = {
501 .status = SCMI_GENERIC_ERROR,
502 };
503
504 parameters = (struct scmi_sensor_trip_point_notify_a2p *)payload;
505
506 if (parameters->sensor_id >= scmi_sensor_ctx.sensor_count) {
507 /* Sensor does not exist */
508 status = FWK_SUCCESS;
509 return_values.status = SCMI_NOT_FOUND;
510 goto exit;
511 }
512
513 status = scmi_sensor_ctx.scmi_api->get_agent_id(service_id, &agent_id);
514 if (status != FWK_SUCCESS)
515 goto exit;
516
517 flags = parameters->flags;
518 if (flags & SCMI_SENSOR_CONFIG_FLAGS_EVENT_CONTROL_MASK)
519 scmi_sensor_ctx.scmi_notification_api->scmi_notification_add_subscriber(
520 MOD_SCMI_PROTOCOL_ID_SENSOR,
521 parameters->sensor_id,
522 MOD_SCMI_SENSOR_TRIP_POINT_NOTIFY,
523 service_id);
524 else
525 scmi_sensor_ctx.scmi_notification_api
526 ->scmi_notification_remove_subscriber(
527 MOD_SCMI_PROTOCOL_ID_SENSOR,
528 agent_id,
529 parameters->sensor_id,
530 MOD_SCMI_PERF_NOTIFY_LEVEL);
531
532 return_values.status = SCMI_SUCCESS;
533 status = FWK_SUCCESS;
534
535 exit:
536 respond_status = scmi_sensor_ctx.scmi_api->respond(
537 service_id,
538 &return_values,
539 (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) :
540 sizeof(return_values.status));
541 if (respond_status != FWK_SUCCESS) {
542 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
543 }
544
545 return status;
546 }
547 #endif
548
549 #ifdef BUILD_HAS_SCMI_SENSOR_EVENTS
scmi_sensor_trip_point_config_handler(fwk_id_t service_id,const uint32_t * payload)550 static int scmi_sensor_trip_point_config_handler(
551 fwk_id_t service_id,
552 const uint32_t *payload)
553 {
554 struct scmi_sensor_trip_point_config_a2p *parameters;
555 struct scmi_sensor_trip_point_config_p2a return_values;
556 struct mod_sensor_complete_info sensor_info;
557 struct mod_sensor_trip_point_params trip_point_param;
558 fwk_id_t sensor_id;
559 uint32_t trip_point_idx;
560 int status, respond_status;
561
562 parameters = (struct scmi_sensor_trip_point_config_a2p *)payload;
563
564 if (parameters->sensor_id >= scmi_sensor_ctx.sensor_count) {
565 /* Sensor does not exist */
566 status = FWK_SUCCESS;
567 return_values.status = SCMI_NOT_FOUND;
568 goto exit;
569 }
570 if ((parameters->flags & SCMI_SENSOR_TRIP_POINT_FLAGS_RESERVED1_MASK) ||
571 (parameters->flags & SCMI_SENSOR_TRIP_POINT_FLAGS_RESERVED2_MASK)) {
572 status = FWK_SUCCESS;
573 return_values.status = SCMI_INVALID_PARAMETERS;
574 goto exit;
575 }
576
577 sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR, parameters->sensor_id);
578 status = scmi_sensor_ctx.sensor_api->get_info(sensor_id, &sensor_info);
579 if (status != FWK_SUCCESS) {
580 /* Unable to get sensor info */
581 fwk_unexpected();
582 goto exit;
583 }
584 trip_point_idx =
585 (parameters->flags & SCMI_SENSOR_TRIP_POINT_FLAGS_ID_MASK) >>
586 SCMI_SENSOR_TRIP_POINT_FLAGS_ID_POS;
587
588 if (trip_point_idx >= sensor_info.trip_point.count) {
589 /* Sensor Trip point does not exist */
590 status = FWK_SUCCESS;
591 return_values.status = SCMI_INVALID_PARAMETERS;
592 goto exit;
593 }
594
595 trip_point_param.tp_value =
596 (((uint64_t)parameters->sensor_value_high << 32) & ~0U) |
597 (((uint64_t)parameters->sensor_value_low) & ~0U);
598
599 trip_point_param.mode =
600 (parameters->flags & SCMI_SENSOR_TRIP_POINT_FLAGS_EV_CTRL_MASK) >>
601 SCMI_SENSOR_TRIP_POINT_FLAGS_EV_CTRL_POS;
602
603 scmi_sensor_ctx.sensor_api->set_trip_point(
604 sensor_id, trip_point_idx, &trip_point_param);
605 return_values.status = SCMI_SUCCESS;
606 status = FWK_SUCCESS;
607
608 exit:
609 respond_status = scmi_sensor_ctx.scmi_api->respond(
610 service_id,
611 &return_values,
612 (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) :
613 sizeof(return_values.status));
614 if (respond_status != FWK_SUCCESS) {
615 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
616 }
617
618 return status;
619 }
620 #endif
621
622 #ifdef BUILD_HAS_SCMI_SENSOR_V2
scmi_sensor_axis_desc_get_handler(fwk_id_t service_id,const uint32_t * payload)623 static int scmi_sensor_axis_desc_get_handler(
624 fwk_id_t service_id,
625 const uint32_t *payload)
626 {
627 int status, respond_status;
628 size_t payload_size;
629 size_t max_payload_size;
630 const struct scmi_sensor_axis_description_get_a2p *parameters =
631 (const struct scmi_sensor_axis_description_get_a2p *)payload;
632 struct scmi_sensor_axis_desc desc = { 0 };
633 unsigned int num_descs, desc_index, desc_index_max;
634 struct mod_sensor_axis_info axis_info;
635 struct mod_sensor_complete_info sensor_info;
636 struct scmi_sensor_axis_description_get_p2a return_values = {
637 .status = (int32_t)SCMI_GENERIC_ERROR,
638 };
639 fwk_id_t sensor_id;
640
641 payload_size = sizeof(return_values);
642
643 status = scmi_sensor_ctx.scmi_api->get_max_payload_size(
644 service_id, &max_payload_size);
645 if (status != FWK_SUCCESS) {
646 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
647 goto exit;
648 }
649
650 if (SCMI_SENSOR_AXIS_DESCS_MAX(max_payload_size) == 0) {
651 /* Can't even fit one sensor axis description in the payload */
652 status = FWK_E_SIZE;
653 goto exit_unexpected;
654 }
655
656 parameters = (const struct scmi_sensor_axis_description_get_a2p *)payload;
657
658 sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR, parameters->sensor_idx);
659 if (!fwk_module_is_valid_element_id(sensor_id)) {
660 /* domain_idx did not map to a sensor device */
661 return_values.status = (int32_t)SCMI_NOT_FOUND;
662 goto exit;
663 }
664
665 status = scmi_sensor_ctx.sensor_api->get_info(sensor_id, &sensor_info);
666 if (status != FWK_SUCCESS) {
667 /* Unable to get sensor info */
668 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
669 goto exit;
670 }
671
672 desc_index = parameters->axis_desc_index;
673
674 if (!sensor_info.multi_axis.support) {
675 return_values.status = (int32_t)SCMI_NOT_SUPPORTED;
676 goto exit;
677 }
678
679 if (desc_index >= sensor_info.multi_axis.axis_count) {
680 return_values.status = (int32_t)SCMI_INVALID_PARAMETERS;
681 goto exit;
682 }
683
684 num_descs = (unsigned int)FWK_MIN(
685 SCMI_SENSOR_AXIS_DESCS_MAX(max_payload_size),
686 (sensor_info.multi_axis.axis_count - desc_index));
687 desc_index_max = (desc_index + num_descs - 1);
688
689 for (; desc_index <= desc_index_max;
690 ++desc_index, payload_size += sizeof(desc)) {
691 status = scmi_sensor_ctx.sensor_api->get_axis_info(
692 sensor_id, desc_index, &axis_info);
693 if (status != FWK_SUCCESS) {
694 /* Unable to get sensor info */
695 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
696 goto exit;
697 }
698
699 desc = (struct scmi_sensor_axis_desc){
700 .axis_idx = desc_index,
701 .axis_attributes_low =
702 SCMI_SENSOR_AXIS_DESC_ATTRIBUTES_LOW(axis_info.extended_attribs)
703 };
704
705 if (axis_info.type >= MOD_SENSOR_TYPE_COUNT) {
706 /* Invalid sensor type */
707 return_values.status = (int32_t)SCMI_NOT_SUPPORTED;
708 goto exit;
709 }
710
711 if ((axis_info.unit_multiplier <
712 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MIN) ||
713 (axis_info.unit_multiplier >
714 SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX)) {
715 /* Sensor unit multiplier out of range */
716 return_values.status = (int32_t)SCMI_INVALID_PARAMETERS;
717 goto exit;
718 }
719
720 desc.axis_attributes_high = SCMI_SENSOR_AXIS_DESC_ATTRIBUTES_HIGH(
721 axis_info.type, axis_info.unit_multiplier);
722
723 scmi_sensor_axis_prop_set(&axis_info, &desc);
724
725 /*
726 * Copy sensor name into description struct. Copy n-1 chars to ensure a
727 * NULL terminator at the end. (struct has been zeroed out)
728 */
729 fwk_str_strncpy(
730 desc.axis_name, axis_info.name, SCMI_SENSOR_AXIS_NAME_LEN - 1);
731
732 status = scmi_sensor_ctx.scmi_api->write_payload(
733 service_id,
734 payload_size,
735 &desc,
736 sizeof(struct scmi_sensor_axis_desc));
737 if (status != FWK_SUCCESS) {
738 /* Failed to write sensor description into message payload */
739 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
740 goto exit;
741 }
742 }
743
744 return_values = (struct scmi_sensor_axis_description_get_p2a){
745 .status = SCMI_SUCCESS,
746 .num_axis_flags = SCMI_SENSOR_NUM_SENSOR_FLAGS(
747 num_descs, (sensor_info.multi_axis.axis_count - desc_index_max - 1))
748 };
749
750 status = scmi_sensor_ctx.scmi_api->write_payload(
751 service_id, 0, &return_values, sizeof(return_values));
752 if (status != FWK_SUCCESS) {
753 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
754 }
755 goto exit;
756
757 exit_unexpected:
758 fwk_unexpected();
759 exit:
760 respond_status = scmi_sensor_ctx.scmi_api->respond(
761 service_id,
762 (return_values.status == SCMI_SUCCESS) ? NULL : &return_values.status,
763 (return_values.status == SCMI_SUCCESS) ? payload_size :
764 sizeof(return_values.status));
765 if (respond_status != FWK_SUCCESS) {
766 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
767 }
768
769 return status;
770 }
771 #endif
772
scmi_sensor_reading_get_handler(fwk_id_t service_id,const uint32_t * payload)773 static int scmi_sensor_reading_get_handler(fwk_id_t service_id,
774 const uint32_t *payload)
775 {
776 const struct scmi_sensor_protocol_reading_get_a2p *parameters;
777 struct scmi_sensor_protocol_reading_get_p2a return_values;
778 struct scmi_sensor_event_parameters *params;
779 unsigned int sensor_idx;
780 uint32_t flags;
781 int status, respond_status;
782
783 parameters = (const struct scmi_sensor_protocol_reading_get_a2p *)payload;
784
785 if (parameters->sensor_id >= scmi_sensor_ctx.sensor_count) {
786 /* Sensor does not exist */
787 status = FWK_SUCCESS;
788 return_values.status = (int32_t)SCMI_NOT_FOUND;
789 goto exit;
790 }
791
792 flags = parameters->flags;
793
794 if ((flags & ~SCMI_SENSOR_PROTOCOL_READING_GET_ASYNC_FLAG_MASK) !=
795 (uint32_t)0) {
796 return_values.status = (int32_t)SCMI_INVALID_PARAMETERS;
797 status = FWK_SUCCESS;
798 goto exit;
799 }
800
801 /* Reject asynchronous read requests for now */
802 if ((flags & SCMI_SENSOR_PROTOCOL_READING_GET_ASYNC_FLAG_MASK) !=
803 (uint32_t)0) {
804 return_values.status = (int32_t)SCMI_NOT_SUPPORTED;
805 status = FWK_SUCCESS;
806 goto exit;
807 }
808
809 sensor_idx = parameters->sensor_id;
810
811 /* Check if there is already a request pending for this sensor */
812 if (!fwk_id_is_equal(
813 scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id,
814 FWK_ID_NONE)){
815 return_values.status = (int32_t)SCMI_BUSY;
816 status = FWK_SUCCESS;
817
818 goto exit;
819 }
820
821 /* The get_data request is processed within the event being generated */
822 struct fwk_event event = {
823 .target_id = fwk_module_id_scmi_sensor,
824 .id = mod_scmi_sensor_event_id_get_request,
825 };
826
827 params = (struct scmi_sensor_event_parameters *)event.params;
828 params->sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR,
829 sensor_idx);
830
831 status = fwk_put_event(&event);
832 if (status != FWK_SUCCESS) {
833 return_values.status = (int32_t)SCMI_GENERIC_ERROR;
834
835 goto exit;
836 }
837
838 /* Store service identifier to indicate there is a pending request */
839 scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id = service_id;
840
841 return FWK_SUCCESS;
842
843 exit:
844 respond_status = scmi_sensor_ctx.scmi_api->respond(
845 service_id,
846 &return_values,
847 (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) :
848 sizeof(return_values.status));
849
850 if (respond_status != FWK_SUCCESS) {
851 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
852 }
853
854 return status;
855 }
856
857 /*
858 * SCMI module -> SCMI sensor module interface
859 */
scmi_sensor_get_scmi_protocol_id(fwk_id_t protocol_id,uint8_t * scmi_protocol_id)860 static int scmi_sensor_get_scmi_protocol_id(fwk_id_t protocol_id,
861 uint8_t *scmi_protocol_id)
862 {
863 *scmi_protocol_id = (uint8_t)MOD_SCMI_PROTOCOL_ID_SENSOR;
864
865 return FWK_SUCCESS;
866 }
867
868 /*
869 * SCMI Resource Permissions handler
870 */
871 #ifdef BUILD_HAS_MOD_RESOURCE_PERMS
get_sensor_id(const uint32_t * payload)872 static unsigned int get_sensor_id(const uint32_t *payload)
873 {
874 /*
875 * Every SCMI Performance message is formatted with the sensor ID
876 * as the first message element. We will use the reading_get
877 * message as a basic format to retrieve the sensor ID to avoid
878 * unnecessary code.
879 */
880 const struct scmi_sensor_protocol_reading_get_a2p *parameters =
881 (const struct scmi_sensor_protocol_reading_get_a2p *)payload;
882 return parameters->sensor_id;
883 }
884
scmi_sensor_permissions_handler(fwk_id_t service_id,const uint32_t * payload,size_t payload_size,unsigned int message_id)885 static int scmi_sensor_permissions_handler(
886 fwk_id_t service_id,
887 const uint32_t *payload,
888 size_t payload_size,
889 unsigned int message_id)
890 {
891 enum mod_res_perms_permissions perms;
892 unsigned int agent_id, sensor_id;
893 int status;
894
895 status = scmi_sensor_ctx.scmi_api->get_agent_id(service_id, &agent_id);
896 if (status != FWK_SUCCESS) {
897 return FWK_E_ACCESS;
898 }
899
900 if (message_id < 3) {
901 perms = scmi_sensor_ctx.res_perms_api->agent_has_protocol_permission(
902 agent_id, MOD_SCMI_PROTOCOL_ID_SENSOR);
903 if (perms == MOD_RES_PERMS_ACCESS_ALLOWED) {
904 return FWK_SUCCESS;
905 }
906 return FWK_E_ACCESS;
907 }
908
909 sensor_id = get_sensor_id(payload);
910 if (sensor_id >= scmi_sensor_ctx.sensor_count) {
911 return FWK_E_PARAM;
912 }
913
914 perms = scmi_sensor_ctx.res_perms_api->agent_has_resource_permission(
915 agent_id, MOD_SCMI_PROTOCOL_ID_SENSOR, message_id, sensor_id);
916
917 if (perms == MOD_RES_PERMS_ACCESS_ALLOWED) {
918 return FWK_SUCCESS;
919 } else {
920 return FWK_E_ACCESS;
921 }
922 }
923 #endif
924
scmi_sensor_message_handler(fwk_id_t protocol_id,fwk_id_t service_id,const uint32_t * payload,size_t payload_size,unsigned int message_id)925 static int scmi_sensor_message_handler(fwk_id_t protocol_id,
926 fwk_id_t service_id,
927 const uint32_t *payload,
928 size_t payload_size,
929 unsigned int message_id)
930 {
931 int32_t return_value;
932 #ifdef BUILD_HAS_MOD_RESOURCE_PERMS
933 int status;
934 #endif
935
936 static_assert(FWK_ARRAY_SIZE(handler_table) ==
937 FWK_ARRAY_SIZE(payload_size_table),
938 "[SCMI] Sensor management protocol table sizes not consistent");
939 fwk_assert(payload != NULL);
940
941 if (message_id >= FWK_ARRAY_SIZE(handler_table)) {
942 return_value = (int32_t)SCMI_NOT_FOUND;
943 goto error;
944 }
945
946 if (payload_size != payload_size_table[message_id]) {
947 /* Incorrect payload size or message is not supported */
948 return_value = (int32_t)SCMI_PROTOCOL_ERROR;
949 goto error;
950 }
951
952 #ifdef BUILD_HAS_MOD_RESOURCE_PERMS
953 status = scmi_sensor_permissions_handler(
954 service_id, payload, payload_size, message_id);
955 if (status != FWK_SUCCESS) {
956 if (status == FWK_E_ACCESS) {
957 return_value = (int32_t)SCMI_DENIED;
958 } else if (message_id == MOD_SCMI_SENSOR_DESCRIPTION_GET) {
959 return_value = (int32_t)SCMI_INVALID_PARAMETERS;
960 } else {
961 return_value = (int32_t)SCMI_NOT_FOUND;
962 }
963 goto error;
964 }
965 #endif
966
967 return handler_table[message_id](service_id, payload);
968
969 error:
970 return scmi_sensor_ctx.scmi_api->respond(
971 service_id, &return_value, sizeof(return_value));
972 }
973
974 static struct mod_scmi_to_protocol_api scmi_sensor_mod_scmi_to_protocol_api = {
975 .get_scmi_protocol_id = scmi_sensor_get_scmi_protocol_id,
976 .message_handler = scmi_sensor_message_handler
977 };
978
scmi_sensor_notify_trip_point(fwk_id_t sensor_id,uint32_t state,uint32_t trip_point_idx)979 static void scmi_sensor_notify_trip_point(
980 fwk_id_t sensor_id,
981 uint32_t state,
982 uint32_t trip_point_idx)
983 {
984 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS
985 struct scmi_sensor_trip_point_event_p2a trip_point_event;
986 int status;
987
988 trip_point_event.sensor_id = fwk_id_get_element_idx(sensor_id);
989 trip_point_event.agent_id = 0x0;
990 trip_point_event.trip_point_desc =
991 SCMI_SENSOR_TRIP_POINT_EVENT_DESC(state, trip_point_idx);
992
993 status = scmi_sensor_ctx.scmi_notification_api->scmi_notification_notify(
994 MOD_SCMI_PROTOCOL_ID_SENSOR,
995 MOD_SCMI_SENSOR_TRIP_POINT_NOTIFY,
996 SCMI_SENSOR_TRIP_POINT_EVENT,
997 &trip_point_event,
998 sizeof(trip_point_event));
999 if (status != FWK_SUCCESS) {
1000 FWK_LOG_DEBUG("[SCMI-SENS] %s @%d", __func__, __LINE__);
1001 }
1002 #endif
1003 }
1004 static struct mod_sensor_trip_point_api sensor_trip_point_api = {
1005 .notify_sensor_trip_point = scmi_sensor_notify_trip_point
1006 };
1007
1008 /*
1009 * Framework interface
1010 */
scmi_sensor_init(fwk_id_t module_id,unsigned int element_count,const void * unused)1011 static int scmi_sensor_init(fwk_id_t module_id,
1012 unsigned int element_count,
1013 const void *unused)
1014 {
1015 if (element_count != 0) {
1016 /* This module should not have any elements */
1017 fwk_unexpected();
1018 return FWK_E_SUPPORT;
1019 }
1020
1021 scmi_sensor_ctx.sensor_count = (unsigned int)fwk_module_get_element_count(
1022 FWK_ID_MODULE(FWK_MODULE_IDX_SENSOR));
1023 if (scmi_sensor_ctx.sensor_count == 0) {
1024 return FWK_E_SUPPORT;
1025 }
1026
1027 scmi_sensor_ctx.sensor_values = fwk_mm_calloc(
1028 scmi_sensor_ctx.sensor_count, sizeof(struct mod_sensor_data));
1029
1030 /* SCMI protocol uses a 16 bit number to store the number of sensors.
1031 * So expose no more than 0xFFFF number of sensors. */
1032 if (scmi_sensor_ctx.sensor_count > UINT16_MAX) {
1033 scmi_sensor_ctx.sensor_count = UINT16_MAX;
1034 }
1035
1036 /* Allocate a table for the sensors state */
1037 scmi_sensor_ctx.sensor_ops_table =
1038 fwk_mm_calloc(scmi_sensor_ctx.sensor_count,
1039 sizeof(struct sensor_operations));
1040
1041 /* Initialize the service identifier for each sensor to 'available' */
1042 for (unsigned int i = 0; i < scmi_sensor_ctx.sensor_count; i++) {
1043 scmi_sensor_ctx.sensor_ops_table[i].service_id = FWK_ID_NONE;
1044 }
1045
1046 return FWK_SUCCESS;
1047 }
1048
1049 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS
scmi_init_notifications(int sensor_count)1050 static int scmi_init_notifications(int sensor_count)
1051 {
1052 int status;
1053
1054 status =
1055 scmi_sensor_ctx.scmi_api->get_agent_count(&scmi_sensor_ctx.agent_count);
1056 if (status != FWK_SUCCESS) {
1057 return status;
1058 }
1059
1060 fwk_assert(scmi_sensor_ctx.agent_count != 0u);
1061
1062 status = scmi_sensor_ctx.scmi_notification_api->scmi_notification_init(
1063 MOD_SCMI_PROTOCOL_ID_SENSOR,
1064 scmi_sensor_ctx.agent_count,
1065 scmi_sensor_ctx.sensor_count,
1066 MOD_SCMI_SENSOR_NOTIFICATION_COUNT);
1067
1068 return status;
1069 }
1070 #endif
1071
scmi_sensor_bind(fwk_id_t id,unsigned int round)1072 static int scmi_sensor_bind(fwk_id_t id, unsigned int round)
1073 {
1074 int status;
1075
1076 if (round == 1) {
1077 return FWK_SUCCESS;
1078 }
1079
1080 status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_SCMI),
1081 FWK_ID_API(FWK_MODULE_IDX_SCMI,
1082 MOD_SCMI_API_IDX_PROTOCOL),
1083 &scmi_sensor_ctx.scmi_api);
1084 if (status != FWK_SUCCESS) {
1085 /* Failed to bind to SCMI module */
1086 fwk_unexpected();
1087 return status;
1088 }
1089
1090 status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_SENSOR),
1091 mod_sensor_api_id_sensor,
1092 &scmi_sensor_ctx.sensor_api);
1093 if (status != FWK_SUCCESS) {
1094 /* Failed to bind to sensor module */
1095 fwk_unexpected();
1096 return status;
1097 }
1098
1099 #ifdef BUILD_HAS_MOD_RESOURCE_PERMS
1100 status = fwk_module_bind(
1101 FWK_ID_MODULE(FWK_MODULE_IDX_RESOURCE_PERMS),
1102 FWK_ID_API(FWK_MODULE_IDX_RESOURCE_PERMS, MOD_RES_PERM_RESOURCE_PERMS),
1103 &scmi_sensor_ctx.res_perms_api);
1104 if (status != FWK_SUCCESS) {
1105 return status;
1106 }
1107 #endif
1108
1109 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS
1110 status = fwk_module_bind(
1111 FWK_ID_MODULE(FWK_MODULE_IDX_SCMI),
1112 FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_NOTIFICATION),
1113 &scmi_sensor_ctx.scmi_notification_api);
1114 if (status != FWK_SUCCESS) {
1115 return status;
1116 }
1117 #endif
1118
1119 return FWK_SUCCESS;
1120 }
1121
scmi_sensor_start(fwk_id_t id)1122 static int scmi_sensor_start(fwk_id_t id)
1123 {
1124 int status = FWK_SUCCESS;
1125
1126 #ifdef BUILD_HAS_SCMI_NOTIFICATIONS
1127 status = scmi_init_notifications((int)scmi_sensor_ctx.sensor_count);
1128 if (status != FWK_SUCCESS) {
1129 return status;
1130 }
1131 #endif
1132
1133 return status;
1134 }
1135
scmi_sensor_process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)1136 static int scmi_sensor_process_bind_request(fwk_id_t source_id,
1137 fwk_id_t target_id,
1138 fwk_id_t api_id,
1139 const void **api)
1140 {
1141 enum scmi_sensor_api_idx api_id_type =
1142 (enum scmi_sensor_api_idx)fwk_id_get_api_idx(api_id);
1143
1144 switch (api_id_type) {
1145 case SCMI_SENSOR_API_IDX_REQUEST:
1146 if (!fwk_id_is_equal(source_id, FWK_ID_MODULE(FWK_MODULE_IDX_SCMI))) {
1147 return FWK_E_ACCESS;
1148 }
1149 *api = &scmi_sensor_mod_scmi_to_protocol_api;
1150 break;
1151
1152 case SCMI_SENSOR_API_IDX_TRIP_POINT:
1153 *api = &sensor_trip_point_api;
1154 break;
1155
1156 default:
1157 return FWK_E_ACCESS;
1158 }
1159 return FWK_SUCCESS;
1160 }
1161
get_sensor_data(fwk_id_t sensor_id)1162 static inline struct mod_sensor_data *get_sensor_data(fwk_id_t sensor_id)
1163 {
1164 return &scmi_sensor_ctx.sensor_values[fwk_id_get_element_idx(sensor_id)];
1165 }
1166
scmi_sensor_process_event(const struct fwk_event * event,struct fwk_event * resp_event)1167 static int scmi_sensor_process_event(const struct fwk_event *event,
1168 struct fwk_event *resp_event)
1169 {
1170 int status;
1171 struct scmi_sensor_event_parameters *scmi_params;
1172 struct mod_sensor_data *sensor_data;
1173
1174 /* Request event to sensor HAL */
1175 if (fwk_id_is_equal(event->id, mod_scmi_sensor_event_id_get_request)) {
1176 scmi_params = (struct scmi_sensor_event_parameters *)event->params;
1177 sensor_data = get_sensor_data(scmi_params->sensor_id);
1178 status = scmi_sensor_ctx.sensor_api->get_data(
1179 scmi_params->sensor_id, sensor_data);
1180 if (status != FWK_PENDING) {
1181 /* Sensor value is ready (successfully or not) */
1182 return scmi_sensor_reading_respond(
1183 scmi_params->sensor_id, sensor_data);
1184
1185 } else {
1186 /* Sensor value will be provided through a response event */
1187 return FWK_SUCCESS;
1188 }
1189 }
1190
1191 /* Response event from sensor HAL */
1192 if (fwk_id_is_equal(event->id, mod_sensor_event_id_read_request)) {
1193 sensor_data = get_sensor_data(event->source_id);
1194
1195 return scmi_sensor_reading_respond(event->source_id, sensor_data);
1196 }
1197
1198 return FWK_SUCCESS;
1199 }
1200
1201 const struct fwk_module module_scmi_sensor = {
1202 .api_count = (unsigned int)SCMI_SENSOR_API_IDX_COUNT,
1203 .event_count = (unsigned int)SCMI_SENSOR_EVENT_IDX_COUNT,
1204 .type = FWK_MODULE_TYPE_PROTOCOL,
1205 .init = scmi_sensor_init,
1206 .bind = scmi_sensor_bind,
1207 .start = scmi_sensor_start,
1208 .process_bind_request = scmi_sensor_process_bind_request,
1209 .process_event = scmi_sensor_process_event,
1210 };
1211
1212 /* No elements, no module configuration data */
1213 struct fwk_module_config config_scmi_sensor = { 0 };
1214