blob: fc717a8aeab3549ba04d595a0ad0e182b272e755 [file] [log] [blame]
Etienne Carriere358599e2020-09-09 18:44:00 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020, Linaro Limited
4 */
5
Patrick Delaunay9f5e4aa2021-02-24 11:19:44 +01006#define LOG_CATEGORY UCLASS_SCMI_AGENT
7
Etienne Carriere358599e2020-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 Carriere87d4f272020-09-09 18:44:05 +020021 * SCMI protocols embedded in U-Boot. Currently:
Etienne Carriere41d62e22022-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 Carriere358599e2020-09-09 18:44:00 +020025 *
Etienne Carriere41d62e22022-02-21 09:22:39 +010026 * As per DT bindings, the device node name shall be scmi.
Etienne Carriere87d4f272020-09-09 18:44:05 +020027 *
Etienne Carriere01242182021-03-08 22:38:07 +010028 * All clocks and regulators are default disabled and reset controller down.
Etienne Carriere358599e2020-09-09 18:44:00 +020029 *
Etienne Carriere41d62e22022-02-21 09:22:39 +010030 * This driver exports sandbox_scmi_service_ctx() for the test sequence to
Etienne Carriere358599e2020-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 Carrierec0dd1772020-09-09 18:44:07 +020033 * various uclass devices, as clocks and reset controllers.
Etienne Carriere358599e2020-09-09 18:44:00 +020034 */
35
Etienne Carriere41d62e22022-02-21 09:22:39 +010036static struct sandbox_scmi_clk scmi_clk[] = {
Etienne Carriere10d3e5d2022-02-21 09:22:41 +010037 { .rate = 333 },
38 { .rate = 200 },
39 { .rate = 1000 },
Etienne Carriere87d4f272020-09-09 18:44:05 +020040};
41
Etienne Carriere41d62e22022-02-21 09:22:39 +010042static struct sandbox_scmi_reset scmi_reset[] = {
Etienne Carrierec0dd1772020-09-09 18:44:07 +020043 { .id = 3 },
44};
45
Etienne Carriere41d62e22022-02-21 09:22:39 +010046static struct sandbox_scmi_voltd scmi_voltd[] = {
Etienne Carriere01242182021-03-08 22:38:07 +010047 { .id = 0, .voltage_uv = 3300000 },
48 { .id = 1, .voltage_uv = 1800000 },
49};
50
Etienne Carriere41d62e22022-02-21 09:22:39 +010051static struct sandbox_scmi_service sandbox_scmi_service_state;
Etienne Carriere358599e2020-09-09 18:44:00 +020052
53struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
54{
55 return &sandbox_scmi_service_state;
56}
57
58static void debug_print_agent_state(struct udevice *dev, char *str)
59{
60 struct sandbox_scmi_agent *agent = dev_get_priv(dev);
61
Etienne Carriere41d62e22022-02-21 09:22:39 +010062 dev_dbg(dev, "Dump sandbox_scmi_agent: %s\n", str);
63 dev_dbg(dev, " scmi_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n",
Etienne Carriere87d4f272020-09-09 18:44:05 +020064 agent->clk_count,
65 agent->clk_count ? agent->clk[0].enabled : -1,
66 agent->clk_count ? agent->clk[0].rate : -1,
67 agent->clk_count > 1 ? agent->clk[1].enabled : -1,
68 agent->clk_count > 1 ? agent->clk[1].rate : -1,
69 agent->clk_count > 2 ? agent->clk[2].enabled : -1,
70 agent->clk_count > 2 ? agent->clk[2].rate : -1);
Etienne Carriere41d62e22022-02-21 09:22:39 +010071 dev_dbg(dev, " scmi_reset (%zu): %d, %d, ...\n",
Etienne Carrierec0dd1772020-09-09 18:44:07 +020072 agent->reset_count,
73 agent->reset_count ? agent->reset[0].asserted : -1,
74 agent->reset_count > 1 ? agent->reset[1].asserted : -1);
Etienne Carriere41d62e22022-02-21 09:22:39 +010075 dev_dbg(dev, " scmi_voltd (%zu): %u/%d, %u/%d, ...\n",
Etienne Carriere01242182021-03-08 22:38:07 +010076 agent->voltd_count,
77 agent->voltd_count ? agent->voltd[0].enabled : -1,
78 agent->voltd_count ? agent->voltd[0].voltage_uv : -1,
79 agent->voltd_count ? agent->voltd[1].enabled : -1,
80 agent->voltd_count ? agent->voltd[1].voltage_uv : -1);
Etienne Carriere358599e2020-09-09 18:44:00 +020081};
82
Etienne Carriere41d62e22022-02-21 09:22:39 +010083static struct sandbox_scmi_clk *get_scmi_clk_state(uint clock_id)
Etienne Carriere87d4f272020-09-09 18:44:05 +020084{
Etienne Carriere10d3e5d2022-02-21 09:22:41 +010085 if (clock_id < ARRAY_SIZE(scmi_clk))
86 return scmi_clk + clock_id;
Etienne Carriere87d4f272020-09-09 18:44:05 +020087
88 return NULL;
89}
90
Etienne Carriere41d62e22022-02-21 09:22:39 +010091static struct sandbox_scmi_reset *get_scmi_reset_state(uint reset_id)
Etienne Carrierec0dd1772020-09-09 18:44:07 +020092{
93 size_t n;
94
Etienne Carriere41d62e22022-02-21 09:22:39 +010095 for (n = 0; n < ARRAY_SIZE(scmi_reset); n++)
96 if (scmi_reset[n].id == reset_id)
97 return scmi_reset + n;
Etienne Carrierec0dd1772020-09-09 18:44:07 +020098
99 return NULL;
100}
101
Etienne Carriere41d62e22022-02-21 09:22:39 +0100102static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
Etienne Carriere01242182021-03-08 22:38:07 +0100103{
104 size_t n;
105
Etienne Carriere41d62e22022-02-21 09:22:39 +0100106 for (n = 0; n < ARRAY_SIZE(scmi_voltd); n++)
107 if (scmi_voltd[n].id == domain_id)
108 return scmi_voltd + n;
Etienne Carriere01242182021-03-08 22:38:07 +0100109
110 return NULL;
111}
112
Etienne Carriere87d4f272020-09-09 18:44:05 +0200113/*
114 * Sandbox SCMI agent ops
115 */
116
117static int sandbox_scmi_clock_rate_set(struct udevice *dev,
118 struct scmi_msg *msg)
119{
Etienne Carriere87d4f272020-09-09 18:44:05 +0200120 struct scmi_clk_rate_set_in *in = NULL;
121 struct scmi_clk_rate_set_out *out = NULL;
122 struct sandbox_scmi_clk *clk_state = NULL;
123
124 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
125 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
126 return -EINVAL;
127
128 in = (struct scmi_clk_rate_set_in *)msg->in_msg;
129 out = (struct scmi_clk_rate_set_out *)msg->out_msg;
130
Etienne Carriere41d62e22022-02-21 09:22:39 +0100131 clk_state = get_scmi_clk_state(in->clock_id);
Etienne Carriere87d4f272020-09-09 18:44:05 +0200132 if (!clk_state) {
133 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
134
135 out->status = SCMI_NOT_FOUND;
136 } else {
137 u64 rate = ((u64)in->rate_msb << 32) + in->rate_lsb;
138
139 clk_state->rate = (ulong)rate;
140
141 out->status = SCMI_SUCCESS;
142 }
143
144 return 0;
145}
146
147static int sandbox_scmi_clock_rate_get(struct udevice *dev,
148 struct scmi_msg *msg)
149{
Etienne Carriere87d4f272020-09-09 18:44:05 +0200150 struct scmi_clk_rate_get_in *in = NULL;
151 struct scmi_clk_rate_get_out *out = NULL;
152 struct sandbox_scmi_clk *clk_state = NULL;
153
154 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
155 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
156 return -EINVAL;
157
158 in = (struct scmi_clk_rate_get_in *)msg->in_msg;
159 out = (struct scmi_clk_rate_get_out *)msg->out_msg;
160
Etienne Carriere41d62e22022-02-21 09:22:39 +0100161 clk_state = get_scmi_clk_state(in->clock_id);
Etienne Carriere87d4f272020-09-09 18:44:05 +0200162 if (!clk_state) {
163 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
164
165 out->status = SCMI_NOT_FOUND;
166 } else {
167 out->rate_msb = (u32)((u64)clk_state->rate >> 32);
168 out->rate_lsb = (u32)clk_state->rate;
169
170 out->status = SCMI_SUCCESS;
171 }
172
173 return 0;
174}
175
176static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
177{
Etienne Carriere87d4f272020-09-09 18:44:05 +0200178 struct scmi_clk_state_in *in = NULL;
179 struct scmi_clk_state_out *out = NULL;
180 struct sandbox_scmi_clk *clk_state = NULL;
181
182 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
183 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
184 return -EINVAL;
185
186 in = (struct scmi_clk_state_in *)msg->in_msg;
187 out = (struct scmi_clk_state_out *)msg->out_msg;
188
Etienne Carriere41d62e22022-02-21 09:22:39 +0100189 clk_state = get_scmi_clk_state(in->clock_id);
Etienne Carriere87d4f272020-09-09 18:44:05 +0200190 if (!clk_state) {
191 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
192
193 out->status = SCMI_NOT_FOUND;
194 } else if (in->attributes > 1) {
195 out->status = SCMI_PROTOCOL_ERROR;
196 } else {
197 clk_state->enabled = in->attributes;
198
199 out->status = SCMI_SUCCESS;
200 }
201
202 return 0;
203}
204
Etienne Carrierec0dd1772020-09-09 18:44:07 +0200205static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
206{
Etienne Carrierec0dd1772020-09-09 18:44:07 +0200207 struct scmi_rd_attr_in *in = NULL;
208 struct scmi_rd_attr_out *out = NULL;
209 struct sandbox_scmi_reset *reset_state = NULL;
210
211 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
212 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
213 return -EINVAL;
214
215 in = (struct scmi_rd_attr_in *)msg->in_msg;
216 out = (struct scmi_rd_attr_out *)msg->out_msg;
217
Etienne Carriere41d62e22022-02-21 09:22:39 +0100218 reset_state = get_scmi_reset_state(in->domain_id);
Etienne Carrierec0dd1772020-09-09 18:44:07 +0200219 if (!reset_state) {
220 dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
221
222 out->status = SCMI_NOT_FOUND;
223 } else {
224 memset(out, 0, sizeof(*out));
225 snprintf(out->name, sizeof(out->name), "rd%u", in->domain_id);
226
227 out->status = SCMI_SUCCESS;
228 }
229
230 return 0;
231}
232
233static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
234{
Etienne Carrierec0dd1772020-09-09 18:44:07 +0200235 struct scmi_rd_reset_in *in = NULL;
236 struct scmi_rd_reset_out *out = NULL;
237 struct sandbox_scmi_reset *reset_state = NULL;
238
239 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
240 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
241 return -EINVAL;
242
243 in = (struct scmi_rd_reset_in *)msg->in_msg;
244 out = (struct scmi_rd_reset_out *)msg->out_msg;
245
Etienne Carriere41d62e22022-02-21 09:22:39 +0100246 reset_state = get_scmi_reset_state(in->domain_id);
Etienne Carrierec0dd1772020-09-09 18:44:07 +0200247 if (!reset_state) {
248 dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
249
250 out->status = SCMI_NOT_FOUND;
251 } else if (in->reset_state > 1) {
252 dev_err(dev, "Invalid reset domain input attribute value\n");
253
254 out->status = SCMI_INVALID_PARAMETERS;
255 } else {
256 if (in->flags & SCMI_RD_RESET_FLAG_CYCLE) {
257 if (in->flags & SCMI_RD_RESET_FLAG_ASYNC) {
258 out->status = SCMI_NOT_SUPPORTED;
259 } else {
260 /* Ends deasserted whatever current state */
261 reset_state->asserted = false;
262 out->status = SCMI_SUCCESS;
263 }
264 } else {
265 reset_state->asserted = in->flags &
266 SCMI_RD_RESET_FLAG_ASSERT;
267
268 out->status = SCMI_SUCCESS;
269 }
270 }
271
272 return 0;
273}
274
Etienne Carriere01242182021-03-08 22:38:07 +0100275static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
276{
Etienne Carriere01242182021-03-08 22:38:07 +0100277 struct scmi_voltd_attr_in *in = NULL;
278 struct scmi_voltd_attr_out *out = NULL;
279 struct sandbox_scmi_voltd *voltd_state = NULL;
280
281 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
282 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
283 return -EINVAL;
284
285 in = (struct scmi_voltd_attr_in *)msg->in_msg;
286 out = (struct scmi_voltd_attr_out *)msg->out_msg;
287
Etienne Carriere41d62e22022-02-21 09:22:39 +0100288 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriere01242182021-03-08 22:38:07 +0100289 if (!voltd_state) {
290 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
291
292 out->status = SCMI_NOT_FOUND;
293 } else {
294 memset(out, 0, sizeof(*out));
295 snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id);
296
297 out->status = SCMI_SUCCESS;
298 }
299
300 return 0;
301}
302
303static int sandbox_scmi_voltd_config_set(struct udevice *dev,
304 struct scmi_msg *msg)
305{
Etienne Carriere01242182021-03-08 22:38:07 +0100306 struct scmi_voltd_config_set_in *in = NULL;
307 struct scmi_voltd_config_set_out *out = NULL;
308 struct sandbox_scmi_voltd *voltd_state = NULL;
309
310 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
311 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
312 return -EINVAL;
313
314 in = (struct scmi_voltd_config_set_in *)msg->in_msg;
315 out = (struct scmi_voltd_config_set_out *)msg->out_msg;
316
Etienne Carriere41d62e22022-02-21 09:22:39 +0100317 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriere01242182021-03-08 22:38:07 +0100318 if (!voltd_state) {
319 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
320
321 out->status = SCMI_NOT_FOUND;
322 } else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) {
323 dev_err(dev, "Invalid config value 0x%x\n", in->config);
324
325 out->status = SCMI_INVALID_PARAMETERS;
326 } else if (in->config != SCMI_VOLTD_CONFIG_ON &&
327 in->config != SCMI_VOLTD_CONFIG_OFF) {
328 dev_err(dev, "Unexpected custom value 0x%x\n", in->config);
329
330 out->status = SCMI_INVALID_PARAMETERS;
331 } else {
332 voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON;
333 out->status = SCMI_SUCCESS;
334 }
335
336 return 0;
337}
338
339static int sandbox_scmi_voltd_config_get(struct udevice *dev,
340 struct scmi_msg *msg)
341{
Etienne Carriere01242182021-03-08 22:38:07 +0100342 struct scmi_voltd_config_get_in *in = NULL;
343 struct scmi_voltd_config_get_out *out = NULL;
344 struct sandbox_scmi_voltd *voltd_state = NULL;
345
346 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
347 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
348 return -EINVAL;
349
350 in = (struct scmi_voltd_config_get_in *)msg->in_msg;
351 out = (struct scmi_voltd_config_get_out *)msg->out_msg;
352
Etienne Carriere41d62e22022-02-21 09:22:39 +0100353 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriere01242182021-03-08 22:38:07 +0100354 if (!voltd_state) {
355 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
356
357 out->status = SCMI_NOT_FOUND;
358 } else {
359 if (voltd_state->enabled)
360 out->config = SCMI_VOLTD_CONFIG_ON;
361 else
362 out->config = SCMI_VOLTD_CONFIG_OFF;
363
364 out->status = SCMI_SUCCESS;
365 }
366
367 return 0;
368}
369
370static int sandbox_scmi_voltd_level_set(struct udevice *dev,
371 struct scmi_msg *msg)
372{
Etienne Carriere01242182021-03-08 22:38:07 +0100373 struct scmi_voltd_level_set_in *in = NULL;
374 struct scmi_voltd_level_set_out *out = NULL;
375 struct sandbox_scmi_voltd *voltd_state = NULL;
376
377 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
378 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
379 return -EINVAL;
380
381 in = (struct scmi_voltd_level_set_in *)msg->in_msg;
382 out = (struct scmi_voltd_level_set_out *)msg->out_msg;
383
Etienne Carriere41d62e22022-02-21 09:22:39 +0100384 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriere01242182021-03-08 22:38:07 +0100385 if (!voltd_state) {
386 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
387
388 out->status = SCMI_NOT_FOUND;
389 } else {
390 voltd_state->voltage_uv = in->voltage_level;
391 out->status = SCMI_SUCCESS;
392 }
393
394 return 0;
395}
396
397static int sandbox_scmi_voltd_level_get(struct udevice *dev,
398 struct scmi_msg *msg)
399{
Etienne Carriere01242182021-03-08 22:38:07 +0100400 struct scmi_voltd_level_get_in *in = NULL;
401 struct scmi_voltd_level_get_out *out = NULL;
402 struct sandbox_scmi_voltd *voltd_state = NULL;
403
404 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
405 !msg->out_msg || msg->out_msg_sz < sizeof(*out))
406 return -EINVAL;
407
408 in = (struct scmi_voltd_level_get_in *)msg->in_msg;
409 out = (struct scmi_voltd_level_get_out *)msg->out_msg;
410
Etienne Carriere41d62e22022-02-21 09:22:39 +0100411 voltd_state = get_scmi_voltd_state(in->domain_id);
Etienne Carriere01242182021-03-08 22:38:07 +0100412 if (!voltd_state) {
413 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
414
415 out->status = SCMI_NOT_FOUND;
416 } else {
417 out->voltage_level = voltd_state->voltage_uv;
418 out->status = SCMI_SUCCESS;
419 }
420
421 return 0;
422}
423
Etienne Carriere358599e2020-09-09 18:44:00 +0200424static int sandbox_scmi_test_process_msg(struct udevice *dev,
425 struct scmi_msg *msg)
426{
427 switch (msg->protocol_id) {
Etienne Carriere87d4f272020-09-09 18:44:05 +0200428 case SCMI_PROTOCOL_ID_CLOCK:
429 switch (msg->message_id) {
430 case SCMI_CLOCK_RATE_SET:
431 return sandbox_scmi_clock_rate_set(dev, msg);
432 case SCMI_CLOCK_RATE_GET:
433 return sandbox_scmi_clock_rate_get(dev, msg);
434 case SCMI_CLOCK_CONFIG_SET:
435 return sandbox_scmi_clock_gate(dev, msg);
436 default:
437 break;
438 }
439 break;
Etienne Carrierec0dd1772020-09-09 18:44:07 +0200440 case SCMI_PROTOCOL_ID_RESET_DOMAIN:
441 switch (msg->message_id) {
442 case SCMI_RESET_DOMAIN_ATTRIBUTES:
443 return sandbox_scmi_rd_attribs(dev, msg);
444 case SCMI_RESET_DOMAIN_RESET:
445 return sandbox_scmi_rd_reset(dev, msg);
446 default:
447 break;
448 }
449 break;
Etienne Carriere01242182021-03-08 22:38:07 +0100450 case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
451 switch (msg->message_id) {
452 case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES:
453 return sandbox_scmi_voltd_attribs(dev, msg);
454 case SCMI_VOLTAGE_DOMAIN_CONFIG_SET:
455 return sandbox_scmi_voltd_config_set(dev, msg);
456 case SCMI_VOLTAGE_DOMAIN_CONFIG_GET:
457 return sandbox_scmi_voltd_config_get(dev, msg);
458 case SCMI_VOLTAGE_DOMAIN_LEVEL_SET:
459 return sandbox_scmi_voltd_level_set(dev, msg);
460 case SCMI_VOLTAGE_DOMAIN_LEVEL_GET:
461 return sandbox_scmi_voltd_level_get(dev, msg);
462 default:
463 break;
464 }
465 break;
Etienne Carriere358599e2020-09-09 18:44:00 +0200466 case SCMI_PROTOCOL_ID_BASE:
467 case SCMI_PROTOCOL_ID_POWER_DOMAIN:
468 case SCMI_PROTOCOL_ID_SYSTEM:
469 case SCMI_PROTOCOL_ID_PERF:
Etienne Carriere358599e2020-09-09 18:44:00 +0200470 case SCMI_PROTOCOL_ID_SENSOR:
Etienne Carriere358599e2020-09-09 18:44:00 +0200471 *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED;
472 return 0;
473 default:
474 break;
475 }
476
477 dev_err(dev, "%s(%s): Unhandled protocol_id %#x/message_id %#x\n",
478 __func__, dev->name, msg->protocol_id, msg->message_id);
479
480 if (msg->out_msg_sz < sizeof(u32))
481 return -EINVAL;
482
483 /* Intentionnaly report unhandled IDs through the SCMI return code */
484 *(u32 *)msg->out_msg = SCMI_PROTOCOL_ERROR;
485 return 0;
486}
487
488static int sandbox_scmi_test_remove(struct udevice *dev)
489{
490 struct sandbox_scmi_agent *agent = dev_get_priv(dev);
491
Etienne Carriere41d62e22022-02-21 09:22:39 +0100492 if (agent != sandbox_scmi_service_ctx()->agent)
493 return -EINVAL;
494
Etienne Carriere358599e2020-09-09 18:44:00 +0200495 debug_print_agent_state(dev, "removed");
496
497 /* We only need to dereference the agent in the context */
Etienne Carriere41d62e22022-02-21 09:22:39 +0100498 sandbox_scmi_service_ctx()->agent = NULL;
Etienne Carriere358599e2020-09-09 18:44:00 +0200499
500 return 0;
501}
502
503static int sandbox_scmi_test_probe(struct udevice *dev)
504{
Etienne Carriere358599e2020-09-09 18:44:00 +0200505 struct sandbox_scmi_agent *agent = dev_get_priv(dev);
Etienne Carriere358599e2020-09-09 18:44:00 +0200506
Etienne Carriere41d62e22022-02-21 09:22:39 +0100507 if (sandbox_scmi_service_ctx()->agent)
508 return -EINVAL;
Etienne Carriere358599e2020-09-09 18:44:00 +0200509
Etienne Carriere41d62e22022-02-21 09:22:39 +0100510 *agent = (struct sandbox_scmi_agent){
511 .clk = scmi_clk,
512 .clk_count = ARRAY_SIZE(scmi_clk),
513 .reset = scmi_reset,
514 .reset_count = ARRAY_SIZE(scmi_reset),
515 .voltd = scmi_voltd,
516 .voltd_count = ARRAY_SIZE(scmi_voltd),
517 };
Etienne Carriere358599e2020-09-09 18:44:00 +0200518
519 debug_print_agent_state(dev, "probed");
520
521 /* Save reference for tests purpose */
Etienne Carriere41d62e22022-02-21 09:22:39 +0100522 sandbox_scmi_service_ctx()->agent = agent;
Etienne Carriere358599e2020-09-09 18:44:00 +0200523
524 return 0;
525};
526
527static const struct udevice_id sandbox_scmi_test_ids[] = {
528 { .compatible = "sandbox,scmi-agent" },
529 { }
530};
531
532struct scmi_agent_ops sandbox_scmi_test_ops = {
533 .process_msg = sandbox_scmi_test_process_msg,
534};
535
536U_BOOT_DRIVER(sandbox_scmi_agent) = {
537 .name = "sandbox-scmi_agent",
538 .id = UCLASS_SCMI_AGENT,
539 .of_match = sandbox_scmi_test_ids,
Simon Glass41575d82020-12-03 16:55:17 -0700540 .priv_auto = sizeof(struct sandbox_scmi_agent),
Etienne Carriere358599e2020-09-09 18:44:00 +0200541 .probe = sandbox_scmi_test_probe,
542 .remove = sandbox_scmi_test_remove,
543 .ops = &sandbox_scmi_test_ops,
544};