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 <errno.h> 11#include <scmi_agent.h> 12#include <scmi_agent-uclass.h> 13#include <scmi_protocols.h> 14#include <dm/device_compat.h> 15#include <dm/device-internal.h> 16#include <linux/compat.h> 17 18/** 19 * struct error_code - Helper structure for SCMI error code conversion 20 * @scmi: SCMI error code 21 * @errno: Related standard error number 22 */ 23struct error_code { 24 int scmi; 25 int errno; 26}; 27 28static const struct error_code scmi_linux_errmap[] = { 29 { .scmi = SCMI_NOT_SUPPORTED, .errno = -EOPNOTSUPP, }, 30 { .scmi = SCMI_INVALID_PARAMETERS, .errno = -EINVAL, }, 31 { .scmi = SCMI_DENIED, .errno = -EACCES, }, 32 { .scmi = SCMI_NOT_FOUND, .errno = -ENOENT, }, 33 { .scmi = SCMI_OUT_OF_RANGE, .errno = -ERANGE, }, 34 { .scmi = SCMI_BUSY, .errno = -EBUSY, }, 35 { .scmi = SCMI_COMMS_ERROR, .errno = -ECOMM, }, 36 { .scmi = SCMI_GENERIC_ERROR, .errno = -EIO, }, 37 { .scmi = SCMI_HARDWARE_ERROR, .errno = -EREMOTEIO, }, 38 { .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, }, 39}; 40 41/** 42 * scmi_protocol_is_supported - check availability of protocol 43 * @dev: SCMI agent device 44 * @proto_id: Identifier of protocol 45 * 46 * check if the protocol, @proto_id, is provided by the SCMI agent, 47 * @dev. 48 * 49 * Return: 0 on success, error code otherwise 50 */ 51static bool scmi_protocol_is_supported(struct udevice *dev, 52 enum scmi_std_protocol proto_id) 53{ 54 struct scmi_agent_priv *priv; 55 int i; 56 57 if (proto_id == SCMI_PROTOCOL_ID_BASE) 58 return true; 59 60 priv = dev_get_uclass_plat(dev); 61 if (!priv) { 62 dev_err(dev, "No priv data found\n"); 63 return false; 64 } 65 66 for (i = 0; i < priv->num_protocols; i++) 67 if (priv->protocols[i] == proto_id) 68 return true; 69 70 return false; 71} 72 73struct udevice *scmi_get_protocol(struct udevice *dev, 74 enum scmi_std_protocol id) 75{ 76 struct scmi_agent_priv *priv; 77 struct udevice *proto; 78 79 priv = dev_get_uclass_plat(dev); 80 if (!priv) { 81 dev_err(dev, "No priv data found\n"); 82 return NULL; 83 } 84 85 switch (id) { 86 case SCMI_PROTOCOL_ID_BASE: 87 proto = priv->base_dev; 88 break; 89 case SCMI_PROTOCOL_ID_POWER_DOMAIN: 90 proto = priv->pwdom_dev; 91 break; 92 case SCMI_PROTOCOL_ID_CLOCK: 93 proto = priv->clock_dev; 94 break; 95 case SCMI_PROTOCOL_ID_RESET_DOMAIN: 96 proto = priv->resetdom_dev; 97 break; 98 case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: 99 proto = priv->voltagedom_dev; 100 break; 101 default: 102 dev_err(dev, "Protocol not supported\n"); 103 proto = NULL; 104 break; 105 } 106 if (proto && device_probe(proto)) 107 dev_err(dev, "Probe failed\n"); 108 109 return proto; 110} 111 112/** 113 * scmi_add_protocol - add protocol to agent 114 * @dev: SCMI agent device 115 * @proto_id: SCMI protocol ID 116 * @proto: SCMI protocol device 117 * 118 * Associate the protocol instance, @proto, to the agent, @dev, 119 * for later use. 120 * 121 * Return: 0 on success, error code on failure 122 */ 123static int scmi_add_protocol(struct udevice *dev, 124 enum scmi_std_protocol proto_id, 125 struct udevice *proto) 126{ 127 struct scmi_agent_priv *priv; 128 129 priv = dev_get_uclass_plat(dev); 130 if (!priv) { 131 dev_err(dev, "No priv data found\n"); 132 return -ENODEV; 133 } 134 135 switch (proto_id) { 136 case SCMI_PROTOCOL_ID_BASE: 137 priv->base_dev = proto; 138 break; 139 case SCMI_PROTOCOL_ID_POWER_DOMAIN: 140 priv->pwdom_dev = proto; 141 break; 142 case SCMI_PROTOCOL_ID_CLOCK: 143 priv->clock_dev = proto; 144 break; 145 case SCMI_PROTOCOL_ID_RESET_DOMAIN: 146 priv->resetdom_dev = proto; 147 break; 148 case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: 149 priv->voltagedom_dev = proto; 150 break; 151 default: 152 dev_err(dev, "Protocol not supported\n"); 153 return -EPROTO; 154 } 155 156 return 0; 157} 158 159int scmi_to_linux_errno(s32 scmi_code) 160{ 161 int n; 162 163 if (!scmi_code) 164 return 0; 165 166 for (n = 0; n < ARRAY_SIZE(scmi_linux_errmap); n++) 167 if (scmi_code == scmi_linux_errmap[n].scmi) 168 return scmi_linux_errmap[n].errno; 169 170 return -EPROTO; 171} 172 173static struct udevice *find_scmi_protocol_device(struct udevice *dev) 174{ 175 struct udevice *parent = NULL, *protocol; 176 177 for (protocol = dev; protocol; protocol = parent) { 178 parent = dev_get_parent(protocol); 179 if (!parent || 180 device_get_uclass_id(parent) == UCLASS_SCMI_AGENT) 181 break; 182 } 183 184 if (!parent) { 185 dev_err(dev, "Invalid SCMI device, agent not found\n"); 186 return NULL; 187 } 188 189 return protocol; 190} 191 192static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev) 193{ 194 return (const struct scmi_agent_ops *)dev->driver->ops; 195} 196 197/** 198 * scmi_of_get_channel() - Get SCMI channel handle 199 * 200 * @dev: SCMI agent device 201 * @channel: Output reference to the SCMI channel upon success 202 * 203 * On return, @channel will be set. 204 * Return 0 on success and a negative errno on failure 205 */ 206static int scmi_of_get_channel(struct udevice *dev, struct udevice *protocol, 207 struct scmi_channel **channel) 208{ 209 const struct scmi_agent_ops *ops; 210 211 ops = transport_dev_ops(dev); 212 if (ops->of_get_channel) 213 return ops->of_get_channel(dev, protocol, channel); 214 else 215 return -EPROTONOSUPPORT; 216} 217 218int devm_scmi_of_get_channel(struct udevice *dev) 219{ 220 struct udevice *protocol; 221 struct scmi_agent_proto_priv *priv; 222 int ret; 223 224 protocol = find_scmi_protocol_device(dev); 225 if (!protocol) 226 return -ENODEV; 227 228 priv = dev_get_parent_priv(protocol); 229 ret = scmi_of_get_channel(protocol->parent, protocol, &priv->channel); 230 if (ret == -EPROTONOSUPPORT) { 231 /* Drivers without a get_channel operator don't need a channel ref */ 232 priv->channel = NULL; 233 234 return 0; 235 } 236 237 return ret; 238} 239 240/** 241 * scmi_process_msg() - Send and process an SCMI message 242 * 243 * Send a message to an SCMI server. 244 * Caller sets scmi_msg::out_msg_sz to the output message buffer size. 245 * 246 * @dev: SCMI agent device 247 * @channel: Communication channel for the device 248 * @msg: Message structure reference 249 * 250 * On return, scmi_msg::out_msg_sz stores the response payload size. 251 * Return: 0 on success and a negative errno on failure 252 */ 253static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel, 254 struct scmi_msg *msg) 255{ 256 const struct scmi_agent_ops *ops; 257 258 ops = transport_dev_ops(dev); 259 if (ops->process_msg) 260 return ops->process_msg(dev, channel, msg); 261 else 262 return -EPROTONOSUPPORT; 263} 264 265int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg) 266{ 267 struct udevice *protocol; 268 struct scmi_agent_proto_priv *priv; 269 270 protocol = find_scmi_protocol_device(dev); 271 if (!protocol) 272 return -ENODEV; 273 274 priv = dev_get_parent_priv(protocol); 275 276 return scmi_process_msg(protocol->parent, priv->channel, msg); 277} 278 279/** 280 * scmi_fill_base_info - get base information about SCMI server 281 * @agent: SCMI agent device 282 * @dev: SCMI protocol device 283 * 284 * By using Base protocol commands, collect the base information 285 * about SCMI server. 286 * 287 * Return: 0 on success, error code on failure 288 */ 289static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev) 290{ 291 struct scmi_agent_priv *priv = dev_get_uclass_plat(agent); 292 int ret; 293 294 ret = scmi_base_protocol_version(dev, &priv->version); 295 if (ret) { 296 dev_err(dev, "protocol_version() failed (%d)\n", ret); 297 return ret; 298 } 299 /* check for required version */ 300 if (priv->version < SCMI_BASE_PROTOCOL_VERSION) { 301 dev_err(dev, "base protocol version (%d) lower than expected\n", 302 priv->version); 303 return -EPROTO; 304 } 305 306 ret = scmi_base_protocol_attrs(dev, &priv->num_agents, 307 &priv->num_protocols); 308 if (ret) { 309 dev_err(dev, "protocol_attrs() failed (%d)\n", ret); 310 return ret; 311 } 312 ret = scmi_base_discover_vendor(dev, &priv->vendor); 313 if (ret) { 314 dev_err(dev, "base_discover_vendor() failed (%d)\n", ret); 315 return ret; 316 } 317 ret = scmi_base_discover_sub_vendor(dev, &priv->sub_vendor); 318 if (ret) { 319 if (ret != -EOPNOTSUPP) { 320 dev_err(dev, "base_discover_sub_vendor() failed (%d)\n", 321 ret); 322 return ret; 323 } 324 priv->sub_vendor = "NA"; 325 } 326 ret = scmi_base_discover_impl_version(dev, &priv->impl_version); 327 if (ret) { 328 dev_err(dev, "base_discover_impl_version() failed (%d)\n", 329 ret); 330 return ret; 331 } 332 333 ret = scmi_base_discover_agent(dev, 0xffffffff, 334 &priv->agent_id, &priv->agent_name); 335 if (ret) { 336 if (ret != -EOPNOTSUPP) { 337 dev_err(dev, 338 "base_discover_agent() failed for myself (%d)\n", 339 ret); 340 return ret; 341 } 342 priv->agent_id = 0xffffffff; 343 priv->agent_name = "NA"; 344 } 345 346 ret = scmi_base_discover_list_protocols(dev, &priv->protocols); 347 if (ret != priv->num_protocols) { 348 dev_err(dev, "base_discover_list_protocols() failed (%d)\n", 349 ret); 350 return -EPROTO; 351 } 352 353 return 0; 354} 355 356/* 357 * SCMI agent devices binds devices of various uclasses depending on 358 * the FDT description. scmi_bind_protocol() is a generic bind sequence 359 * called by the uclass at bind stage, that is uclass post_bind. 360 */ 361static int scmi_bind_protocols(struct udevice *dev) 362{ 363 int ret = 0; 364 ofnode node; 365 const char *name; 366 struct driver *drv; 367 struct udevice *agent, *proto; 368 369 if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) { 370 /* This is a second SCMI agent */ 371 dev_err(dev, "Cannot have more than one SCMI agent\n"); 372 return -EEXIST; 373 } 374 375 /* initialize the device from device tree */ 376 drv = DM_DRIVER_GET(scmi_base_drv); 377 name = "scmi-base.0"; 378 ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto); 379 if (ret) { 380 dev_err(dev, "failed to bind base protocol\n"); 381 return ret; 382 } 383 ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto); 384 if (ret) { 385 dev_err(dev, "failed to add protocol: %s, ret: %d\n", 386 proto->name, ret); 387 return ret; 388 } 389 390 ret = device_probe(proto); 391 if (ret) { 392 dev_err(dev, "failed to probe base protocol\n"); 393 return ret; 394 } 395 396 ret = scmi_fill_base_info(dev, proto); 397 if (ret) { 398 dev_err(dev, "failed to get base information\n"); 399 return ret; 400 } 401 402 dev_for_each_subnode(node, dev) { 403 u32 protocol_id; 404 405 if (!ofnode_is_enabled(node)) 406 continue; 407 408 if (ofnode_read_u32(node, "reg", &protocol_id)) 409 continue; 410 411 drv = NULL; 412 name = ofnode_get_name(node); 413 switch (protocol_id) { 414 case SCMI_PROTOCOL_ID_POWER_DOMAIN: 415 if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN) && 416 scmi_protocol_is_supported(dev, protocol_id)) 417 drv = DM_DRIVER_GET(scmi_power_domain); 418 break; 419 case SCMI_PROTOCOL_ID_CLOCK: 420 if (CONFIG_IS_ENABLED(CLK_SCMI) && 421 scmi_protocol_is_supported(dev, protocol_id)) 422 drv = DM_DRIVER_GET(scmi_clock); 423 break; 424 case SCMI_PROTOCOL_ID_RESET_DOMAIN: 425 if (IS_ENABLED(CONFIG_RESET_SCMI) && 426 scmi_protocol_is_supported(dev, protocol_id)) 427 drv = DM_DRIVER_GET(scmi_reset_domain); 428 break; 429 case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: 430 if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) && 431 scmi_protocol_is_supported(dev, protocol_id)) { 432 node = ofnode_find_subnode(node, "regulators"); 433 if (!ofnode_valid(node)) { 434 dev_err(dev, "no regulators node\n"); 435 return -ENXIO; 436 } 437 drv = DM_DRIVER_GET(scmi_voltage_domain); 438 } 439 break; 440 default: 441 break; 442 } 443 444 if (!drv) { 445 dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n", 446 protocol_id); 447 continue; 448 } 449 450 ret = device_bind(dev, drv, name, NULL, node, &proto); 451 if (ret) { 452 dev_err(dev, "failed to bind %s protocol\n", drv->name); 453 break; 454 } 455 ret = scmi_add_protocol(dev, protocol_id, proto); 456 if (ret) { 457 dev_err(dev, "failed to add protocol: %s, ret: %d\n", 458 proto->name, ret); 459 break; 460 } 461 } 462 463 return ret; 464} 465 466UCLASS_DRIVER(scmi_agent) = { 467 .id = UCLASS_SCMI_AGENT, 468 .name = "scmi_agent", 469 .post_bind = scmi_bind_protocols, 470 .per_device_plat_auto = sizeof(struct scmi_agent_priv), 471 .per_child_auto = sizeof(struct scmi_agent_proto_priv), 472}; 473