aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2015-01-08 01:53:20 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-01-16 09:35:37 -0500
commit5445b640f38efa9c571584d44df5673804194397 (patch)
tree012c300bd5bb5270eaf18c5611393ebebb44a33b /arch/arm/mach-exynos
parentcf0681ca4cc5c9faa85a2df4c063b926fc09c977 (diff)
ARM: 8263/1: EXYNOS: Add .write_sec outer cache callback for L2C-310
Exynos4 SoCs equipped with an L2C-310 cache controller and running under secure firmware require certain registers of aforementioned IP to be accessed only from secure mode. This means that SMC calls are required for certain register writes. To handle this, an implementation of .write_sec and .configure callbacks is provided by this patch. [added comment and reworked unconditional call to SMC_CMD_L2X0INVALL] Signed-off-by: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-exynos')
-rw-r--r--arch/arm/mach-exynos/firmware.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index 766f57d2f029..4791a3cc00f9 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -17,6 +17,7 @@
17#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
18#include <asm/cputype.h> 18#include <asm/cputype.h>
19#include <asm/firmware.h> 19#include <asm/firmware.h>
20#include <asm/hardware/cache-l2x0.h>
20#include <asm/suspend.h> 21#include <asm/suspend.h>
21 22
22#include <mach/map.h> 23#include <mach/map.h>
@@ -136,6 +137,43 @@ static const struct firmware_ops exynos_firmware_ops = {
136 .resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL, 137 .resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
137}; 138};
138 139
140static void exynos_l2_write_sec(unsigned long val, unsigned reg)
141{
142 static int l2cache_enabled;
143
144 switch (reg) {
145 case L2X0_CTRL:
146 if (val & L2X0_CTRL_EN) {
147 /*
148 * Before the cache can be enabled, due to firmware
149 * design, SMC_CMD_L2X0INVALL must be called.
150 */
151 if (!l2cache_enabled) {
152 exynos_smc(SMC_CMD_L2X0INVALL, 0, 0, 0);
153 l2cache_enabled = 1;
154 }
155 } else {
156 l2cache_enabled = 0;
157 }
158 exynos_smc(SMC_CMD_L2X0CTRL, val, 0, 0);
159 break;
160
161 case L2X0_DEBUG_CTRL:
162 exynos_smc(SMC_CMD_L2X0DEBUG, val, 0, 0);
163 break;
164
165 default:
166 WARN_ONCE(1, "%s: ignoring write to reg 0x%x\n", __func__, reg);
167 }
168}
169
170static void exynos_l2_configure(const struct l2x0_regs *regs)
171{
172 exynos_smc(SMC_CMD_L2X0SETUP1, regs->tag_latency, regs->data_latency,
173 regs->prefetch_ctrl);
174 exynos_smc(SMC_CMD_L2X0SETUP2, regs->pwr_ctrl, regs->aux_ctrl, 0);
175}
176
139void __init exynos_firmware_init(void) 177void __init exynos_firmware_init(void)
140{ 178{
141 struct device_node *nd; 179 struct device_node *nd;
@@ -155,4 +193,16 @@ void __init exynos_firmware_init(void)
155 pr_info("Running under secure firmware.\n"); 193 pr_info("Running under secure firmware.\n");
156 194
157 register_firmware_ops(&exynos_firmware_ops); 195 register_firmware_ops(&exynos_firmware_ops);
196
197 /*
198 * Exynos 4 SoCs (based on Cortex A9 and equipped with L2C-310),
199 * running under secure firmware, require certain registers of L2
200 * cache controller to be written in secure mode. Here .write_sec
201 * callback is provided to perform necessary SMC calls.
202 */
203 if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
204 read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
205 outer_cache.write_sec = exynos_l2_write_sec;
206 outer_cache.configure = exynos_l2_configure;
207 }
158} 208}