Lines Matching +full:channel +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019-2021 Linaro Ltd.
22 * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities
30 * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer
32 * [in] value[0].a: Channel handle
35 * already identified and bound to channel handle in both SCMI agent
36 * and SCMI server (OP-TEE) parts.
37 * The memory uses SMT header to carry SCMI meta-data (protocol ID and
40 PTA_SCMI_CMD_PROCESS_SMT_CHANNEL = 1,
43 * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SMT/SCMI message
45 * [in] value[0].a: Channel handle
46 * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload)
49 * referenced by param[1]. It shall be 128 bytes large to fit response
51 * The memory uses SMT header to carry SCMI meta-data (protocol ID and
57 * PTA_SCMI_CMD_GET_CHANNEL - Get channel handle
59 * SCMI shm information are 0 if agent expects to use OP-TEE regular SHM
61 * [in] value[0].a: Channel identifier
62 * [out] value[0].a: Returned channel handle
68 * PTA_SCMI_CMD_PROCESS_MSG_CHANNEL - Process SCMI message in a MSG
71 * [in] value[0].a: Channel handle
72 * [in] memref[1]: Message buffer (MSG and SCMI payload)
76 * referenced by param[1] and param[2]. MSG transport protocol
77 * uses a 32bit header to carry SCMI meta-data (protocol ID and
85 * OP-TEE SCMI service capabilities bit flags (32bit)
88 * When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in
92 * When set, OP-TEE supports command using MSG header protocol in an OP-TEE
98 #define PTA_SCMI_CAPS_MSG_HEADER BIT(1)
103 * struct scmi_optee_channel - Description of an OP-TEE SCMI channel
105 * @channel_id: OP-TEE channel ID used for this transport
107 * @caps: OP-TEE SCMI channel capabilities
109 * @mu: Mutex protection on channel access
110 * @cinfo: SCMI channel information
117 * @link: Reference in agent's channel list
136 * struct scmi_optee_agent - OP-TEE transport private data
140 * @caps: Supported channel capabilities
154 /* There can be only 1 SCMI service in OP-TEE we connect to */
157 /* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */
160 struct device *dev = agent->dev; in open_session()
165 memcpy(arg.uuid, scmi_pta->id.uuid.b, TEE_IOCTL_UUID_LEN); in open_session()
168 ret = tee_client_open_session(agent->tee_ctx, &arg, NULL); in open_session()
171 return -EOPNOTSUPP; in open_session()
181 tee_client_close_session(agent->tee_ctx, tee_session); in close_session()
187 struct tee_param param[1] = { }; in get_capabilities()
198 arg.num_params = 1; in get_capabilities()
202 ret = tee_client_invoke_func(agent->tee_ctx, &arg, param); in get_capabilities()
207 dev_err(agent->dev, "Can't get capabilities: %d / %#x\n", ret, arg.ret); in get_capabilities()
208 return -EOPNOTSUPP; in get_capabilities()
214 dev_err(agent->dev, "OP-TEE SCMI PTA doesn't support SMT and MSG\n"); in get_capabilities()
215 return -EOPNOTSUPP; in get_capabilities()
218 agent->caps = caps; in get_capabilities()
223 static int get_channel(struct scmi_optee_channel *channel) in get_channel() argument
225 struct device *dev = scmi_optee_private->dev; in get_channel()
227 struct tee_param param[1] = { }; in get_channel()
231 if (channel->tee_shm) in get_channel()
237 arg.session = channel->tee_session; in get_channel()
238 arg.num_params = 1; in get_channel()
241 param[0].u.value.a = channel->channel_id; in get_channel()
244 ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); in get_channel()
247 dev_err(dev, "Can't get channel with caps %#x: %d / %#x\n", caps, ret, arg.ret); in get_channel()
248 return -EOPNOTSUPP; in get_channel()
251 /* From now on use channel identifer provided by OP-TEE SCMI service */ in get_channel()
252 channel->channel_id = param[0].u.value.a; in get_channel()
253 channel->caps = caps; in get_channel()
258 static int invoke_process_smt_channel(struct scmi_optee_channel *channel) in invoke_process_smt_channel() argument
262 .session = channel->tee_session, in invoke_process_smt_channel()
263 .num_params = 1, in invoke_process_smt_channel()
265 struct tee_param param[1] = { }; in invoke_process_smt_channel()
269 param[0].u.value.a = channel->channel_id; in invoke_process_smt_channel()
271 ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); in invoke_process_smt_channel()
273 dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n", in invoke_process_smt_channel()
274 channel->channel_id, ret, arg.ret); in invoke_process_smt_channel()
275 return -EIO; in invoke_process_smt_channel()
281 static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t msg_size) in invoke_process_msg_channel() argument
285 .session = channel->tee_session, in invoke_process_msg_channel()
292 param[0].u.value.a = channel->channel_id; in invoke_process_msg_channel()
294 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; in invoke_process_msg_channel()
295 param[1].u.memref.shm = channel->tee_shm; in invoke_process_msg_channel()
296 param[1].u.memref.size = msg_size; in invoke_process_msg_channel()
299 param[2].u.memref.shm = channel->tee_shm; in invoke_process_msg_channel()
302 ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); in invoke_process_msg_channel()
304 dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n", in invoke_process_msg_channel()
305 channel->channel_id, ret, arg.ret); in invoke_process_msg_channel()
306 return -EIO; in invoke_process_msg_channel()
310 channel->rx_len = param[2].u.memref.size; in invoke_process_msg_channel()
319 return !of_property_read_u32_index(of_node, "linaro,optee-channel-id", in scmi_optee_chan_available()
325 struct scmi_optee_channel *channel = cinfo->transport_info; in scmi_optee_clear_channel() local
327 if (!channel->tee_shm) in scmi_optee_clear_channel()
328 core->shmem->clear_channel(channel->req.shmem); in scmi_optee_clear_channel()
331 static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *channel) in setup_dynamic_shmem() argument
336 channel->tee_shm = tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx, msg_size); in setup_dynamic_shmem()
337 if (IS_ERR(channel->tee_shm)) { in setup_dynamic_shmem()
338 dev_err(channel->cinfo->dev, "shmem allocation failed\n"); in setup_dynamic_shmem()
339 return -ENOMEM; in setup_dynamic_shmem()
342 shbuf = tee_shm_get_va(channel->tee_shm, 0); in setup_dynamic_shmem()
344 channel->req.msg = shbuf; in setup_dynamic_shmem()
345 channel->rx_len = msg_size; in setup_dynamic_shmem()
351 struct scmi_optee_channel *channel) in setup_static_shmem() argument
353 channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL, in setup_static_shmem()
354 &channel->io_ops); in setup_static_shmem()
355 if (IS_ERR(channel->req.shmem)) in setup_static_shmem()
356 return PTR_ERR(channel->req.shmem); in setup_static_shmem()
362 struct scmi_optee_channel *channel) in setup_shmem() argument
364 if (of_property_present(cinfo->dev->of_node, "shmem")) in setup_shmem()
365 return setup_static_shmem(dev, cinfo, channel); in setup_shmem()
367 return setup_dynamic_shmem(dev, channel); in setup_shmem()
372 struct scmi_optee_channel *channel; in scmi_optee_chan_setup() local
377 return -ENODEV; in scmi_optee_chan_setup()
379 channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL); in scmi_optee_chan_setup()
380 if (!channel) in scmi_optee_chan_setup()
381 return -ENOMEM; in scmi_optee_chan_setup()
383 ret = of_property_read_u32_index(cinfo->dev->of_node, "linaro,optee-channel-id", in scmi_optee_chan_setup()
388 cinfo->transport_info = channel; in scmi_optee_chan_setup()
389 channel->cinfo = cinfo; in scmi_optee_chan_setup()
390 channel->channel_id = channel_id; in scmi_optee_chan_setup()
391 mutex_init(&channel->mu); in scmi_optee_chan_setup()
393 ret = setup_shmem(dev, cinfo, channel); in scmi_optee_chan_setup()
397 ret = open_session(scmi_optee_private, &channel->tee_session); in scmi_optee_chan_setup()
401 ret = tee_client_system_session(scmi_optee_private->tee_ctx, channel->tee_session); in scmi_optee_chan_setup()
405 ret = get_channel(channel); in scmi_optee_chan_setup()
410 cinfo->no_completion_irq = true; in scmi_optee_chan_setup()
412 mutex_lock(&scmi_optee_private->mu); in scmi_optee_chan_setup()
413 list_add(&channel->link, &scmi_optee_private->channel_list); in scmi_optee_chan_setup()
414 mutex_unlock(&scmi_optee_private->mu); in scmi_optee_chan_setup()
419 close_session(scmi_optee_private, channel->tee_session); in scmi_optee_chan_setup()
421 if (channel->tee_shm) in scmi_optee_chan_setup()
422 tee_shm_free(channel->tee_shm); in scmi_optee_chan_setup()
430 struct scmi_optee_channel *channel = cinfo->transport_info; in scmi_optee_chan_free() local
436 if (!channel) in scmi_optee_chan_free()
439 mutex_lock(&scmi_optee_private->mu); in scmi_optee_chan_free()
440 list_del(&channel->link); in scmi_optee_chan_free()
441 mutex_unlock(&scmi_optee_private->mu); in scmi_optee_chan_free()
443 close_session(scmi_optee_private, channel->tee_session); in scmi_optee_chan_free()
445 if (channel->tee_shm) { in scmi_optee_chan_free()
446 tee_shm_free(channel->tee_shm); in scmi_optee_chan_free()
447 channel->tee_shm = NULL; in scmi_optee_chan_free()
450 cinfo->transport_info = NULL; in scmi_optee_chan_free()
451 channel->cinfo = NULL; in scmi_optee_chan_free()
459 struct scmi_optee_channel *channel = cinfo->transport_info; in scmi_optee_send_message() local
462 mutex_lock(&channel->mu); in scmi_optee_send_message()
464 if (channel->tee_shm) { in scmi_optee_send_message()
465 core->msg->tx_prepare(channel->req.msg, xfer); in scmi_optee_send_message()
466 ret = invoke_process_msg_channel(channel, in scmi_optee_send_message()
467 core->msg->command_size(xfer)); in scmi_optee_send_message()
469 core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo, in scmi_optee_send_message()
470 channel->io_ops->toio); in scmi_optee_send_message()
471 ret = invoke_process_smt_channel(channel); in scmi_optee_send_message()
475 mutex_unlock(&channel->mu); in scmi_optee_send_message()
483 struct scmi_optee_channel *channel = cinfo->transport_info; in scmi_optee_fetch_response() local
485 if (channel->tee_shm) in scmi_optee_fetch_response()
486 core->msg->fetch_response(channel->req.msg, in scmi_optee_fetch_response()
487 channel->rx_len, xfer); in scmi_optee_fetch_response()
489 core->shmem->fetch_response(channel->req.shmem, xfer, in scmi_optee_fetch_response()
490 channel->io_ops->fromio); in scmi_optee_fetch_response()
496 struct scmi_optee_channel *channel = cinfo->transport_info; in scmi_optee_mark_txdone() local
498 mutex_unlock(&channel->mu); in scmi_optee_mark_txdone()
513 return ver->impl_id == TEE_IMPL_ID_OPTEE; in scmi_optee_ctx_match()
525 { .compatible = "linaro,scmi-optee" },
538 /* Only one SCMI OP-TEE device allowed */ in scmi_optee_service_probe()
540 dev_err(dev, "An SCMI OP-TEE device was already initialized: only one allowed\n"); in scmi_optee_service_probe()
541 return -EBUSY; in scmi_optee_service_probe()
546 return -ENODEV; in scmi_optee_service_probe()
550 ret = -ENOMEM; in scmi_optee_service_probe()
554 agent->dev = dev; in scmi_optee_service_probe()
555 agent->tee_ctx = tee_ctx; in scmi_optee_service_probe()
556 INIT_LIST_HEAD(&agent->channel_list); in scmi_optee_service_probe()
557 mutex_init(&agent->mu); in scmi_optee_service_probe()
586 return -EINVAL; in scmi_optee_service_remove()
590 if (!list_empty(&scmi_optee_private->channel_list)) in scmi_optee_service_remove()
591 return -EBUSY; in scmi_optee_service_remove()
596 tee_client_close_context(agent->tee_ctx); in scmi_optee_service_remove()
614 .name = "scmi-optee",