aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firmware/Kconfig16
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/trusted_foundations.c176
3 files changed, 193 insertions, 0 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index cac16c4b0df3..f0646ac75868 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -267,6 +267,22 @@ config TI_SCI_PROTOCOL
267 This protocol library is used by client drivers to use the features 267 This protocol library is used by client drivers to use the features
268 provided by the system controller. 268 provided by the system controller.
269 269
270config TRUSTED_FOUNDATIONS
271 bool "Trusted Foundations secure monitor support"
272 depends on ARM
273 help
274 Some devices (including most early Tegra-based consumer devices on
275 the market) are booted with the Trusted Foundations secure monitor
276 active, requiring some core operations to be performed by the secure
277 monitor instead of the kernel.
278
279 This option allows the kernel to invoke the secure monitor whenever
280 required on devices using Trusted Foundations. See the functions and
281 comments in linux/firmware/trusted_foundations.h or the device tree
282 bindings for "tlm,trusted-foundations" for details on how to use it.
283
284 Choose N if you don't know what this is about.
285
270config HAVE_ARM_SMCCC 286config HAVE_ARM_SMCCC
271 bool 287 bool
272 288
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 80feb635120f..745f4907e69b 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o
23obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o 23obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
24CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a 24CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
25obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o 25obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
26obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
26 27
27obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/ 28obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
28obj-y += broadcom/ 29obj-y += broadcom/
diff --git a/drivers/firmware/trusted_foundations.c b/drivers/firmware/trusted_foundations.c
new file mode 100644
index 000000000000..fd4999388ff1
--- /dev/null
+++ b/drivers/firmware/trusted_foundations.c
@@ -0,0 +1,176 @@
1/*
2 * Trusted Foundations support for ARM CPUs
3 *
4 * Copyright (c) 2013, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/of.h>
20
21#include <linux/firmware/trusted_foundations.h>
22
23#include <asm/firmware.h>
24#include <asm/hardware/cache-l2x0.h>
25#include <asm/outercache.h>
26
27#define TF_CACHE_MAINT 0xfffff100
28
29#define TF_CACHE_ENABLE 1
30#define TF_CACHE_DISABLE 2
31
32#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
33
34#define TF_CPU_PM 0xfffffffc
35#define TF_CPU_PM_S3 0xffffffe3
36#define TF_CPU_PM_S2 0xffffffe6
37#define TF_CPU_PM_S2_NO_MC_CLK 0xffffffe5
38#define TF_CPU_PM_S1 0xffffffe4
39#define TF_CPU_PM_S1_NOFLUSH_L2 0xffffffe7
40
41static unsigned long cpu_boot_addr;
42
43static void tf_generic_smc(u32 type, u32 arg1, u32 arg2)
44{
45 register u32 r0 asm("r0") = type;
46 register u32 r1 asm("r1") = arg1;
47 register u32 r2 asm("r2") = arg2;
48
49 asm volatile(
50 ".arch_extension sec\n\t"
51 "stmfd sp!, {r4 - r11}\n\t"
52 __asmeq("%0", "r0")
53 __asmeq("%1", "r1")
54 __asmeq("%2", "r2")
55 "mov r3, #0\n\t"
56 "mov r4, #0\n\t"
57 "smc #0\n\t"
58 "ldmfd sp!, {r4 - r11}\n\t"
59 :
60 : "r" (r0), "r" (r1), "r" (r2)
61 : "memory", "r3", "r12", "lr");
62}
63
64static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
65{
66 cpu_boot_addr = boot_addr;
67 tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0);
68
69 return 0;
70}
71
72static int tf_prepare_idle(unsigned long mode)
73{
74 switch (mode) {
75 case TF_PM_MODE_LP0:
76 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S3, cpu_boot_addr);
77 break;
78
79 case TF_PM_MODE_LP1:
80 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2, cpu_boot_addr);
81 break;
82
83 case TF_PM_MODE_LP1_NO_MC_CLK:
84 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2_NO_MC_CLK,
85 cpu_boot_addr);
86 break;
87
88 case TF_PM_MODE_LP2:
89 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1, cpu_boot_addr);
90 break;
91
92 case TF_PM_MODE_LP2_NOFLUSH_L2:
93 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2,
94 cpu_boot_addr);
95 break;
96
97 default:
98 return -EINVAL;
99 }
100
101 return 0;
102}
103
104#ifdef CONFIG_CACHE_L2X0
105static void tf_cache_write_sec(unsigned long val, unsigned int reg)
106{
107 u32 l2x0_way_mask = 0xff;
108
109 switch (reg) {
110 case L2X0_CTRL:
111 if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16)
112 l2x0_way_mask = 0xffff;
113
114 if (val == L2X0_CTRL_EN)
115 tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE,
116 l2x0_saved_regs.aux_ctrl);
117 else
118 tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE,
119 l2x0_way_mask);
120 break;
121
122 default:
123 break;
124 }
125}
126
127static int tf_init_cache(void)
128{
129 outer_cache.write_sec = tf_cache_write_sec;
130
131 return 0;
132}
133#endif /* CONFIG_CACHE_L2X0 */
134
135static const struct firmware_ops trusted_foundations_ops = {
136 .set_cpu_boot_addr = tf_set_cpu_boot_addr,
137 .prepare_idle = tf_prepare_idle,
138#ifdef CONFIG_CACHE_L2X0
139 .l2x0_init = tf_init_cache,
140#endif
141};
142
143void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
144{
145 /*
146 * we are not using version information for now since currently
147 * supported SMCs are compatible with all TF releases
148 */
149 register_firmware_ops(&trusted_foundations_ops);
150}
151
152void of_register_trusted_foundations(void)
153{
154 struct device_node *node;
155 struct trusted_foundations_platform_data pdata;
156 int err;
157
158 node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
159 if (!node)
160 return;
161
162 err = of_property_read_u32(node, "tlm,version-major",
163 &pdata.version_major);
164 if (err != 0)
165 panic("Trusted Foundation: missing version-major property\n");
166 err = of_property_read_u32(node, "tlm,version-minor",
167 &pdata.version_minor);
168 if (err != 0)
169 panic("Trusted Foundation: missing version-minor property\n");
170 register_trusted_foundations(&pdata);
171}
172
173bool trusted_foundations_registered(void)
174{
175 return firmware_ops == &trusted_foundations_ops;
176}