blob: a47018d887db86653717927b5189e8d3b3038fcd [file] [log] [blame]
Jacky Baid1806aa2023-09-21 11:06:34 +08001// 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
15static bool message_id_is_supported(size_t message_id);
16
17uint16_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
26uint8_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
35uint32_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
45int32_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
56uint32_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
67uint32_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
77uint32_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
87uint32_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
97static 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
112static 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
138static 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
160static 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
186static 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
215static 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
246static void scmi_sensor_list_update_intervals(struct scmi_msg *msg)
247{
248 /* TODO */
249 scmi_status_response(msg, SCMI_NOT_SUPPORTED);
250}
251
252static 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
262static bool message_id_is_supported(size_t message_id)
263{
264 return scmi_sensor_handler_table[message_id] != NULL;
265}
266
267scmi_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}