summaryrefslogtreecommitdiff
path: root/arch/arm/include/asm/armv7_mpu.h
blob: 16b9d0d1aeb3ad8f8146038910ec72e45e9ba820 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
 * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
 */

#ifndef _ASM_ARMV7_MPU_H
#define _ASM_ARMV7_MPU_H

#ifndef __ASSEMBLY__
#include <linux/bitops.h>
#endif

#ifdef CONFIG_CPU_V7M
#define AP_SHIFT			24
#define XN_SHIFT			28
#define TEX_SHIFT			19
#define S_SHIFT				18
#define C_SHIFT				17
#define B_SHIFT				16
#else /* CONFIG_CPU_V7R */
#define XN_SHIFT			12
#define AP_SHIFT			8
#define TEX_SHIFT			3
#define S_SHIFT				2
#define C_SHIFT				1
#define B_SHIFT				0
#endif /* CONFIG_CPU_V7R */

#define CACHEABLE			BIT(C_SHIFT)
#define BUFFERABLE			BIT(B_SHIFT)
#define SHAREABLE			BIT(S_SHIFT)
#define REGION_SIZE_SHIFT		1
#define ENABLE_REGION			BIT(0)
#define DISABLE_REGION			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);
int mpu_enabled(void);
void mpu_config(struct mpu_region_config *reg_config);
void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns);

static inline u32 get_attr_encoding(u32 mr_attr)
{
	u32 attr;

	switch (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;
		break;
	default:
		attr = 0; /* strongly ordered */
		break;
	};

	return attr;
}

#endif /* _ASM_ARMV7_MPU_H */