1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * SCMI Base protocol as U-Boot device 4 * 5 * Copyright (C) 2023 Linaro Limited 6 * author: AKASHI Takahiro <takahiro.akashi@linaro.org> 7 */ 8 9#include <common.h> 10#include <dm.h> 11#include <scmi_agent.h> 12#include <scmi_protocols.h> 13#include <stdlib.h> 14#include <string.h> 15#include <asm/types.h> 16#include <dm/device_compat.h> 17#include <linux/kernel.h> 18 19/** 20 * scmi_generic_protocol_version - get protocol version 21 * @dev: SCMI device 22 * @id: SCMI protocol ID 23 * @version: Pointer to SCMI protocol version 24 * 25 * Obtain the protocol version number in @version. 26 * 27 * Return: 0 on success, error code on failure 28 */ 29int scmi_generic_protocol_version(struct udevice *dev, 30 enum scmi_std_protocol id, u32 *version) 31{ 32 struct scmi_protocol_version_out out; 33 struct scmi_msg msg = { 34 .protocol_id = id, 35 .message_id = SCMI_PROTOCOL_VERSION, 36 .out_msg = (u8 *)&out, 37 .out_msg_sz = sizeof(out), 38 }; 39 int ret; 40 41 ret = devm_scmi_process_msg(dev, &msg); 42 if (ret) 43 return ret; 44 if (out.status) 45 return scmi_to_linux_errno(out.status); 46 47 *version = out.version; 48 49 return 0; 50} 51 52/** 53 * scmi_base_protocol_version_int - get Base protocol version 54 * @dev: SCMI device 55 * @version: Pointer to SCMI protocol version 56 * 57 * Obtain the protocol version number in @version for Base protocol. 58 * 59 * Return: 0 on success, error code on failure 60 */ 61static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version) 62{ 63 return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE, 64 version); 65} 66 67/** 68 * scmi_protocol_attrs_int - get protocol attributes 69 * @dev: SCMI device 70 * @num_agents: Number of SCMI agents 71 * @num_protocols: Number of SCMI protocols 72 * 73 * Obtain the protocol attributes, the number of agents and the number 74 * of protocols, in @num_agents and @num_protocols respectively, that 75 * the device provides. 76 * 77 * Return: 0 on success, error code on failure 78 */ 79static int scmi_protocol_attrs_int(struct udevice *dev, u32 *num_agents, 80 u32 *num_protocols) 81{ 82 struct scmi_protocol_attrs_out out; 83 struct scmi_msg msg = { 84 .protocol_id = SCMI_PROTOCOL_ID_BASE, 85 .message_id = SCMI_PROTOCOL_ATTRIBUTES, 86 .out_msg = (u8 *)&out, 87 .out_msg_sz = sizeof(out), 88 }; 89 int ret; 90 91 ret = devm_scmi_process_msg(dev, &msg); 92 if (ret) 93 return ret; 94 if (out.status) 95 return scmi_to_linux_errno(out.status); 96 97 *num_agents = SCMI_PROTOCOL_ATTRS_NUM_AGENTS(out.attributes); 98 *num_protocols = SCMI_PROTOCOL_ATTRS_NUM_PROTOCOLS(out.attributes); 99 100 return 0; 101} 102 103/** 104 * scmi_protocol_message_attrs_int - get message-specific attributes 105 * @dev: SCMI device 106 * @message_id: SCMI message ID 107 * @attributes: Message-specific attributes 108 * 109 * Obtain the message-specific attributes in @attributes. 110 * This command succeeds if the message is implemented and available. 111 * 112 * Return: 0 on success, error code on failure 113 */ 114static int scmi_protocol_message_attrs_int(struct udevice *dev, u32 message_id, 115 u32 *attributes) 116{ 117 struct scmi_protocol_msg_attrs_out out; 118 struct scmi_msg msg = { 119 .protocol_id = SCMI_PROTOCOL_ID_BASE, 120 .message_id = SCMI_PROTOCOL_MESSAGE_ATTRIBUTES, 121 .in_msg = (u8 *)&message_id, 122 .in_msg_sz = sizeof(message_id), 123 .out_msg = (u8 *)&out, 124 .out_msg_sz = sizeof(out), 125 }; 126 int ret; 127 128 ret = devm_scmi_process_msg(dev, &msg); 129 if (ret) 130 return ret; 131 if (out.status) 132 return scmi_to_linux_errno(out.status); 133 134 *attributes = out.attributes; 135 136 return 0; 137} 138 139/** 140 * scmi_base_discover_vendor_int - get vendor name 141 * @dev: SCMI device 142 * @vendor: Pointer to vendor name 143 * 144 * Obtain the vendor's name in @vendor. 145 * It is a caller's responsibility to free @vendor. 146 * 147 * Return: 0 on success, error code on failure 148 */ 149static int scmi_base_discover_vendor_int(struct udevice *dev, u8 **vendor) 150{ 151 struct scmi_base_discover_vendor_out out; 152 struct scmi_msg msg = { 153 .protocol_id = SCMI_PROTOCOL_ID_BASE, 154 .message_id = SCMI_BASE_DISCOVER_VENDOR, 155 .out_msg = (u8 *)&out, 156 .out_msg_sz = sizeof(out), 157 }; 158 int ret; 159 160 if (!vendor) 161 return -EINVAL; 162 163 ret = devm_scmi_process_msg(dev, &msg); 164 if (ret) 165 return ret; 166 if (out.status) 167 return scmi_to_linux_errno(out.status); 168 169 *vendor = strdup(out.vendor_identifier); 170 if (!*vendor) 171 return -ENOMEM; 172 173 return 0; 174} 175 176/** 177 * scmi_base_discover_sub_vendor_int - get sub-vendor name 178 * @dev: SCMI device 179 * @sub_vendor: Pointer to sub-vendor name 180 * 181 * Obtain the sub-vendor's name in @sub_vendor. 182 * It is a caller's responsibility to free @sub_vendor. 183 * 184 * Return: 0 on success, error code on failure 185 */ 186static int scmi_base_discover_sub_vendor_int(struct udevice *dev, 187 u8 **sub_vendor) 188{ 189 struct scmi_base_discover_vendor_out out; 190 struct scmi_msg msg = { 191 .protocol_id = SCMI_PROTOCOL_ID_BASE, 192 .message_id = SCMI_BASE_DISCOVER_SUB_VENDOR, 193 .out_msg = (u8 *)&out, 194 .out_msg_sz = sizeof(out), 195 }; 196 int ret; 197 198 if (!sub_vendor) 199 return -EINVAL; 200 201 ret = devm_scmi_process_msg(dev, &msg); 202 if (ret) 203 return ret; 204 if (out.status) 205 return scmi_to_linux_errno(out.status); 206 207 *sub_vendor = strdup(out.vendor_identifier); 208 if (!*sub_vendor) 209 return -ENOMEM; 210 211 return 0; 212} 213 214/** 215 * scmi_base_discover_impl_version_int - get implementation version 216 * @dev: SCMI device 217 * @impl_version: Pointer to implementation version 218 * 219 * Obtain the implementation version number in @impl_version. 220 * 221 * Return: 0 on success, error code on failure 222 */ 223static int scmi_base_discover_impl_version_int(struct udevice *dev, 224 u32 *impl_version) 225{ 226 struct scmi_base_discover_impl_version_out out; 227 struct scmi_msg msg = { 228 .protocol_id = SCMI_PROTOCOL_ID_BASE, 229 .message_id = SCMI_BASE_DISCOVER_IMPL_VERSION, 230 .out_msg = (u8 *)&out, 231 .out_msg_sz = sizeof(out), 232 }; 233 int ret; 234 235 ret = devm_scmi_process_msg(dev, &msg); 236 if (ret) 237 return ret; 238 if (out.status) 239 return scmi_to_linux_errno(out.status); 240 241 *impl_version = out.impl_version; 242 243 return 0; 244} 245 246/** 247 * scmi_base_discover_list_protocols_int - get list of protocols 248 * @dev: SCMI device 249 * @protocols: Pointer to array of SCMI protocols 250 * 251 * Obtain the list of protocols provided in @protocols. 252 * The number of elements in @protocols always match to the number of 253 * protocols returned by smci_protocol_attrs() when this function succeeds. 254 * It is a caller's responsibility to free @protocols. 255 * 256 * Return: the number of protocols in @protocols on success, error code on 257 * failure 258 */ 259static int scmi_base_discover_list_protocols_int(struct udevice *dev, 260 u8 **protocols) 261{ 262 struct scmi_base_discover_list_protocols_out out; 263 int cur; 264 struct scmi_msg msg = { 265 .protocol_id = SCMI_PROTOCOL_ID_BASE, 266 .message_id = SCMI_BASE_DISCOVER_LIST_PROTOCOLS, 267 .in_msg = (u8 *)&cur, 268 .in_msg_sz = sizeof(cur), 269 .out_msg = (u8 *)&out, 270 .out_msg_sz = sizeof(out), 271 }; 272 u32 num_agents, num_protocols; 273 u8 *buf; 274 int i, ret; 275 276 ret = scmi_base_protocol_attrs(dev, &num_agents, &num_protocols); 277 if (ret) 278 return ret; 279 280 buf = calloc(sizeof(u8), num_protocols); 281 if (!buf) 282 return -ENOMEM; 283 284 cur = 0; 285 do { 286 ret = devm_scmi_process_msg(dev, &msg); 287 if (ret) 288 goto err; 289 if (out.status) { 290 ret = scmi_to_linux_errno(out.status); 291 goto err; 292 } 293 294 for (i = 0; i < out.num_protocols; i++, cur++) 295 buf[cur] = out.protocols[i / 4] >> ((i % 4) * 8); 296 } while (cur < num_protocols); 297 298 *protocols = buf; 299 300 return num_protocols; 301err: 302 free(buf); 303 304 return ret; 305} 306 307/** 308 * scmi_base_discover_agent_int - identify agent 309 * @dev: SCMI device 310 * @agent_id: SCMI agent ID 311 * @ret_agent_id: Pointer to SCMI agent ID 312 * @name: Pointer to SCMI agent name 313 * 314 * Obtain the agent's name in @name. If @agent_id is equal to 0xffffffff, 315 * this function returns the caller's agent id in @ret_agent_id. 316 * It is a caller's responsibility to free @name. 317 * 318 * Return: 0 on success, error code on failure 319 */ 320static int scmi_base_discover_agent_int(struct udevice *dev, u32 agent_id, 321 u32 *ret_agent_id, u8 **name) 322{ 323 struct scmi_base_discover_agent_out out; 324 struct scmi_msg msg = { 325 .protocol_id = SCMI_PROTOCOL_ID_BASE, 326 .message_id = SCMI_BASE_DISCOVER_AGENT, 327 .in_msg = (u8 *)&agent_id, 328 .in_msg_sz = sizeof(agent_id), 329 .out_msg = (u8 *)&out, 330 .out_msg_sz = sizeof(out), 331 }; 332 int ret; 333 334 ret = devm_scmi_process_msg(dev, &msg); 335 if (ret) 336 return ret; 337 if (out.status) 338 return scmi_to_linux_errno(out.status); 339 340 if (ret_agent_id) 341 *ret_agent_id = out.agent_id; 342 if (name) { 343 *name = strdup(out.name); 344 if (!*name) 345 return -ENOMEM; 346 } 347 348 return 0; 349} 350 351/** 352 * scmi_base_set_device_permissions_int - configure access permission to device 353 * @dev: SCMI device 354 * @agent_id: SCMI agent ID 355 * @device_id: ID of device to access 356 * @flags: A set of flags 357 * 358 * Ask for allowing or denying access permission to the device, @device_id. 359 * The meaning of @flags is defined in SCMI specification. 360 * 361 * Return: 0 on success, error code on failure 362 */ 363static int scmi_base_set_device_permissions_int(struct udevice *dev, u32 agent_id, 364 u32 device_id, u32 flags) 365{ 366 struct scmi_base_set_device_permissions_in in = { 367 .agent_id = agent_id, 368 .device_id = device_id, 369 .flags = flags, 370 }; 371 s32 status; 372 struct scmi_msg msg = { 373 .protocol_id = SCMI_PROTOCOL_ID_BASE, 374 .message_id = SCMI_BASE_SET_DEVICE_PERMISSIONS, 375 .in_msg = (u8 *)&in, 376 .in_msg_sz = sizeof(in), 377 .out_msg = (u8 *)&status, 378 .out_msg_sz = sizeof(status), 379 }; 380 int ret; 381 382 ret = devm_scmi_process_msg(dev, &msg); 383 if (ret) 384 return ret; 385 if (status) 386 return scmi_to_linux_errno(status); 387 388 return 0; 389} 390 391/** 392 * scmi_base_set_protocol_permissions_int - configure access permission to 393 * protocol on device 394 * @dev: SCMI device 395 * @agent_id: SCMI agent ID 396 * @device_id: ID of device to access 397 * @command_id: SCMI command ID 398 * @flags: A set of flags 399 * 400 * Ask for allowing or denying access permission to the protocol, @command_id, 401 * on the device, @device_id. 402 * The meaning of @flags is defined in SCMI specification. 403 * 404 * Return: 0 on success, error code on failure 405 */ 406static int scmi_base_set_protocol_permissions_int(struct udevice *dev, 407 u32 agent_id, u32 device_id, 408 u32 command_id, u32 flags) 409{ 410 struct scmi_base_set_protocol_permissions_in in = { 411 .agent_id = agent_id, 412 .device_id = device_id, 413 .command_id = command_id, 414 .flags = flags, 415 }; 416 s32 status; 417 struct scmi_msg msg = { 418 .protocol_id = SCMI_PROTOCOL_ID_BASE, 419 .message_id = SCMI_BASE_SET_PROTOCOL_PERMISSIONS, 420 .in_msg = (u8 *)&in, 421 .in_msg_sz = sizeof(in), 422 .out_msg = (u8 *)&status, 423 .out_msg_sz = sizeof(status), 424 }; 425 int ret; 426 427 ret = devm_scmi_process_msg(dev, &msg); 428 if (ret) 429 return ret; 430 if (status) 431 return scmi_to_linux_errno(status); 432 433 return 0; 434} 435 436/** 437 * scmi_base_reset_agent_configuration_int - reset resource settings 438 * @dev: SCMI device 439 * @agent_id: SCMI agent ID 440 * @flags: A set of flags 441 * 442 * Reset all the resource settings against @agent_id. 443 * The meaning of @flags is defined in SCMI specification. 444 * 445 * Return: 0 on success, error code on failure 446 */ 447static int scmi_base_reset_agent_configuration_int(struct udevice *dev, 448 u32 agent_id, u32 flags) 449{ 450 struct scmi_base_reset_agent_configuration_in in = { 451 .agent_id = agent_id, 452 .flags = flags, 453 }; 454 s32 status; 455 struct scmi_msg msg = { 456 .protocol_id = SCMI_PROTOCOL_ID_BASE, 457 .message_id = SCMI_BASE_RESET_AGENT_CONFIGURATION, 458 .in_msg = (u8 *)&in, 459 .in_msg_sz = sizeof(in), 460 .out_msg = (u8 *)&status, 461 .out_msg_sz = sizeof(status), 462 }; 463 int ret; 464 465 ret = devm_scmi_process_msg(dev, &msg); 466 if (ret) 467 return ret; 468 if (status) 469 return scmi_to_linux_errno(status); 470 471 return 0; 472} 473 474/** 475 * scmi_base_probe - probe base protocol device 476 * @dev: SCMI device 477 * 478 * Probe the device for SCMI base protocol and initialize the private data. 479 * 480 * Return: 0 on success, error code on failure 481 */ 482static int scmi_base_probe(struct udevice *dev) 483{ 484 u32 version; 485 int ret; 486 487 ret = devm_scmi_of_get_channel(dev); 488 if (ret) { 489 dev_err(dev, "get_channel failed\n"); 490 return ret; 491 } 492 ret = scmi_base_protocol_version_int(dev, &version); 493 if (ret) { 494 dev_err(dev, "getting protocol version failed\n"); 495 return ret; 496 } 497 if (version < SCMI_BASE_PROTOCOL_VERSION) 498 return -EINVAL; 499 500 return ret; 501} 502 503static struct scmi_base_ops scmi_base_ops = { 504 /* Commands */ 505 .protocol_version = scmi_base_protocol_version_int, 506 .protocol_attrs = scmi_protocol_attrs_int, 507 .protocol_message_attrs = scmi_protocol_message_attrs_int, 508 .base_discover_vendor = scmi_base_discover_vendor_int, 509 .base_discover_sub_vendor = scmi_base_discover_sub_vendor_int, 510 .base_discover_impl_version = scmi_base_discover_impl_version_int, 511 .base_discover_list_protocols = scmi_base_discover_list_protocols_int, 512 .base_discover_agent = scmi_base_discover_agent_int, 513 .base_notify_errors = NULL, 514 .base_set_device_permissions = scmi_base_set_device_permissions_int, 515 .base_set_protocol_permissions = scmi_base_set_protocol_permissions_int, 516 .base_reset_agent_configuration = 517 scmi_base_reset_agent_configuration_int, 518}; 519 520int scmi_base_protocol_version(struct udevice *dev, u32 *version) 521{ 522 const struct scmi_base_ops *ops = device_get_ops(dev); 523 524 if (ops->protocol_version) 525 return (*ops->protocol_version)(dev, version); 526 527 return -EOPNOTSUPP; 528} 529 530int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents, 531 u32 *num_protocols) 532{ 533 const struct scmi_base_ops *ops = device_get_ops(dev); 534 535 if (ops->protocol_attrs) 536 return (*ops->protocol_attrs)(dev, num_agents, num_protocols); 537 538 return -EOPNOTSUPP; 539} 540 541int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id, 542 u32 *attributes) 543{ 544 const struct scmi_base_ops *ops = device_get_ops(dev); 545 546 if (ops->protocol_message_attrs) 547 return (*ops->protocol_message_attrs)(dev, message_id, 548 attributes); 549 550 return -EOPNOTSUPP; 551} 552 553int scmi_base_discover_vendor(struct udevice *dev, u8 **vendor) 554{ 555 const struct scmi_base_ops *ops = device_get_ops(dev); 556 557 if (ops->base_discover_vendor) 558 return (*ops->base_discover_vendor)(dev, vendor); 559 560 return -EOPNOTSUPP; 561} 562 563int scmi_base_discover_sub_vendor(struct udevice *dev, u8 **sub_vendor) 564{ 565 const struct scmi_base_ops *ops = device_get_ops(dev); 566 567 if (ops->base_discover_sub_vendor) 568 return (*ops->base_discover_sub_vendor)(dev, sub_vendor); 569 570 return -EOPNOTSUPP; 571} 572 573int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version) 574{ 575 const struct scmi_base_ops *ops = device_get_ops(dev); 576 577 if (ops->base_discover_impl_version) 578 return (*ops->base_discover_impl_version)(dev, impl_version); 579 580 return -EOPNOTSUPP; 581} 582 583int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols) 584{ 585 const struct scmi_base_ops *ops = device_get_ops(dev); 586 587 if (ops->base_discover_list_protocols) 588 return (*ops->base_discover_list_protocols)(dev, protocols); 589 590 return -EOPNOTSUPP; 591} 592 593int scmi_base_discover_agent(struct udevice *dev, u32 agent_id, 594 u32 *ret_agent_id, u8 **name) 595{ 596 const struct scmi_base_ops *ops = device_get_ops(dev); 597 598 if (ops->base_discover_agent) 599 return (*ops->base_discover_agent)(dev, agent_id, ret_agent_id, 600 name); 601 602 return -EOPNOTSUPP; 603} 604 605int scmi_base_notify_errors(struct udevice *dev, u32 enable) 606{ 607 const struct scmi_base_ops *ops = device_get_ops(dev); 608 609 if (ops->base_notify_errors) 610 return (*ops->base_notify_errors)(dev, enable); 611 612 return -EOPNOTSUPP; 613} 614 615int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id, 616 u32 device_id, u32 flags) 617{ 618 const struct scmi_base_ops *ops = device_get_ops(dev); 619 620 if (ops->base_set_device_permissions) 621 return (*ops->base_set_device_permissions)(dev, agent_id, 622 device_id, flags); 623 624 return -EOPNOTSUPP; 625} 626 627int scmi_base_set_protocol_permissions(struct udevice *dev, 628 u32 agent_id, u32 device_id, 629 u32 command_id, u32 flags) 630{ 631 const struct scmi_base_ops *ops = device_get_ops(dev); 632 633 if (ops->base_set_protocol_permissions) 634 return (*ops->base_set_protocol_permissions)(dev, agent_id, 635 device_id, 636 command_id, 637 flags); 638 639 return -EOPNOTSUPP; 640} 641 642int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id, 643 u32 flags) 644{ 645 const struct scmi_base_ops *ops = device_get_ops(dev); 646 647 if (ops->base_reset_agent_configuration) 648 return (*ops->base_reset_agent_configuration)(dev, agent_id, 649 flags); 650 651 return -EOPNOTSUPP; 652} 653 654U_BOOT_DRIVER(scmi_base_drv) = { 655 .id = UCLASS_SCMI_BASE, 656 .name = "scmi_base_drv", 657 .ops = &scmi_base_ops, 658 .probe = scmi_base_probe, 659}; 660 661UCLASS_DRIVER(scmi_base) = { 662 .id = UCLASS_SCMI_BASE, 663 .name = "scmi_base", 664}; 665