sandbox-scmi_agent.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020, Linaro Limited
  4. */
  5. #define LOG_CATEGORY UCLASS_SCMI_AGENT
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <malloc.h>
  9. #include <scmi_agent.h>
  10. #include <scmi_agent-uclass.h>
  11. #include <scmi_protocols.h>
  12. #include <asm/io.h>
  13. #include <asm/scmi_test.h>
  14. #include <dm/device_compat.h>
  15. /*
  16. * The sandbox SCMI agent driver simulates to some extend a SCMI message
  17. * processing. It simulates few of the SCMI services for some of the
  18. * SCMI protocols embedded in U-Boot. Currently:
  19. * - SCMI clock protocol emulates an agent exposing 2 clocks
  20. * - SCMI reset protocol emulates an agent exposing a reset controller
  21. * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
  22. *
  23. * As per DT bindings, the device node name shall be scmi.
  24. *
  25. * All clocks and regulators are default disabled and reset controller down.
  26. *
  27. * This driver exports sandbox_scmi_service_ctx() for the test sequence to
  28. * get the state of the simulated services (clock state, rate, ...) and
  29. * check back-end device state reflects the request send through the
  30. * various uclass devices, as clocks and reset controllers.
  31. */
  32. static struct sandbox_scmi_clk scmi_clk[] = {
  33. { .rate = 333 },
  34. { .rate = 200 },
  35. { .rate = 1000 },
  36. };
  37. static struct sandbox_scmi_reset scmi_reset[] = {
  38. { .id = 3 },
  39. };
  40. static struct sandbox_scmi_voltd scmi_voltd[] = {
  41. { .id = 0, .voltage_uv = 3300000 },
  42. { .id = 1, .voltage_uv = 1800000 },
  43. };
  44. static struct sandbox_scmi_service sandbox_scmi_service_state;
  45. struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
  46. {
  47. return &sandbox_scmi_service_state;
  48. }
  49. static void debug_print_agent_state(struct udevice *dev, char *str)
  50. {
  51. struct sandbox_scmi_agent *agent = dev_get_priv(dev);
  52. dev_dbg(dev, "Dump sandbox_scmi_agent: %s\n", str);
  53. dev_dbg(dev, " scmi_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n",
  54. agent->clk_count,
  55. agent->clk_count ? agent->clk[0].enabled : -1,
  56. agent->clk_count ? agent->clk[0].rate : -1,
  57. agent->clk_count > 1 ? agent->clk[1].enabled : -1,
  58. agent->clk_count > 1 ? agent->clk[1].rate : -1,
  59. agent->clk_count > 2 ? agent->clk[2].enabled : -1,
  60. agent->clk_count > 2 ? agent->clk[2].rate : -1);
  61. dev_dbg(dev, " scmi_reset (%zu): %d, %d, ...\n",
  62. agent->reset_count,
  63. agent->reset_count ? agent->reset[0].asserted : -1,
  64. agent->reset_count > 1 ? agent->reset[1].asserted : -1);
  65. dev_dbg(dev, " scmi_voltd (%zu): %u/%d, %u/%d, ...\n",
  66. agent->voltd_count,
  67. agent->voltd_count ? agent->voltd[0].enabled : -1,
  68. agent->voltd_count ? agent->voltd[0].voltage_uv : -1,
  69. agent->voltd_count ? agent->voltd[1].enabled : -1,
  70. agent->voltd_count ? agent->voltd[1].voltage_uv : -1);
  71. };
  72. static struct sandbox_scmi_clk *get_scmi_clk_state(uint clock_id)
  73. {
  74. if (clock_id < ARRAY_SIZE(scmi_clk))
  75. return scmi_clk + clock_id;
  76. return NULL;
  77. }
  78. static struct sandbox_scmi_reset *get_scmi_reset_state(uint reset_id)
  79. {
  80. size_t n;
  81. for (n = 0; n < ARRAY_SIZE(scmi_reset); n++)
  82. if (scmi_reset[n].id == reset_id)
  83. return scmi_reset + n;
  84. return NULL;
  85. }
  86. static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
  87. {
  88. size_t n;
  89. for (n = 0; n < ARRAY_SIZE(scmi_voltd); n++)
  90. if (scmi_voltd[n].id == domain_id)
  91. return scmi_voltd + n;
  92. return NULL;
  93. }
  94. /*
  95. * Sandbox SCMI agent ops
  96. */
  97. static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
  98. struct scmi_msg *msg)
  99. {
  100. struct scmi_clk_protocol_attr_out *out = NULL;
  101. if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
  102. return -EINVAL;
  103. out = (struct scmi_clk_protocol_attr_out *)msg->out_msg;
  104. out->attributes = ARRAY_SIZE(scmi_clk);
  105. out->status = SCMI_SUCCESS;
  106. return 0;
  107. }
  108. static int sandbox_scmi_clock_attribs(struct udevice *dev, struct scmi_msg *msg)
  109. {
  110. struct scmi_clk_attribute_in *in = NULL;
  111. struct scmi_clk_attribute_out *out = NULL;
  112. struct sandbox_scmi_clk *clk_state = NULL;
  113. int ret;
  114. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  115. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  116. return -EINVAL;
  117. in = (struct scmi_clk_attribute_in *)msg->in_msg;
  118. out = (struct scmi_clk_attribute_out *)msg->out_msg;
  119. clk_state = get_scmi_clk_state(in->clock_id);
  120. if (!clk_state) {
  121. dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
  122. out->status = SCMI_NOT_FOUND;
  123. } else {
  124. memset(out, 0, sizeof(*out));
  125. if (clk_state->enabled)
  126. out->attributes = 1;
  127. ret = snprintf(out->clock_name, sizeof(out->clock_name),
  128. "clk%u", in->clock_id);
  129. assert(ret > 0 && ret < sizeof(out->clock_name));
  130. out->status = SCMI_SUCCESS;
  131. }
  132. return 0;
  133. }
  134. static int sandbox_scmi_clock_rate_set(struct udevice *dev,
  135. struct scmi_msg *msg)
  136. {
  137. struct scmi_clk_rate_set_in *in = NULL;
  138. struct scmi_clk_rate_set_out *out = NULL;
  139. struct sandbox_scmi_clk *clk_state = NULL;
  140. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  141. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  142. return -EINVAL;
  143. in = (struct scmi_clk_rate_set_in *)msg->in_msg;
  144. out = (struct scmi_clk_rate_set_out *)msg->out_msg;
  145. clk_state = get_scmi_clk_state(in->clock_id);
  146. if (!clk_state) {
  147. dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
  148. out->status = SCMI_NOT_FOUND;
  149. } else {
  150. u64 rate = ((u64)in->rate_msb << 32) + in->rate_lsb;
  151. clk_state->rate = (ulong)rate;
  152. out->status = SCMI_SUCCESS;
  153. }
  154. return 0;
  155. }
  156. static int sandbox_scmi_clock_rate_get(struct udevice *dev,
  157. struct scmi_msg *msg)
  158. {
  159. struct scmi_clk_rate_get_in *in = NULL;
  160. struct scmi_clk_rate_get_out *out = NULL;
  161. struct sandbox_scmi_clk *clk_state = NULL;
  162. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  163. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  164. return -EINVAL;
  165. in = (struct scmi_clk_rate_get_in *)msg->in_msg;
  166. out = (struct scmi_clk_rate_get_out *)msg->out_msg;
  167. clk_state = get_scmi_clk_state(in->clock_id);
  168. if (!clk_state) {
  169. dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
  170. out->status = SCMI_NOT_FOUND;
  171. } else {
  172. out->rate_msb = (u32)((u64)clk_state->rate >> 32);
  173. out->rate_lsb = (u32)clk_state->rate;
  174. out->status = SCMI_SUCCESS;
  175. }
  176. return 0;
  177. }
  178. static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
  179. {
  180. struct scmi_clk_state_in *in = NULL;
  181. struct scmi_clk_state_out *out = NULL;
  182. struct sandbox_scmi_clk *clk_state = NULL;
  183. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  184. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  185. return -EINVAL;
  186. in = (struct scmi_clk_state_in *)msg->in_msg;
  187. out = (struct scmi_clk_state_out *)msg->out_msg;
  188. clk_state = get_scmi_clk_state(in->clock_id);
  189. if (!clk_state) {
  190. dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
  191. out->status = SCMI_NOT_FOUND;
  192. } else if (in->attributes > 1) {
  193. out->status = SCMI_PROTOCOL_ERROR;
  194. } else {
  195. clk_state->enabled = in->attributes;
  196. out->status = SCMI_SUCCESS;
  197. }
  198. return 0;
  199. }
  200. static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
  201. {
  202. struct scmi_rd_attr_in *in = NULL;
  203. struct scmi_rd_attr_out *out = NULL;
  204. struct sandbox_scmi_reset *reset_state = NULL;
  205. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  206. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  207. return -EINVAL;
  208. in = (struct scmi_rd_attr_in *)msg->in_msg;
  209. out = (struct scmi_rd_attr_out *)msg->out_msg;
  210. reset_state = get_scmi_reset_state(in->domain_id);
  211. if (!reset_state) {
  212. dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
  213. out->status = SCMI_NOT_FOUND;
  214. } else {
  215. memset(out, 0, sizeof(*out));
  216. snprintf(out->name, sizeof(out->name), "rd%u", in->domain_id);
  217. out->status = SCMI_SUCCESS;
  218. }
  219. return 0;
  220. }
  221. static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
  222. {
  223. struct scmi_rd_reset_in *in = NULL;
  224. struct scmi_rd_reset_out *out = NULL;
  225. struct sandbox_scmi_reset *reset_state = NULL;
  226. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  227. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  228. return -EINVAL;
  229. in = (struct scmi_rd_reset_in *)msg->in_msg;
  230. out = (struct scmi_rd_reset_out *)msg->out_msg;
  231. reset_state = get_scmi_reset_state(in->domain_id);
  232. if (!reset_state) {
  233. dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
  234. out->status = SCMI_NOT_FOUND;
  235. } else if (in->reset_state > 1) {
  236. dev_err(dev, "Invalid reset domain input attribute value\n");
  237. out->status = SCMI_INVALID_PARAMETERS;
  238. } else {
  239. if (in->flags & SCMI_RD_RESET_FLAG_CYCLE) {
  240. if (in->flags & SCMI_RD_RESET_FLAG_ASYNC) {
  241. out->status = SCMI_NOT_SUPPORTED;
  242. } else {
  243. /* Ends deasserted whatever current state */
  244. reset_state->asserted = false;
  245. out->status = SCMI_SUCCESS;
  246. }
  247. } else {
  248. reset_state->asserted = in->flags &
  249. SCMI_RD_RESET_FLAG_ASSERT;
  250. out->status = SCMI_SUCCESS;
  251. }
  252. }
  253. return 0;
  254. }
  255. static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
  256. {
  257. struct scmi_voltd_attr_in *in = NULL;
  258. struct scmi_voltd_attr_out *out = NULL;
  259. struct sandbox_scmi_voltd *voltd_state = NULL;
  260. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  261. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  262. return -EINVAL;
  263. in = (struct scmi_voltd_attr_in *)msg->in_msg;
  264. out = (struct scmi_voltd_attr_out *)msg->out_msg;
  265. voltd_state = get_scmi_voltd_state(in->domain_id);
  266. if (!voltd_state) {
  267. dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
  268. out->status = SCMI_NOT_FOUND;
  269. } else {
  270. memset(out, 0, sizeof(*out));
  271. snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id);
  272. out->status = SCMI_SUCCESS;
  273. }
  274. return 0;
  275. }
  276. static int sandbox_scmi_voltd_config_set(struct udevice *dev,
  277. struct scmi_msg *msg)
  278. {
  279. struct scmi_voltd_config_set_in *in = NULL;
  280. struct scmi_voltd_config_set_out *out = NULL;
  281. struct sandbox_scmi_voltd *voltd_state = NULL;
  282. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  283. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  284. return -EINVAL;
  285. in = (struct scmi_voltd_config_set_in *)msg->in_msg;
  286. out = (struct scmi_voltd_config_set_out *)msg->out_msg;
  287. voltd_state = get_scmi_voltd_state(in->domain_id);
  288. if (!voltd_state) {
  289. dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
  290. out->status = SCMI_NOT_FOUND;
  291. } else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) {
  292. dev_err(dev, "Invalid config value 0x%x\n", in->config);
  293. out->status = SCMI_INVALID_PARAMETERS;
  294. } else if (in->config != SCMI_VOLTD_CONFIG_ON &&
  295. in->config != SCMI_VOLTD_CONFIG_OFF) {
  296. dev_err(dev, "Unexpected custom value 0x%x\n", in->config);
  297. out->status = SCMI_INVALID_PARAMETERS;
  298. } else {
  299. voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON;
  300. out->status = SCMI_SUCCESS;
  301. }
  302. return 0;
  303. }
  304. static int sandbox_scmi_voltd_config_get(struct udevice *dev,
  305. struct scmi_msg *msg)
  306. {
  307. struct scmi_voltd_config_get_in *in = NULL;
  308. struct scmi_voltd_config_get_out *out = NULL;
  309. struct sandbox_scmi_voltd *voltd_state = NULL;
  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. in = (struct scmi_voltd_config_get_in *)msg->in_msg;
  314. out = (struct scmi_voltd_config_get_out *)msg->out_msg;
  315. voltd_state = get_scmi_voltd_state(in->domain_id);
  316. if (!voltd_state) {
  317. dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
  318. out->status = SCMI_NOT_FOUND;
  319. } else {
  320. if (voltd_state->enabled)
  321. out->config = SCMI_VOLTD_CONFIG_ON;
  322. else
  323. out->config = SCMI_VOLTD_CONFIG_OFF;
  324. out->status = SCMI_SUCCESS;
  325. }
  326. return 0;
  327. }
  328. static int sandbox_scmi_voltd_level_set(struct udevice *dev,
  329. struct scmi_msg *msg)
  330. {
  331. struct scmi_voltd_level_set_in *in = NULL;
  332. struct scmi_voltd_level_set_out *out = NULL;
  333. struct sandbox_scmi_voltd *voltd_state = NULL;
  334. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  335. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  336. return -EINVAL;
  337. in = (struct scmi_voltd_level_set_in *)msg->in_msg;
  338. out = (struct scmi_voltd_level_set_out *)msg->out_msg;
  339. voltd_state = get_scmi_voltd_state(in->domain_id);
  340. if (!voltd_state) {
  341. dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
  342. out->status = SCMI_NOT_FOUND;
  343. } else {
  344. voltd_state->voltage_uv = in->voltage_level;
  345. out->status = SCMI_SUCCESS;
  346. }
  347. return 0;
  348. }
  349. static int sandbox_scmi_voltd_level_get(struct udevice *dev,
  350. struct scmi_msg *msg)
  351. {
  352. struct scmi_voltd_level_get_in *in = NULL;
  353. struct scmi_voltd_level_get_out *out = NULL;
  354. struct sandbox_scmi_voltd *voltd_state = NULL;
  355. if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
  356. !msg->out_msg || msg->out_msg_sz < sizeof(*out))
  357. return -EINVAL;
  358. in = (struct scmi_voltd_level_get_in *)msg->in_msg;
  359. out = (struct scmi_voltd_level_get_out *)msg->out_msg;
  360. voltd_state = get_scmi_voltd_state(in->domain_id);
  361. if (!voltd_state) {
  362. dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
  363. out->status = SCMI_NOT_FOUND;
  364. } else {
  365. out->voltage_level = voltd_state->voltage_uv;
  366. out->status = SCMI_SUCCESS;
  367. }
  368. return 0;
  369. }
  370. static int sandbox_scmi_test_process_msg(struct udevice *dev,
  371. struct scmi_channel *channel,
  372. struct scmi_msg *msg)
  373. {
  374. switch (msg->protocol_id) {
  375. case SCMI_PROTOCOL_ID_CLOCK:
  376. switch (msg->message_id) {
  377. case SCMI_PROTOCOL_ATTRIBUTES:
  378. return sandbox_scmi_clock_protocol_attribs(dev, msg);
  379. case SCMI_CLOCK_ATTRIBUTES:
  380. return sandbox_scmi_clock_attribs(dev, msg);
  381. case SCMI_CLOCK_RATE_SET:
  382. return sandbox_scmi_clock_rate_set(dev, msg);
  383. case SCMI_CLOCK_RATE_GET:
  384. return sandbox_scmi_clock_rate_get(dev, msg);
  385. case SCMI_CLOCK_CONFIG_SET:
  386. return sandbox_scmi_clock_gate(dev, msg);
  387. default:
  388. break;
  389. }
  390. break;
  391. case SCMI_PROTOCOL_ID_RESET_DOMAIN:
  392. switch (msg->message_id) {
  393. case SCMI_RESET_DOMAIN_ATTRIBUTES:
  394. return sandbox_scmi_rd_attribs(dev, msg);
  395. case SCMI_RESET_DOMAIN_RESET:
  396. return sandbox_scmi_rd_reset(dev, msg);
  397. default:
  398. break;
  399. }
  400. break;
  401. case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
  402. switch (msg->message_id) {
  403. case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES:
  404. return sandbox_scmi_voltd_attribs(dev, msg);
  405. case SCMI_VOLTAGE_DOMAIN_CONFIG_SET:
  406. return sandbox_scmi_voltd_config_set(dev, msg);
  407. case SCMI_VOLTAGE_DOMAIN_CONFIG_GET:
  408. return sandbox_scmi_voltd_config_get(dev, msg);
  409. case SCMI_VOLTAGE_DOMAIN_LEVEL_SET:
  410. return sandbox_scmi_voltd_level_set(dev, msg);
  411. case SCMI_VOLTAGE_DOMAIN_LEVEL_GET:
  412. return sandbox_scmi_voltd_level_get(dev, msg);
  413. default:
  414. break;
  415. }
  416. break;
  417. case SCMI_PROTOCOL_ID_BASE:
  418. case SCMI_PROTOCOL_ID_POWER_DOMAIN:
  419. case SCMI_PROTOCOL_ID_SYSTEM:
  420. case SCMI_PROTOCOL_ID_PERF:
  421. case SCMI_PROTOCOL_ID_SENSOR:
  422. *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED;
  423. return 0;
  424. default:
  425. break;
  426. }
  427. dev_err(dev, "%s(%s): Unhandled protocol_id %#x/message_id %#x\n",
  428. __func__, dev->name, msg->protocol_id, msg->message_id);
  429. if (msg->out_msg_sz < sizeof(u32))
  430. return -EINVAL;
  431. /* Intentionnaly report unhandled IDs through the SCMI return code */
  432. *(u32 *)msg->out_msg = SCMI_PROTOCOL_ERROR;
  433. return 0;
  434. }
  435. static int sandbox_scmi_test_remove(struct udevice *dev)
  436. {
  437. struct sandbox_scmi_agent *agent = dev_get_priv(dev);
  438. if (agent != sandbox_scmi_service_ctx()->agent)
  439. return -EINVAL;
  440. debug_print_agent_state(dev, "removed");
  441. /* We only need to dereference the agent in the context */
  442. sandbox_scmi_service_ctx()->agent = NULL;
  443. return 0;
  444. }
  445. static int sandbox_scmi_test_probe(struct udevice *dev)
  446. {
  447. struct sandbox_scmi_agent *agent = dev_get_priv(dev);
  448. if (sandbox_scmi_service_ctx()->agent)
  449. return -EINVAL;
  450. *agent = (struct sandbox_scmi_agent){
  451. .clk = scmi_clk,
  452. .clk_count = ARRAY_SIZE(scmi_clk),
  453. .reset = scmi_reset,
  454. .reset_count = ARRAY_SIZE(scmi_reset),
  455. .voltd = scmi_voltd,
  456. .voltd_count = ARRAY_SIZE(scmi_voltd),
  457. };
  458. debug_print_agent_state(dev, "probed");
  459. /* Save reference for tests purpose */
  460. sandbox_scmi_service_ctx()->agent = agent;
  461. return 0;
  462. };
  463. static const struct udevice_id sandbox_scmi_test_ids[] = {
  464. { .compatible = "sandbox,scmi-agent" },
  465. { }
  466. };
  467. struct scmi_agent_ops sandbox_scmi_test_ops = {
  468. .process_msg = sandbox_scmi_test_process_msg,
  469. };
  470. U_BOOT_DRIVER(sandbox_scmi_agent) = {
  471. .name = "sandbox-scmi_agent",
  472. .id = UCLASS_SCMI_AGENT,
  473. .of_match = sandbox_scmi_test_ids,
  474. .priv_auto = sizeof(struct sandbox_scmi_agent),
  475. .probe = sandbox_scmi_test_probe,
  476. .remove = sandbox_scmi_test_remove,
  477. .ops = &sandbox_scmi_test_ops,
  478. };