optee_agent.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020-2022 Linaro Limited.
  4. */
  5. #define LOG_CATEGORY UCLASS_SCMI_AGENT
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <errno.h>
  9. #include <scmi_agent.h>
  10. #include <scmi_agent-uclass.h>
  11. #include <string.h>
  12. #include <tee.h>
  13. #include <asm/types.h>
  14. #include <dm/device_compat.h>
  15. #include <dm/devres.h>
  16. #include <linux/arm-smccc.h>
  17. #include <linux/bug.h>
  18. #include <linux/compat.h>
  19. #include "smt.h"
  20. #define SCMI_SHM_SIZE 128
  21. /**
  22. * struct scmi_optee_channel - Description of an SCMI OP-TEE transport
  23. * @channel_id: Channel identifier
  24. * @smt: Shared memory buffer with synchronisation protocol
  25. * @dyn_shm: True if using dynamically allocated shared memory
  26. */
  27. struct scmi_optee_channel {
  28. unsigned int channel_id;
  29. struct scmi_smt smt;
  30. bool dyn_shm;
  31. };
  32. /**
  33. * struct scmi_channel - Channel instance referenced in SCMI drivers
  34. * @ref: Reference to local channel instance
  35. **/
  36. struct scmi_channel {
  37. struct scmi_optee_channel ref;
  38. };
  39. /**
  40. * struct channel_session - Aggreates SCMI service session context references
  41. * @tee: OP-TEE device to invoke
  42. * @tee_session: OP-TEE session identifier
  43. * @tee_shm: Dynamically allocated OP-TEE shared memory, or NULL
  44. * @channel_hdl: Channel handle provided by OP-TEE SCMI service
  45. */
  46. struct channel_session {
  47. struct udevice *tee;
  48. u32 tee_session;
  49. struct tee_shm *tee_shm;
  50. u32 channel_hdl;
  51. };
  52. #define TA_SCMI_UUID { 0xa8cfe406, 0xd4f5, 0x4a2e, \
  53. { 0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99 } }
  54. enum optee_smci_pta_cmd {
  55. /*
  56. * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities
  57. *
  58. * [out] value[0].a: Capability bit mask (enum pta_scmi_caps)
  59. * [out] value[0].b: Extended capabilities or 0
  60. */
  61. PTA_SCMI_CMD_CAPABILITIES = 0,
  62. /*
  63. * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer
  64. *
  65. * [in] value[0].a: Channel handle
  66. *
  67. * Shared memory used for SCMI message/response exhange is expected
  68. * already identified and bound to channel handle in both SCMI agent
  69. * and SCMI server (OP-TEE) parts.
  70. * The memory uses SMT header to carry SCMI meta-data (protocol ID and
  71. * protocol message ID).
  72. */
  73. PTA_SCMI_CMD_PROCESS_SMT_CHANNEL = 1,
  74. /*
  75. * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SMT/SCMI message
  76. *
  77. * [in] value[0].a: Channel handle
  78. * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload)
  79. *
  80. * Shared memory used for SCMI message/response is a SMT buffer
  81. * referenced by param[1]. It shall be 128 bytes large to fit response
  82. * payload whatever message playload size.
  83. * The memory uses SMT header to carry SCMI meta-data (protocol ID and
  84. * protocol message ID).
  85. */
  86. PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE = 2,
  87. /*
  88. * PTA_SCMI_CMD_GET_CHANNEL - Get channel handle
  89. *
  90. * [in] value[0].a: Channel identifier
  91. * [out] value[0].a: Returned channel handle
  92. * [in] value[0].b: Requested capabilities mask (enum pta_scmi_caps)
  93. */
  94. PTA_SCMI_CMD_GET_CHANNEL = 3,
  95. /*
  96. * PTA_SCMI_CMD_PROCESS_MSG_CHANNEL - Process SCMI message in MSG
  97. * buffers pointed by memref parameters
  98. *
  99. * [in] value[0].a: Channel handle
  100. * [in] memref[1]: Message buffer (MSG header and SCMI payload)
  101. * [out] memref[2]: Response buffer (MSG header and SCMI payload)
  102. *
  103. * Shared memories used for SCMI message/response are MSG buffers
  104. * referenced by param[1] and param[2]. MSG transport protocol
  105. * uses a 32bit header to carry SCMI meta-data (protocol ID and
  106. * protocol message ID) followed by the effective SCMI message
  107. * payload.
  108. */
  109. PTA_SCMI_CMD_PROCESS_MSG_CHANNEL = 4,
  110. };
  111. /*
  112. * OP-TEE SCMI service capabilities bit flags (32bit)
  113. *
  114. * PTA_SCMI_CAPS_SMT_HEADER
  115. * When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in
  116. * shared memory buffers to carry SCMI protocol synchronisation information.
  117. *
  118. * PTA_SCMI_CAPS_MSG_HEADER
  119. * When set, OP-TEE supports command using MSG header protocol in an OP-TEE
  120. * shared memory to carry SCMI protocol synchronisation information and SCMI
  121. * message payload.
  122. */
  123. #define PTA_SCMI_CAPS_NONE 0
  124. #define PTA_SCMI_CAPS_SMT_HEADER BIT(0)
  125. #define PTA_SCMI_CAPS_MSG_HEADER BIT(1)
  126. #define PTA_SCMI_CAPS_MASK (PTA_SCMI_CAPS_SMT_HEADER | \
  127. PTA_SCMI_CAPS_MSG_HEADER)
  128. static int open_channel(struct udevice *dev, struct scmi_optee_channel *chan,
  129. struct channel_session *sess)
  130. {
  131. const struct tee_optee_ta_uuid uuid = TA_SCMI_UUID;
  132. struct tee_open_session_arg sess_arg = { };
  133. struct tee_invoke_arg cmd_arg = { };
  134. struct tee_param param[1] = { };
  135. int ret;
  136. memset(sess, 0, sizeof(sess));
  137. sess->tee = tee_find_device(NULL, NULL, NULL, NULL);
  138. if (!sess->tee)
  139. return -ENODEV;
  140. sess_arg.clnt_login = TEE_LOGIN_REE_KERNEL;
  141. tee_optee_ta_uuid_to_octets(sess_arg.uuid, &uuid);
  142. ret = tee_open_session(sess->tee, &sess_arg, 0, NULL);
  143. if (ret) {
  144. dev_err(dev, "can't open session: %d\n", ret);
  145. return ret;
  146. }
  147. cmd_arg.func = PTA_SCMI_CMD_GET_CHANNEL;
  148. cmd_arg.session = sess_arg.session;
  149. param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INOUT;
  150. param[0].u.value.a = chan->channel_id;
  151. if (chan->dyn_shm)
  152. param[0].u.value.b = PTA_SCMI_CAPS_MSG_HEADER;
  153. else
  154. param[0].u.value.b = PTA_SCMI_CAPS_SMT_HEADER;
  155. ret = tee_invoke_func(sess->tee, &cmd_arg, ARRAY_SIZE(param), param);
  156. if (ret || cmd_arg.ret) {
  157. dev_err(dev, "Invoke failed: %d, 0x%x\n", ret, cmd_arg.ret);
  158. if (!ret)
  159. ret = -EPROTO;
  160. tee_close_session(sess->tee, sess_arg.session);
  161. return ret;
  162. }
  163. sess->tee_session = sess_arg.session;
  164. sess->channel_hdl = param[0].u.value.a;
  165. return 0;
  166. }
  167. static void close_channel(struct channel_session *sess)
  168. {
  169. tee_close_session(sess->tee, sess->tee_session);
  170. }
  171. static int invoke_cmd(struct udevice *dev, struct scmi_optee_channel *chan,
  172. struct channel_session *sess, struct scmi_msg *msg)
  173. {
  174. struct tee_invoke_arg arg = { };
  175. struct tee_param param[3] = { };
  176. int ret;
  177. arg.session = sess->tee_session;
  178. param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
  179. param[0].u.value.a = sess->channel_hdl;
  180. if (sess->tee_shm) {
  181. size_t in_size;
  182. ret = scmi_msg_to_smt_msg(dev, &chan->smt, msg, &in_size);
  183. if (ret < 0)
  184. return ret;
  185. arg.func = PTA_SCMI_CMD_PROCESS_MSG_CHANNEL;
  186. param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
  187. param[1].u.memref.shm = sess->tee_shm;
  188. param[1].u.memref.size = in_size;
  189. param[2].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
  190. param[2].u.memref.shm = sess->tee_shm;
  191. param[2].u.memref.size = sess->tee_shm->size;
  192. } else {
  193. arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL;
  194. scmi_write_msg_to_smt(dev, &chan->smt, msg);
  195. }
  196. ret = tee_invoke_func(sess->tee, &arg, ARRAY_SIZE(param), param);
  197. if (ret || arg.ret) {
  198. if (!ret)
  199. ret = -EPROTO;
  200. return ret;
  201. }
  202. if (sess->tee_shm) {
  203. ret = scmi_msg_from_smt_msg(dev, &chan->smt, msg,
  204. param[2].u.memref.size);
  205. } else {
  206. ret = scmi_read_resp_from_smt(dev, &chan->smt, msg);
  207. scmi_clear_smt_channel(&chan->smt);
  208. }
  209. return ret;
  210. }
  211. static int prepare_shm(struct udevice *dev, struct scmi_optee_channel *chan,
  212. struct channel_session *sess)
  213. {
  214. int ret;
  215. /* Static shm is already prepared by the firmware: nothing to do */
  216. if (!chan->dyn_shm)
  217. return 0;
  218. chan->smt.size = SCMI_SHM_SIZE;
  219. ret = tee_shm_alloc(sess->tee, chan->smt.size, 0, &sess->tee_shm);
  220. if (ret) {
  221. dev_err(dev, "Failed to allocated shmem: %d\n", ret);
  222. return ret;
  223. }
  224. chan->smt.buf = sess->tee_shm->addr;
  225. return 0;
  226. }
  227. static void release_shm(struct udevice *dev, struct channel_session *sess)
  228. {
  229. struct scmi_optee_channel *chan = dev_get_plat(dev);
  230. if (chan->dyn_shm)
  231. tee_shm_free(sess->tee_shm);
  232. }
  233. static int scmi_optee_process_msg(struct udevice *dev,
  234. struct scmi_channel *channel,
  235. struct scmi_msg *msg)
  236. {
  237. struct scmi_optee_channel *chan = &channel->ref;
  238. struct channel_session sess = { };
  239. int ret;
  240. ret = open_channel(dev, chan, &sess);
  241. if (ret)
  242. return ret;
  243. ret = prepare_shm(dev, chan, &sess);
  244. if (ret)
  245. goto out;
  246. ret = invoke_cmd(dev, chan, &sess, msg);
  247. release_shm(dev, &sess);
  248. out:
  249. close_channel(&sess);
  250. return ret;
  251. }
  252. static int setup_channel(struct udevice *dev, struct scmi_optee_channel *chan)
  253. {
  254. int ret;
  255. if (dev_read_u32(dev, "linaro,optee-channel-id", &chan->channel_id)) {
  256. dev_err(dev, "Missing property linaro,optee-channel-id\n");
  257. return -EINVAL;
  258. }
  259. if (dev_read_prop(dev, "shmem", NULL)) {
  260. ret = scmi_dt_get_smt_buffer(dev, &chan->smt);
  261. if (ret) {
  262. dev_err(dev, "Failed to get smt resources: %d\n", ret);
  263. return ret;
  264. }
  265. chan->dyn_shm = false;
  266. } else {
  267. chan->dyn_shm = true;
  268. }
  269. return 0;
  270. }
  271. static int scmi_optee_get_channel(struct udevice *dev,
  272. struct scmi_channel **channel)
  273. {
  274. struct scmi_optee_channel *base_chan = dev_get_plat(dev);
  275. struct scmi_optee_channel *chan;
  276. u32 channel_id;
  277. int ret;
  278. if (dev_read_u32(dev, "linaro,optee-channel-id", &channel_id)) {
  279. /* Uses agent base channel */
  280. *channel = container_of(base_chan, struct scmi_channel, ref);
  281. return 0;
  282. }
  283. /* Setup a dedicated channel */
  284. chan = calloc(1, sizeof(*chan));
  285. if (!chan)
  286. return -ENOMEM;
  287. ret = setup_channel(dev, chan);
  288. if (ret) {
  289. free(chan);
  290. return ret;
  291. }
  292. *channel = container_of(chan, struct scmi_channel, ref);
  293. return 0;
  294. }
  295. static int scmi_optee_of_to_plat(struct udevice *dev)
  296. {
  297. struct scmi_optee_channel *chan = dev_get_plat(dev);
  298. return setup_channel(dev, chan);
  299. }
  300. static int scmi_optee_probe(struct udevice *dev)
  301. {
  302. struct scmi_optee_channel *chan = dev_get_plat(dev);
  303. struct channel_session sess;
  304. int ret;
  305. /* Check OP-TEE service acknowledges the SCMI channel */
  306. ret = open_channel(dev, chan, &sess);
  307. if (!ret)
  308. close_channel(&sess);
  309. return ret;
  310. }
  311. static const struct udevice_id scmi_optee_ids[] = {
  312. { .compatible = "linaro,scmi-optee" },
  313. { }
  314. };
  315. static const struct scmi_agent_ops scmi_optee_ops = {
  316. .of_get_channel = scmi_optee_get_channel,
  317. .process_msg = scmi_optee_process_msg,
  318. };
  319. U_BOOT_DRIVER(scmi_optee) = {
  320. .name = "scmi-over-optee",
  321. .id = UCLASS_SCMI_AGENT,
  322. .of_match = scmi_optee_ids,
  323. .plat_auto = sizeof(struct scmi_optee_channel),
  324. .of_to_plat = scmi_optee_of_to_plat,
  325. .probe = scmi_optee_probe,
  326. .flags = DM_FLAG_OS_PREPARE,
  327. .ops = &scmi_optee_ops,
  328. };