aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/firmware.c')
-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}