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