|
@@ -17,6 +17,7 @@
|
|
|
#include <asm/cacheflush.h>
|
|
|
#include <asm/cputype.h>
|
|
|
#include <asm/firmware.h>
|
|
|
+#include <asm/hardware/cache-l2x0.h>
|
|
|
#include <asm/suspend.h>
|
|
|
|
|
|
#include <mach/map.h>
|
|
@@ -136,6 +137,43 @@ static const struct firmware_ops exynos_firmware_ops = {
|
|
|
.resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
|
|
|
};
|
|
|
|
|
|
+static void exynos_l2_write_sec(unsigned long val, unsigned reg)
|
|
|
+{
|
|
|
+ static int l2cache_enabled;
|
|
|
+
|
|
|
+ switch (reg) {
|
|
|
+ case L2X0_CTRL:
|
|
|
+ if (val & L2X0_CTRL_EN) {
|
|
|
+ /*
|
|
|
+ * Before the cache can be enabled, due to firmware
|
|
|
+ * design, SMC_CMD_L2X0INVALL must be called.
|
|
|
+ */
|
|
|
+ if (!l2cache_enabled) {
|
|
|
+ exynos_smc(SMC_CMD_L2X0INVALL, 0, 0, 0);
|
|
|
+ l2cache_enabled = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ l2cache_enabled = 0;
|
|
|
+ }
|
|
|
+ exynos_smc(SMC_CMD_L2X0CTRL, val, 0, 0);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case L2X0_DEBUG_CTRL:
|
|
|
+ exynos_smc(SMC_CMD_L2X0DEBUG, val, 0, 0);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ WARN_ONCE(1, "%s: ignoring write to reg 0x%x\n", __func__, reg);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void exynos_l2_configure(const struct l2x0_regs *regs)
|
|
|
+{
|
|
|
+ exynos_smc(SMC_CMD_L2X0SETUP1, regs->tag_latency, regs->data_latency,
|
|
|
+ regs->prefetch_ctrl);
|
|
|
+ exynos_smc(SMC_CMD_L2X0SETUP2, regs->pwr_ctrl, regs->aux_ctrl, 0);
|
|
|
+}
|
|
|
+
|
|
|
void __init exynos_firmware_init(void)
|
|
|
{
|
|
|
struct device_node *nd;
|
|
@@ -155,4 +193,16 @@ void __init exynos_firmware_init(void)
|
|
|
pr_info("Running under secure firmware.\n");
|
|
|
|
|
|
register_firmware_ops(&exynos_firmware_ops);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Exynos 4 SoCs (based on Cortex A9 and equipped with L2C-310),
|
|
|
+ * running under secure firmware, require certain registers of L2
|
|
|
+ * cache controller to be written in secure mode. Here .write_sec
|
|
|
+ * callback is provided to perform necessary SMC calls.
|
|
|
+ */
|
|
|
+ if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
|
|
|
+ read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
|
|
|
+ outer_cache.write_sec = exynos_l2_write_sec;
|
|
|
+ outer_cache.configure = exynos_l2_configure;
|
|
|
+ }
|
|
|
}
|