1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
4  * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
5  */
6 
7 #ifndef _ASM_ARMV7_MPU_H
8 #define _ASM_ARMV7_MPU_H
9 
10 #ifndef __ASSEMBLY__
11 #include <linux/bitops.h>
12 #endif
13 
14 #ifdef CONFIG_CPU_V7M
15 #define AP_SHIFT			24
16 #define XN_SHIFT			28
17 #define TEX_SHIFT			19
18 #define S_SHIFT				18
19 #define C_SHIFT				17
20 #define B_SHIFT				16
21 #else /* CONFIG_CPU_V7R */
22 #define XN_SHIFT			12
23 #define AP_SHIFT			8
24 #define TEX_SHIFT			3
25 #define S_SHIFT				2
26 #define C_SHIFT				1
27 #define B_SHIFT				0
28 #endif /* CONFIG_CPU_V7R */
29 
30 #define CACHEABLE			BIT(C_SHIFT)
31 #define BUFFERABLE			BIT(B_SHIFT)
32 #define SHAREABLE			BIT(S_SHIFT)
33 #define REGION_SIZE_SHIFT		1
34 #define ENABLE_REGION			BIT(0)
35 #define DISABLE_REGION			0
36 
37 enum region_number {
38 	REGION_0 = 0,
39 	REGION_1,
40 	REGION_2,
41 	REGION_3,
42 	REGION_4,
43 	REGION_5,
44 	REGION_6,
45 	REGION_7,
46 };
47 
48 enum ap {
49 	NO_ACCESS = 0,
50 	PRIV_RW_USR_NO,
51 	PRIV_RW_USR_RO,
52 	PRIV_RW_USR_RW,
53 	UNPREDICTABLE,
54 	PRIV_RO_USR_NO,
55 	PRIV_RO_USR_RO,
56 };
57 
58 enum mr_attr {
59 	STRONG_ORDER = 0,
60 	SHARED_WRITE_BUFFERED,
61 	O_I_WT_NO_WR_ALLOC,
62 	O_I_WB_NO_WR_ALLOC,
63 	O_I_NON_CACHEABLE,
64 	O_I_WB_RD_WR_ALLOC,
65 	DEVICE_NON_SHARED,
66 };
67 enum size {
68 	REGION_8MB = 22,
69 	REGION_16MB,
70 	REGION_32MB,
71 	REGION_64MB,
72 	REGION_128MB,
73 	REGION_256MB,
74 	REGION_512MB,
75 	REGION_1GB,
76 	REGION_2GB,
77 	REGION_4GB,
78 };
79 
80 enum xn {
81 	XN_DIS = 0,
82 	XN_EN,
83 };
84 
85 struct mpu_region_config {
86 	uint32_t start_addr;
87 	enum region_number region_no;
88 	enum xn xn;
89 	enum ap ap;
90 	enum mr_attr mr_attr;
91 	enum size reg_size;
92 };
93 
94 void disable_mpu(void);
95 void enable_mpu(void);
96 int mpu_enabled(void);
97 void mpu_config(struct mpu_region_config *reg_config);
98 void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns);
99 
get_attr_encoding(u32 mr_attr)100 static inline u32 get_attr_encoding(u32 mr_attr)
101 {
102 	u32 attr;
103 
104 	switch (mr_attr) {
105 	case STRONG_ORDER:
106 		attr = SHAREABLE;
107 		break;
108 	case SHARED_WRITE_BUFFERED:
109 		attr = BUFFERABLE;
110 		break;
111 	case O_I_WT_NO_WR_ALLOC:
112 		attr = CACHEABLE;
113 		break;
114 	case O_I_WB_NO_WR_ALLOC:
115 		attr = CACHEABLE | BUFFERABLE;
116 		break;
117 	case O_I_NON_CACHEABLE:
118 		attr = 1 << TEX_SHIFT;
119 		break;
120 	case O_I_WB_RD_WR_ALLOC:
121 		attr = (1 << TEX_SHIFT) | CACHEABLE | BUFFERABLE;
122 		break;
123 	case DEVICE_NON_SHARED:
124 		attr = (2 << TEX_SHIFT) | BUFFERABLE;
125 		break;
126 	default:
127 		attr = 0; /* strongly ordered */
128 		break;
129 	};
130 
131 	return attr;
132 }
133 
134 #endif /* _ASM_ARMV7_MPU_H */
135