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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 262 static bool message_id_is_supported(size_t message_id) 263 { 264 return scmi_sensor_handler_table[message_id] != NULL; 265 } 266 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