1
2
3
4
5
6
7
8
9#include <common.h>
10#include <command.h>
11#include <asm/armv7.h>
12#include <asm/system.h>
13#include <asm/barriers.h>
14#include <linux/compiler.h>
15
16#include <asm/armv7_mpu.h>
17
18
19#define MPUIR_S_SHIFT 0
20#define MPUIR_S_MASK BIT(MPUIR_S_SHIFT)
21#define MPUIR_DREGION_SHIFT 8
22#define MPUIR_DREGION_MASK (0xff << 8)
23
24
25
26
27
28
29
30
31
32
33void disable_mpu(void)
34{
35 u32 reg;
36
37 reg = get_cr();
38 reg &= ~CR_M;
39 dsb();
40 set_cr(reg);
41 isb();
42}
43
44void enable_mpu(void)
45{
46 u32 reg;
47
48 reg = get_cr();
49 reg |= CR_M;
50 dsb();
51 set_cr(reg);
52 isb();
53}
54
55int mpu_enabled(void)
56{
57 return get_cr() & CR_M;
58}
59
60void mpu_config(struct mpu_region_config *rgn)
61{
62 u32 attr, val;
63
64 attr = get_attr_encoding(rgn->mr_attr);
65
66
67 asm volatile ("mcr p15, 0, %0, c6, c2, 0" : : "r" (rgn->region_no));
68
69
70 asm volatile ("mcr p15, 0, %0, c6, c1, 0" : : "r" (rgn->start_addr));
71
72
73 if (rgn->reg_size)
74 val = (rgn->reg_size << REGION_SIZE_SHIFT) | ENABLE_REGION;
75 else
76 val = DISABLE_REGION;
77 asm volatile ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val));
78
79
80 val = rgn->xn << XN_SHIFT | rgn->ap << AP_SHIFT | attr;
81 asm volatile ("mcr p15, 0, %0, c6, c1, 4" : : "r" (val));
82}
83
84void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns)
85{
86 u32 num, i;
87
88 asm volatile ("mrc p15, 0, %0, c0, c0, 4" : "=r" (num));
89 num = (num & MPUIR_DREGION_MASK) >> MPUIR_DREGION_SHIFT;
90
91 if (num < num_rgns)
92 num_rgns = num;
93
94
95
96
97 icache_disable();
98 invalidate_icache_all();
99
100 disable_mpu();
101
102 for (i = 0; i < num_rgns; i++)
103 mpu_config(&rgns[i]);
104
105 enable_mpu();
106
107 icache_enable();
108}
109
110void enable_caches(void)
111{
112
113
114
115
116 if (!icache_status())
117 icache_enable();
118 dcache_enable();
119}
120