1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2020, Linaro Limited 4 */ 5 6#define LOG_CATEGORY UCLASS_SCMI_AGENT 7 8#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#include <linux/bitfield.h> 18#include <linux/kernel.h> 19 20/* 21 * The sandbox SCMI agent driver simulates to some extend a SCMI message 22 * processing. It simulates few of the SCMI services for some of the 23 * SCMI protocols embedded in U-Boot. Currently: 24 * - SCMI base protocol 25 * - SCMI clock protocol emulates an agent exposing 2 clocks 26 * - SCMI reset protocol emulates an agent exposing a reset controller 27 * - SCMI voltage domain protocol emulates an agent exposing 2 regulators 28 * 29 * As per DT bindings, the device node name shall be scmi. 30 * 31 * All clocks and regulators are default disabled and reset controller down. 32 * 33 * This driver exports sandbox_scmi_service_ctx() for the test sequence to 34 * get the state of the simulated services (clock state, rate, ...) and 35 * check back-end device state reflects the request send through the 36 * various uclass devices, as clocks and reset controllers. 37 */ 38 39#define SANDBOX_SCMI_BASE_PROTOCOL_VERSION SCMI_BASE_PROTOCOL_VERSION 40#define SANDBOX_SCMI_VENDOR "U-Boot" 41#define SANDBOX_SCMI_SUB_VENDOR "Sandbox" 42#define SANDBOX_SCMI_IMPL_VERSION 0x1 43#define SANDBOX_SCMI_AGENT_NAME "OSPM" 44#define SANDBOX_SCMI_PLATFORM_NAME "platform" 45 46#define SANDBOX_SCMI_PWD_PROTOCOL_VERSION SCMI_PWD_PROTOCOL_VERSION 47 48/** 49 * struct sandbox_channel - Description of sandbox transport 50 * @channel_id: Channel identifier 51 * 52 * Dummy channel. This will be used to test if a protocol-specific 53 * channel is properly used. 54 * Id 0 means a channel for the sandbox agent. 55 */ 56struct sandbox_channel { 57 unsigned int channel_id; 58}; 59 60/** 61 * struct scmi_channel - Channel instance referenced in SCMI drivers 62 * @ref: Reference to local channel instance 63 **/ 64struct scmi_channel { 65 struct sandbox_channel ref; 66}; 67 68static u8 protocols[] = { 69 CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN, (SCMI_PROTOCOL_ID_POWER_DOMAIN,)) 70 CONFIG_IS_ENABLED(CLK_SCMI, (SCMI_PROTOCOL_ID_CLOCK,)) 71 CONFIG_IS_ENABLED(RESET_SCMI, (SCMI_PROTOCOL_ID_RESET_DOMAIN,)) 72 CONFIG_IS_ENABLED(DM_REGULATOR_SCMI, (SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,)) 73}; 74 75#define NUM_PROTOCOLS ARRAY_SIZE(protocols) 76 77static struct sandbox_scmi_pwd scmi_pwdom[] = { 78 { .id = 0 }, 79 { .id = 1 }, 80 { .id = 2 }, 81}; 82 83static struct sandbox_scmi_clk scmi_clk[] = { 84 { .rate = 333 }, 85 { .rate = 200 }, 86 { .rate = 1000 }, 87}; 88 89static struct sandbox_scmi_reset scmi_reset[] = { 90 { .id = 3 }, 91}; 92 93static struct sandbox_scmi_voltd scmi_voltd[] = { 94 { .id = 0, .voltage_uv = 3300000 }, 95 { .id = 1, .voltage_uv = 1800000 }, 96}; 97 98struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev) 99{ 100 return dev_get_priv(dev); 101} 102 103static void debug_print_agent_state(struct udevice *dev, char *str) 104{ 105 struct sandbox_scmi_agent *agent = dev_get_priv(dev); 106 107 dev_dbg(dev, "Dump sandbox_scmi_agent: %s\n", str); 108 dev_dbg(dev, " scmi_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n", 109 agent->clk_count, 110 agent->clk_count ? agent->clk[0].enabled : -1, 111 agent->clk_count ? agent->clk[0].rate : -1, 112 agent->clk_count > 1 ? agent->clk[1].enabled : -1, 113 agent->clk_count > 1 ? agent->clk[1].rate : -1, 114 agent->clk_count > 2 ? agent->clk[2].enabled : -1, 115 agent->clk_count > 2 ? agent->clk[2].rate : -1); 116 dev_dbg(dev, " scmi_reset (%zu): %d, %d, ...\n", 117 agent->reset_count, 118 agent->reset_count ? agent->reset[0].asserted : -1, 119 agent->reset_count > 1 ? agent->reset[1].asserted : -1); 120 dev_dbg(dev, " scmi_voltd (%zu): %u/%d, %u/%d, ...\n", 121 agent->voltd_count, 122 agent->voltd_count ? agent->voltd[0].enabled : -1, 123 agent->voltd_count ? agent->voltd[0].voltage_uv : -1, 124 agent->voltd_count ? agent->voltd[1].enabled : -1, 125 agent->voltd_count ? agent->voltd[1].voltage_uv : -1); 126}; 127 128static struct sandbox_scmi_clk *get_scmi_clk_state(uint clock_id) 129{ 130 if (clock_id < ARRAY_SIZE(scmi_clk)) 131 return scmi_clk + clock_id; 132 133 return NULL; 134} 135 136static struct sandbox_scmi_reset *get_scmi_reset_state(uint reset_id) 137{ 138 size_t n; 139 140 for (n = 0; n < ARRAY_SIZE(scmi_reset); n++) 141 if (scmi_reset[n].id == reset_id) 142 return scmi_reset + n; 143 144 return NULL; 145} 146 147static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id) 148{ 149 size_t n; 150 151 for (n = 0; n < ARRAY_SIZE(scmi_voltd); n++) 152 if (scmi_voltd[n].id == domain_id) 153 return scmi_voltd + n; 154 155 return NULL; 156} 157 158/* 159 * Sandbox SCMI agent ops 160 */ 161 162/* Base Protocol */ 163 164/** 165 * sandbox_scmi_base_protocol_version - implement SCMI_BASE_PROTOCOL_VERSION 166 * @dev: SCMI device 167 * @msg: SCMI message 168 * 169 * Implement SCMI_BASE_PROTOCOL_VERSION command. 170 */ 171static int sandbox_scmi_base_protocol_version(struct udevice *dev, 172 struct scmi_msg *msg) 173{ 174 struct scmi_protocol_version_out *out = NULL; 175 176 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 177 return -EINVAL; 178 179 out = (struct scmi_protocol_version_out *)msg->out_msg; 180 out->version = SANDBOX_SCMI_BASE_PROTOCOL_VERSION; 181 out->status = SCMI_SUCCESS; 182 183 return 0; 184} 185 186/** 187 * sandbox_scmi_base_protocol_attrs - implement SCMI_BASE_PROTOCOL_ATTRIBUTES 188 * @dev: SCMI device 189 * @msg: SCMI message 190 * 191 * Implement SCMI_BASE_PROTOCOL_ATTRIBUTES command. 192 */ 193static int sandbox_scmi_base_protocol_attrs(struct udevice *dev, 194 struct scmi_msg *msg) 195{ 196 struct scmi_protocol_attrs_out *out = NULL; 197 198 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 199 return -EINVAL; 200 201 out = (struct scmi_protocol_attrs_out *)msg->out_msg; 202 out->attributes = FIELD_PREP(0xff00, 2) | NUM_PROTOCOLS; 203 out->status = SCMI_SUCCESS; 204 205 return 0; 206} 207 208/** 209 * sandbox_scmi_base_message_attrs - implement 210 * SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES 211 * @dev: SCMI device 212 * @msg: SCMI message 213 * 214 * Implement SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES command. 215 */ 216static int sandbox_scmi_base_message_attrs(struct udevice *dev, 217 struct scmi_msg *msg) 218{ 219 u32 message_id; 220 struct scmi_protocol_msg_attrs_out *out = NULL; 221 222 if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) || 223 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 224 return -EINVAL; 225 226 message_id = *(u32 *)msg->in_msg; 227 out = (struct scmi_protocol_msg_attrs_out *)msg->out_msg; 228 229 if (message_id >= SCMI_PROTOCOL_VERSION && 230 message_id <= SCMI_BASE_RESET_AGENT_CONFIGURATION && 231 message_id != SCMI_BASE_NOTIFY_ERRORS) { 232 out->attributes = 0; 233 out->status = SCMI_SUCCESS; 234 } else { 235 out->status = SCMI_NOT_FOUND; 236 } 237 238 return 0; 239} 240 241/** 242 * sandbox_scmi_base_discover_vendor - implement SCMI_BASE_DISCOVER_VENDOR 243 * @dev: SCMI device 244 * @msg: SCMI message 245 * 246 * Implement SCMI_BASE_DISCOVER_VENDOR command 247 */ 248static int sandbox_scmi_base_discover_vendor(struct udevice *dev, 249 struct scmi_msg *msg) 250{ 251 struct scmi_base_discover_vendor_out *out = NULL; 252 253 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 254 return -EINVAL; 255 256 out = (struct scmi_base_discover_vendor_out *)msg->out_msg; 257 strcpy(out->vendor_identifier, SANDBOX_SCMI_VENDOR); 258 out->status = SCMI_SUCCESS; 259 260 return 0; 261} 262 263/** 264 * sandbox_scmi_base_discover_sub_vendor - implement 265 * SCMI_BASE_DISCOVER_SUB_VENDOR 266 * @dev: SCMI device 267 * @msg: SCMI message 268 * 269 * Implement SCMI_BASE_DISCOVER_SUB_VENDOR command 270 */ 271static int sandbox_scmi_base_discover_sub_vendor(struct udevice *dev, 272 struct scmi_msg *msg) 273{ 274 struct scmi_base_discover_vendor_out *out = NULL; 275 276 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 277 return -EINVAL; 278 279 out = (struct scmi_base_discover_vendor_out *)msg->out_msg; 280 strcpy(out->vendor_identifier, SANDBOX_SCMI_SUB_VENDOR); 281 out->status = SCMI_SUCCESS; 282 283 return 0; 284} 285 286/** 287 * sandbox_scmi_base_discover_impl_version - implement 288 * SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION 289 * @dev: SCMI device 290 * @msg: SCMI message 291 * 292 * Implement SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION command 293 */ 294static int sandbox_scmi_base_discover_impl_version(struct udevice *dev, 295 struct scmi_msg *msg) 296{ 297 struct scmi_base_discover_impl_version_out *out = NULL; 298 299 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 300 return -EINVAL; 301 302 out = (struct scmi_base_discover_impl_version_out *)msg->out_msg; 303 out->impl_version = SANDBOX_SCMI_IMPL_VERSION; 304 out->status = SCMI_SUCCESS; 305 306 return 0; 307} 308 309/** 310 * sandbox_scmi_base_discover_list_protocols - implement 311 * SCMI_BASE_DISCOVER_LIST_PROTOCOLS 312 * @dev: SCMI device 313 * @msg: SCMI message 314 * 315 * Implement SCMI_BASE_DISCOVER_LIST_PROTOCOLS command 316 */ 317static int sandbox_scmi_base_discover_list_protocols(struct udevice *dev, 318 struct scmi_msg *msg) 319{ 320 struct scmi_base_discover_list_protocols_out *out = NULL; 321 322 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 323 return -EINVAL; 324 325 out = (struct scmi_base_discover_list_protocols_out *)msg->out_msg; 326 memcpy(out->protocols, protocols, sizeof(protocols)); 327 out->num_protocols = NUM_PROTOCOLS; 328 out->status = SCMI_SUCCESS; 329 330 return 0; 331} 332 333/** 334 * sandbox_scmi_base_discover_agent - implement SCMI_BASE_DISCOVER_AGENT 335 * @dev: SCMI device 336 * @msg: SCMI message 337 * 338 * Implement SCMI_BASE_DISCOVER_AGENT command 339 */ 340static int sandbox_scmi_base_discover_agent(struct udevice *dev, 341 struct scmi_msg *msg) 342{ 343 u32 agent_id; 344 struct scmi_base_discover_agent_out *out = NULL; 345 346 if (!msg->in_msg || msg->in_msg_sz < sizeof(agent_id) || 347 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 348 return -EINVAL; 349 350 agent_id = *(u32 *)msg->in_msg; 351 out = (struct scmi_base_discover_agent_out *)msg->out_msg; 352 out->status = SCMI_SUCCESS; 353 if (agent_id == 0xffffffff || agent_id == 1) { 354 out->agent_id = 1; 355 strcpy(out->name, SANDBOX_SCMI_AGENT_NAME); 356 } else if (!agent_id) { 357 out->agent_id = agent_id; 358 strcpy(out->name, SANDBOX_SCMI_PLATFORM_NAME); 359 } else { 360 out->status = SCMI_NOT_FOUND; 361 } 362 363 return 0; 364} 365 366/** 367 * sandbox_scmi_base_set_device_permissions - implement 368 * SCMI_BASE_SET_DEVICE_PERMISSIONS 369 * @dev: SCMI device 370 * @msg: SCMI message 371 * 372 * Implement SCMI_BASE_SET_DEVICE_PERMISSIONS command 373 */ 374static int sandbox_scmi_base_set_device_permissions(struct udevice *dev, 375 struct scmi_msg *msg) 376{ 377 struct scmi_base_set_device_permissions_in *in = NULL; 378 u32 *status; 379 380 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 381 !msg->out_msg || msg->out_msg_sz < sizeof(*status)) 382 return -EINVAL; 383 384 in = (struct scmi_base_set_device_permissions_in *)msg->in_msg; 385 status = (u32 *)msg->out_msg; 386 387 if (in->agent_id != 1 || in->device_id != 0) 388 *status = SCMI_NOT_FOUND; 389 else if (in->flags & ~SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS) 390 *status = SCMI_INVALID_PARAMETERS; 391 else if (in->flags & SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS) 392 *status = SCMI_SUCCESS; 393 else 394 /* unset not allowed */ 395 *status = SCMI_DENIED; 396 397 return 0; 398} 399 400/** 401 * sandbox_scmi_base_set_protocol_permissions - implement 402 * SCMI_BASE_SET_PROTOCOL_PERMISSIONS 403 * @dev: SCMI device 404 * @msg: SCMI message 405 * 406 * Implement SCMI_BASE_SET_PROTOCOL_PERMISSIONS command 407 */ 408static int sandbox_scmi_base_set_protocol_permissions(struct udevice *dev, 409 struct scmi_msg *msg) 410{ 411 struct scmi_base_set_protocol_permissions_in *in = NULL; 412 u32 *status; 413 int i; 414 415 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 416 !msg->out_msg || msg->out_msg_sz < sizeof(*status)) 417 return -EINVAL; 418 419 in = (struct scmi_base_set_protocol_permissions_in *)msg->in_msg; 420 status = (u32 *)msg->out_msg; 421 422 for (i = 0; i < ARRAY_SIZE(protocols); i++) 423 if (protocols[i] == in->command_id) 424 break; 425 if (in->agent_id != 1 || in->device_id != 0 || 426 i == ARRAY_SIZE(protocols)) 427 *status = SCMI_NOT_FOUND; 428 else if (in->flags & ~SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS) 429 *status = SCMI_INVALID_PARAMETERS; 430 else if (in->flags & SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS) 431 *status = SCMI_SUCCESS; 432 else 433 /* unset not allowed */ 434 *status = SCMI_DENIED; 435 436 return 0; 437} 438 439/** 440 * sandbox_scmi_base_reset_agent_configuration - implement 441 * SCMI_BASE_RESET_AGENT_CONFIGURATION 442 * @dev: SCMI device 443 * @msg: SCMI message 444 * 445 * Implement SCMI_BASE_RESET_AGENT_CONFIGURATION command 446 */ 447static int sandbox_scmi_base_reset_agent_configuration(struct udevice *dev, 448 struct scmi_msg *msg) 449{ 450 struct scmi_base_reset_agent_configuration_in *in = NULL; 451 u32 *status; 452 453 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 454 !msg->out_msg || msg->out_msg_sz < sizeof(*status)) 455 return -EINVAL; 456 457 in = (struct scmi_base_reset_agent_configuration_in *)msg->in_msg; 458 status = (u32 *)msg->out_msg; 459 460 if (in->agent_id != 1) 461 *status = SCMI_NOT_FOUND; 462 else if (in->flags & ~SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS) 463 *status = SCMI_INVALID_PARAMETERS; 464 else 465 *status = SCMI_DENIED; 466 467 return 0; 468} 469 470/* Power Domain Management Protocol */ 471 472/** 473 * sandbox_scmi_pwd_protocol_version - implement SCMI_PROTOCOL_VERSION 474 * @dev: SCMI device 475 * @msg: SCMI message 476 * 477 * Implement SCMI_PROTOCOL_VERSION command. 478 * 479 * Return: 0 on success, error code on failure 480 */ 481static int sandbox_scmi_pwd_protocol_version(struct udevice *dev, 482 struct scmi_msg *msg) 483{ 484 struct scmi_protocol_version_out *out = NULL; 485 486 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 487 return -EINVAL; 488 489 out = (struct scmi_protocol_version_out *)msg->out_msg; 490 out->version = SANDBOX_SCMI_PWD_PROTOCOL_VERSION; 491 out->status = SCMI_SUCCESS; 492 493 return 0; 494} 495 496/** 497 * sandbox_scmi_pwd_protocol_attribs - implement SCMI_PWD_PROTOCOL_ATTRS 498 * @dev: SCMI device 499 * @msg: SCMI message 500 * 501 * Implement SCMI_PWD_PROTOCOL_ATTRS command. 502 * 503 * Return: 0 on success, error code on failure 504 */ 505static int sandbox_scmi_pwd_protocol_attribs(struct udevice *dev, 506 struct scmi_msg *msg) 507{ 508 struct scmi_pwd_protocol_attrs_out *out; 509 510 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 511 return -EINVAL; 512 513 out = (struct scmi_pwd_protocol_attrs_out *)msg->out_msg; 514 515 out->attributes = ARRAY_SIZE(scmi_pwdom); 516 out->stats_addr_low = 0; 517 out->stats_addr_high = 0; 518 out->stats_len = 0; 519 out->status = SCMI_SUCCESS; 520 521 return 0; 522} 523 524/** 525 * sandbox_scmi_pwd_protocol_msg_attribs - implement 526 SCMI_PWD_PROTOCOL_MESSAGE_ATTRS 527 * @dev: SCMI device 528 * @msg: SCMI message 529 * 530 * Implement SCMI_PWD_PROTOCOL_MESSAGE_ATTRS command. 531 * 532 * Return: 0 on success, error code on failure 533 */ 534static int sandbox_scmi_pwd_protocol_msg_attribs(struct udevice *dev, 535 struct scmi_msg *msg) 536{ 537 u32 message_id; 538 struct scmi_pwd_protocol_msg_attrs_out *out; 539 540 if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) || 541 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 542 return -EINVAL; 543 544 message_id = *(u32 *)msg->in_msg; 545 546 out = (struct scmi_pwd_protocol_msg_attrs_out *)msg->out_msg; 547 if (message_id <= SCMI_PWD_STATE_GET || 548 message_id == SCMI_PWD_NAME_GET) { 549 out->attributes = 0; 550 out->status = SCMI_SUCCESS; 551 } else { 552 out->status = SCMI_NOT_FOUND; 553 } 554 555 return 0; 556} 557 558/** 559 * sandbox_scmi_pwd_attribs - implement SCMI_PWD_ATTRS 560 * @dev: SCMI device 561 * @msg: SCMI message 562 * 563 * Implement SCMI_PWD_ATTRS command. 564 * 565 * Return: 0 on success, error code on failure 566 */ 567static int sandbox_scmi_pwd_attribs(struct udevice *dev, struct scmi_msg *msg) 568{ 569 u32 domain_id; 570 struct scmi_pwd_attrs_out *out; 571 572 if (!msg->in_msg || msg->in_msg_sz < sizeof(domain_id) || 573 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 574 return -EINVAL; 575 576 domain_id = *(u32 *)msg->in_msg; 577 out = (struct scmi_pwd_attrs_out *)msg->out_msg; 578 579 if (domain_id >= ARRAY_SIZE(scmi_pwdom)) { 580 out->status = SCMI_NOT_FOUND; 581 582 return 0; 583 } 584 585 out->attributes = 586 SCMI_PWD_ATTR_PSTATE_SYNC | SCMI_PWD_ATTR_EXTENDED_NAME; 587 /* just 15-char + NULL */ 588 snprintf(out->name, SCMI_PWD_NAME_LENGTH_MAX, "power-domain--%d", 589 domain_id); 590 out->status = SCMI_SUCCESS; 591 592 return 0; 593} 594 595/** 596 * sandbox_scmi_pwd_state_set - implement SCMI_PWD_STATE_SET 597 * @dev: SCMI device 598 * @msg: SCMI message 599 * 600 * Implement SCMI_PWD_STATE_SET command. 601 * 602 * Return: 0 on success, error code on failure 603 */ 604static int sandbox_scmi_pwd_state_set(struct udevice *dev, struct scmi_msg *msg) 605{ 606 struct scmi_pwd_state_set_in *in; 607 s32 *status; 608 609 if (!msg->in_msg || msg->in_msg_sz < sizeof(in) || 610 !msg->out_msg || msg->out_msg_sz < sizeof(*status)) 611 return -EINVAL; 612 613 in = (struct scmi_pwd_state_set_in *)msg->in_msg; 614 status = (s32 *)msg->out_msg; 615 616 if (in->domain_id >= ARRAY_SIZE(scmi_pwdom)) { 617 *status = SCMI_NOT_FOUND; 618 619 return 0; 620 } 621 622 if ((in->flags & SCMI_PWD_SET_FLAGS_ASYNC) || 623 (in->pstate != SCMI_PWD_PSTATE_TYPE_LOST && in->pstate)) { 624 *status = SCMI_INVALID_PARAMETERS; 625 626 return 0; 627 } 628 629 scmi_pwdom[in->domain_id].pstate = in->pstate; 630 *status = SCMI_SUCCESS; 631 632 return 0; 633} 634 635/** 636 * sandbox_scmi_pwd_state_get - implement SCMI_PWD_STATE_GET 637 * @dev: SCMI device 638 * @msg: SCMI message 639 * 640 * Implement SCMI_PWD_STATE_GET command. 641 * 642 * Return: 0 on success, error code on failure 643 */ 644static int sandbox_scmi_pwd_state_get(struct udevice *dev, struct scmi_msg *msg) 645{ 646 u32 domain_id; 647 struct scmi_pwd_state_get_out *out; 648 649 if (!msg->in_msg || msg->in_msg_sz < sizeof(domain_id) || 650 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 651 return -EINVAL; 652 653 domain_id = *(u32 *)msg->in_msg; 654 out = (struct scmi_pwd_state_get_out *)msg->out_msg; 655 656 if (domain_id >= ARRAY_SIZE(scmi_pwdom)) { 657 out->status = SCMI_NOT_FOUND; 658 659 return 0; 660 } 661 662 out->pstate = scmi_pwdom[domain_id].pstate; 663 out->status = SCMI_SUCCESS; 664 665 return 0; 666} 667 668/** 669 * sandbox_scmi_pwd_name_get - implement SCMI_PWD_NAME_GET 670 * @dev: SCMI device 671 * @msg: SCMI message 672 * 673 * Implement SCMI_PWD_NAME_GET command. 674 * 675 * Return: 0 on success, error code on failure 676 */ 677static int sandbox_scmi_pwd_name_get(struct udevice *dev, struct scmi_msg *msg) 678{ 679 u32 domain_id; 680 struct scmi_pwd_name_get_out *out; 681 682 if (!msg->in_msg || msg->in_msg_sz < sizeof(domain_id) || 683 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 684 return -EINVAL; 685 686 domain_id = *(u32 *)msg->in_msg; 687 out = (struct scmi_pwd_name_get_out *)msg->out_msg; 688 689 if (domain_id >= ARRAY_SIZE(scmi_pwdom)) { 690 out->status = SCMI_NOT_FOUND; 691 692 return 0; 693 } 694 695 snprintf(out->extended_name, SCMI_PWD_EXTENDED_NAME_MAX, 696 "power-domain--%d-extended", domain_id); 697 out->status = SCMI_SUCCESS; 698 699 return 0; 700} 701 702/* Clock Protocol */ 703 704static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev, 705 struct scmi_msg *msg) 706{ 707 struct scmi_clk_protocol_attr_out *out = NULL; 708 709 if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) 710 return -EINVAL; 711 712 out = (struct scmi_clk_protocol_attr_out *)msg->out_msg; 713 out->attributes = ARRAY_SIZE(scmi_clk); 714 out->status = SCMI_SUCCESS; 715 716 return 0; 717} 718 719static int sandbox_scmi_clock_attribs(struct udevice *dev, struct scmi_msg *msg) 720{ 721 struct scmi_clk_attribute_in *in = NULL; 722 struct scmi_clk_attribute_out *out = NULL; 723 struct sandbox_scmi_clk *clk_state = NULL; 724 int ret; 725 726 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 727 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 728 return -EINVAL; 729 730 in = (struct scmi_clk_attribute_in *)msg->in_msg; 731 out = (struct scmi_clk_attribute_out *)msg->out_msg; 732 733 clk_state = get_scmi_clk_state(in->clock_id); 734 if (!clk_state) { 735 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); 736 737 out->status = SCMI_NOT_FOUND; 738 } else { 739 memset(out, 0, sizeof(*out)); 740 741 if (clk_state->enabled) 742 out->attributes = 1; 743 744 ret = snprintf(out->clock_name, sizeof(out->clock_name), 745 "clk%u", in->clock_id); 746 assert(ret > 0 && ret < sizeof(out->clock_name)); 747 748 out->status = SCMI_SUCCESS; 749 } 750 751 return 0; 752} 753static int sandbox_scmi_clock_rate_set(struct udevice *dev, 754 struct scmi_msg *msg) 755{ 756 struct scmi_clk_rate_set_in *in = NULL; 757 struct scmi_clk_rate_set_out *out = NULL; 758 struct sandbox_scmi_clk *clk_state = NULL; 759 760 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 761 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 762 return -EINVAL; 763 764 in = (struct scmi_clk_rate_set_in *)msg->in_msg; 765 out = (struct scmi_clk_rate_set_out *)msg->out_msg; 766 767 clk_state = get_scmi_clk_state(in->clock_id); 768 if (!clk_state) { 769 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); 770 771 out->status = SCMI_NOT_FOUND; 772 } else { 773 u64 rate = ((u64)in->rate_msb << 32) + in->rate_lsb; 774 775 clk_state->rate = (ulong)rate; 776 777 out->status = SCMI_SUCCESS; 778 } 779 780 return 0; 781} 782 783static int sandbox_scmi_clock_rate_get(struct udevice *dev, 784 struct scmi_msg *msg) 785{ 786 struct scmi_clk_rate_get_in *in = NULL; 787 struct scmi_clk_rate_get_out *out = NULL; 788 struct sandbox_scmi_clk *clk_state = NULL; 789 790 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 791 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 792 return -EINVAL; 793 794 in = (struct scmi_clk_rate_get_in *)msg->in_msg; 795 out = (struct scmi_clk_rate_get_out *)msg->out_msg; 796 797 clk_state = get_scmi_clk_state(in->clock_id); 798 if (!clk_state) { 799 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); 800 801 out->status = SCMI_NOT_FOUND; 802 } else { 803 out->rate_msb = (u32)((u64)clk_state->rate >> 32); 804 out->rate_lsb = (u32)clk_state->rate; 805 806 out->status = SCMI_SUCCESS; 807 } 808 809 return 0; 810} 811 812static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) 813{ 814 struct scmi_clk_state_in *in = NULL; 815 struct scmi_clk_state_out *out = NULL; 816 struct sandbox_scmi_clk *clk_state = NULL; 817 818 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 819 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 820 return -EINVAL; 821 822 in = (struct scmi_clk_state_in *)msg->in_msg; 823 out = (struct scmi_clk_state_out *)msg->out_msg; 824 825 clk_state = get_scmi_clk_state(in->clock_id); 826 if (!clk_state) { 827 dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); 828 829 out->status = SCMI_NOT_FOUND; 830 } else if (in->attributes > 1) { 831 out->status = SCMI_PROTOCOL_ERROR; 832 } else { 833 clk_state->enabled = in->attributes; 834 835 out->status = SCMI_SUCCESS; 836 } 837 838 return 0; 839} 840 841static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg) 842{ 843 struct scmi_rd_attr_in *in = NULL; 844 struct scmi_rd_attr_out *out = NULL; 845 struct sandbox_scmi_reset *reset_state = NULL; 846 847 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 848 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 849 return -EINVAL; 850 851 in = (struct scmi_rd_attr_in *)msg->in_msg; 852 out = (struct scmi_rd_attr_out *)msg->out_msg; 853 854 reset_state = get_scmi_reset_state(in->domain_id); 855 if (!reset_state) { 856 dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id); 857 858 out->status = SCMI_NOT_FOUND; 859 } else { 860 memset(out, 0, sizeof(*out)); 861 snprintf(out->name, sizeof(out->name), "rd%u", in->domain_id); 862 863 out->status = SCMI_SUCCESS; 864 } 865 866 return 0; 867} 868 869static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg) 870{ 871 struct scmi_rd_reset_in *in = NULL; 872 struct scmi_rd_reset_out *out = NULL; 873 struct sandbox_scmi_reset *reset_state = NULL; 874 875 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 876 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 877 return -EINVAL; 878 879 in = (struct scmi_rd_reset_in *)msg->in_msg; 880 out = (struct scmi_rd_reset_out *)msg->out_msg; 881 882 reset_state = get_scmi_reset_state(in->domain_id); 883 if (!reset_state) { 884 dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id); 885 886 out->status = SCMI_NOT_FOUND; 887 } else if (in->reset_state > 1) { 888 dev_err(dev, "Invalid reset domain input attribute value\n"); 889 890 out->status = SCMI_INVALID_PARAMETERS; 891 } else { 892 if (in->flags & SCMI_RD_RESET_FLAG_CYCLE) { 893 if (in->flags & SCMI_RD_RESET_FLAG_ASYNC) { 894 out->status = SCMI_NOT_SUPPORTED; 895 } else { 896 /* Ends deasserted whatever current state */ 897 reset_state->asserted = false; 898 out->status = SCMI_SUCCESS; 899 } 900 } else { 901 reset_state->asserted = in->flags & 902 SCMI_RD_RESET_FLAG_ASSERT; 903 904 out->status = SCMI_SUCCESS; 905 } 906 } 907 908 return 0; 909} 910 911static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg) 912{ 913 struct scmi_voltd_attr_in *in = NULL; 914 struct scmi_voltd_attr_out *out = NULL; 915 struct sandbox_scmi_voltd *voltd_state = NULL; 916 917 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 918 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 919 return -EINVAL; 920 921 in = (struct scmi_voltd_attr_in *)msg->in_msg; 922 out = (struct scmi_voltd_attr_out *)msg->out_msg; 923 924 voltd_state = get_scmi_voltd_state(in->domain_id); 925 if (!voltd_state) { 926 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); 927 928 out->status = SCMI_NOT_FOUND; 929 } else { 930 memset(out, 0, sizeof(*out)); 931 snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id); 932 933 out->status = SCMI_SUCCESS; 934 } 935 936 return 0; 937} 938 939static int sandbox_scmi_voltd_config_set(struct udevice *dev, 940 struct scmi_msg *msg) 941{ 942 struct scmi_voltd_config_set_in *in = NULL; 943 struct scmi_voltd_config_set_out *out = NULL; 944 struct sandbox_scmi_voltd *voltd_state = NULL; 945 946 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 947 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 948 return -EINVAL; 949 950 in = (struct scmi_voltd_config_set_in *)msg->in_msg; 951 out = (struct scmi_voltd_config_set_out *)msg->out_msg; 952 953 voltd_state = get_scmi_voltd_state(in->domain_id); 954 if (!voltd_state) { 955 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); 956 957 out->status = SCMI_NOT_FOUND; 958 } else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) { 959 dev_err(dev, "Invalid config value 0x%x\n", in->config); 960 961 out->status = SCMI_INVALID_PARAMETERS; 962 } else if (in->config != SCMI_VOLTD_CONFIG_ON && 963 in->config != SCMI_VOLTD_CONFIG_OFF) { 964 dev_err(dev, "Unexpected custom value 0x%x\n", in->config); 965 966 out->status = SCMI_INVALID_PARAMETERS; 967 } else { 968 voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON; 969 out->status = SCMI_SUCCESS; 970 } 971 972 return 0; 973} 974 975static int sandbox_scmi_voltd_config_get(struct udevice *dev, 976 struct scmi_msg *msg) 977{ 978 struct scmi_voltd_config_get_in *in = NULL; 979 struct scmi_voltd_config_get_out *out = NULL; 980 struct sandbox_scmi_voltd *voltd_state = NULL; 981 982 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 983 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 984 return -EINVAL; 985 986 in = (struct scmi_voltd_config_get_in *)msg->in_msg; 987 out = (struct scmi_voltd_config_get_out *)msg->out_msg; 988 989 voltd_state = get_scmi_voltd_state(in->domain_id); 990 if (!voltd_state) { 991 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); 992 993 out->status = SCMI_NOT_FOUND; 994 } else { 995 if (voltd_state->enabled) 996 out->config = SCMI_VOLTD_CONFIG_ON; 997 else 998 out->config = SCMI_VOLTD_CONFIG_OFF; 999 1000 out->status = SCMI_SUCCESS; 1001 } 1002 1003 return 0; 1004} 1005 1006static int sandbox_scmi_voltd_level_set(struct udevice *dev, 1007 struct scmi_msg *msg) 1008{ 1009 struct scmi_voltd_level_set_in *in = NULL; 1010 struct scmi_voltd_level_set_out *out = NULL; 1011 struct sandbox_scmi_voltd *voltd_state = NULL; 1012 1013 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 1014 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 1015 return -EINVAL; 1016 1017 in = (struct scmi_voltd_level_set_in *)msg->in_msg; 1018 out = (struct scmi_voltd_level_set_out *)msg->out_msg; 1019 1020 voltd_state = get_scmi_voltd_state(in->domain_id); 1021 if (!voltd_state) { 1022 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); 1023 1024 out->status = SCMI_NOT_FOUND; 1025 } else { 1026 voltd_state->voltage_uv = in->voltage_level; 1027 out->status = SCMI_SUCCESS; 1028 } 1029 1030 return 0; 1031} 1032 1033static int sandbox_scmi_voltd_level_get(struct udevice *dev, 1034 struct scmi_msg *msg) 1035{ 1036 struct scmi_voltd_level_get_in *in = NULL; 1037 struct scmi_voltd_level_get_out *out = NULL; 1038 struct sandbox_scmi_voltd *voltd_state = NULL; 1039 1040 if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || 1041 !msg->out_msg || msg->out_msg_sz < sizeof(*out)) 1042 return -EINVAL; 1043 1044 in = (struct scmi_voltd_level_get_in *)msg->in_msg; 1045 out = (struct scmi_voltd_level_get_out *)msg->out_msg; 1046 1047 voltd_state = get_scmi_voltd_state(in->domain_id); 1048 if (!voltd_state) { 1049 dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); 1050 1051 out->status = SCMI_NOT_FOUND; 1052 } else { 1053 out->voltage_level = voltd_state->voltage_uv; 1054 out->status = SCMI_SUCCESS; 1055 } 1056 1057 return 0; 1058} 1059 1060/** 1061 * sandbox_scmi_of_get_channel - assigne a channel 1062 * @dev: SCMI agent device 1063 * @protocol: SCMI protocol device 1064 * @channel: Pointer to channel info 1065 * 1066 * Assign a channel for the protocol, @protocol, in @channel, 1067 * based on a device tree's property. 1068 * 1069 * Return: 0 on success, error code on failure 1070 */ 1071static int sandbox_scmi_of_get_channel(struct udevice *dev, 1072 struct udevice *protocol, 1073 struct scmi_channel **channel) 1074{ 1075 struct sandbox_channel *agent_chan = dev_get_plat(dev); 1076 struct sandbox_channel *chan; 1077 u32 channel_id; 1078 1079 if (dev_read_u32(protocol, "linaro,sandbox-channel-id", &channel_id)) { 1080 /* Uses agent channel */ 1081 *channel = container_of(agent_chan, struct scmi_channel, ref); 1082 1083 return 0; 1084 } 1085 1086 /* Setup a dedicated channel */ 1087 chan = calloc(1, sizeof(*chan)); 1088 if (!chan) 1089 return -ENOMEM; 1090 1091 chan->channel_id = channel_id; 1092 1093 *channel = container_of(chan, struct scmi_channel, ref); 1094 1095 return 0; 1096} 1097 1098/** 1099 * sandbox_scmi_of_to_plat - assigne a channel to agent 1100 * @dev: SCMI agent device 1101 * 1102 * Assign a channel for the agent, @protocol. 1103 * 1104 * Return: always 0 1105 */ 1106static int sandbox_scmi_of_to_plat(struct udevice *dev) 1107{ 1108 struct sandbox_channel *chan = dev_get_plat(dev); 1109 1110 /* The channel for agent is always 0 */ 1111 chan->channel_id = 0; 1112 1113 return 0; 1114} 1115 1116unsigned int sandbox_scmi_channel_id(struct udevice *dev) 1117{ 1118 struct scmi_agent_proto_priv *priv; 1119 struct sandbox_channel *chan; 1120 1121 priv = dev_get_parent_priv(dev); 1122 chan = (struct sandbox_channel *)&priv->channel->ref; 1123 1124 return chan->channel_id; 1125} 1126 1127static int sandbox_proto_not_supported(struct scmi_msg *msg) 1128{ 1129 *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; 1130 1131 return 0; 1132} 1133 1134static int sandbox_scmi_test_process_msg(struct udevice *dev, 1135 struct scmi_channel *channel, 1136 struct scmi_msg *msg) 1137{ 1138 switch (msg->protocol_id) { 1139 case SCMI_PROTOCOL_ID_BASE: 1140 switch (msg->message_id) { 1141 case SCMI_PROTOCOL_VERSION: 1142 return sandbox_scmi_base_protocol_version(dev, msg); 1143 case SCMI_PROTOCOL_ATTRIBUTES: 1144 return sandbox_scmi_base_protocol_attrs(dev, msg); 1145 case SCMI_PROTOCOL_MESSAGE_ATTRIBUTES: 1146 return sandbox_scmi_base_message_attrs(dev, msg); 1147 case SCMI_BASE_DISCOVER_VENDOR: 1148 return sandbox_scmi_base_discover_vendor(dev, msg); 1149 case SCMI_BASE_DISCOVER_SUB_VENDOR: 1150 return sandbox_scmi_base_discover_sub_vendor(dev, msg); 1151 case SCMI_BASE_DISCOVER_IMPL_VERSION: 1152 return sandbox_scmi_base_discover_impl_version(dev, msg); 1153 case SCMI_BASE_DISCOVER_LIST_PROTOCOLS: 1154 return sandbox_scmi_base_discover_list_protocols(dev, msg); 1155 case SCMI_BASE_DISCOVER_AGENT: 1156 return sandbox_scmi_base_discover_agent(dev, msg); 1157 case SCMI_BASE_NOTIFY_ERRORS: 1158 break; 1159 case SCMI_BASE_SET_DEVICE_PERMISSIONS: 1160 return sandbox_scmi_base_set_device_permissions(dev, msg); 1161 case SCMI_BASE_SET_PROTOCOL_PERMISSIONS: 1162 return sandbox_scmi_base_set_protocol_permissions(dev, msg); 1163 case SCMI_BASE_RESET_AGENT_CONFIGURATION: 1164 return sandbox_scmi_base_reset_agent_configuration(dev, msg); 1165 default: 1166 break; 1167 } 1168 break; 1169 case SCMI_PROTOCOL_ID_POWER_DOMAIN: 1170 if (!CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN)) 1171 return sandbox_proto_not_supported(msg); 1172 1173 switch (msg->message_id) { 1174 case SCMI_PROTOCOL_VERSION: 1175 return sandbox_scmi_pwd_protocol_version(dev, msg); 1176 case SCMI_PROTOCOL_ATTRIBUTES: 1177 return sandbox_scmi_pwd_protocol_attribs(dev, msg); 1178 case SCMI_PROTOCOL_MESSAGE_ATTRIBUTES: 1179 return sandbox_scmi_pwd_protocol_msg_attribs(dev, msg); 1180 case SCMI_PWD_ATTRIBUTES: 1181 return sandbox_scmi_pwd_attribs(dev, msg); 1182 case SCMI_PWD_STATE_SET: 1183 return sandbox_scmi_pwd_state_set(dev, msg); 1184 case SCMI_PWD_STATE_GET: 1185 return sandbox_scmi_pwd_state_get(dev, msg); 1186 case SCMI_PWD_NAME_GET: 1187 return sandbox_scmi_pwd_name_get(dev, msg); 1188 default: 1189 break; 1190 } 1191 break; 1192 case SCMI_PROTOCOL_ID_CLOCK: 1193 if (!CONFIG_IS_ENABLED(CLK_SCMI)) 1194 return sandbox_proto_not_supported(msg); 1195 1196 switch (msg->message_id) { 1197 case SCMI_PROTOCOL_ATTRIBUTES: 1198 return sandbox_scmi_clock_protocol_attribs(dev, msg); 1199 case SCMI_CLOCK_ATTRIBUTES: 1200 return sandbox_scmi_clock_attribs(dev, msg); 1201 case SCMI_CLOCK_RATE_SET: 1202 return sandbox_scmi_clock_rate_set(dev, msg); 1203 case SCMI_CLOCK_RATE_GET: 1204 return sandbox_scmi_clock_rate_get(dev, msg); 1205 case SCMI_CLOCK_CONFIG_SET: 1206 return sandbox_scmi_clock_gate(dev, msg); 1207 default: 1208 break; 1209 } 1210 break; 1211 case SCMI_PROTOCOL_ID_RESET_DOMAIN: 1212 if (!CONFIG_IS_ENABLED(RESET_SCMI)) 1213 return sandbox_proto_not_supported(msg); 1214 1215 switch (msg->message_id) { 1216 case SCMI_RESET_DOMAIN_ATTRIBUTES: 1217 return sandbox_scmi_rd_attribs(dev, msg); 1218 case SCMI_RESET_DOMAIN_RESET: 1219 return sandbox_scmi_rd_reset(dev, msg); 1220 default: 1221 break; 1222 } 1223 break; 1224 case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: 1225 if (!CONFIG_IS_ENABLED(DM_REGULATOR_SCMI)) 1226 return sandbox_proto_not_supported(msg); 1227 1228 switch (msg->message_id) { 1229 case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES: 1230 return sandbox_scmi_voltd_attribs(dev, msg); 1231 case SCMI_VOLTAGE_DOMAIN_CONFIG_SET: 1232 return sandbox_scmi_voltd_config_set(dev, msg); 1233 case SCMI_VOLTAGE_DOMAIN_CONFIG_GET: 1234 return sandbox_scmi_voltd_config_get(dev, msg); 1235 case SCMI_VOLTAGE_DOMAIN_LEVEL_SET: 1236 return sandbox_scmi_voltd_level_set(dev, msg); 1237 case SCMI_VOLTAGE_DOMAIN_LEVEL_GET: 1238 return sandbox_scmi_voltd_level_get(dev, msg); 1239 default: 1240 break; 1241 } 1242 break; 1243 case SCMI_PROTOCOL_ID_SYSTEM: 1244 case SCMI_PROTOCOL_ID_PERF: 1245 case SCMI_PROTOCOL_ID_SENSOR: 1246 return sandbox_proto_not_supported(msg); 1247 default: 1248 break; 1249 } 1250 1251 dev_err(dev, "%s(%s): Unhandled protocol_id %#x/message_id %#x\n", 1252 __func__, dev->name, msg->protocol_id, msg->message_id); 1253 1254 if (msg->out_msg_sz < sizeof(u32)) 1255 return -EINVAL; 1256 1257 /* Intentionnaly report unhandled IDs through the SCMI return code */ 1258 *(u32 *)msg->out_msg = SCMI_PROTOCOL_ERROR; 1259 return 0; 1260} 1261 1262static int sandbox_scmi_test_remove(struct udevice *dev) 1263{ 1264 debug_print_agent_state(dev, "removed"); 1265 1266 return 0; 1267} 1268 1269static int sandbox_scmi_test_probe(struct udevice *dev) 1270{ 1271 struct sandbox_scmi_agent *agent = dev_get_priv(dev); 1272 1273 *agent = (struct sandbox_scmi_agent){ 1274 .pwdom_version = SANDBOX_SCMI_PWD_PROTOCOL_VERSION, 1275 .pwdom = scmi_pwdom, 1276 .pwdom_count = ARRAY_SIZE(scmi_pwdom), 1277 .clk = scmi_clk, 1278 .clk_count = ARRAY_SIZE(scmi_clk), 1279 .reset = scmi_reset, 1280 .reset_count = ARRAY_SIZE(scmi_reset), 1281 .voltd = scmi_voltd, 1282 .voltd_count = ARRAY_SIZE(scmi_voltd), 1283 }; 1284 1285 debug_print_agent_state(dev, "probed"); 1286 1287 return 0; 1288}; 1289 1290static const struct udevice_id sandbox_scmi_test_ids[] = { 1291 { .compatible = "sandbox,scmi-agent" }, 1292 { } 1293}; 1294 1295struct scmi_agent_ops sandbox_scmi_test_ops = { 1296 .of_get_channel = sandbox_scmi_of_get_channel, 1297 .process_msg = sandbox_scmi_test_process_msg, 1298}; 1299 1300U_BOOT_DRIVER(sandbox_scmi_agent) = { 1301 .name = "sandbox-scmi_agent", 1302 .id = UCLASS_SCMI_AGENT, 1303 .of_match = sandbox_scmi_test_ids, 1304 .priv_auto = sizeof(struct sandbox_scmi_agent), 1305 .plat_auto = sizeof(struct sandbox_channel), 1306 .of_to_plat = sandbox_scmi_of_to_plat, 1307 .probe = sandbox_scmi_test_probe, 1308 .remove = sandbox_scmi_test_remove, 1309 .ops = &sandbox_scmi_test_ops, 1310}; 1311