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