summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/l2x0-prefetch.c
blob: 48a4495533f14493c738019d15367a80ca06feb2 (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * Copyright (C) ST-Ericsson SA 2011
 *
 * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
 * License terms: GNU General Public License (GPL) version 2
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/tee.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/hardware/cache-l2x0.h>

static struct tee_session session;
static struct tee_context context;
static void __iomem *l2x0_base;

#define L2X0_PREFETCH_CTRL_REG (0x00000F60)
#define L2X0_PREFETCH_CTRL_BIT_DATA_EN (1 << 28)
#define L2X0_PREFETCH_CTRL_BIT_INST_EN (1 << 29)

#define L2X0_UUID_TEE_TA_START_LOW	0xBC765EDE
#define L2X0_UUID_TEE_TA_START_MID	0x6724
#define L2X0_UUID_TEE_TA_START_HIGH	0x11DF
#define L2X0_UUID_TEE_TA_START_CLOCKSEQ  \
	{0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85}

static void prefetch_enable(void)
{
	struct tee_operation operation;
	u32 data;
	int err;
	int origin_err;

	data = readl(l2x0_base + L2X0_PREFETCH_CTRL_REG);

	pr_debug("l2x0-prefetch: %s start, preftect_ctrl=0x%08x\n", __func__,
									data);
	if (!(data & L2X0_PREFETCH_CTRL_BIT_INST_EN) ||
		!(data & L2X0_PREFETCH_CTRL_BIT_DATA_EN)) {

		data |= (L2X0_PREFETCH_CTRL_BIT_INST_EN |
				L2X0_PREFETCH_CTRL_BIT_DATA_EN);

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

		err = teec_invoke_command(&session,
			TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER,
			&operation, &origin_err);
		if (err)
			pr_err("l2x0-prefetch: prefetch enable failed, err=%d",
									err);
	}
	pr_debug("l2x0-prefetch: %s end, prefetch_ctrl=0x%08x\n", __func__,
		readl(l2x0_base + L2X0_PREFETCH_CTRL_REG));
}

static void prefetch_disable(void)
{
	struct tee_operation operation;
	u32 data;
	int err;
	int origin_err;

	data = readl(l2x0_base + L2X0_PREFETCH_CTRL_REG);

	pr_debug("l2x0-prefetch: %s start, preftect_ctrl=0x%08x\n", __func__,
									data);
	if (data & (L2X0_PREFETCH_CTRL_BIT_INST_EN |
			L2X0_PREFETCH_CTRL_BIT_DATA_EN)) {

		data &= ~(L2X0_PREFETCH_CTRL_BIT_INST_EN |
				L2X0_PREFETCH_CTRL_BIT_DATA_EN);

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

		err = teec_invoke_command(&session,
			TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER,
			&operation, &origin_err);
		if (err)
			pr_err("l2x0-prefetch: prefetch disable failed, err=%d",
									err);
	}
	pr_debug("l2x0-prefetch: %s end, prefetch_ctrl=0x%08x\n", __func__,
		readl(l2x0_base + L2X0_PREFETCH_CTRL_REG));
}

static int __init prefetch_ctrl_init(void)
{
	int err;
	int origin_err;
	/* Selects trustzone application needed for the job. */
	struct tee_uuid static_uuid = {
		L2X0_UUID_TEE_TA_START_LOW,
		L2X0_UUID_TEE_TA_START_MID,
		L2X0_UUID_TEE_TA_START_HIGH,
		L2X0_UUID_TEE_TA_START_CLOCKSEQ,
	};

	/* Get PL310 base address. It will be used as readonly. */
	if (cpu_is_u5500())
		l2x0_base = __io_address(U5500_L2CC_BASE);
	else if (cpu_is_u8500())
		l2x0_base = __io_address(U8500_L2CC_BASE);
	else
		ux500_unknown_soc();

	err = teec_initialize_context(NULL, &context);
	if (err) {
		pr_err("l2x0-prefetch: 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("l2x0-prefetch: unable to open tee session,"
			" tee error = %d, origin error = %d\n",
			err, origin_err);
		err = -EINVAL;
		goto error1;
	}

	outer_cache.prefetch_enable = prefetch_enable;
	outer_cache.prefetch_disable = prefetch_disable;

	pr_info("l2x0-prefetch: initialized.\n");

	return 0;

error1:
	(void)teec_finalize_context(&context);
error0:
	return err;
}

static void __exit prefetch_ctrl_exit(void)
{
	outer_cache.prefetch_enable = NULL;
	outer_cache.prefetch_disable = NULL;

	(void)teec_close_session(&session);
	(void)teec_finalize_context(&context);
}

/* Wait for TEE driver to be initialized. */
late_initcall(prefetch_ctrl_init);
module_exit(prefetch_ctrl_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PL310 prefetch control");