summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv7m/Makefile2
-rw-r--r--arch/arm/cpu/armv7m/mpu.c82
-rw-r--r--arch/arm/include/asm/armv7m.h20
-rw-r--r--arch/arm/include/asm/armv7m_mpu.h67
4 files changed, 150 insertions, 21 deletions
diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile
index 93c9085..257fc7f 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/mpu.c b/arch/arm/cpu/armv7m/mpu.c
new file mode 100644
index 0000000..31a243b
--- /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/include/asm/armv7m.h b/arch/arm/include/asm/armv7m.h
index 9a6224f..af8a97e 100644
--- a/arch/arm/include/asm/armv7m.h
+++ b/arch/arm/include/asm/armv7m.h
@@ -70,25 +70,5 @@ struct v7m_mpu {
};
#define V7M_MPU ((struct v7m_mpu *)V7M_MPU_BASE)
-#define V7M_MPU_CTRL_ENABLE (1 << 0)
-#define V7M_MPU_CTRL_HFNMIENA (1 << 1)
-
-#define V7M_MPU_CTRL_ENABLE (1 << 0)
-#define V7M_MPU_CTRL_DISABLE (0 << 0)
-#define V7M_MPU_CTRL_HFNMIENA (1 << 1)
-
-#define V7M_MPU_RASR_EN (1 << 0)
-#define V7M_MPU_RASR_SIZE_BITS 1
-#define V7M_MPU_RASR_SIZE_4GB (31 << V7M_MPU_RASR_SIZE_BITS)
-#define V7M_MPU_RASR_SIZE_8MB (22 << V7M_MPU_RASR_SIZE_BITS)
-
-#define V7M_MPU_RASR_TEX_SHIFT 19
-#define V7M_MPU_RASR_S_SHIFT 18
-#define V7M_MPU_RASR_C_SHIFT 17
-#define V7M_MPU_RASR_B_SHIFT 16
-#define V7M_MPU_RASR_AP_RW_RW (3 << 24)
-#define V7M_MPU_RASR_XN_ENABLE (0 << 28)
-#define V7M_MPU_RASR_XN_DISABLE (1 << 28)
-
#endif /* !defined(__ASSEMBLY__) */
#endif /* ARMV7M_H */
diff --git a/arch/arm/include/asm/armv7m_mpu.h b/arch/arm/include/asm/armv7m_mpu.h
new file mode 100644
index 0000000..d7e99b4
--- /dev/null
+++ b/arch/arm/include/asm/armv7m_mpu.h
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2017
+ * Vikas Manocha, ST Micoelectronics, vikas.manocha@st.com.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+enum region_number {
+ REGION_0 = 0,
+ REGION_1,
+ REGION_2,
+ REGION_3,
+ REGION_4,
+ REGION_5,
+ REGION_6,
+ REGION_7,
+};
+
+enum ap {
+ NO_ACCESS = 0,
+ PRIV_RW_USR_NO,
+ PRIV_RW_USR_RO,
+ PRIV_RW_USR_RW,
+ UNPREDICTABLE,
+ PRIV_RO_USR_NO,
+ PRIV_RO_USR_RO,
+};
+
+enum mr_attr {
+ STRONG_ORDER = 0,
+ SHARED_WRITE_BUFFERED,
+ O_I_WT_NO_WR_ALLOC,
+ O_I_WB_NO_WR_ALLOC,
+ O_I_NON_CACHEABLE,
+ O_I_WB_RD_WR_ALLOC,
+ DEVICE_NON_SHARED,
+};
+enum size {
+ REGION_8MB = 22,
+ REGION_16MB,
+ REGION_32MB,
+ REGION_64MB,
+ REGION_128MB,
+ REGION_256MB,
+ REGION_512MB,
+ REGION_1GB,
+ REGION_2GB,
+ REGION_4GB,
+};
+
+enum xn {
+ XN_DIS = 0,
+ XN_EN,
+};
+
+struct mpu_region_config {
+ uint32_t start_addr;
+ enum region_number region_no;
+ enum xn xn;
+ enum ap ap;
+ enum mr_attr mr_attr;
+ enum size reg_size;
+};
+
+void disable_mpu(void);
+void enable_mpu(void);
+void mpu_config(struct mpu_region_config *reg_config);