aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/armv7m/Makefile2
-rw-r--r--arch/arm/cpu/armv7m/cache.c23
-rw-r--r--arch/arm/cpu/armv7m/cpu.c19
-rw-r--r--arch/arm/cpu/armv7m/mpu.c82
-rw-r--r--arch/arm/cpu/armv8/cache.S24
-rw-r--r--arch/arm/cpu/armv8/cache_v8.c2
-rw-r--r--arch/arm/cpu/armv8/generic_timer.c2
7 files changed, 151 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile
index 93c9085219..257fc7faf3 100644
--- a/arch/arm/cpu/armv7m/Makefile
+++ b/arch/arm/cpu/armv7m/Makefile
@@ -6,5 +6,5 @@
#
extra-y := start.o
-obj-y += cpu.o cache.o
+obj-y += cpu.o cache.o mpu.o
obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
diff --git a/arch/arm/cpu/armv7m/cache.c b/arch/arm/cpu/armv7m/cache.c
index 162cfe3928..e8f86420cf 100644
--- a/arch/arm/cpu/armv7m/cache.c
+++ b/arch/arm/cpu/armv7m/cache.c
@@ -253,6 +253,21 @@ void flush_dcache_range(unsigned long start, unsigned long stop)
return;
}
}
+void flush_dcache_all(void)
+{
+ if (action_dcache_all(FLUSH_SET_WAY)) {
+ printf("ERR: D-cache not flushed\n");
+ return;
+ }
+}
+
+void invalidate_dcache_all(void)
+{
+ if (action_dcache_all(INVALIDATE_SET_WAY)) {
+ printf("ERR: D-cache not invalidated\n");
+ return;
+ }
+}
#else
void dcache_enable(void)
{
@@ -268,6 +283,14 @@ int dcache_status(void)
{
return 0;
}
+
+void flush_dcache_all(void)
+{
+}
+
+void invalidate_dcache_all(void)
+{
+}
#endif
#ifndef CONFIG_SYS_ICACHE_OFF
diff --git a/arch/arm/cpu/armv7m/cpu.c b/arch/arm/cpu/armv7m/cpu.c
index 58cde9391f..a424babde5 100644
--- a/arch/arm/cpu/armv7m/cpu.c
+++ b/arch/arm/cpu/armv7m/cpu.c
@@ -18,6 +18,25 @@
*/
int cleanup_before_linux(void)
{
+ /*
+ * this function is called just before we call linux
+ * it prepares the processor for linux
+ *
+ * disable interrupt and turn off caches etc ...
+ */
+ disable_interrupts();
+ /*
+ * turn off D-cache
+ * dcache_disable() in turn flushes the d-cache
+ * MPU is still enabled & can't be disabled as the u-boot
+ * code might be running in sdram which by default is not
+ * executable area.
+ */
+ dcache_disable();
+ /* invalidate to make sure no cache line gets dirty between
+ * dcache flushing and disabling dcache */
+ invalidate_dcache_all();
+
return 0;
}
diff --git a/arch/arm/cpu/armv7m/mpu.c b/arch/arm/cpu/armv7m/mpu.c
new file mode 100644
index 0000000000..31a243b49a
--- /dev/null
+++ b/arch/arm/cpu/armv7m/mpu.c
@@ -0,0 +1,82 @@
+/*
+ * (C) Copyright 2017
+ * Vikas Manocha, ST Micoelectronics, vikas.manocha@st.com.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/bitops.h>
+#include <asm/armv7m.h>
+#include <asm/armv7m_mpu.h>
+#include <asm/io.h>
+
+#define V7M_MPU_CTRL_ENABLE (1 << 0)
+#define V7M_MPU_CTRL_DISABLE (0 << 0)
+#define V7M_MPU_CTRL_HFNMIENA (1 << 1)
+#define VALID_REGION (1 << 4)
+
+#define ENABLE_REGION (1 << 0)
+
+#define AP_SHIFT 24
+#define XN_SHIFT 28
+#define TEX_SHIFT 19
+#define S_SHIFT 18
+#define C_SHIFT 17
+#define B_SHIFT 16
+#define REGION_SIZE_SHIFT 1
+
+#define CACHEABLE (1 << C_SHIFT)
+#define BUFFERABLE (1 << B_SHIFT)
+#define SHAREABLE (1 << S_SHIFT)
+
+void disable_mpu(void)
+{
+ writel(0, &V7M_MPU->ctrl);
+}
+
+void enable_mpu(void)
+{
+ writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl);
+
+ /* Make sure new mpu config is effective for next memory access */
+ dsb();
+ isb(); /* Make sure instruction stream sees it */
+}
+
+void mpu_config(struct mpu_region_config *reg_config)
+{
+ uint32_t attr;
+
+ switch (reg_config->mr_attr) {
+ case STRONG_ORDER:
+ attr = SHAREABLE;
+ break;
+ case SHARED_WRITE_BUFFERED:
+ attr = BUFFERABLE;
+ break;
+ case O_I_WT_NO_WR_ALLOC:
+ attr = CACHEABLE;
+ break;
+ case O_I_WB_NO_WR_ALLOC:
+ attr = CACHEABLE | BUFFERABLE;
+ break;
+ case O_I_NON_CACHEABLE:
+ attr = 1 << TEX_SHIFT;
+ break;
+ case O_I_WB_RD_WR_ALLOC:
+ attr = (1 << TEX_SHIFT) | CACHEABLE | BUFFERABLE;
+ break;
+ case DEVICE_NON_SHARED:
+ attr = (2 << TEX_SHIFT) | BUFFERABLE;
+ default:
+ attr = 0; /* strongly ordered */
+ break;
+ };
+
+ writel(reg_config->start_addr | VALID_REGION | reg_config->region_no,
+ &V7M_MPU->rbar);
+
+ writel(reg_config->xn << XN_SHIFT | reg_config->ap << AP_SHIFT | attr
+ | reg_config->reg_size << REGION_SIZE_SHIFT | ENABLE_REGION
+ , &V7M_MPU->rasr);
+}
diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index f1deaa7230..7cba308ee7 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -138,6 +138,30 @@ ENTRY(__asm_flush_dcache_range)
dsb sy
ret
ENDPROC(__asm_flush_dcache_range)
+/*
+ * void __asm_invalidate_dcache_range(start, end)
+ *
+ * invalidate data cache in the range
+ *
+ * x0: start address
+ * x1: end address
+ */
+ENTRY(__asm_invalidate_dcache_range)
+ mrs x3, ctr_el0
+ ubfm x3, x3, #16, #19
+ mov x2, #4
+ lsl x2, x2, x3 /* cache line size */
+
+ /* x2 <- minimal cache line size in cache system */
+ sub x3, x2, #1
+ bic x0, x0, x3
+1: dc ivac, x0 /* invalidate data or unified cache */
+ add x0, x0, x2
+ cmp x0, x1
+ b.lo 1b
+ dsb sy
+ ret
+ENDPROC(__asm_invalidate_dcache_range)
/*
* void __asm_invalidate_icache_all(void)
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index bd1c3e0335..adc7e1746f 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -446,7 +446,7 @@ inline void flush_dcache_all(void)
*/
void invalidate_dcache_range(unsigned long start, unsigned long stop)
{
- __asm_flush_dcache_range(start, stop);
+ __asm_invalidate_dcache_range(start, stop);
}
/*
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c
index cd92b2c761..a2dda333fe 100644
--- a/arch/arm/cpu/armv8/generic_timer.c
+++ b/arch/arm/cpu/armv8/generic_timer.c
@@ -43,7 +43,7 @@ unsigned long timer_read_counter(void)
return cntpct;
}
-unsigned long long get_ticks(void)
+uint64_t get_ticks(void)
{
unsigned long ticks = timer_read_counter();