• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * @io_ops: Transport specific I/O operations
118  * @tee_shm: TEE shared memory handle @req or NULL if using IOMEM shmem
119  * @link: Reference in agent's channel list
120  */
121 struct scmi_optee_channel {
122 	u32 channel_id;
123 	u32 tee_session;
124 	u32 caps;
125 	u32 rx_len;
126 	struct mutex mu;
127 	struct scmi_chan_info *cinfo;
128 	union {
129 		struct scmi_shared_mem __iomem *shmem;
130 		struct scmi_msg_payld *msg;
131 	} req;
132 	struct scmi_shmem_io_ops *io_ops;
133 	struct tee_shm *tee_shm;
134 	struct list_head link;
135 };
136 
137 /**
138  * struct scmi_optee_agent - OP-TEE transport private data
139  *
140  * @dev: Device used for communication with TEE
141  * @tee_ctx: TEE context used for communication
142  * @caps: Supported channel capabilities
143  * @mu: Mutex for protection of @channel_list
144  * @channel_list: List of all created channels for the agent
145  */
146 struct scmi_optee_agent {
147 	struct device *dev;
148 	struct tee_context *tee_ctx;
149 	u32 caps;
150 	struct mutex mu;
151 	struct list_head channel_list;
152 };
153 
154 static struct scmi_transport_core_operations *core;
155 
156 /* There can be only 1 SCMI service in OP-TEE we connect to */
157 static struct scmi_optee_agent *scmi_optee_private;
158 
159 /* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */
open_session(struct scmi_optee_agent * agent,u32 * tee_session)160 static int open_session(struct scmi_optee_agent *agent, u32 *tee_session)
161 {
162 	struct device *dev = agent->dev;
163 	struct tee_client_device *scmi_pta = to_tee_client_device(dev);
164 	struct tee_ioctl_open_session_arg arg = { };
165 	int ret;
166 
167 	memcpy(arg.uuid, scmi_pta->id.uuid.b, TEE_IOCTL_UUID_LEN);
168 	arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
169 
170 	ret = tee_client_open_session(agent->tee_ctx, &arg, NULL);
171 	if (ret < 0 || arg.ret) {
172 		dev_err(dev, "Can't open tee session: %d / %#x\n", ret, arg.ret);
173 		return -EOPNOTSUPP;
174 	}
175 
176 	*tee_session = arg.session;
177 
178 	return 0;
179 }
180 
close_session(struct scmi_optee_agent * agent,u32 tee_session)181 static void close_session(struct scmi_optee_agent *agent, u32 tee_session)
182 {
183 	tee_client_close_session(agent->tee_ctx, tee_session);
184 }
185 
get_capabilities(struct scmi_optee_agent * agent)186 static int get_capabilities(struct scmi_optee_agent *agent)
187 {
188 	struct tee_ioctl_invoke_arg arg = { };
189 	struct tee_param param[1] = { };
190 	u32 caps;
191 	u32 tee_session;
192 	int ret;
193 
194 	ret = open_session(agent, &tee_session);
195 	if (ret)
196 		return ret;
197 
198 	arg.func = PTA_SCMI_CMD_CAPABILITIES;
199 	arg.session = tee_session;
200 	arg.num_params = 1;
201 
202 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
203 
204 	ret = tee_client_invoke_func(agent->tee_ctx, &arg, param);
205 
206 	close_session(agent, tee_session);
207 
208 	if (ret < 0 || arg.ret) {
209 		dev_err(agent->dev, "Can't get capabilities: %d / %#x\n", ret, arg.ret);
210 		return -EOPNOTSUPP;
211 	}
212 
213 	caps = param[0].u.value.a;
214 
215 	if (!(caps & (PTA_SCMI_CAPS_SMT_HEADER | PTA_SCMI_CAPS_MSG_HEADER))) {
216 		dev_err(agent->dev, "OP-TEE SCMI PTA doesn't support SMT and MSG\n");
217 		return -EOPNOTSUPP;
218 	}
219 
220 	agent->caps = caps;
221 
222 	return 0;
223 }
224 
get_channel(struct scmi_optee_channel * channel)225 static int get_channel(struct scmi_optee_channel *channel)
226 {
227 	struct device *dev = scmi_optee_private->dev;
228 	struct tee_ioctl_invoke_arg arg = { };
229 	struct tee_param param[1] = { };
230 	unsigned int caps = 0;
231 	int ret;
232 
233 	if (channel->tee_shm)
234 		caps = PTA_SCMI_CAPS_MSG_HEADER;
235 	else
236 		caps = PTA_SCMI_CAPS_SMT_HEADER;
237 
238 	arg.func = PTA_SCMI_CMD_GET_CHANNEL;
239 	arg.session = channel->tee_session;
240 	arg.num_params = 1;
241 
242 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
243 	param[0].u.value.a = channel->channel_id;
244 	param[0].u.value.b = caps;
245 
246 	ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
247 
248 	if (ret || arg.ret) {
249 		dev_err(dev, "Can't get channel with caps %#x: %d / %#x\n", caps, ret, arg.ret);
250 		return -EOPNOTSUPP;
251 	}
252 
253 	/* From now on use channel identifer provided by OP-TEE SCMI service */
254 	channel->channel_id = param[0].u.value.a;
255 	channel->caps = caps;
256 
257 	return 0;
258 }
259 
invoke_process_smt_channel(struct scmi_optee_channel * channel)260 static int invoke_process_smt_channel(struct scmi_optee_channel *channel)
261 {
262 	struct tee_ioctl_invoke_arg arg = {
263 		.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL,
264 		.session = channel->tee_session,
265 		.num_params = 1,
266 	};
267 	struct tee_param param[1] = { };
268 	int ret;
269 
270 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
271 	param[0].u.value.a = channel->channel_id;
272 
273 	ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
274 	if (ret < 0 || arg.ret) {
275 		dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n",
276 			channel->channel_id, ret, arg.ret);
277 		return -EIO;
278 	}
279 
280 	return 0;
281 }
282 
invoke_process_msg_channel(struct scmi_optee_channel * channel,size_t msg_size)283 static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t msg_size)
284 {
285 	struct tee_ioctl_invoke_arg arg = {
286 		.func = PTA_SCMI_CMD_PROCESS_MSG_CHANNEL,
287 		.session = channel->tee_session,
288 		.num_params = 3,
289 	};
290 	struct tee_param param[3] = { };
291 	int ret;
292 
293 	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
294 	param[0].u.value.a = channel->channel_id;
295 
296 	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
297 	param[1].u.memref.shm = channel->tee_shm;
298 	param[1].u.memref.size = msg_size;
299 
300 	param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
301 	param[2].u.memref.shm = channel->tee_shm;
302 	param[2].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE;
303 
304 	ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
305 	if (ret < 0 || arg.ret) {
306 		dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n",
307 			channel->channel_id, ret, arg.ret);
308 		return -EIO;
309 	}
310 
311 	/* Save response size */
312 	channel->rx_len = param[2].u.memref.size;
313 
314 	return 0;
315 }
316 
scmi_optee_chan_available(struct device_node * of_node,int idx)317 static bool scmi_optee_chan_available(struct device_node *of_node, int idx)
318 {
319 	u32 channel_id;
320 
321 	return !of_property_read_u32_index(of_node, "linaro,optee-channel-id",
322 					   idx, &channel_id);
323 }
324 
scmi_optee_clear_channel(struct scmi_chan_info * cinfo)325 static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo)
326 {
327 	struct scmi_optee_channel *channel = cinfo->transport_info;
328 
329 	if (!channel->tee_shm)
330 		core->shmem->clear_channel(channel->req.shmem);
331 }
332 
setup_dynamic_shmem(struct device * dev,struct scmi_optee_channel * channel)333 static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *channel)
334 {
335 	const size_t msg_size = SCMI_OPTEE_MAX_MSG_SIZE;
336 	void *shbuf;
337 
338 	channel->tee_shm = tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx, msg_size);
339 	if (IS_ERR(channel->tee_shm)) {
340 		dev_err(channel->cinfo->dev, "shmem allocation failed\n");
341 		return -ENOMEM;
342 	}
343 
344 	shbuf = tee_shm_get_va(channel->tee_shm, 0);
345 	memset(shbuf, 0, msg_size);
346 	channel->req.msg = shbuf;
347 	channel->rx_len = msg_size;
348 
349 	return 0;
350 }
351 
setup_static_shmem(struct device * dev,struct scmi_chan_info * cinfo,struct scmi_optee_channel * channel)352 static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo,
353 			      struct scmi_optee_channel *channel)
354 {
355 	channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL,
356 						      &channel->io_ops);
357 	if (IS_ERR(channel->req.shmem))
358 		return PTR_ERR(channel->req.shmem);
359 
360 	return 0;
361 }
362 
setup_shmem(struct device * dev,struct scmi_chan_info * cinfo,struct scmi_optee_channel * channel)363 static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo,
364 		       struct scmi_optee_channel *channel)
365 {
366 	if (of_property_present(cinfo->dev->of_node, "shmem"))
367 		return setup_static_shmem(dev, cinfo, channel);
368 	else
369 		return setup_dynamic_shmem(dev, channel);
370 }
371 
scmi_optee_chan_setup(struct scmi_chan_info * cinfo,struct device * dev,bool tx)372 static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool tx)
373 {
374 	struct scmi_optee_channel *channel;
375 	uint32_t channel_id;
376 	int ret;
377 
378 	if (!tx)
379 		return -ENODEV;
380 
381 	channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL);
382 	if (!channel)
383 		return -ENOMEM;
384 
385 	ret = of_property_read_u32_index(cinfo->dev->of_node, "linaro,optee-channel-id",
386 					 0, &channel_id);
387 	if (ret)
388 		return ret;
389 
390 	cinfo->transport_info = channel;
391 	channel->cinfo = cinfo;
392 	channel->channel_id = channel_id;
393 	mutex_init(&channel->mu);
394 
395 	ret = setup_shmem(dev, cinfo, channel);
396 	if (ret)
397 		return ret;
398 
399 	ret = open_session(scmi_optee_private, &channel->tee_session);
400 	if (ret)
401 		goto err_free_shm;
402 
403 	ret = tee_client_system_session(scmi_optee_private->tee_ctx, channel->tee_session);
404 	if (ret)
405 		dev_warn(dev, "Could not switch to system session, do best effort\n");
406 
407 	ret = get_channel(channel);
408 	if (ret)
409 		goto err_close_sess;
410 
411 	/* Enable polling */
412 	cinfo->no_completion_irq = true;
413 
414 	mutex_lock(&scmi_optee_private->mu);
415 	list_add(&channel->link, &scmi_optee_private->channel_list);
416 	mutex_unlock(&scmi_optee_private->mu);
417 
418 	return 0;
419 
420 err_close_sess:
421 	close_session(scmi_optee_private, channel->tee_session);
422 err_free_shm:
423 	if (channel->tee_shm)
424 		tee_shm_free(channel->tee_shm);
425 
426 	return ret;
427 }
428 
scmi_optee_chan_free(int id,void * p,void * data)429 static int scmi_optee_chan_free(int id, void *p, void *data)
430 {
431 	struct scmi_chan_info *cinfo = p;
432 	struct scmi_optee_channel *channel = cinfo->transport_info;
433 
434 	/*
435 	 * Different protocols might share the same chan info, so a previous
436 	 * call might have already freed the structure.
437 	 */
438 	if (!channel)
439 		return 0;
440 
441 	mutex_lock(&scmi_optee_private->mu);
442 	list_del(&channel->link);
443 	mutex_unlock(&scmi_optee_private->mu);
444 
445 	close_session(scmi_optee_private, channel->tee_session);
446 
447 	if (channel->tee_shm) {
448 		tee_shm_free(channel->tee_shm);
449 		channel->tee_shm = NULL;
450 	}
451 
452 	cinfo->transport_info = NULL;
453 	channel->cinfo = NULL;
454 
455 	return 0;
456 }
457 
scmi_optee_send_message(struct scmi_chan_info * cinfo,struct scmi_xfer * xfer)458 static int scmi_optee_send_message(struct scmi_chan_info *cinfo,
459 				   struct scmi_xfer *xfer)
460 {
461 	struct scmi_optee_channel *channel = cinfo->transport_info;
462 	int ret;
463 
464 	mutex_lock(&channel->mu);
465 
466 	if (channel->tee_shm) {
467 		core->msg->tx_prepare(channel->req.msg, xfer);
468 		ret = invoke_process_msg_channel(channel,
469 						 core->msg->command_size(xfer));
470 	} else {
471 		core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo,
472 					channel->io_ops->toio);
473 		ret = invoke_process_smt_channel(channel);
474 	}
475 
476 	if (ret)
477 		mutex_unlock(&channel->mu);
478 
479 	return ret;
480 }
481 
scmi_optee_fetch_response(struct scmi_chan_info * cinfo,struct scmi_xfer * xfer)482 static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
483 				      struct scmi_xfer *xfer)
484 {
485 	struct scmi_optee_channel *channel = cinfo->transport_info;
486 
487 	if (channel->tee_shm)
488 		core->msg->fetch_response(channel->req.msg,
489 					  channel->rx_len, xfer);
490 	else
491 		core->shmem->fetch_response(channel->req.shmem, xfer,
492 					    channel->io_ops->fromio);
493 }
494 
scmi_optee_mark_txdone(struct scmi_chan_info * cinfo,int ret,struct scmi_xfer * __unused)495 static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret,
496 				   struct scmi_xfer *__unused)
497 {
498 	struct scmi_optee_channel *channel = cinfo->transport_info;
499 
500 	mutex_unlock(&channel->mu);
501 }
502 
503 static struct scmi_transport_ops scmi_optee_ops = {
504 	.chan_available = scmi_optee_chan_available,
505 	.chan_setup = scmi_optee_chan_setup,
506 	.chan_free = scmi_optee_chan_free,
507 	.send_message = scmi_optee_send_message,
508 	.mark_txdone = scmi_optee_mark_txdone,
509 	.fetch_response = scmi_optee_fetch_response,
510 	.clear_channel = scmi_optee_clear_channel,
511 };
512 
scmi_optee_ctx_match(struct tee_ioctl_version_data * ver,const void * data)513 static int scmi_optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
514 {
515 	return ver->impl_id == TEE_IMPL_ID_OPTEE;
516 }
517 
518 static struct scmi_desc scmi_optee_desc = {
519 	.ops = &scmi_optee_ops,
520 	.max_rx_timeout_ms = 30,
521 	.max_msg = 20,
522 	.max_msg_size = SCMI_OPTEE_MAX_MSG_SIZE,
523 	.sync_cmds_completed_on_ret = true,
524 };
525 
526 static const struct of_device_id scmi_of_match[] = {
527 	{ .compatible = "linaro,scmi-optee" },
528 	{ /* Sentinel */ },
529 };
530 
531 DEFINE_SCMI_TRANSPORT_DRIVER(scmi_optee, scmi_optee_driver, scmi_optee_desc,
532 			     scmi_of_match, core);
533 
scmi_optee_service_probe(struct device * dev)534 static int scmi_optee_service_probe(struct device *dev)
535 {
536 	struct scmi_optee_agent *agent;
537 	struct tee_context *tee_ctx;
538 	int ret;
539 
540 	/* Only one SCMI OP-TEE device allowed */
541 	if (scmi_optee_private) {
542 		dev_err(dev, "An SCMI OP-TEE device was already initialized: only one allowed\n");
543 		return -EBUSY;
544 	}
545 
546 	tee_ctx = tee_client_open_context(NULL, scmi_optee_ctx_match, NULL, NULL);
547 	if (IS_ERR(tee_ctx))
548 		return -ENODEV;
549 
550 	agent = devm_kzalloc(dev, sizeof(*agent), GFP_KERNEL);
551 	if (!agent) {
552 		ret = -ENOMEM;
553 		goto err;
554 	}
555 
556 	agent->dev = dev;
557 	agent->tee_ctx = tee_ctx;
558 	INIT_LIST_HEAD(&agent->channel_list);
559 	mutex_init(&agent->mu);
560 
561 	ret = get_capabilities(agent);
562 	if (ret)
563 		goto err;
564 
565 	/* Ensure agent resources are all visible before scmi_optee_private is */
566 	smp_mb();
567 	scmi_optee_private = agent;
568 
569 	ret = platform_driver_register(&scmi_optee_driver);
570 	if (ret) {
571 		scmi_optee_private = NULL;
572 		goto err;
573 	}
574 
575 	return 0;
576 
577 err:
578 	tee_client_close_context(tee_ctx);
579 
580 	return ret;
581 }
582 
scmi_optee_service_remove(struct device * dev)583 static int scmi_optee_service_remove(struct device *dev)
584 {
585 	struct scmi_optee_agent *agent = scmi_optee_private;
586 
587 	if (!scmi_optee_private)
588 		return -EINVAL;
589 
590 	platform_driver_unregister(&scmi_optee_driver);
591 
592 	if (!list_empty(&scmi_optee_private->channel_list))
593 		return -EBUSY;
594 
595 	/* Ensure cleared reference is visible before resources are released */
596 	smp_store_mb(scmi_optee_private, NULL);
597 
598 	tee_client_close_context(agent->tee_ctx);
599 
600 	return 0;
601 }
602 
603 static const struct tee_client_device_id scmi_optee_service_id[] = {
604 	{
605 		UUID_INIT(0xa8cfe406, 0xd4f5, 0x4a2e,
606 			  0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99)
607 	},
608 	{ }
609 };
610 
611 MODULE_DEVICE_TABLE(tee, scmi_optee_service_id);
612 
613 static struct tee_client_driver scmi_optee_service_driver = {
614 	.id_table	= scmi_optee_service_id,
615 	.driver		= {
616 		.name = "scmi-optee",
617 		.bus = &tee_bus_type,
618 		.probe = scmi_optee_service_probe,
619 		.remove = scmi_optee_service_remove,
620 	},
621 };
622 
scmi_transport_optee_init(void)623 static int __init scmi_transport_optee_init(void)
624 {
625 	return driver_register(&scmi_optee_service_driver.driver);
626 }
627 module_init(scmi_transport_optee_init);
628 
scmi_transport_optee_exit(void)629 static void __exit scmi_transport_optee_exit(void)
630 {
631 	driver_unregister(&scmi_optee_service_driver.driver);
632 }
633 module_exit(scmi_transport_optee_exit);
634 
635 MODULE_AUTHOR("Etienne Carriere <etienne.carriere@foss.st.com>");
636 MODULE_DESCRIPTION("SCMI OPTEE Transport driver");
637 MODULE_LICENSE("GPL");
638