]> Git Repo - J-u-boot.git/blob - arch/arm/cpu/armv7/mpu_v7r.c
2d83e4c721d25603bf4ec55391a767d23d06504c
[J-u-boot.git] / arch / arm / cpu / armv7 / mpu_v7r.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Cortex-R Memory Protection Unit specific code
4  *
5  * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
6  *      Lokesh Vutla <[email protected]>
7  */
8
9 #include <command.h>
10 #include <cpu_func.h>
11 #include <asm/armv7.h>
12 #include <asm/system.h>
13 #include <asm/barriers.h>
14 #include <linux/bitops.h>
15 #include <linux/compiler.h>
16
17 #include <asm/armv7_mpu.h>
18
19 /* MPU Type register definitions */
20 #define MPUIR_S_SHIFT           0
21 #define MPUIR_S_MASK            BIT(MPUIR_S_SHIFT)
22 #define MPUIR_DREGION_SHIFT     8
23 #define MPUIR_DREGION_MASK      (0xff << 8)
24
25 /**
26  * Note:
27  * The Memory Protection Unit(MPU) allows to partition memory into regions
28  * and set individual protection attributes for each region. In absence
29  * of MPU a default map[1] will take effect. make sure to run this code
30  * from a region which has execution permissions by default.
31  * [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0460d/I1002400.html
32  */
33
34 void disable_mpu(void)
35 {
36         u32 reg;
37
38         reg = get_cr();
39         reg &= ~CR_M;
40         dsb();
41         set_cr(reg);
42         isb();
43 }
44
45 void enable_mpu(void)
46 {
47         u32 reg;
48
49         reg = get_cr();
50         reg |= CR_M;
51         dsb();
52         set_cr(reg);
53         isb();
54 }
55
56 int mpu_enabled(void)
57 {
58         return get_cr() & CR_M;
59 }
60
61 void mpu_config(struct mpu_region_config *rgn)
62 {
63         u32 attr, val;
64
65         attr = get_attr_encoding(rgn->mr_attr);
66
67         /* MPU Region Number Register */
68         asm volatile ("mcr p15, 0, %0, c6, c2, 0" : : "r" (rgn->region_no));
69
70         /* MPU Region Base Address Register */
71         asm volatile ("mcr p15, 0, %0, c6, c1, 0" : : "r" (rgn->start_addr));
72
73         /* MPU Region Size and Enable Register */
74         if (rgn->reg_size)
75                 val = (rgn->reg_size << REGION_SIZE_SHIFT) | ENABLE_REGION;
76         else
77                 val = DISABLE_REGION;
78         asm volatile ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val));
79
80         /* MPU Region Access Control Register */
81         val = rgn->xn << XN_SHIFT | rgn->ap << AP_SHIFT | attr;
82         asm volatile ("mcr p15, 0, %0, c6, c1, 4" : : "r" (val));
83 }
84
85 void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns)
86 {
87         u32 num, i;
88
89         asm volatile ("mrc p15, 0, %0, c0, c0, 4" : "=r" (num));
90         num = (num & MPUIR_DREGION_MASK) >> MPUIR_DREGION_SHIFT;
91         /* Regions to be configured cannot be greater than available regions */
92         if (num < num_rgns)
93                 num_rgns = num;
94         /**
95          * Assuming dcache might not be enabled at this point, disabling
96          * and invalidating only icache.
97          */
98         icache_disable();
99         invalidate_icache_all();
100
101         disable_mpu();
102
103         for (i = 0; i < num_rgns; i++)
104                 mpu_config(&rgns[i]);
105
106         enable_mpu();
107
108         icache_enable();
109 }
110
111 void enable_caches(void)
112 {
113         /*
114          * setup_mpu_regions() might have enabled Icache. So add a check
115          * before enabling Icache
116          */
117         if (!icache_status())
118                 icache_enable();
119         dcache_enable();
120 }
This page took 0.021468 seconds and 2 git commands to generate.