xref: /openbmc/u-boot/arch/arm/cpu/armv7m/mpu.c (revision 203e94f6)
1 /*
2  * (C) Copyright 2017
3  * Vikas Manocha, ST Micoelectronics, vikas.manocha@st.com.
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <linux/bitops.h>
9 #include <asm/armv7m.h>
10 #include <asm/armv7m_mpu.h>
11 #include <asm/io.h>
12 
13 #define V7M_MPU_CTRL_ENABLE		(1 << 0)
14 #define V7M_MPU_CTRL_DISABLE		(0 << 0)
15 #define V7M_MPU_CTRL_HFNMIENA		(1 << 1)
16 #define VALID_REGION			(1 << 4)
17 
18 #define ENABLE_REGION			(1 << 0)
19 
20 #define AP_SHIFT			24
21 #define XN_SHIFT			28
22 #define TEX_SHIFT			19
23 #define S_SHIFT				18
24 #define C_SHIFT				17
25 #define B_SHIFT				16
26 #define REGION_SIZE_SHIFT		1
27 
28 #define CACHEABLE			(1 << C_SHIFT)
29 #define BUFFERABLE			(1 << B_SHIFT)
30 #define SHAREABLE			(1 << S_SHIFT)
31 
32 void disable_mpu(void)
33 {
34 	writel(0, &V7M_MPU->ctrl);
35 }
36 
37 void enable_mpu(void)
38 {
39 	writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl);
40 
41 	/* Make sure new mpu config is effective for next memory access */
42 	dsb();
43 	isb();	/* Make sure instruction stream sees it */
44 }
45 
46 void mpu_config(struct mpu_region_config *reg_config)
47 {
48 	uint32_t attr;
49 
50 	switch (reg_config->mr_attr) {
51 	case STRONG_ORDER:
52 		attr = SHAREABLE;
53 		break;
54 	case SHARED_WRITE_BUFFERED:
55 		attr = BUFFERABLE;
56 		break;
57 	case O_I_WT_NO_WR_ALLOC:
58 		attr = CACHEABLE;
59 		break;
60 	case O_I_WB_NO_WR_ALLOC:
61 		attr = CACHEABLE | BUFFERABLE;
62 		break;
63 	case O_I_NON_CACHEABLE:
64 		attr = 1 << TEX_SHIFT;
65 		break;
66 	case O_I_WB_RD_WR_ALLOC:
67 		attr = (1 << TEX_SHIFT) | CACHEABLE | BUFFERABLE;
68 		break;
69 	case DEVICE_NON_SHARED:
70 		attr = (2 << TEX_SHIFT) | BUFFERABLE;
71 		break;
72 	default:
73 		attr = 0; /* strongly ordered */
74 		break;
75 	};
76 
77 	writel(reg_config->start_addr | VALID_REGION | reg_config->region_no,
78 	       &V7M_MPU->rbar);
79 
80 	writel(reg_config->xn << XN_SHIFT | reg_config->ap << AP_SHIFT | attr
81 		| reg_config->reg_size << REGION_SIZE_SHIFT | ENABLE_REGION
82 	       , &V7M_MPU->rasr);
83 }
84