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 <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 /* 17 * The sandbox SCMI agent driver simulates to some extend a SCMI message 18 * processing. It simulates few of the SCMI services for some of the 19 * SCMI protocols embedded in U-Boot. Currently none. 20 * 21 * This driver simulates 2 SCMI agents for test purpose. 22 * 23 * This Driver exports sandbox_scmi_service_ct() for the test sequence to 24 * get the state of the simulated services (clock state, rate, ...) and 25 * check back-end device state reflects the request send through the 26 * various uclass devices, currently nothing. 27 */ 28 29 #define SANDBOX_SCMI_AGENT_COUNT 2 30 31 /* The list saves to simulted end devices references for test purpose */ 32 struct sandbox_scmi_agent *sandbox_scmi_agent_list[SANDBOX_SCMI_AGENT_COUNT]; 33 34 static struct sandbox_scmi_service sandbox_scmi_service_state = { 35 .agent = sandbox_scmi_agent_list, 36 .agent_count = SANDBOX_SCMI_AGENT_COUNT, 37 }; 38 39 struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) 40 { 41 return &sandbox_scmi_service_state; 42 } 43 44 static void debug_print_agent_state(struct udevice *dev, char *str) 45 { 46 struct sandbox_scmi_agent *agent = dev_get_priv(dev); 47 48 dev_dbg(dev, "Dump sandbox_scmi_agent %u: %s\n", agent->idx, str); 49 }; 50 51 static int sandbox_scmi_test_process_msg(struct udevice *dev, 52 struct scmi_msg *msg) 53 { 54 switch (msg->protocol_id) { 55 case SCMI_PROTOCOL_ID_BASE: 56 case SCMI_PROTOCOL_ID_POWER_DOMAIN: 57 case SCMI_PROTOCOL_ID_SYSTEM: 58 case SCMI_PROTOCOL_ID_PERF: 59 case SCMI_PROTOCOL_ID_CLOCK: 60 case SCMI_PROTOCOL_ID_SENSOR: 61 case SCMI_PROTOCOL_ID_RESET_DOMAIN: 62 *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; 63 return 0; 64 default: 65 break; 66 } 67 68 dev_err(dev, "%s(%s): Unhandled protocol_id %#x/message_id %#x\n", 69 __func__, dev->name, msg->protocol_id, msg->message_id); 70 71 if (msg->out_msg_sz < sizeof(u32)) 72 return -EINVAL; 73 74 /* Intentionnaly report unhandled IDs through the SCMI return code */ 75 *(u32 *)msg->out_msg = SCMI_PROTOCOL_ERROR; 76 return 0; 77 } 78 79 static int sandbox_scmi_test_remove(struct udevice *dev) 80 { 81 struct sandbox_scmi_agent *agent = dev_get_priv(dev); 82 83 debug_print_agent_state(dev, "removed"); 84 85 /* We only need to dereference the agent in the context */ 86 sandbox_scmi_service_ctx()->agent[agent->idx] = NULL; 87 88 return 0; 89 } 90 91 static int sandbox_scmi_test_probe(struct udevice *dev) 92 { 93 static const char basename[] = "sandbox-scmi-agent@"; 94 struct sandbox_scmi_agent *agent = dev_get_priv(dev); 95 const size_t basename_size = sizeof(basename) - 1; 96 97 if (strncmp(basename, dev->name, basename_size)) 98 return -ENOENT; 99 100 switch (dev->name[basename_size]) { 101 case '0': 102 *agent = (struct sandbox_scmi_agent){ 103 .idx = 0, 104 }; 105 break; 106 case '1': 107 *agent = (struct sandbox_scmi_agent){ 108 .idx = 1, 109 }; 110 break; 111 default: 112 dev_err(dev, "%s(): Unexpected agent ID %s\n", 113 __func__, dev->name + basename_size); 114 return -ENOENT; 115 } 116 117 debug_print_agent_state(dev, "probed"); 118 119 /* Save reference for tests purpose */ 120 sandbox_scmi_service_ctx()->agent[agent->idx] = agent; 121 122 return 0; 123 }; 124 125 static const struct udevice_id sandbox_scmi_test_ids[] = { 126 { .compatible = "sandbox,scmi-agent" }, 127 { } 128 }; 129 130 struct scmi_agent_ops sandbox_scmi_test_ops = { 131 .process_msg = sandbox_scmi_test_process_msg, 132 }; 133 134 U_BOOT_DRIVER(sandbox_scmi_agent) = { 135 .name = "sandbox-scmi_agent", 136 .id = UCLASS_SCMI_AGENT, 137 .of_match = sandbox_scmi_test_ids, 138 .priv_auto_alloc_size = sizeof(struct sandbox_scmi_agent), 139 .probe = sandbox_scmi_test_probe, 140 .remove = sandbox_scmi_test_remove, 141 .ops = &sandbox_scmi_test_ops, 142 }; 143