1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019-2021, Linaro Limited 4 * Copyright (c) 2019-2021, STMicroelectronics 5 */ 6 #include <compiler.h> 7 #include <config.h> 8 #include <drivers/scmi-msg.h> 9 #include <kernel/pseudo_ta.h> 10 #include <pta_scmi_client.h> 11 #include <stdint.h> 12 #include <string.h> 13 14 static TEE_Result cmd_capabilities(uint32_t ptypes, 15 TEE_Param param[TEE_NUM_PARAMS]) 16 { 17 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 18 TEE_PARAM_TYPE_NONE, 19 TEE_PARAM_TYPE_NONE, 20 TEE_PARAM_TYPE_NONE); 21 uint32_t caps = 0; 22 23 if (ptypes != exp_ptypes) 24 return TEE_ERROR_BAD_PARAMETERS; 25 26 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) 27 caps |= PTA_SCMI_CAPS_SMT_HEADER; 28 29 param[0].value.a = caps; 30 param[0].value.b = 0; 31 32 return TEE_SUCCESS; 33 } 34 35 static TEE_Result cmd_process_smt_channel(uint32_t ptypes, 36 TEE_Param params[TEE_NUM_PARAMS]) 37 { 38 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 39 TEE_PARAM_TYPE_NONE, 40 TEE_PARAM_TYPE_NONE, 41 TEE_PARAM_TYPE_NONE); 42 unsigned int channel_id = params[0].value.a; 43 44 if (ptypes != exp_ptypes) 45 return TEE_ERROR_BAD_PARAMETERS; 46 47 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 48 struct scmi_msg_channel *channel = NULL; 49 50 channel = plat_scmi_get_channel(channel_id); 51 if (!channel) 52 return TEE_ERROR_BAD_PARAMETERS; 53 54 scmi_smt_threaded_entry(channel_id); 55 56 return TEE_SUCCESS; 57 } 58 59 return TEE_ERROR_NOT_SUPPORTED; 60 } 61 62 static TEE_Result cmd_process_smt_message(uint32_t ptypes, 63 TEE_Param params[TEE_NUM_PARAMS]) 64 { 65 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 66 TEE_PARAM_TYPE_MEMREF_INOUT, 67 TEE_PARAM_TYPE_NONE, 68 TEE_PARAM_TYPE_NONE); 69 unsigned int channel_id = params[0].value.a; 70 TEE_Param *param1 = params + 1; 71 72 if (ptypes != exp_ptypes) 73 return TEE_ERROR_BAD_PARAMETERS; 74 75 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 76 struct scmi_msg_channel *channel = NULL; 77 78 if (param1->memref.size < SMT_BUF_SLOT_SIZE) 79 return TEE_ERROR_BAD_PARAMETERS; 80 81 channel = plat_scmi_get_channel(channel_id); 82 if (!channel) 83 return TEE_ERROR_BAD_PARAMETERS; 84 85 /* 86 * Caller provides the buffer, we bind channel to that buffer. 87 * Once message is processed, unbind the buffer since it is 88 * valid only for the current invocation. 89 */ 90 scmi_smt_set_shared_buffer(channel, param1->memref.buffer); 91 scmi_smt_threaded_entry(channel_id); 92 scmi_smt_set_shared_buffer(channel, NULL); 93 94 return TEE_SUCCESS; 95 } 96 97 return TEE_ERROR_NOT_SUPPORTED; 98 } 99 100 static TEE_Result cmd_get_channel_handle(uint32_t ptypes, 101 TEE_Param params[TEE_NUM_PARAMS]) 102 { 103 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, 104 TEE_PARAM_TYPE_NONE, 105 TEE_PARAM_TYPE_NONE, 106 TEE_PARAM_TYPE_NONE); 107 unsigned int channel_id = params[0].value.a; 108 unsigned int caps = params[0].value.b; 109 110 if (ptypes != exp_ptypes) 111 return TEE_ERROR_BAD_PARAMETERS; 112 113 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 114 struct scmi_msg_channel *channel = NULL; 115 116 if (caps != PTA_SCMI_CAPS_SMT_HEADER) 117 return TEE_ERROR_NOT_SUPPORTED; 118 119 channel = plat_scmi_get_channel(channel_id); 120 if (!channel) 121 return TEE_ERROR_BAD_PARAMETERS; 122 123 params[0].value.a = scmi_smt_channel_handle(channel_id); 124 125 return TEE_SUCCESS; 126 } 127 128 return TEE_ERROR_NOT_SUPPORTED; 129 } 130 131 static TEE_Result pta_scmi_open_session(uint32_t ptypes __unused, 132 TEE_Param par[TEE_NUM_PARAMS] __unused, 133 void **session __unused) 134 { 135 struct ts_session *ts = ts_get_current_session(); 136 struct tee_ta_session *ta_session = to_ta_session(ts); 137 138 /* Only REE kernel is allowed to access SCMI resources */ 139 if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) { 140 DMSG("Expecting TEE_LOGIN_REE_KERNEL"); 141 return TEE_ERROR_ACCESS_DENIED; 142 } 143 144 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) 145 return TEE_SUCCESS; 146 147 return TEE_ERROR_NOT_SUPPORTED; 148 } 149 150 static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd, 151 uint32_t ptypes, 152 TEE_Param params[TEE_NUM_PARAMS]) 153 { 154 FMSG("SCMI command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); 155 156 switch (cmd) { 157 case PTA_SCMI_CMD_CAPABILITIES: 158 return cmd_capabilities(ptypes, params); 159 case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL: 160 return cmd_process_smt_channel(ptypes, params); 161 case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE: 162 return cmd_process_smt_message(ptypes, params); 163 case PTA_SCMI_CMD_GET_CHANNEL_HANDLE: 164 return cmd_get_channel_handle(ptypes, params); 165 default: 166 return TEE_ERROR_NOT_SUPPORTED; 167 } 168 } 169 170 pseudo_ta_register(.uuid = PTA_SCMI_UUID, .name = PTA_SCMI_NAME, 171 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | 172 TA_FLAG_DEVICE_ENUM, 173 .open_session_entry_point = pta_scmi_open_session, 174 .invoke_command_entry_point = pta_scmi_invoke_command); 175