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