blob: 51474b57608f114bba44aff38baa8500f531b329 [file] [log] [blame]
Etienne Carriere02fd1262020-09-09 18:44:00 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020, Linaro Limited
4 */
5
Patrick Delaunay5dd84d42021-02-24 11:19:44 +01006#define LOG_CATEGORY UCLASS_SCMI_AGENT
7
Etienne Carriere02fd1262020-09-09 18:44:00 +02008#include <common.h>
9#include <dm.h>
10#include <malloc.h>
11#include <scmi_agent.h>
12#include <scmi_agent-uclass.h>
13#include <scmi_protocols.h>
14#include <asm/io.h>
15#include <asm/scmi_test.h>
16#include <dm/device_compat.h>
17
18/*
19 * The sandbox SCMI agent driver simulates to some extend a SCMI message
20 * processing. It simulates few of the SCMI services for some of the
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020021 * SCMI protocols embedded in U-Boot. Currently:
Etienne Carriere09665cb2022-02-21 09:22:39 +010022 * - SCMI clock protocol emulates an agent exposing 2 clocks
23 * - SCMI reset protocol emulates an agent exposing a reset controller
24 * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
Etienne Carriere02fd1262020-09-09 18:44:00 +020025 *
Etienne Carriere09665cb2022-02-21 09:22:39 +010026 * As per DT bindings, the device node name shall be scmi.
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020027 *
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010028 * All clocks and regulators are default disabled and reset controller down.
Etienne Carriere02fd1262020-09-09 18:44:00 +020029 *
Etienne Carriere09665cb2022-02-21 09:22:39 +010030 * This driver exports sandbox_scmi_service_ctx() for the test sequence to
Etienne Carriere02fd1262020-09-09 18:44:00 +020031 * get the state of the simulated services (clock state, rate, ...) and
32 * check back-end device state reflects the request send through the
Etienne Carriere8b9b6892020-09-09 18:44:07 +020033 * various uclass devices, as clocks and reset controllers.
Etienne Carriere02fd1262020-09-09 18:44:00 +020034 */
35
Etienne Carriere09665cb2022-02-21 09:22:39 +010036static struct sandbox_scmi_clk scmi_clk[] = {
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020037 { .id = 7, .rate = 1000 },
38 { .id = 3, .rate = 333 },
39};
40
Etienne Carriere09665cb2022-02-21 09:22:39 +010041static struct sandbox_scmi_reset scmi_reset[] = {
Etienne Carriere8b9b6892020-09-09 18:44:07 +020042 { .id = 3 },
43};
44
Etienne Carriere09665cb2022-02-21 09:22:39 +010045static struct sandbox_scmi_voltd scmi_voltd[] = {
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010046 { .id = 0, .voltage_uv = 3300000 },
47 { .id = 1, .voltage_uv = 1800000 },
48};
49
Etienne Carriere09665cb2022-02-21 09:22:39 +010050static struct sandbox_scmi_service sandbox_scmi_service_state;
Etienne Carriere02fd1262020-09-09 18:44:00 +020051
52struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
53{
54 return &sandbox_scmi_service_state;
55}
56
57static void debug_print_agent_state(struct udevice *dev, char *str)
58{
59 struct sandbox_scmi_agent *agent = dev_get_priv(dev);
60
Etienne Carriere09665cb2022-02-21 09:22:39 +010061 dev_dbg(dev, "Dump sandbox_scmi_agent: %s\n", str);
62 dev_dbg(dev, " scmi_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n",
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020063 agent->clk_count,
64 agent->clk_count ? agent->clk[0].enabled : -1,
65 agent->clk_count ? agent->clk[0].rate : -1,
66 agent->clk_count > 1 ? agent->clk[1].enabled : -1,
67 agent->clk_count > 1 ? agent->clk[1].rate : -1,
68 agent->clk_count > 2 ? agent->clk[2].enabled : -1,
69 agent->clk_count > 2 ? agent->clk[2].rate : -1);
Etienne Carriere09665cb2022-02-21 09:22:39 +010070 dev_dbg(dev, " scmi_reset (%zu): %d, %d, ...\n",
Etienne Carriere8b9b6892020-09-09 18:44:07 +020071 agent->reset_count,
72 agent->reset_count ? agent->reset[0].asserted : -1,
73 agent->reset_count > 1 ? agent->reset[1].asserted : -1);
Etienne Carriere09665cb2022-02-21 09:22:39 +010074 dev_dbg(dev, " scmi_voltd (%zu): %u/%d, %u/%d, ...\n",
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010075 agent->voltd_count,
76 agent->voltd_count ? agent->voltd[0].enabled : -1,
77 agent->voltd_count ? agent->voltd[0].voltage_uv : -1,
78 agent->voltd_count ? agent->voltd[1].enabled : -1,
79 agent->voltd_count ? agent->voltd[1].voltage_uv : -1);
Etienne Carriere02fd1262020-09-09 18:44:00 +020080};
81
Etienne Carriere09665cb2022-02-21 09:22:39 +010082static struct sandbox_scmi_clk *get_scmi_clk_state(uint clock_id)
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020083{
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020084 size_t n;
85
Etienne Carriere09665cb2022-02-21 09:22:39 +010086 for (n = 0; n < ARRAY_SIZE(scmi_clk); n++)
87 if (scmi_clk[n].id == clock_id)
88 return scmi_clk + n;
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020089
90 return NULL;
91}
92
Etienne Carriere09665cb2022-02-21 09:22:39 +010093static struct sandbox_scmi_reset *get_scmi_reset_state(uint reset_id)
Etienne Carriere8b9b6892020-09-09 18:44:07 +020094{
95 size_t n;
96
Etienne Carriere09665cb2022-02-21 09:22:39 +010097 for (n = 0; n < ARRAY_SIZE(scmi_reset); n++)
98 if (scmi_reset[n].id == reset_id)
99 return scmi_reset + n;
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200100
101 return NULL;
102}
103
Etienne Carriere09665cb2022-02-21 09:22:39 +0100104static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100105{
106 size_t n;
107
Etienne Carriere09665cb2022-02-21 09:22:39 +0100108 for (n = 0; n < ARRAY_SIZE(scmi_voltd); n++)
109 if (scmi_voltd[n].id == domain_id)
110 return scmi_voltd + n;
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100111
112 return NULL;
113}
114
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200115/*
116 * Sandbox SCMI agent ops
117 */
118
119static int sandbox_scmi_clock_rate_set(struct udevice *dev,
120 struct scmi_msg *msg)
121{
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200122 struct scmi_clk_rate_set_in *in = NULL;
123 struct scmi_clk_rate_set_out *out = NULL;
124 struct sandbox_scmi_clk *clk_state = NULL;
125
126 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
127 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
128 return -EINVAL;
129
130 in = (struct scmi_clk_rate_set_in *)msg->in_msg;
131 out = (struct scmi_clk_rate_set_out *)msg->out_msg;
132
Etienne Carriere09665cb2022-02-21 09:22:39 +0100133 clk_state = get_scmi_clk_state(in->clock_id);
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200134 if (!clk_state) {
135 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
136
137 out->status = SCMI_NOT_FOUND;
138 } else {
139 u64 rate = ((u64)in->rate_msb << 32) + in->rate_lsb;
140
141 clk_state->rate = (ulong)rate;
142
143 out->status = SCMI_SUCCESS;
144 }
145
146 return 0;
147}
148
149static int sandbox_scmi_clock_rate_get(struct udevice *dev,
150 struct scmi_msg *msg)
151{
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200152 struct scmi_clk_rate_get_in *in = NULL;
153 struct scmi_clk_rate_get_out *out = NULL;
154 struct sandbox_scmi_clk *clk_state = NULL;
155
156 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
157 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
158 return -EINVAL;
159
160 in = (struct scmi_clk_rate_get_in *)msg->in_msg;
161 out = (struct scmi_clk_rate_get_out *)msg->out_msg;
162
Etienne Carriere09665cb2022-02-21 09:22:39 +0100163 clk_state = get_scmi_clk_state(in->clock_id);
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200164 if (!clk_state) {
165 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
166
167 out->status = SCMI_NOT_FOUND;
168 } else {
169 out->rate_msb = (u32)((u64)clk_state->rate >> 32);
170 out->rate_lsb = (u32)clk_state->rate;
171
172 out->status = SCMI_SUCCESS;
173 }
174
175 return 0;
176}
177
178static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
179{
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200180 struct scmi_clk_state_in *in = NULL;
181 struct scmi_clk_state_out *out = NULL;
182 struct sandbox_scmi_clk *clk_state = NULL;
183
184 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
185 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
186 return -EINVAL;
187
188 in = (struct scmi_clk_state_in *)msg->in_msg;
189 out = (struct scmi_clk_state_out *)msg->out_msg;
190
Etienne Carriere09665cb2022-02-21 09:22:39 +0100191 clk_state = get_scmi_clk_state(in->clock_id);
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200192 if (!clk_state) {
193 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
194
195 out->status = SCMI_NOT_FOUND;
196 } else if (in->attributes > 1) {
197 out->status = SCMI_PROTOCOL_ERROR;
198 } else {
199 clk_state->enabled = in->attributes;
200
201 out->status = SCMI_SUCCESS;
202 }
203
204 return 0;
205}
206
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200207static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
208{
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200209 struct scmi_rd_attr_in *in = NULL;
210 struct scmi_rd_attr_out *out = NULL;
211 struct sandbox_scmi_reset *reset_state = NULL;
212
213 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
214 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
215 return -EINVAL;
216
217 in = (struct scmi_rd_attr_in *)msg->in_msg;
218 out = (struct scmi_rd_attr_out *)msg->out_msg;
219
Etienne Carriere09665cb2022-02-21 09:22:39 +0100220 reset_state = get_scmi_reset_state(in->domain_id);
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200221 if (!reset_state) {
222 dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
223
224 out->status = SCMI_NOT_FOUND;
225 } else {
226 memset(out, 0, sizeof(*out));
227 snprintf(out->name, sizeof(out->name), "rd%u", in->domain_id);
228
229 out->status = SCMI_SUCCESS;
230 }
231
232 return 0;
233}
234
235static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
236{
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200237 struct scmi_rd_reset_in *in = NULL;
238 struct scmi_rd_reset_out *out = NULL;
239 struct sandbox_scmi_reset *reset_state = NULL;
240
241 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
242 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
243 return -EINVAL;
244
245 in = (struct scmi_rd_reset_in *)msg->in_msg;
246 out = (struct scmi_rd_reset_out *)msg->out_msg;
247
Etienne Carriere09665cb2022-02-21 09:22:39 +0100248 reset_state = get_scmi_reset_state(in->domain_id);
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200249 if (!reset_state) {
250 dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
251
252 out->status = SCMI_NOT_FOUND;
253 } else if (in->reset_state > 1) {
254 dev_err(dev, "Invalid reset domain input attribute value\n");
255
256 out->status = SCMI_INVALID_PARAMETERS;
257 } else {
258 if (in->flags & SCMI_RD_RESET_FLAG_CYCLE) {
259 if (in->flags & SCMI_RD_RESET_FLAG_ASYNC) {
260 out->status = SCMI_NOT_SUPPORTED;
261 } else {
262 /* Ends deasserted whatever current state */
263 reset_state->asserted = false;
264 out->status = SCMI_SUCCESS;
265 }
266 } else {
267 reset_state->asserted = in->flags &
268 SCMI_RD_RESET_FLAG_ASSERT;
269
270 out->status = SCMI_SUCCESS;
271 }
272 }
273
274 return 0;
275}
276
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100277static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
278{
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100279 struct scmi_voltd_attr_in *in = NULL;
280 struct scmi_voltd_attr_out *out = NULL;
281 struct sandbox_scmi_voltd *voltd_state = NULL;
282
283 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
284 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
285 return -EINVAL;
286
287 in = (struct scmi_voltd_attr_in *)msg->in_msg;
288 out = (struct scmi_voltd_attr_out *)msg->out_msg;
289
Etienne Carriere09665cb2022-02-21 09:22:39 +0100290 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100291 if (!voltd_state) {
292 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
293
294 out->status = SCMI_NOT_FOUND;
295 } else {
296 memset(out, 0, sizeof(*out));
297 snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id);
298
299 out->status = SCMI_SUCCESS;
300 }
301
302 return 0;
303}
304
305static int sandbox_scmi_voltd_config_set(struct udevice *dev,
306 struct scmi_msg *msg)
307{
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100308 struct scmi_voltd_config_set_in *in = NULL;
309 struct scmi_voltd_config_set_out *out = NULL;
310 struct sandbox_scmi_voltd *voltd_state = NULL;
311
312 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
313 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
314 return -EINVAL;
315
316 in = (struct scmi_voltd_config_set_in *)msg->in_msg;
317 out = (struct scmi_voltd_config_set_out *)msg->out_msg;
318
Etienne Carriere09665cb2022-02-21 09:22:39 +0100319 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100320 if (!voltd_state) {
321 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
322
323 out->status = SCMI_NOT_FOUND;
324 } else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) {
325 dev_err(dev, "Invalid config value 0x%x\n", in->config);
326
327 out->status = SCMI_INVALID_PARAMETERS;
328 } else if (in->config != SCMI_VOLTD_CONFIG_ON &&
329 in->config != SCMI_VOLTD_CONFIG_OFF) {
330 dev_err(dev, "Unexpected custom value 0x%x\n", in->config);
331
332 out->status = SCMI_INVALID_PARAMETERS;
333 } else {
334 voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON;
335 out->status = SCMI_SUCCESS;
336 }
337
338 return 0;
339}
340
341static int sandbox_scmi_voltd_config_get(struct udevice *dev,
342 struct scmi_msg *msg)
343{
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100344 struct scmi_voltd_config_get_in *in = NULL;
345 struct scmi_voltd_config_get_out *out = NULL;
346 struct sandbox_scmi_voltd *voltd_state = NULL;
347
348 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
349 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
350 return -EINVAL;
351
352 in = (struct scmi_voltd_config_get_in *)msg->in_msg;
353 out = (struct scmi_voltd_config_get_out *)msg->out_msg;
354
Etienne Carriere09665cb2022-02-21 09:22:39 +0100355 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100356 if (!voltd_state) {
357 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
358
359 out->status = SCMI_NOT_FOUND;
360 } else {
361 if (voltd_state->enabled)
362 out->config = SCMI_VOLTD_CONFIG_ON;
363 else
364 out->config = SCMI_VOLTD_CONFIG_OFF;
365
366 out->status = SCMI_SUCCESS;
367 }
368
369 return 0;
370}
371
372static int sandbox_scmi_voltd_level_set(struct udevice *dev,
373 struct scmi_msg *msg)
374{
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100375 struct scmi_voltd_level_set_in *in = NULL;
376 struct scmi_voltd_level_set_out *out = NULL;
377 struct sandbox_scmi_voltd *voltd_state = NULL;
378
379 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
380 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
381 return -EINVAL;
382
383 in = (struct scmi_voltd_level_set_in *)msg->in_msg;
384 out = (struct scmi_voltd_level_set_out *)msg->out_msg;
385
Etienne Carriere09665cb2022-02-21 09:22:39 +0100386 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100387 if (!voltd_state) {
388 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
389
390 out->status = SCMI_NOT_FOUND;
391 } else {
392 voltd_state->voltage_uv = in->voltage_level;
393 out->status = SCMI_SUCCESS;
394 }
395
396 return 0;
397}
398
399static int sandbox_scmi_voltd_level_get(struct udevice *dev,
400 struct scmi_msg *msg)
401{
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100402 struct scmi_voltd_level_get_in *in = NULL;
403 struct scmi_voltd_level_get_out *out = NULL;
404 struct sandbox_scmi_voltd *voltd_state = NULL;
405
406 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
407 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
408 return -EINVAL;
409
410 in = (struct scmi_voltd_level_get_in *)msg->in_msg;
411 out = (struct scmi_voltd_level_get_out *)msg->out_msg;
412
Etienne Carriere09665cb2022-02-21 09:22:39 +0100413 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100414 if (!voltd_state) {
415 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
416
417 out->status = SCMI_NOT_FOUND;
418 } else {
419 out->voltage_level = voltd_state->voltage_uv;
420 out->status = SCMI_SUCCESS;
421 }
422
423 return 0;
424}
425
Etienne Carriere02fd1262020-09-09 18:44:00 +0200426static int sandbox_scmi_test_process_msg(struct udevice *dev,
427 struct scmi_msg *msg)
428{
429 switch (msg->protocol_id) {
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200430 case SCMI_PROTOCOL_ID_CLOCK:
431 switch (msg->message_id) {
432 case SCMI_CLOCK_RATE_SET:
433 return sandbox_scmi_clock_rate_set(dev, msg);
434 case SCMI_CLOCK_RATE_GET:
435 return sandbox_scmi_clock_rate_get(dev, msg);
436 case SCMI_CLOCK_CONFIG_SET:
437 return sandbox_scmi_clock_gate(dev, msg);
438 default:
439 break;
440 }
441 break;
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200442 case SCMI_PROTOCOL_ID_RESET_DOMAIN:
443 switch (msg->message_id) {
444 case SCMI_RESET_DOMAIN_ATTRIBUTES:
445 return sandbox_scmi_rd_attribs(dev, msg);
446 case SCMI_RESET_DOMAIN_RESET:
447 return sandbox_scmi_rd_reset(dev, msg);
448 default:
449 break;
450 }
451 break;
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100452 case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
453 switch (msg->message_id) {
454 case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES:
455 return sandbox_scmi_voltd_attribs(dev, msg);
456 case SCMI_VOLTAGE_DOMAIN_CONFIG_SET:
457 return sandbox_scmi_voltd_config_set(dev, msg);
458 case SCMI_VOLTAGE_DOMAIN_CONFIG_GET:
459 return sandbox_scmi_voltd_config_get(dev, msg);
460 case SCMI_VOLTAGE_DOMAIN_LEVEL_SET:
461 return sandbox_scmi_voltd_level_set(dev, msg);
462 case SCMI_VOLTAGE_DOMAIN_LEVEL_GET:
463 return sandbox_scmi_voltd_level_get(dev, msg);
464 default:
465 break;
466 }
467 break;
Etienne Carriere02fd1262020-09-09 18:44:00 +0200468 case SCMI_PROTOCOL_ID_BASE:
469 case SCMI_PROTOCOL_ID_POWER_DOMAIN:
470 case SCMI_PROTOCOL_ID_SYSTEM:
471 case SCMI_PROTOCOL_ID_PERF:
Etienne Carriere02fd1262020-09-09 18:44:00 +0200472 case SCMI_PROTOCOL_ID_SENSOR:
Etienne Carriere02fd1262020-09-09 18:44:00 +0200473 *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED;
474 return 0;
475 default:
476 break;
477 }
478
479 dev_err(dev, "%s(%s): Unhandled protocol_id %#x/message_id %#x\n",
480 __func__, dev->name, msg->protocol_id, msg->message_id);
481
482 if (msg->out_msg_sz < sizeof(u32))
483 return -EINVAL;
484
485 /* Intentionnaly report unhandled IDs through the SCMI return code */
486 *(u32 *)msg->out_msg = SCMI_PROTOCOL_ERROR;
487 return 0;
488}
489
490static int sandbox_scmi_test_remove(struct udevice *dev)
491{
492 struct sandbox_scmi_agent *agent = dev_get_priv(dev);
493
Etienne Carriere09665cb2022-02-21 09:22:39 +0100494 if (agent != sandbox_scmi_service_ctx()->agent)
495 return -EINVAL;
496
Etienne Carriere02fd1262020-09-09 18:44:00 +0200497 debug_print_agent_state(dev, "removed");
498
499 /* We only need to dereference the agent in the context */
Etienne Carriere09665cb2022-02-21 09:22:39 +0100500 sandbox_scmi_service_ctx()->agent = NULL;
Etienne Carriere02fd1262020-09-09 18:44:00 +0200501
502 return 0;
503}
504
505static int sandbox_scmi_test_probe(struct udevice *dev)
506{
Etienne Carriere02fd1262020-09-09 18:44:00 +0200507 struct sandbox_scmi_agent *agent = dev_get_priv(dev);
Etienne Carriere02fd1262020-09-09 18:44:00 +0200508
Etienne Carriere09665cb2022-02-21 09:22:39 +0100509 if (sandbox_scmi_service_ctx()->agent)
510 return -EINVAL;
Etienne Carriere02fd1262020-09-09 18:44:00 +0200511
Etienne Carriere09665cb2022-02-21 09:22:39 +0100512 *agent = (struct sandbox_scmi_agent){
513 .clk = scmi_clk,
514 .clk_count = ARRAY_SIZE(scmi_clk),
515 .reset = scmi_reset,
516 .reset_count = ARRAY_SIZE(scmi_reset),
517 .voltd = scmi_voltd,
518 .voltd_count = ARRAY_SIZE(scmi_voltd),
519 };
Etienne Carriere02fd1262020-09-09 18:44:00 +0200520
521 debug_print_agent_state(dev, "probed");
522
523 /* Save reference for tests purpose */
Etienne Carriere09665cb2022-02-21 09:22:39 +0100524 sandbox_scmi_service_ctx()->agent = agent;
Etienne Carriere02fd1262020-09-09 18:44:00 +0200525
526 return 0;
527};
528
529static const struct udevice_id sandbox_scmi_test_ids[] = {
530 { .compatible = "sandbox,scmi-agent" },
531 { }
532};
533
534struct scmi_agent_ops sandbox_scmi_test_ops = {
535 .process_msg = sandbox_scmi_test_process_msg,
536};
537
538U_BOOT_DRIVER(sandbox_scmi_agent) = {
539 .name = "sandbox-scmi_agent",
540 .id = UCLASS_SCMI_AGENT,
541 .of_match = sandbox_scmi_test_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700542 .priv_auto = sizeof(struct sandbox_scmi_agent),
Etienne Carriere02fd1262020-09-09 18:44:00 +0200543 .probe = sandbox_scmi_test_probe,
544 .remove = sandbox_scmi_test_remove,
545 .ops = &sandbox_scmi_test_ops,
546};