summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/tee_ux500.c
blob: 9fa985a48c80355a821aa3d4427492ed49881977 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * TEE service to handle the calls to trusted applications.
 *
 * Copyright (C) ST-Ericsson SA 2010
 * Author: Joakim Bech <joakim.xx.bech@stericsson.com>
 * License terms: GNU General Public License (GPL) version 2
 */
#include <linux/kernel.h>
#include <linux/tee.h>
#include <linux/io.h>
#include <linux/errno.h>

#include <mach/hardware.h>

#define ISSWAPI_EXECUTE_TA 0x11000001
#define ISSWAPI_CLOSE_TA   0x11000002

#define SEC_ROM_NO_FLAG_MASK    0x0000

static u32 call_sec_rom_bridge(u32 service_id, u32 cfg, ...)
{
	typedef u32 (*bridge_func)(u32, u32, va_list);
	bridge_func hw_sec_rom_pub_bridge;
	va_list ap;
	u32 ret;

	if (cpu_is_u9540())
		hw_sec_rom_pub_bridge = (bridge_func)
			((u32)IO_ADDRESS_DB9540_ROM
			 (U9540_BOOT_ROM_BASE + 0x17300));
	else if (cpu_is_u8500())
		hw_sec_rom_pub_bridge = (bridge_func)
			((u32)IO_ADDRESS(U8500_BOOT_ROM_BASE + 0x17300));
	else if (cpu_is_u5500())
		hw_sec_rom_pub_bridge = (bridge_func)
			((u32)IO_ADDRESS(U5500_BOOT_ROM_BASE + 0x18300));
	else
		ux500_unknown_soc();

	va_start(ap, cfg);
	ret = hw_sec_rom_pub_bridge(service_id, cfg, ap);
	va_end(ap);

	return ret;
}

int call_sec_world(struct tee_session *ts, int sec_cmd)
{
	/*
	 * ts->ta and ts->uuid is set to NULL when opening the device,
	 * hence it should be safe to just do the call here.
	 */

	switch (sec_cmd) {
	case TEED_INVOKE:
	if (!ts->uuid) {
		call_sec_rom_bridge(ISSWAPI_EXECUTE_TA,
				SEC_ROM_NO_FLAG_MASK,
				virt_to_phys(&ts->id),
				NULL,
				virt_to_phys(ts->ta),
				ts->cmd,
				virt_to_phys((void *)(ts->op)),
				virt_to_phys((void *)(&ts->err)),
				virt_to_phys((void *)(&ts->origin)));
	} else {
		call_sec_rom_bridge(ISSWAPI_EXECUTE_TA,
				SEC_ROM_NO_FLAG_MASK,
				virt_to_phys(&ts->id),
				virt_to_phys(ts->uuid),
				virt_to_phys(ts->ta),
				ts->cmd,
				virt_to_phys((void *)(ts->op)),
				virt_to_phys((void *)(&ts->err)),
				virt_to_phys((void *)(&ts->origin)));
	}
	break;

	case TEED_CLOSE_SESSION:
		call_sec_rom_bridge(ISSWAPI_CLOSE_TA,
				SEC_ROM_NO_FLAG_MASK,
				ts->id,
				NULL,
				virt_to_phys(ts->ta),
				virt_to_phys((void *)(&ts->err)));

		/* Since the TEE Client API does NOT take care of
		 * the return value, we print a warning here if
		 * something went wrong in secure world.
		 */
		if (ts->err != TEED_SUCCESS)
				pr_warning("[%s] failed in secure world\n",
							__func__);

	break;
	}

	return 0;
}