1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Copyright 2021-2024 NXP
4 */
5
6 #include <cdefs.h>
7 #include <string.h>
8
9 #include "common.h"
10
11 #include <drivers/scmi-msg.h>
12 #include <drivers/scmi.h>
13 #include <lib/utils_def.h>
14
15 static bool message_id_is_supported(size_t message_id);
16
plat_scmi_sensor_count(unsigned int agent_id __unused)17 uint16_t plat_scmi_sensor_count(unsigned int agent_id __unused)
18 {
19 if (sensor_ops.sensor_count != NULL) {
20 return sensor_ops.sensor_count(agent_id);
21 }
22
23 return 0U;
24 }
25
plat_scmi_sensor_max_requests(unsigned int agent_id __unused)26 uint8_t plat_scmi_sensor_max_requests(unsigned int agent_id __unused)
27 {
28 if (sensor_ops.sensor_max_request != NULL) {
29 return sensor_ops.sensor_max_request(agent_id);
30 }
31
32 return 0U;
33 }
34
plat_scmi_sensor_reg(unsigned int agent_id __unused,unsigned int * addr)35 uint32_t plat_scmi_sensor_reg(unsigned int agent_id __unused,
36 unsigned int *addr)
37 {
38 if (sensor_ops.get_sensor_req != NULL) {
39 return sensor_ops.get_sensor_req(agent_id, addr);
40 }
41
42 return 0U;
43 }
44
plat_scmi_sensor_reading_get(uint32_t agent_id __unused,uint16_t sensor_id __unused,uint32_t * val __unused)45 int32_t plat_scmi_sensor_reading_get(uint32_t agent_id __unused,
46 uint16_t sensor_id __unused,
47 uint32_t *val __unused)
48 {
49 if (sensor_ops.sensor_reading_get != NULL) {
50 return sensor_ops.sensor_reading_get(agent_id, sensor_id, val);
51 }
52
53 return 0;
54 }
55
plat_scmi_sensor_description_get(uint32_t agent_id __unused,uint16_t desc_index __unused,struct scmi_sensor_desc * desc __unused)56 uint32_t plat_scmi_sensor_description_get(uint32_t agent_id __unused,
57 uint16_t desc_index __unused,
58 struct scmi_sensor_desc *desc __unused)
59 {
60 if (sensor_ops.sensor_description_get != NULL) {
61 return sensor_ops.sensor_description_get(agent_id, desc_index, desc);
62 }
63
64 return 0U;
65 }
66
plat_scmi_sensor_update_interval(uint32_t agent_id __unused,uint16_t sensor_id __unused)67 uint32_t plat_scmi_sensor_update_interval(uint32_t agent_id __unused,
68 uint16_t sensor_id __unused)
69 {
70 if (sensor_ops.sensor_update_interval != NULL) {
71 return sensor_ops.sensor_update_interval(agent_id, sensor_id);
72 }
73
74 return 0U;
75 }
76
plat_scmi_sensor_state(uint32_t agent_id __unused,uint16_t sensor_id __unused)77 uint32_t plat_scmi_sensor_state(uint32_t agent_id __unused,
78 uint16_t sensor_id __unused)
79 {
80 if (sensor_ops.sensor_state != NULL) {
81 return sensor_ops.sensor_state(agent_id, sensor_id);
82 }
83
84 return 0U;
85 }
86
plat_scmi_sensor_timestamped(uint32_t agent_id __unused,uint16_t sensor_id __unused)87 uint32_t plat_scmi_sensor_timestamped(uint32_t agent_id __unused,
88 uint16_t sensor_id __unused)
89 {
90 if (sensor_ops.sensor_timestamped != NULL) {
91 return sensor_ops.sensor_timestamped(agent_id, sensor_id);
92 }
93
94 return 0U;
95 }
96
report_version(struct scmi_msg * msg)97 static void report_version(struct scmi_msg *msg)
98 {
99 struct scmi_protocol_version_p2a return_values = {
100 .status = SCMI_SUCCESS,
101 .version = SCMI_PROTOCOL_VERSION_SENSOR,
102 };
103
104 if (msg->in_size != 0U) {
105 scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
106 return;
107 }
108
109 scmi_write_response(msg, &return_values, sizeof(return_values));
110 }
111
report_attributes(struct scmi_msg * msg)112 static void report_attributes(struct scmi_msg *msg)
113 {
114 unsigned int addr[2];
115 unsigned int len;
116
117 struct scmi_protocol_attributes_p2a_sensor return_values = {
118 .status = SCMI_SUCCESS,
119 };
120
121 if (msg->in_size != 0U) {
122 scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
123 return;
124 }
125
126 return_values.num_sensors = plat_scmi_sensor_count(msg->agent_id);
127 return_values.max_reqs = plat_scmi_sensor_max_requests(msg->agent_id);
128 len = plat_scmi_sensor_reg(msg->agent_id, addr);
129 if (len != 0U) {
130 return_values.sensor_reg_low = addr[0];
131 return_values.sensor_reg_high = addr[1];
132 return_values.sensor_reg_len = len;
133 }
134
135 scmi_write_response(msg, &return_values, sizeof(return_values));
136 }
137
report_message_attributes(struct scmi_msg * msg)138 static void report_message_attributes(struct scmi_msg *msg)
139 {
140 struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
141 struct scmi_protocol_message_attributes_p2a return_values = {
142 .status = SCMI_SUCCESS,
143 /* For this protocol, attributes shall be zero */
144 .attributes = 0U,
145 };
146
147 if (msg->in_size != sizeof(*in_args)) {
148 scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
149 return;
150 }
151
152 if (!message_id_is_supported(in_args->message_id)) {
153 scmi_status_response(msg, SCMI_NOT_FOUND);
154 return;
155 }
156
157 scmi_write_response(msg, &return_values, sizeof(return_values));
158 }
159
scmi_sensor_description_get(struct scmi_msg * msg)160 static void scmi_sensor_description_get(struct scmi_msg *msg)
161 {
162 const struct scmi_sensor_description_get_a2p *in_args = (void *)msg->in;
163 struct scmi_sensor_description_get_p2a return_values = {
164 .status = SCMI_SUCCESS,
165 };
166 struct scmi_sensor_desc desc;
167 unsigned int desc_index = 0U;
168 unsigned int num_sensor_flags;
169
170 if (msg->in_size != sizeof(*in_args)) {
171 scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
172 return;
173 }
174
175 desc_index = SPECULATION_SAFE_VALUE(in_args->desc_index);
176
177 num_sensor_flags = plat_scmi_sensor_description_get(msg->agent_id, desc_index,
178 &desc);
179 return_values.num_sensor_flags = num_sensor_flags;
180
181 memcpy(msg->out, &return_values, sizeof(return_values));
182 memcpy(msg->out + sizeof(return_values), &desc, sizeof(desc));
183 msg->out_size_out = sizeof(return_values) + sizeof(struct scmi_sensor_desc);
184 }
185
scmi_sensor_config_get(struct scmi_msg * msg)186 static void scmi_sensor_config_get(struct scmi_msg *msg)
187 {
188 const struct scmi_sensor_config_get_a2p *in_args = (void *)msg->in;
189 struct scmi_sensor_config_get_p2a return_values = {
190 .status = SCMI_SUCCESS,
191 };
192 unsigned int sensor_id = 0U;
193 uint32_t update_interval, state, timestamped;
194
195 if (msg->in_size != sizeof(*in_args)) {
196 scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
197 return;
198 }
199
200 sensor_id = SPECULATION_SAFE_VALUE(in_args->sensor_id);
201
202 if (sensor_id >= plat_scmi_sensor_count(msg->agent_id)) {
203 scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
204 return;
205 }
206
207 update_interval = plat_scmi_sensor_update_interval(msg->agent_id, sensor_id);
208 state = plat_scmi_sensor_state(msg->agent_id, sensor_id);
209 timestamped = plat_scmi_sensor_timestamped(msg->agent_id, sensor_id);
210 return_values.sensor_config = (update_interval << 11) | (timestamped << 1) | state;
211
212 scmi_write_response(msg, &return_values, sizeof(return_values));
213 }
214
scmi_sensor_reading_get(struct scmi_msg * msg)215 static void scmi_sensor_reading_get(struct scmi_msg *msg)
216 {
217 const struct scmi_sensor_reading_get_a2p *in_args = (void *)msg->in;
218 struct scmi_sensor_reading_get_p2a return_values = {
219 .status = SCMI_SUCCESS,
220 };
221 unsigned int sensor_id = 0U;
222 int32_t ret;
223
224 if (msg->in_size != sizeof(*in_args)) {
225 scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
226 return;
227 }
228
229 sensor_id = SPECULATION_SAFE_VALUE(in_args->sensor_id);
230
231 if (sensor_id >= plat_scmi_sensor_count(msg->agent_id)) {
232 scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
233 return;
234 }
235
236 ret = plat_scmi_sensor_reading_get(msg->agent_id, sensor_id,
237 (uint32_t *)&return_values.val);
238 if (ret) {
239 scmi_status_response(msg, SCMI_HARDWARE_ERROR);
240 return;
241 }
242
243 scmi_write_response(msg, &return_values, sizeof(return_values));
244 }
245
scmi_sensor_list_update_intervals(struct scmi_msg * msg)246 static void scmi_sensor_list_update_intervals(struct scmi_msg *msg)
247 {
248 /* TODO */
249 scmi_status_response(msg, SCMI_NOT_SUPPORTED);
250 }
251
252 static const scmi_msg_handler_t scmi_sensor_handler_table[SCMI_SENSOR_MAX] = {
253 [SCMI_PROTOCOL_VERSION] = report_version,
254 [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
255 [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
256 [SCMI_SENSOR_DESCRIPTION_GET] = scmi_sensor_description_get,
257 [SCMI_SENSOR_CONFIG_GET] = scmi_sensor_config_get,
258 [SCMI_SENSOR_LIST_UPDATE_INTERVALS] = scmi_sensor_list_update_intervals,
259 [SCMI_SENSOR_READING_GET] = scmi_sensor_reading_get,
260 };
261
message_id_is_supported(size_t message_id)262 static bool message_id_is_supported(size_t message_id)
263 {
264 return scmi_sensor_handler_table[message_id] != NULL;
265 }
266
scmi_msg_get_sensor_handler(struct scmi_msg * msg)267 scmi_msg_handler_t scmi_msg_get_sensor_handler(struct scmi_msg *msg)
268 {
269 unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
270
271 if (!message_id_is_supported(message_id)) {
272 VERBOSE("pd handle not found %u\n", msg->message_id);
273 return NULL;
274 }
275
276 return scmi_sensor_handler_table[message_id];
277 }
278