sandbox-scmi_agent.c 17 KB

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