diff options
Diffstat (limited to 'arch/arm/mach-exynos/firmware.c')
-rw-r--r-- | arch/arm/mach-exynos/firmware.c | 50 |
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 | ||
140 | static 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 | |||
170 | static 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 | |||
139 | void __init exynos_firmware_init(void) | 177 | void __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 | } |