1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 */
8
9 #include <mod_sensor.h>
10 #include <mod_sensor_smcf_drv.h>
11
12 #include <fwk_event.h>
13 #include <fwk_id.h>
14 #include <fwk_log.h>
15 #include <fwk_macros.h>
16 #include <fwk_mm.h>
17 #include <fwk_module.h>
18 #include <fwk_module_idx.h>
19 #include <fwk_notification.h>
20 #include <fwk_status.h>
21
22 #define MOD_NAME "[sensor_smcf_drv]"
23
24 /*!
25 * \brief sensor_smcf_drv module context.
26 */
27 struct mod_sensor_smcf_drv_ctx {
28 /*! Number of devices */
29 uint32_t num_of_devices;
30
31 /*! Per device config table for sensor_smcf_drv */
32 struct sensor_smcf_drv_element_config *element_config_table;
33
34 /*! SMCF data buffer for sensor sample data for each device */
35 struct mod_smcf_buffer sensor_smcf_data_buf;
36
37 /*! SMCF data sampling API */
38 const struct smcf_data_api *data_api;
39 } sensor_smcf_drv_ctx;
40
_get_smcf_sensor_data(unsigned int device_index)41 static int _get_smcf_sensor_data(unsigned int device_index)
42 {
43 int status;
44 struct mod_smcf_buffer smcf_tag_buf;
45 static uint32_t tag_buf[SENSOR_SMCF_TAG_BUFFER_SIZE];
46
47 /* Prepare smcf get_data arguments */
48 memset(tag_buf, 0, sizeof(uint32_t) * SENSOR_SMCF_TAG_BUFFER_SIZE);
49 memset(
50 sensor_smcf_drv_ctx.sensor_smcf_data_buf.ptr,
51 0,
52 sensor_smcf_drv_ctx.sensor_smcf_data_buf.size);
53 smcf_tag_buf.ptr = tag_buf;
54 smcf_tag_buf.size = SENSOR_SMCF_TAG_BUFFER_SIZE;
55
56 /* Prepare smcf get data arguments */
57 status = sensor_smcf_drv_ctx.data_api->get_data(
58 sensor_smcf_drv_ctx.element_config_table[device_index].smcf_mli_id,
59 sensor_smcf_drv_ctx.sensor_smcf_data_buf,
60 smcf_tag_buf);
61
62 return status;
63 }
64
sensor_smcf_drv_get_sensor_single_value(fwk_id_t sensor_id,mod_sensor_value_t * value)65 static int sensor_smcf_drv_get_sensor_single_value(
66 fwk_id_t sensor_id,
67 mod_sensor_value_t *value)
68 {
69 int status;
70 unsigned int device_idx;
71
72 if (!fwk_module_is_valid_element_id(sensor_id) || value == NULL) {
73 return FWK_E_PARAM;
74 }
75
76 device_idx = fwk_id_get_element_idx(sensor_id);
77 status = _get_smcf_sensor_data(device_idx);
78 if (status != FWK_SUCCESS) {
79 return status;
80 }
81
82 *value =
83 *((mod_sensor_value_t *)sensor_smcf_drv_ctx.sensor_smcf_data_buf.ptr);
84
85 return FWK_SUCCESS;
86 }
87
sensor_smcf_drv_get_sensor_multiple_samples(fwk_id_t sensor_id,uint32_t * sample_buff,size_t buffer_size)88 static int sensor_smcf_drv_get_sensor_multiple_samples(
89 fwk_id_t sensor_id,
90 uint32_t *sample_buff,
91 size_t buffer_size)
92 {
93 int status = FWK_SUCCESS;
94 struct sensor_smcf_drv_element_config *device_sensor_cfg;
95 unsigned int device_idx;
96
97 if (!fwk_module_is_valid_element_id(sensor_id) || sample_buff == NULL ||
98 buffer_size == 0) {
99 return FWK_E_PARAM;
100 };
101
102 device_idx = fwk_id_get_element_idx(sensor_id);
103 device_sensor_cfg = &(sensor_smcf_drv_ctx.element_config_table[device_idx]);
104 if (buffer_size > device_sensor_cfg->max_samples_size) {
105 return FWK_E_RANGE;
106 }
107
108 status = _get_smcf_sensor_data(device_idx);
109 if (status != FWK_SUCCESS) {
110 return status;
111 }
112
113 memcpy(
114 sample_buff, sensor_smcf_drv_ctx.sensor_smcf_data_buf.ptr, buffer_size);
115
116 return FWK_SUCCESS;
117 }
118
119 static const struct mod_sensor_driver_api sensor_smcf_drv_get_value_api = {
120 .get_value = sensor_smcf_drv_get_sensor_single_value,
121 };
122
123 static const struct mod_sensor_smcf_drv_multiple_samples_api
124 sensor_smcf_drv_get_samples_api = {
125 .get_samples = sensor_smcf_drv_get_sensor_multiple_samples,
126 };
127
128 /*
129 * Framework handlers
130 */
sensor_smcf_drv_mod_init(fwk_id_t module_id,unsigned int element_count,const void * unused)131 static int sensor_smcf_drv_mod_init(
132 fwk_id_t module_id,
133 unsigned int element_count,
134 const void *unused)
135 {
136 if (element_count == 0) {
137 return FWK_E_PARAM;
138 }
139
140 sensor_smcf_drv_ctx.num_of_devices = element_count;
141 sensor_smcf_drv_ctx.element_config_table = fwk_mm_calloc(
142 element_count, sizeof(struct sensor_smcf_drv_element_config));
143
144 return FWK_SUCCESS;
145 }
146
sensor_smcf_drv_bind(fwk_id_t id,unsigned int round)147 static int sensor_smcf_drv_bind(fwk_id_t id, unsigned int round)
148 {
149 if (round > 0) {
150 return FWK_SUCCESS;
151 }
152
153 /* Bind to SMCF Data API */
154 return fwk_module_bind(
155 FWK_ID_MODULE(FWK_MODULE_IDX_SMCF),
156 FWK_ID_API(FWK_MODULE_IDX_SMCF, MOD_SMCF_API_IDX_DATA),
157 &sensor_smcf_drv_ctx.data_api);
158 }
159
sensor_smcf_drv_process_bind_request(fwk_id_t requester_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)160 static int sensor_smcf_drv_process_bind_request(
161 fwk_id_t requester_id,
162 fwk_id_t target_id,
163 fwk_id_t api_id,
164 const void **api)
165 {
166 int status = FWK_SUCCESS;
167 enum mod_sensor_smcf_drv_api_idx api_idx;
168
169 if (fwk_id_is_equal(
170 requester_id, FWK_ID_MODULE(FWK_MODULE_IDX_SENSOR_SMCF_DRV))) {
171 return FWK_E_PARAM;
172 }
173
174 api_idx = (enum mod_sensor_smcf_drv_api_idx)fwk_id_get_api_idx(api_id);
175 switch (api_idx) {
176 case MOD_SENSOR_SMCF_DRV_API_IDX_GET_VALUE:
177 *api = &sensor_smcf_drv_get_value_api;
178 status = FWK_SUCCESS;
179 break;
180
181 case MOD_SENSOR_SMCF_DRV_API_IDX_GET_MULTIPLE_SAMPLES:
182 *api = &sensor_smcf_drv_get_samples_api;
183 status = FWK_SUCCESS;
184 break;
185
186 default:
187 status = FWK_E_PARAM;
188 };
189
190 return status;
191 }
192
sensor_smcf_drv_start(fwk_id_t id)193 static int sensor_smcf_drv_start(fwk_id_t id)
194 {
195 unsigned int i;
196 uint32_t per_device_sample_data_max_size;
197
198 if (fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) {
199 /* elements has already been started with module start */
200 return FWK_SUCCESS;
201 }
202
203 if (!fwk_module_is_valid_module_id(id)) {
204 return FWK_E_PARAM;
205 }
206
207 /* Calculate the max size for the smcf counter data buffer to accomodate
208 * counter data for each element.
209 * SMCF_COUNTER_DATA_SZ = MAX(COUNTER_DATA_SZ_FOR_EACH_device)
210 */
211 per_device_sample_data_max_size = 0;
212 for (i = 0; i < sensor_smcf_drv_ctx.num_of_devices; ++i) {
213 per_device_sample_data_max_size = FWK_MAX(
214 per_device_sample_data_max_size,
215 sensor_smcf_drv_ctx.element_config_table[i].max_samples_size);
216 }
217
218 sensor_smcf_drv_ctx.sensor_smcf_data_buf.size =
219 (per_device_sample_data_max_size / sizeof(uint32_t));
220 sensor_smcf_drv_ctx.sensor_smcf_data_buf.ptr = fwk_mm_calloc(
221 sensor_smcf_drv_ctx.sensor_smcf_data_buf.size, sizeof(uint32_t));
222
223 return FWK_SUCCESS;
224 }
225
sensor_smcf_drv_element_init(fwk_id_t element_id,unsigned int unused,const void * data)226 static int sensor_smcf_drv_element_init(
227 fwk_id_t element_id,
228 unsigned int unused,
229 const void *data)
230 {
231 unsigned int device_idx;
232 struct sensor_smcf_drv_element_config *element_cfg;
233 if (!fwk_module_is_valid_element_id(element_id) || data == NULL) {
234 return FWK_E_PARAM;
235 }
236
237 device_idx = fwk_id_get_element_idx(element_id);
238 element_cfg = (struct sensor_smcf_drv_element_config *)data;
239 sensor_smcf_drv_ctx.element_config_table[device_idx] = *element_cfg;
240
241 return FWK_SUCCESS;
242 }
243
244 const struct fwk_module module_sensor_smcf_drv = {
245 .type = FWK_MODULE_TYPE_DRIVER,
246 .api_count = MOD_SENSOR_SMCF_DRV_API_IDX_COUNT,
247 .init = sensor_smcf_drv_mod_init,
248 .element_init = sensor_smcf_drv_element_init,
249 .start = sensor_smcf_drv_start,
250 .bind = sensor_smcf_drv_bind,
251 .process_bind_request = sensor_smcf_drv_process_bind_request,
252 };
253