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
plat_scmi_sensor_count(unsigned int agent_id __unused)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
plat_scmi_sensor_max_requests(unsigned int agent_id __unused)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
plat_scmi_sensor_reg(unsigned int agent_id __unused,unsigned int * addr)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
plat_scmi_sensor_reading_get(uint32_t agent_id __unused,uint16_t sensor_id __unused,uint32_t * val __unused)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
plat_scmi_sensor_description_get(uint32_t agent_id __unused,uint16_t desc_index __unused,struct scmi_sensor_desc * desc __unused)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
plat_scmi_sensor_update_interval(uint32_t agent_id __unused,uint16_t sensor_id __unused)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
plat_scmi_sensor_state(uint32_t agent_id __unused,uint16_t sensor_id __unused)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
plat_scmi_sensor_timestamped(uint32_t agent_id __unused,uint16_t sensor_id __unused)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
report_version(struct scmi_msg * msg)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
report_attributes(struct scmi_msg * msg)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
report_message_attributes(struct scmi_msg * msg)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
scmi_sensor_description_get(struct scmi_msg * msg)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
scmi_sensor_config_get(struct scmi_msg * msg)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
scmi_sensor_reading_get(struct scmi_msg * msg)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
scmi_sensor_list_update_intervals(struct scmi_msg * msg)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
message_id_is_supported(size_t message_id)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
scmi_msg_get_sensor_handler(struct scmi_msg * msg)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