1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <mod_mock_sensor.h>
9 #include <mod_sensor.h>
10 #include <mod_timer.h>
11 
12 #include <fwk_assert.h>
13 #include <fwk_element.h>
14 #include <fwk_id.h>
15 #include <fwk_mm.h>
16 #include <fwk_module.h>
17 #include <fwk_module_idx.h>
18 
19 #include <stdint.h>
20 
21 #define MOCK_SENSOR_ALARM_DELAY_MS  10
22 struct mock_sensor_dev_ctx {
23     struct mod_mock_sensor_dev_config *config;
24     struct mod_timer_alarm_api *alarm_api;
25     struct mod_sensor_driver_response_api *driver_response_api;
26 };
27 
28 static struct mock_sensor_dev_ctx *ctx_table;
29 
mock_sensor_callback(uintptr_t param)30 static void mock_sensor_callback(uintptr_t param)
31 {
32     struct mod_sensor_driver_resp_params response;
33     struct mock_sensor_dev_ctx *ctx;
34     unsigned int sensor_hal_idx;
35 #ifdef BUILD_HAS_SCMI_SENSOR_V2
36     unsigned int i;
37 #endif
38 
39     ctx = (struct mock_sensor_dev_ctx *)param;
40     sensor_hal_idx = fwk_id_get_element_idx(ctx->config->sensor_hal_id);
41 
42     response.status = FWK_SUCCESS;
43 #ifdef BUILD_HAS_SCMI_SENSOR_V2
44     if (ctx->config->axis_count > 1) {
45         for (i = 0; i < ctx->config->axis_count; i++) {
46             response.axis_value[i] = ctx->config->read_value[i];
47         }
48     } else {
49         response.value = *ctx->config->read_value;
50     }
51 #else
52     response.value = *ctx->config->read_value;
53 #endif
54 
55     fwk_id_t sensor_id = fwk_id_build_element_id(
56         fwk_module_id_sensor, (unsigned int)sensor_hal_idx);
57     ctx->driver_response_api->reading_complete(sensor_id, &response);
58 
59     return;
60 }
61 
62 /*
63  * Module API
64  */
get_value(fwk_id_t id,mod_sensor_value_t * value)65 static int get_value(fwk_id_t id, mod_sensor_value_t *value)
66 {
67     struct mock_sensor_dev_ctx *ctx;
68     int status;
69 
70     ctx = ctx_table + fwk_id_get_element_idx(id);
71 
72     status = ctx->alarm_api->start(
73         ctx->config->alarm_id,
74         MOCK_SENSOR_ALARM_DELAY_MS,
75         MOD_TIMER_ALARM_TYPE_ONCE,
76         mock_sensor_callback,
77         (uintptr_t)ctx);
78     if (status != FWK_SUCCESS) {
79         return status;
80     }
81 
82     /* Mock sensor always defers this request */
83     return FWK_PENDING;
84 }
85 
get_info(fwk_id_t id,struct mod_sensor_info * info)86 static int get_info(fwk_id_t id, struct mod_sensor_info *info)
87 {
88     struct mock_sensor_dev_ctx *ctx;
89 
90     ctx = ctx_table + fwk_id_get_element_idx(id);
91 
92     if (info == NULL) {
93         return FWK_E_PARAM;
94     }
95 
96     *info = *ctx->config->info;
97     return FWK_SUCCESS;
98 }
99 
100 #ifdef BUILD_HAS_SCMI_SENSOR_V2
get_axis_count(fwk_id_t id)101 unsigned int get_axis_count(fwk_id_t id)
102 {
103     struct mock_sensor_dev_ctx *ctx;
104 
105     ctx = ctx_table + fwk_id_get_element_idx(id);
106 
107     return ctx->config->axis_count;
108 }
109 
get_axis_info(fwk_id_t id,uint32_t axis,struct mod_sensor_axis_info * info)110 int get_axis_info(fwk_id_t id, uint32_t axis, struct mod_sensor_axis_info *info)
111 {
112     struct mock_sensor_dev_ctx *ctx;
113 
114     ctx = ctx_table + fwk_id_get_element_idx(id);
115 
116     fwk_assert(info != NULL || axis < ctx->config->axis_count);
117 
118     *info = ctx->config->axis_info[axis];
119     return FWK_SUCCESS;
120 }
121 #endif
122 
123 static const struct mod_sensor_driver_api mock_sensor_api = {
124     .get_value = get_value,
125     .get_info = get_info,
126 #ifdef BUILD_HAS_SCMI_SENSOR_V2
127     .get_axis_count = get_axis_count,
128     .get_axis_info = get_axis_info,
129 #endif
130 };
131 
132 /*
133  * Framework handlers
134  */
mock_sensor_init(fwk_id_t module_id,unsigned int element_count,const void * data)135 static int mock_sensor_init(fwk_id_t module_id,
136                             unsigned int element_count,
137                             const void *data)
138 {
139     ctx_table =
140         fwk_mm_calloc(element_count, sizeof(struct mock_sensor_dev_ctx));
141     return FWK_SUCCESS;
142 }
143 
mock_sensor_element_init(fwk_id_t element_id,unsigned int unused,const void * data)144 static int mock_sensor_element_init(fwk_id_t element_id,
145                                     unsigned int unused,
146                                     const void *data)
147 {
148     struct mock_sensor_dev_ctx *ctx;
149 
150     fwk_assert(data != NULL);
151 
152     ctx = ctx_table + fwk_id_get_element_idx(element_id);
153     ctx->config = (struct mod_mock_sensor_dev_config *)data;
154 
155     return FWK_SUCCESS;
156 }
157 
mock_sensor_bind(fwk_id_t id,unsigned int round)158 static int mock_sensor_bind(fwk_id_t id, unsigned int round)
159 {
160     int status;
161     struct mock_sensor_dev_ctx *ctx;
162 
163     if ((round > 0) || fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) {
164         /*
165          * Only bind in first round of calls
166          * Nothing to do for module
167          */
168         return FWK_SUCCESS;
169     }
170 
171     ctx = ctx_table + fwk_id_get_element_idx(id);
172 
173     status = fwk_module_bind(
174         ctx->config->alarm_id,
175         FWK_ID_API(FWK_MODULE_IDX_TIMER, 1),
176         &ctx->alarm_api);
177     if (status != FWK_SUCCESS) {
178         return status;
179     }
180 
181     return fwk_module_bind(
182         ctx->config->sensor_hal_id,
183         mod_sensor_api_id_driver_response,
184         &ctx->driver_response_api);
185 }
186 
mock_sensor_process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_type,const void ** api)187 static int mock_sensor_process_bind_request(fwk_id_t source_id,
188                                             fwk_id_t target_id,
189                                             fwk_id_t api_type,
190                                             const void **api)
191 {
192     *api = &mock_sensor_api;
193     return FWK_SUCCESS;
194 }
195 
196 const struct fwk_module module_mock_sensor = {
197     .api_count = 1,
198     .type = FWK_MODULE_TYPE_DRIVER,
199     .init = mock_sensor_init,
200     .element_init = mock_sensor_element_init,
201     .bind = mock_sensor_bind,
202     .process_bind_request = mock_sensor_process_bind_request,
203 };
204