blob: b122009f890cd4ee44ea692fb2f685b5ff81f90a [file] [log] [blame]
Jens Wiklander18ebb2f2015-04-14 14:33:20 +02001/*
2 * Copyright (c) 2015, Linaro Limited
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17#include <linux/arm-smccc.h>
18#include <linux/errno.h>
19#include <linux/io.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/of_platform.h>
23#include <linux/platform_device.h>
24#include <linux/slab.h>
25#include <linux/string.h>
26#include <linux/tee_drv.h>
27#include <linux/types.h>
28#include <linux/uaccess.h>
29#include "optee_private.h"
30#include "optee_smc.h"
31
32#define DRIVER_NAME "optee"
33
34#define OPTEE_SHM_NUM_PRIV_PAGES 1
35
36/**
37 * optee_from_msg_param() - convert from OPTEE_MSG parameters to
38 * struct tee_param
39 * @params: subsystem internal parameter representation
40 * @num_params: number of elements in the parameter arrays
41 * @msg_params: OPTEE_MSG parameters
42 * Returns 0 on success or <0 on failure
43 */
44int optee_from_msg_param(struct tee_param *params, size_t num_params,
45 const struct optee_msg_param *msg_params)
46{
47 int rc;
48 size_t n;
49 struct tee_shm *shm;
50 phys_addr_t pa;
51
52 for (n = 0; n < num_params; n++) {
53 struct tee_param *p = params + n;
54 const struct optee_msg_param *mp = msg_params + n;
55 u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
56
57 switch (attr) {
58 case OPTEE_MSG_ATTR_TYPE_NONE:
59 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
60 memset(&p->u, 0, sizeof(p->u));
61 break;
62 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
63 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
64 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
65 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
66 attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
67 p->u.value.a = mp->u.value.a;
68 p->u.value.b = mp->u.value.b;
69 p->u.value.c = mp->u.value.c;
70 break;
71 case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
72 case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
73 case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
74 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
75 attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
76 p->u.memref.size = mp->u.tmem.size;
77 shm = (struct tee_shm *)(unsigned long)
78 mp->u.tmem.shm_ref;
79 if (!shm) {
80 p->u.memref.shm_offs = 0;
81 p->u.memref.shm = NULL;
82 break;
83 }
84 rc = tee_shm_get_pa(shm, 0, &pa);
85 if (rc)
86 return rc;
87 p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
88 p->u.memref.shm = shm;
89
90 /* Check that the memref is covered by the shm object */
91 if (p->u.memref.size) {
92 size_t o = p->u.memref.shm_offs +
93 p->u.memref.size - 1;
94
95 rc = tee_shm_get_pa(shm, o, NULL);
96 if (rc)
97 return rc;
98 }
99 break;
Volodymyr Babchuk7ec482b2017-11-29 14:48:32 +0200100 case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
101 case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
102 case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
103 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
104 attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
105 p->u.memref.size = mp->u.rmem.size;
106 shm = (struct tee_shm *)(unsigned long)
107 mp->u.rmem.shm_ref;
108
109 if (!shm) {
110 p->u.memref.shm_offs = 0;
111 p->u.memref.shm = NULL;
112 break;
113 }
114 p->u.memref.shm_offs = mp->u.rmem.offs;
115 p->u.memref.shm = shm;
116
117 break;
118
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200119 default:
120 return -EINVAL;
121 }
122 }
123 return 0;
124}
125
Volodymyr Babchuk7ec482b2017-11-29 14:48:32 +0200126static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
127 const struct tee_param *p)
128{
129 int rc;
130 phys_addr_t pa;
131
132 mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
133 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
134
135 mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
136 mp->u.tmem.size = p->u.memref.size;
137
138 if (!p->u.memref.shm) {
139 mp->u.tmem.buf_ptr = 0;
140 return 0;
141 }
142
143 rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa);
144 if (rc)
145 return rc;
146
147 mp->u.tmem.buf_ptr = pa;
148 mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
149 OPTEE_MSG_ATTR_CACHE_SHIFT;
150
151 return 0;
152}
153
154static int to_msg_param_reg_mem(struct optee_msg_param *mp,
155 const struct tee_param *p)
156{
157 mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
158 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
159
160 mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm;
161 mp->u.rmem.size = p->u.memref.size;
162 mp->u.rmem.offs = p->u.memref.shm_offs;
163 return 0;
164}
165
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200166/**
167 * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
168 * @msg_params: OPTEE_MSG parameters
169 * @num_params: number of elements in the parameter arrays
170 * @params: subsystem itnernal parameter representation
171 * Returns 0 on success or <0 on failure
172 */
173int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
174 const struct tee_param *params)
175{
176 int rc;
177 size_t n;
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200178
179 for (n = 0; n < num_params; n++) {
180 const struct tee_param *p = params + n;
181 struct optee_msg_param *mp = msg_params + n;
182
183 switch (p->attr) {
184 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
185 mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
186 memset(&mp->u, 0, sizeof(mp->u));
187 break;
188 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
189 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
190 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
191 mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
192 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
193 mp->u.value.a = p->u.value.a;
194 mp->u.value.b = p->u.value.b;
195 mp->u.value.c = p->u.value.c;
196 break;
197 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
198 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
199 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
Volodymyr Babchuk7ec482b2017-11-29 14:48:32 +0200200 if (tee_shm_is_registered(p->u.memref.shm))
201 rc = to_msg_param_reg_mem(mp, p);
202 else
203 rc = to_msg_param_tmp_mem(mp, p);
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200204 if (rc)
205 return rc;
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200206 break;
207 default:
208 return -EINVAL;
209 }
210 }
211 return 0;
212}
213
214static void optee_get_version(struct tee_device *teedev,
215 struct tee_ioctl_version_data *vers)
216{
217 struct tee_ioctl_version_data v = {
218 .impl_id = TEE_IMPL_ID_OPTEE,
219 .impl_caps = TEE_OPTEE_CAP_TZ,
220 .gen_caps = TEE_GEN_CAP_GP,
221 };
222 *vers = v;
223}
224
225static int optee_open(struct tee_context *ctx)
226{
227 struct optee_context_data *ctxdata;
228 struct tee_device *teedev = ctx->teedev;
229 struct optee *optee = tee_get_drvdata(teedev);
230
231 ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
232 if (!ctxdata)
233 return -ENOMEM;
234
235 if (teedev == optee->supp_teedev) {
236 bool busy = true;
237
Jens Wiklanderad675fa2016-12-23 13:13:39 +0100238 mutex_lock(&optee->supp.mutex);
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200239 if (!optee->supp.ctx) {
240 busy = false;
241 optee->supp.ctx = ctx;
242 }
Jens Wiklanderad675fa2016-12-23 13:13:39 +0100243 mutex_unlock(&optee->supp.mutex);
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200244 if (busy) {
245 kfree(ctxdata);
246 return -EBUSY;
247 }
248 }
249
250 mutex_init(&ctxdata->mutex);
251 INIT_LIST_HEAD(&ctxdata->sess_list);
252
253 ctx->data = ctxdata;
254 return 0;
255}
256
257static void optee_release(struct tee_context *ctx)
258{
259 struct optee_context_data *ctxdata = ctx->data;
260 struct tee_device *teedev = ctx->teedev;
261 struct optee *optee = tee_get_drvdata(teedev);
262 struct tee_shm *shm;
263 struct optee_msg_arg *arg = NULL;
264 phys_addr_t parg;
265 struct optee_session *sess;
266 struct optee_session *sess_tmp;
267
268 if (!ctxdata)
269 return;
270
271 shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
272 if (!IS_ERR(shm)) {
273 arg = tee_shm_get_va(shm, 0);
274 /*
Jens Wiklander14edc412017-05-15 11:09:28 +0200275 * If va2pa fails for some reason, we can't call into
276 * secure world, only free the memory. Secure OS will leak
277 * sessions and finally refuse more sessions, but we will
278 * at least let normal world reclaim its memory.
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200279 */
280 if (!IS_ERR(arg))
Jens Wiklander14edc412017-05-15 11:09:28 +0200281 if (tee_shm_va2pa(shm, arg, &parg))
282 arg = NULL; /* prevent usage of parg below */
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200283 }
284
285 list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
286 list_node) {
287 list_del(&sess->list_node);
288 if (!IS_ERR_OR_NULL(arg)) {
289 memset(arg, 0, sizeof(*arg));
290 arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
291 arg->session = sess->session_id;
292 optee_do_call_with_arg(ctx, parg);
293 }
294 kfree(sess);
295 }
296 kfree(ctxdata);
297
298 if (!IS_ERR(shm))
299 tee_shm_free(shm);
300
301 ctx->data = NULL;
302
Jens Wiklanderad675fa2016-12-23 13:13:39 +0100303 if (teedev == optee->supp_teedev)
304 optee_supp_release(&optee->supp);
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200305}
306
Bhumika Goyal7b22a542017-06-29 15:05:04 +0530307static const struct tee_driver_ops optee_ops = {
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200308 .get_version = optee_get_version,
309 .open = optee_open,
310 .release = optee_release,
311 .open_session = optee_open_session,
312 .close_session = optee_close_session,
313 .invoke_func = optee_invoke_func,
314 .cancel_req = optee_cancel_req,
Volodymyr Babchuk88be5b82017-11-29 14:48:31 +0200315 .shm_register = optee_shm_register,
316 .shm_unregister = optee_shm_unregister,
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200317};
318
Bhumika Goyal7b22a542017-06-29 15:05:04 +0530319static const struct tee_desc optee_desc = {
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200320 .name = DRIVER_NAME "-clnt",
321 .ops = &optee_ops,
322 .owner = THIS_MODULE,
323};
324
Bhumika Goyal7b22a542017-06-29 15:05:04 +0530325static const struct tee_driver_ops optee_supp_ops = {
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200326 .get_version = optee_get_version,
327 .open = optee_open,
328 .release = optee_release,
329 .supp_recv = optee_supp_recv,
330 .supp_send = optee_supp_send,
331};
332
Bhumika Goyal7b22a542017-06-29 15:05:04 +0530333static const struct tee_desc optee_supp_desc = {
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200334 .name = DRIVER_NAME "-supp",
335 .ops = &optee_supp_ops,
336 .owner = THIS_MODULE,
337 .flags = TEE_DESC_PRIVILEGED,
338};
339
340static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
341{
342 struct arm_smccc_res res;
343
344 invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
345
346 if (res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
347 res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3)
348 return true;
349 return false;
350}
351
352static bool optee_msg_api_revision_is_compatible(optee_invoke_fn *invoke_fn)
353{
354 union {
355 struct arm_smccc_res smccc;
356 struct optee_smc_calls_revision_result result;
357 } res;
358
359 invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
360
361 if (res.result.major == OPTEE_MSG_REVISION_MAJOR &&
362 (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR)
363 return true;
364 return false;
365}
366
367static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
368 u32 *sec_caps)
369{
370 union {
371 struct arm_smccc_res smccc;
372 struct optee_smc_exchange_capabilities_result result;
373 } res;
374 u32 a1 = 0;
375
376 /*
377 * TODO This isn't enough to tell if it's UP system (from kernel
378 * point of view) or not, is_smp() returns the the information
379 * needed, but can't be called directly from here.
380 */
381 if (!IS_ENABLED(CONFIG_SMP) || nr_cpu_ids == 1)
382 a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR;
383
384 invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0,
385 &res.smccc);
386
387 if (res.result.status != OPTEE_SMC_RETURN_OK)
388 return false;
389
390 *sec_caps = res.result.capabilities;
391 return true;
392}
393
394static struct tee_shm_pool *
395optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
396{
397 union {
398 struct arm_smccc_res smccc;
399 struct optee_smc_get_shm_config_result result;
400 } res;
401 struct tee_shm_pool *pool;
402 unsigned long vaddr;
403 phys_addr_t paddr;
404 size_t size;
405 phys_addr_t begin;
406 phys_addr_t end;
407 void *va;
408 struct tee_shm_pool_mem_info priv_info;
409 struct tee_shm_pool_mem_info dmabuf_info;
410
411 invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
412 if (res.result.status != OPTEE_SMC_RETURN_OK) {
413 pr_info("shm service not available\n");
414 return ERR_PTR(-ENOENT);
415 }
416
417 if (res.result.settings != OPTEE_SMC_SHM_CACHED) {
418 pr_err("only normal cached shared memory supported\n");
419 return ERR_PTR(-EINVAL);
420 }
421
422 begin = roundup(res.result.start, PAGE_SIZE);
423 end = rounddown(res.result.start + res.result.size, PAGE_SIZE);
424 paddr = begin;
425 size = end - begin;
426
427 if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) {
428 pr_err("too small shared memory area\n");
429 return ERR_PTR(-EINVAL);
430 }
431
432 va = memremap(paddr, size, MEMREMAP_WB);
433 if (!va) {
434 pr_err("shared memory ioremap failed\n");
435 return ERR_PTR(-EINVAL);
436 }
437 vaddr = (unsigned long)va;
438
439 priv_info.vaddr = vaddr;
440 priv_info.paddr = paddr;
441 priv_info.size = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
442 dmabuf_info.vaddr = vaddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
443 dmabuf_info.paddr = paddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
444 dmabuf_info.size = size - OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
445
446 pool = tee_shm_pool_alloc_res_mem(&priv_info, &dmabuf_info);
447 if (IS_ERR(pool)) {
448 memunmap(va);
449 goto out;
450 }
451
452 *memremaped_shm = va;
453out:
454 return pool;
455}
456
457/* Simple wrapper functions to be able to use a function pointer */
458static void optee_smccc_smc(unsigned long a0, unsigned long a1,
459 unsigned long a2, unsigned long a3,
460 unsigned long a4, unsigned long a5,
461 unsigned long a6, unsigned long a7,
462 struct arm_smccc_res *res)
463{
464 arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
465}
466
467static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
468 unsigned long a2, unsigned long a3,
469 unsigned long a4, unsigned long a5,
470 unsigned long a6, unsigned long a7,
471 struct arm_smccc_res *res)
472{
473 arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
474}
475
476static optee_invoke_fn *get_invoke_func(struct device_node *np)
477{
478 const char *method;
479
480 pr_info("probing for conduit method from DT.\n");
481
482 if (of_property_read_string(np, "method", &method)) {
483 pr_warn("missing \"method\" property\n");
484 return ERR_PTR(-ENXIO);
485 }
486
487 if (!strcmp("hvc", method))
488 return optee_smccc_hvc;
489 else if (!strcmp("smc", method))
490 return optee_smccc_smc;
491
492 pr_warn("invalid \"method\" property: %s\n", method);
493 return ERR_PTR(-EINVAL);
494}
495
496static struct optee *optee_probe(struct device_node *np)
497{
498 optee_invoke_fn *invoke_fn;
499 struct tee_shm_pool *pool;
500 struct optee *optee = NULL;
501 void *memremaped_shm = NULL;
502 struct tee_device *teedev;
503 u32 sec_caps;
504 int rc;
505
506 invoke_fn = get_invoke_func(np);
507 if (IS_ERR(invoke_fn))
508 return (void *)invoke_fn;
509
510 if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
511 pr_warn("api uid mismatch\n");
512 return ERR_PTR(-EINVAL);
513 }
514
515 if (!optee_msg_api_revision_is_compatible(invoke_fn)) {
516 pr_warn("api revision mismatch\n");
517 return ERR_PTR(-EINVAL);
518 }
519
520 if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) {
521 pr_warn("capabilities mismatch\n");
522 return ERR_PTR(-EINVAL);
523 }
524
525 /*
526 * We have no other option for shared memory, if secure world
527 * doesn't have any reserved memory we can use we can't continue.
528 */
529 if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
530 return ERR_PTR(-EINVAL);
531
532 pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm);
533 if (IS_ERR(pool))
534 return (void *)pool;
535
536 optee = kzalloc(sizeof(*optee), GFP_KERNEL);
537 if (!optee) {
538 rc = -ENOMEM;
539 goto err;
540 }
541
542 optee->invoke_fn = invoke_fn;
543
544 teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
545 if (IS_ERR(teedev)) {
546 rc = PTR_ERR(teedev);
547 goto err;
548 }
549 optee->teedev = teedev;
550
551 teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
552 if (IS_ERR(teedev)) {
553 rc = PTR_ERR(teedev);
554 goto err;
555 }
556 optee->supp_teedev = teedev;
557
558 rc = tee_device_register(optee->teedev);
559 if (rc)
560 goto err;
561
562 rc = tee_device_register(optee->supp_teedev);
563 if (rc)
564 goto err;
565
566 mutex_init(&optee->call_queue.mutex);
567 INIT_LIST_HEAD(&optee->call_queue.waiters);
568 optee_wait_queue_init(&optee->wait_queue);
569 optee_supp_init(&optee->supp);
570 optee->memremaped_shm = memremaped_shm;
571 optee->pool = pool;
572
573 optee_enable_shm_cache(optee);
574
575 pr_info("initialized driver\n");
576 return optee;
577err:
578 if (optee) {
579 /*
580 * tee_device_unregister() is safe to call even if the
581 * devices hasn't been registered with
582 * tee_device_register() yet.
583 */
584 tee_device_unregister(optee->supp_teedev);
585 tee_device_unregister(optee->teedev);
586 kfree(optee);
587 }
588 if (pool)
589 tee_shm_pool_free(pool);
590 if (memremaped_shm)
591 memunmap(memremaped_shm);
592 return ERR_PTR(rc);
593}
594
595static void optee_remove(struct optee *optee)
596{
597 /*
598 * Ask OP-TEE to free all cached shared memory objects to decrease
599 * reference counters and also avoid wild pointers in secure world
600 * into the old shared memory range.
601 */
602 optee_disable_shm_cache(optee);
603
604 /*
605 * The two devices has to be unregistered before we can free the
606 * other resources.
607 */
608 tee_device_unregister(optee->supp_teedev);
609 tee_device_unregister(optee->teedev);
610
611 tee_shm_pool_free(optee->pool);
612 if (optee->memremaped_shm)
613 memunmap(optee->memremaped_shm);
614 optee_wait_queue_exit(&optee->wait_queue);
615 optee_supp_uninit(&optee->supp);
616 mutex_destroy(&optee->call_queue.mutex);
617
618 kfree(optee);
619}
620
621static const struct of_device_id optee_match[] = {
622 { .compatible = "linaro,optee-tz" },
623 {},
624};
625
626static struct optee *optee_svc;
627
628static int __init optee_driver_init(void)
629{
630 struct device_node *fw_np;
631 struct device_node *np;
632 struct optee *optee;
633
634 /* Node is supposed to be below /firmware */
635 fw_np = of_find_node_by_name(NULL, "firmware");
636 if (!fw_np)
637 return -ENODEV;
638
639 np = of_find_matching_node(fw_np, optee_match);
Jens Wiklander18ebb2f2015-04-14 14:33:20 +0200640 if (!np)
641 return -ENODEV;
642
643 optee = optee_probe(np);
644 of_node_put(np);
645
646 if (IS_ERR(optee))
647 return PTR_ERR(optee);
648
649 optee_svc = optee;
650
651 return 0;
652}
653module_init(optee_driver_init);
654
655static void __exit optee_driver_exit(void)
656{
657 struct optee *optee = optee_svc;
658
659 optee_svc = NULL;
660 if (optee)
661 optee_remove(optee);
662}
663module_exit(optee_driver_exit);
664
665MODULE_AUTHOR("Linaro");
666MODULE_DESCRIPTION("OP-TEE driver");
667MODULE_SUPPORTED_DEVICE("");
668MODULE_VERSION("1.0");
669MODULE_LICENSE("GPL v2");