xref: /linux/drivers/firmware/arm_scmi/transports/optee.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2019-2021 Linaro Ltd.
4  */
5 
6 #include <linux/io.h>
7 #include <linux/of.h>
8 #include <linux/of_address.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/platform_device.h>
13 #include <linux/slab.h>
14 #include <linux/tee_drv.h>
15 #include <linux/uuid.h>
16 #include <uapi/linux/tee.h>
17 
18 #include "../common.h"
19 
20 #define SCMI_OPTEE_MAX_MSG_SIZE		128
21 
22 enum scmi_optee_pta_cmd {
23 	/*
24 	 * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities
25 	 *
26 	 * [out]    value[0].a: Capability bit mask (enum pta_scmi_caps)
27 	 * [out]    value[0].b: Extended capabilities or 0
28 	 */
29 	PTA_SCMI_CMD_CAPABILITIES = 0,
30 
31 	/*
32 	 * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer
33 	 *
34 	 * [in]     value[0].a: Channel handle
35 	 *
36 	 * Shared memory used for SCMI message/response exhange is expected
37 	 * already identified and bound to channel handle in both SCMI agent
38 	 * and SCMI server (OP-TEE) parts.
39 	 * The memory uses SMT header to carry SCMI meta-data (protocol ID and
40 	 * protocol message ID).
41 	 */
42 	PTA_SCMI_CMD_PROCESS_SMT_CHANNEL = 1,
43 
44 	/*
45 	 * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SMT/SCMI message
46 	 *
47 	 * [in]     value[0].a: Channel handle
48 	 * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload)
49 	 *
50 	 * Shared memory used for SCMI message/response is a SMT buffer
51 	 * referenced by param[1]. It shall be 128 bytes large to fit response
52 	 * payload whatever message playload size.
53 	 * The memory uses SMT header to carry SCMI meta-data (protocol ID and
54 	 * protocol message ID).
55 	 */
56 	PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE = 2,
57 
58 	/*
59 	 * PTA_SCMI_CMD_GET_CHANNEL - Get channel handle
60 	 *
61 	 * SCMI shm information are 0 if agent expects to use OP-TEE regular SHM
62 	 *
63 	 * [in]     value[0].a: Channel identifier
64 	 * [out]    value[0].a: Returned channel handle
65 	 * [in]     value[0].b: Requested capabilities mask (enum pta_scmi_caps)
66 	 */
67 	PTA_SCMI_CMD_GET_CHANNEL = 3,
68 
69 	/*
70 	 * PTA_SCMI_CMD_PROCESS_MSG_CHANNEL - Process SCMI message in a MSG
71 	 * buffer pointed by memref parameters
72 	 *
73 	 * [in]     value[0].a: Channel handle
74 	 * [in]     memref[1]: Message buffer (MSG and SCMI payload)
75 	 * [out]    memref[2]: Response buffer (MSG and SCMI payload)
76 	 *
77 	 * Shared memories used for SCMI message/response are MSG buffers
78 	 * referenced by param[1] and param[2]. MSG transport protocol
79 	 * uses a 32bit header to carry SCMI meta-data (protocol ID and
80 	 * protocol message ID) followed by the effective SCMI message
81 	 * payload.
82 	 */
83 	PTA_SCMI_CMD_PROCESS_MSG_CHANNEL = 4,
84 };
85 
86 /*
87  * OP-TEE SCMI service capabilities bit flags (32bit)
88  *
89  * PTA_SCMI_CAPS_SMT_HEADER
90  * When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in
91  * shared memory buffers to carry SCMI protocol synchronisation information.
92  *
93  * PTA_SCMI_CAPS_MSG_HEADER
94  * When set, OP-TEE supports command using MSG header protocol in an OP-TEE
95  * shared memory to carry SCMI protocol synchronisation information and SCMI
96  * message payload.
97  */
98 #define PTA_SCMI_CAPS_NONE		0
99 #define PTA_SCMI_CAPS_SMT_HEADER	BIT(0)
100 #define PTA_SCMI_CAPS_MSG_HEADER	BIT(1)
101 #define PTA_SCMI_CAPS_MASK		(PTA_SCMI_CAPS_SMT_HEADER | \
102 					 PTA_SCMI_CAPS_MSG_HEADER)
103 
104 /**
105  * struct scmi_optee_channel - Description of an OP-TEE SCMI channel
106  *
107  * @channel_id: OP-TEE channel ID used for this transport
108  * @tee_session: TEE session identifier
109  * @caps: OP-TEE SCMI channel capabilities
110  * @rx_len: Response size
111  * @mu: Mutex protection on channel access
112  * @cinfo: SCMI channel information
113  * @req: union for SCMI interface
114  * @req.shmem: Virtual base address of the shared memory
115  * @req.msg: Shared memory protocol handle for SCMI request and
116  *   synchronous response
117  * @tee_shm: TEE shared memory handle @req or NULL if using IOMEM shmem
118  * @link: Reference in agent's channel list
119  */
120 struct scmi_optee_channel {
121 	u32 channel_id;
122 	u32 tee_session;
123 	u32 caps;
124 	u32 rx_len;
125 	struct mutex mu;
126 	struct scmi_chan_info *cinfo;
127 	union {
128 		struct scmi_shared_mem __iomem *shmem;
129 		struct scmi_msg_payld *msg;
130 	} req;
131 	struct tee_shm *tee_shm;
132 	struct list_head link;
133 };
134 
135 /**
136  * struct scmi_optee_agent - OP-TEE transport private data
137  *
138  * @dev: Device used for communication with TEE
139  * @tee_ctx: TEE context used for communication
140  * @caps: Supported channel capabilities
141  * @mu: Mutex for protection of @channel_list
142  * @channel_list: List of all created channels for the agent
143  */
144 struct scmi_optee_agent {
145 	struct device *dev;
146 	struct tee_context *tee_ctx;
147 	u32 caps;
148 	struct mutex mu;
149 	struct list_head channel_list;
150 };
151 
152 static struct scmi_transport_core_operations *core;
153 
154 /* There can be only 1 SCMI service in OP-TEE we connect to */
155 static struct scmi_optee_agent *scmi_optee_private;
156 
157 /* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */
open_session(struct scmi_optee_agent * agent,u32 * tee_session)158 static int open_session(struct scmi_optee_agent *agent, u32 *tee_session)
159 {
160 	struct device *dev = agent->dev;
161 	struct tee_client_device *scmi_pta = to_tee_client_device(dev);
162 	struct tee_ioctl_open_session_arg arg = { };
163 	int ret;
164 
165 	memcpy(arg.uuid, scmi_pta->id.uuid.b, TEE_IOCTL_UUID_LEN);
166 	arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
167 
168 	ret = tee_client_open_session(agent->tee_ctx, &arg, NULL);
169 	if (ret < 0 || arg.ret) {
170 		dev_err(dev, "Can't open tee session: %d / %#x\n", ret, arg.ret);
171 		return -EOPNOTSUPP;
172 	}
173 
174 	*tee_session = arg.session;
175 
176 	return 0;
177 }
178 
close_session(struct scmi_optee_agent * agent,u32 tee_session)179 static void close_session(struct scmi_optee_agent *agent, u32 tee_session)
180 {
181 	tee_client_close_session(agent->tee_ctx, tee_session);
182 }
183 
get_capabilities(struct scmi_optee_agent * agent)184 static int get_capabilities(struct scmi_optee_agent *agent)
185 {
186 	struct tee_ioctl_invoke_arg arg = { };
187 	struct tee_param param[1] = { };
188 	u32 caps;
189 	u32 tee_session;
190 	int ret;
191 
192 	ret = open_session(agent, &tee_session);
193 	if (ret)
194 		return ret;
195 
196 	arg.func = PTA_SCMI_CMD_CAPABILITIES;
197 	arg.session = tee_session;
198 	arg.num_params = 1;
199 
200 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
201 
202 	ret = tee_client_invoke_func(agent->tee_ctx, &arg, param);
203 
204 	close_session(agent, tee_session);
205 
206 	if (ret < 0 || arg.ret) {
207 		dev_err(agent->dev, "Can't get capabilities: %d / %#x\n", ret, arg.ret);
208 		return -EOPNOTSUPP;
209 	}
210 
211 	caps = param[0].u.value.a;
212 
213 	if (!(caps & (PTA_SCMI_CAPS_SMT_HEADER | PTA_SCMI_CAPS_MSG_HEADER))) {
214 		dev_err(agent->dev, "OP-TEE SCMI PTA doesn't support SMT and MSG\n");
215 		return -EOPNOTSUPP;
216 	}
217 
218 	agent->caps = caps;
219 
220 	return 0;
221 }
222 
get_channel(struct scmi_optee_channel * channel)223 static int get_channel(struct scmi_optee_channel *channel)
224 {
225 	struct device *dev = scmi_optee_private->dev;
226 	struct tee_ioctl_invoke_arg arg = { };
227 	struct tee_param param[1] = { };
228 	unsigned int caps = 0;
229 	int ret;
230 
231 	if (channel->tee_shm)
232 		caps = PTA_SCMI_CAPS_MSG_HEADER;
233 	else
234 		caps = PTA_SCMI_CAPS_SMT_HEADER;
235 
236 	arg.func = PTA_SCMI_CMD_GET_CHANNEL;
237 	arg.session = channel->tee_session;
238 	arg.num_params = 1;
239 
240 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
241 	param[0].u.value.a = channel->channel_id;
242 	param[0].u.value.b = caps;
243 
244 	ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
245 
246 	if (ret || arg.ret) {
247 		dev_err(dev, "Can't get channel with caps %#x: %d / %#x\n", caps, ret, arg.ret);
248 		return -EOPNOTSUPP;
249 	}
250 
251 	/* From now on use channel identifer provided by OP-TEE SCMI service */
252 	channel->channel_id = param[0].u.value.a;
253 	channel->caps = caps;
254 
255 	return 0;
256 }
257 
invoke_process_smt_channel(struct scmi_optee_channel * channel)258 static int invoke_process_smt_channel(struct scmi_optee_channel *channel)
259 {
260 	struct tee_ioctl_invoke_arg arg = {
261 		.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL,
262 		.session = channel->tee_session,
263 		.num_params = 1,
264 	};
265 	struct tee_param param[1] = { };
266 	int ret;
267 
268 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
269 	param[0].u.value.a = channel->channel_id;
270 
271 	ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
272 	if (ret < 0 || arg.ret) {
273 		dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n",
274 			channel->channel_id, ret, arg.ret);
275 		return -EIO;
276 	}
277 
278 	return 0;
279 }
280 
invoke_process_msg_channel(struct scmi_optee_channel * channel,size_t msg_size)281 static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t msg_size)
282 {
283 	struct tee_ioctl_invoke_arg arg = {
284 		.func = PTA_SCMI_CMD_PROCESS_MSG_CHANNEL,
285 		.session = channel->tee_session,
286 		.num_params = 3,
287 	};
288 	struct tee_param param[3] = { };
289 	int ret;
290 
291 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
292 	param[0].u.value.a = channel->channel_id;
293 
294 	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
295 	param[1].u.memref.shm = channel->tee_shm;
296 	param[1].u.memref.size = msg_size;
297 
298 	param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
299 	param[2].u.memref.shm = channel->tee_shm;
300 	param[2].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE;
301 
302 	ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
303 	if (ret < 0 || arg.ret) {
304 		dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n",
305 			channel->channel_id, ret, arg.ret);
306 		return -EIO;
307 	}
308 
309 	/* Save response size */
310 	channel->rx_len = param[2].u.memref.size;
311 
312 	return 0;
313 }
314 
scmi_optee_chan_available(struct device_node * of_node,int idx)315 static bool scmi_optee_chan_available(struct device_node *of_node, int idx)
316 {
317 	u32 channel_id;
318 
319 	return !of_property_read_u32_index(of_node, "linaro,optee-channel-id",
320 					   idx, &channel_id);
321 }
322 
scmi_optee_clear_channel(struct scmi_chan_info * cinfo)323 static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo)
324 {
325 	struct scmi_optee_channel *channel = cinfo->transport_info;
326 
327 	if (!channel->tee_shm)
328 		core->shmem->clear_channel(channel->req.shmem);
329 }
330 
setup_dynamic_shmem(struct device * dev,struct scmi_optee_channel * channel)331 static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *channel)
332 {
333 	const size_t msg_size = SCMI_OPTEE_MAX_MSG_SIZE;
334 	void *shbuf;
335 
336 	channel->tee_shm = tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx, msg_size);
337 	if (IS_ERR(channel->tee_shm)) {
338 		dev_err(channel->cinfo->dev, "shmem allocation failed\n");
339 		return -ENOMEM;
340 	}
341 
342 	shbuf = tee_shm_get_va(channel->tee_shm, 0);
343 	memset(shbuf, 0, msg_size);
344 	channel->req.msg = shbuf;
345 	channel->rx_len = msg_size;
346 
347 	return 0;
348 }
349 
setup_static_shmem(struct device * dev,struct scmi_chan_info * cinfo,struct scmi_optee_channel * channel)350 static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo,
351 			      struct scmi_optee_channel *channel)
352 {
353 	channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL);
354 	if (IS_ERR(channel->req.shmem))
355 		return PTR_ERR(channel->req.shmem);
356 
357 	return 0;
358 }
359 
setup_shmem(struct device * dev,struct scmi_chan_info * cinfo,struct scmi_optee_channel * channel)360 static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo,
361 		       struct scmi_optee_channel *channel)
362 {
363 	if (of_property_present(cinfo->dev->of_node, "shmem"))
364 		return setup_static_shmem(dev, cinfo, channel);
365 	else
366 		return setup_dynamic_shmem(dev, channel);
367 }
368 
scmi_optee_chan_setup(struct scmi_chan_info * cinfo,struct device * dev,bool tx)369 static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool tx)
370 {
371 	struct scmi_optee_channel *channel;
372 	uint32_t channel_id;
373 	int ret;
374 
375 	if (!tx)
376 		return -ENODEV;
377 
378 	channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL);
379 	if (!channel)
380 		return -ENOMEM;
381 
382 	ret = of_property_read_u32_index(cinfo->dev->of_node, "linaro,optee-channel-id",
383 					 0, &channel_id);
384 	if (ret)
385 		return ret;
386 
387 	cinfo->transport_info = channel;
388 	channel->cinfo = cinfo;
389 	channel->channel_id = channel_id;
390 	mutex_init(&channel->mu);
391 
392 	ret = setup_shmem(dev, cinfo, channel);
393 	if (ret)
394 		return ret;
395 
396 	ret = open_session(scmi_optee_private, &channel->tee_session);
397 	if (ret)
398 		goto err_free_shm;
399 
400 	ret = tee_client_system_session(scmi_optee_private->tee_ctx, channel->tee_session);
401 	if (ret)
402 		dev_warn(dev, "Could not switch to system session, do best effort\n");
403 
404 	ret = get_channel(channel);
405 	if (ret)
406 		goto err_close_sess;
407 
408 	/* Enable polling */
409 	cinfo->no_completion_irq = true;
410 
411 	mutex_lock(&scmi_optee_private->mu);
412 	list_add(&channel->link, &scmi_optee_private->channel_list);
413 	mutex_unlock(&scmi_optee_private->mu);
414 
415 	return 0;
416 
417 err_close_sess:
418 	close_session(scmi_optee_private, channel->tee_session);
419 err_free_shm:
420 	if (channel->tee_shm)
421 		tee_shm_free(channel->tee_shm);
422 
423 	return ret;
424 }
425 
scmi_optee_chan_free(int id,void * p,void * data)426 static int scmi_optee_chan_free(int id, void *p, void *data)
427 {
428 	struct scmi_chan_info *cinfo = p;
429 	struct scmi_optee_channel *channel = cinfo->transport_info;
430 
431 	/*
432 	 * Different protocols might share the same chan info, so a previous
433 	 * call might have already freed the structure.
434 	 */
435 	if (!channel)
436 		return 0;
437 
438 	mutex_lock(&scmi_optee_private->mu);
439 	list_del(&channel->link);
440 	mutex_unlock(&scmi_optee_private->mu);
441 
442 	close_session(scmi_optee_private, channel->tee_session);
443 
444 	if (channel->tee_shm) {
445 		tee_shm_free(channel->tee_shm);
446 		channel->tee_shm = NULL;
447 	}
448 
449 	cinfo->transport_info = NULL;
450 	channel->cinfo = NULL;
451 
452 	return 0;
453 }
454 
scmi_optee_send_message(struct scmi_chan_info * cinfo,struct scmi_xfer * xfer)455 static int scmi_optee_send_message(struct scmi_chan_info *cinfo,
456 				   struct scmi_xfer *xfer)
457 {
458 	struct scmi_optee_channel *channel = cinfo->transport_info;
459 	int ret;
460 
461 	mutex_lock(&channel->mu);
462 
463 	if (channel->tee_shm) {
464 		core->msg->tx_prepare(channel->req.msg, xfer);
465 		ret = invoke_process_msg_channel(channel,
466 						 core->msg->command_size(xfer));
467 	} else {
468 		core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo);
469 		ret = invoke_process_smt_channel(channel);
470 	}
471 
472 	if (ret)
473 		mutex_unlock(&channel->mu);
474 
475 	return ret;
476 }
477 
scmi_optee_fetch_response(struct scmi_chan_info * cinfo,struct scmi_xfer * xfer)478 static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
479 				      struct scmi_xfer *xfer)
480 {
481 	struct scmi_optee_channel *channel = cinfo->transport_info;
482 
483 	if (channel->tee_shm)
484 		core->msg->fetch_response(channel->req.msg,
485 					  channel->rx_len, xfer);
486 	else
487 		core->shmem->fetch_response(channel->req.shmem, xfer);
488 }
489 
scmi_optee_mark_txdone(struct scmi_chan_info * cinfo,int ret,struct scmi_xfer * __unused)490 static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret,
491 				   struct scmi_xfer *__unused)
492 {
493 	struct scmi_optee_channel *channel = cinfo->transport_info;
494 
495 	mutex_unlock(&channel->mu);
496 }
497 
498 static struct scmi_transport_ops scmi_optee_ops = {
499 	.chan_available = scmi_optee_chan_available,
500 	.chan_setup = scmi_optee_chan_setup,
501 	.chan_free = scmi_optee_chan_free,
502 	.send_message = scmi_optee_send_message,
503 	.mark_txdone = scmi_optee_mark_txdone,
504 	.fetch_response = scmi_optee_fetch_response,
505 	.clear_channel = scmi_optee_clear_channel,
506 };
507 
scmi_optee_ctx_match(struct tee_ioctl_version_data * ver,const void * data)508 static int scmi_optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
509 {
510 	return ver->impl_id == TEE_IMPL_ID_OPTEE;
511 }
512 
513 static struct scmi_desc scmi_optee_desc = {
514 	.ops = &scmi_optee_ops,
515 	.max_rx_timeout_ms = 30,
516 	.max_msg = 20,
517 	.max_msg_size = SCMI_OPTEE_MAX_MSG_SIZE,
518 	.sync_cmds_completed_on_ret = true,
519 };
520 
521 static const struct of_device_id scmi_of_match[] = {
522 	{ .compatible = "linaro,scmi-optee" },
523 	{ /* Sentinel */ },
524 };
525 
526 DEFINE_SCMI_TRANSPORT_DRIVER(scmi_optee, scmi_optee_driver, scmi_optee_desc,
527 			     scmi_of_match, core);
528 
scmi_optee_service_probe(struct device * dev)529 static int scmi_optee_service_probe(struct device *dev)
530 {
531 	struct scmi_optee_agent *agent;
532 	struct tee_context *tee_ctx;
533 	int ret;
534 
535 	/* Only one SCMI OP-TEE device allowed */
536 	if (scmi_optee_private) {
537 		dev_err(dev, "An SCMI OP-TEE device was already initialized: only one allowed\n");
538 		return -EBUSY;
539 	}
540 
541 	tee_ctx = tee_client_open_context(NULL, scmi_optee_ctx_match, NULL, NULL);
542 	if (IS_ERR(tee_ctx))
543 		return -ENODEV;
544 
545 	agent = devm_kzalloc(dev, sizeof(*agent), GFP_KERNEL);
546 	if (!agent) {
547 		ret = -ENOMEM;
548 		goto err;
549 	}
550 
551 	agent->dev = dev;
552 	agent->tee_ctx = tee_ctx;
553 	INIT_LIST_HEAD(&agent->channel_list);
554 	mutex_init(&agent->mu);
555 
556 	ret = get_capabilities(agent);
557 	if (ret)
558 		goto err;
559 
560 	/* Ensure agent resources are all visible before scmi_optee_private is */
561 	smp_mb();
562 	scmi_optee_private = agent;
563 
564 	ret = platform_driver_register(&scmi_optee_driver);
565 	if (ret) {
566 		scmi_optee_private = NULL;
567 		goto err;
568 	}
569 
570 	return 0;
571 
572 err:
573 	tee_client_close_context(tee_ctx);
574 
575 	return ret;
576 }
577 
scmi_optee_service_remove(struct device * dev)578 static int scmi_optee_service_remove(struct device *dev)
579 {
580 	struct scmi_optee_agent *agent = scmi_optee_private;
581 
582 	if (!scmi_optee_private)
583 		return -EINVAL;
584 
585 	platform_driver_unregister(&scmi_optee_driver);
586 
587 	if (!list_empty(&scmi_optee_private->channel_list))
588 		return -EBUSY;
589 
590 	/* Ensure cleared reference is visible before resources are released */
591 	smp_store_mb(scmi_optee_private, NULL);
592 
593 	tee_client_close_context(agent->tee_ctx);
594 
595 	return 0;
596 }
597 
598 static const struct tee_client_device_id scmi_optee_service_id[] = {
599 	{
600 		UUID_INIT(0xa8cfe406, 0xd4f5, 0x4a2e,
601 			  0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99)
602 	},
603 	{ }
604 };
605 
606 MODULE_DEVICE_TABLE(tee, scmi_optee_service_id);
607 
608 static struct tee_client_driver scmi_optee_service_driver = {
609 	.id_table	= scmi_optee_service_id,
610 	.driver		= {
611 		.name = "scmi-optee",
612 		.bus = &tee_bus_type,
613 		.probe = scmi_optee_service_probe,
614 		.remove = scmi_optee_service_remove,
615 	},
616 };
617 
scmi_transport_optee_init(void)618 static int __init scmi_transport_optee_init(void)
619 {
620 	return driver_register(&scmi_optee_service_driver.driver);
621 }
622 module_init(scmi_transport_optee_init);
623 
scmi_transport_optee_exit(void)624 static void __exit scmi_transport_optee_exit(void)
625 {
626 	driver_unregister(&scmi_optee_service_driver.driver);
627 }
628 module_exit(scmi_transport_optee_exit);
629 
630 MODULE_AUTHOR("Etienne Carriere <etienne.carriere@foss.st.com>");
631 MODULE_DESCRIPTION("SCMI OPTEE Transport driver");
632 MODULE_LICENSE("GPL");
633