summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/product.c
blob: 5e8eba9b16a7ae002975614b2e7d379c02db13d7 (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
100
101
102
103
104
105
106
107
/*
 * Copyright (C) ST-Ericsson SA 2011
 *
 * Author: Jens Wiklander <jens.wiklander@stericsson.com>
 * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
 * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
 *
 * License terms: GNU General Public License (GPL) version 2
 *
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/tee.h>
#include <linux/module.h>
#include <mach/hardware.h>

#define STATIC_TEE_TA_START_LOW	0xBC765EDE
#define STATIC_TEE_TA_START_MID	0x6724
#define STATIC_TEE_TA_START_HIGH	0x11DF
#define STATIC_TEE_TA_START_CLOCKSEQ  \
	{0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85}

#define U5500_PRCMU_DBG_PWRCTRL         (U5500_PRCMU_BASE + 0x4AC)
#define PRCMU_DBG_PWRCTRL_A9DBGCLKEN    (1 << 4)

static struct tee_product_config product_config;

bool ux500_jtag_enabled(void)
{
#ifdef CONFIG_UX500_DEBUG_NO_LAUTERBACH
        return false;
#else
        if (cpu_is_u5500())
                return readl_relaxed(__io_address(U5500_PRCMU_DBG_PWRCTRL))
                        & PRCMU_DBG_PWRCTRL_A9DBGCLKEN;

        if (cpu_is_u8500())
		return (product_config.rt_flags & TEE_RT_FLAGS_JTAG_ENABLED) ==
			TEE_RT_FLAGS_JTAG_ENABLED;

	return true;
#endif
}

static int __init product_detect(void)
{
	int err;
	int origin_err;
	struct tee_operation operation = { { { 0 } } };
	struct tee_context context;
	struct tee_session session;

	/* Selects trustzone application needed for the job. */
	struct tee_uuid static_uuid = {
		STATIC_TEE_TA_START_LOW,
		STATIC_TEE_TA_START_MID,
		STATIC_TEE_TA_START_HIGH,
		STATIC_TEE_TA_START_CLOCKSEQ,
	};

	if (cpu_is_u5500())
		return -ENODEV;

	err = teec_initialize_context(NULL, &context);
	if (err) {
		pr_err("ux500-product: unable to initialize tee context,"
			" err = %d\n", err);
		err = -EINVAL;
		goto error0;
	}

	err = teec_open_session(&context, &session, &static_uuid,
				TEEC_LOGIN_PUBLIC, NULL, NULL, &origin_err);
	if (err) {
		pr_err("ux500-product: unable to open tee session,"
			" tee error = %d, origin error = %d\n",
			err, origin_err);
		err = -EINVAL;
		goto error1;
	}

	operation.shm[0].buffer = &product_config;
	operation.shm[0].size = sizeof(product_config);
	operation.shm[0].flags = TEEC_MEM_OUTPUT;
	operation.flags = TEEC_MEMREF_0_USED;

	err = teec_invoke_command(&session,
				  TEE_STA_GET_PRODUCT_CONFIG,
				  &operation, &origin_err);
	if (err) {
		pr_err("ux500-product: fetching product settings failed, err=%d",
		       err);
		err = -EINVAL;
		goto error1;
	}

	pr_info("ux500-product: JTAG is %s\n",
		ux500_jtag_enabled()? "enabled" : "disabled");
error1:
	(void) teec_finalize_context(&context);
error0:
	return err;
}
device_initcall(product_detect);