1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2020 Linaro Limited. 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <scmi_agent-uclass.h> 10 #include <scmi_protocols.h> 11 12 #include <dm/device-internal.h> 13 #include <linux/compat.h> 14 15 /** 16 * struct error_code - Helper structure for SCMI error code conversion 17 * @scmi: SCMI error code 18 * @errno: Related standard error number 19 */ 20 struct error_code { 21 int scmi; 22 int errno; 23 }; 24 25 static const struct error_code scmi_linux_errmap[] = { 26 { .scmi = SCMI_NOT_SUPPORTED, .errno = -EOPNOTSUPP, }, 27 { .scmi = SCMI_INVALID_PARAMETERS, .errno = -EINVAL, }, 28 { .scmi = SCMI_DENIED, .errno = -EACCES, }, 29 { .scmi = SCMI_NOT_FOUND, .errno = -ENOENT, }, 30 { .scmi = SCMI_OUT_OF_RANGE, .errno = -ERANGE, }, 31 { .scmi = SCMI_BUSY, .errno = -EBUSY, }, 32 { .scmi = SCMI_COMMS_ERROR, .errno = -ECOMM, }, 33 { .scmi = SCMI_GENERIC_ERROR, .errno = -EIO, }, 34 { .scmi = SCMI_HARDWARE_ERROR, .errno = -EREMOTEIO, }, 35 { .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, }, 36 }; 37 38 int scmi_to_linux_errno(s32 scmi_code) 39 { 40 int n; 41 42 if (!scmi_code) 43 return 0; 44 45 for (n = 0; n < ARRAY_SIZE(scmi_linux_errmap); n++) 46 if (scmi_code == scmi_linux_errmap[n].scmi) 47 return scmi_linux_errmap[1].errno; 48 49 return -EPROTO; 50 } 51 52 /* 53 * SCMI agent devices binds devices of various uclasses depeding on 54 * the FDT description. scmi_bind_protocol() is a generic bind sequence 55 * called by the uclass at bind stage, that is uclass post_bind. 56 */ 57 static int scmi_bind_protocols(struct udevice *dev) 58 { 59 int ret = 0; 60 ofnode node; 61 struct driver *drv; 62 63 dev_for_each_subnode(node, dev) { 64 u32 protocol_id; 65 66 if (!ofnode_is_available(node)) 67 continue; 68 69 if (ofnode_read_u32(node, "reg", &protocol_id)) 70 continue; 71 72 switch (protocol_id) { 73 default: 74 dev_info(dev, "Ignore unsupported SCMI protocol %#x\n", 75 protocol_id); 76 continue; 77 } 78 79 ret = device_bind_ofnode(dev, drv, ofnode_get_name(node), 80 NULL, node, NULL); 81 if (ret) 82 break; 83 } 84 85 return ret; 86 } 87 88 static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev) 89 { 90 return (const struct scmi_agent_ops *)dev->driver->ops; 91 } 92 93 int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg) 94 { 95 const struct scmi_agent_ops *ops = transport_dev_ops(dev); 96 97 if (ops->process_msg) 98 return ops->process_msg(dev, msg); 99 100 return -EPROTONOSUPPORT; 101 } 102 103 UCLASS_DRIVER(scmi_agent) = { 104 .id = UCLASS_SCMI_AGENT, 105 .name = "scmi_agent", 106 .post_bind = scmi_bind_protocols, 107 }; 108