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