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