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