1 // SPDX-License-Identifier: GPL-2.0+
3 * Cortex-R Memory Protection Unit specific code
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
11 #include <asm/armv7.h>
12 #include <asm/system.h>
13 #include <asm/barriers.h>
14 #include <linux/compiler.h>
16 #include <asm/armv7_mpu.h>
18 /* MPU Type register definitions */
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)
26 * The Memory Protection Unit(MPU) allows to partition memory into regions
27 * and set individual protection attributes for each region. In absence
28 * of MPU a default map[1] will take effect. make sure to run this code
29 * from a region which has execution permissions by default.
30 * [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0460d/I1002400.html
33 void disable_mpu(void)
57 return get_cr() & CR_M;
60 void mpu_config(struct mpu_region_config *rgn)
64 attr = get_attr_encoding(rgn->mr_attr);
66 /* MPU Region Number Register */
67 asm volatile ("mcr p15, 0, %0, c6, c2, 0" : : "r" (rgn->region_no));
69 /* MPU Region Base Address Register */
70 asm volatile ("mcr p15, 0, %0, c6, c1, 0" : : "r" (rgn->start_addr));
72 /* MPU Region Size and Enable Register */
74 val = (rgn->reg_size << REGION_SIZE_SHIFT) | ENABLE_REGION;
77 asm volatile ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val));
79 /* MPU Region Access Control Register */
80 val = rgn->xn << XN_SHIFT | rgn->ap << AP_SHIFT | attr;
81 asm volatile ("mcr p15, 0, %0, c6, c1, 4" : : "r" (val));
84 void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns)
88 asm volatile ("mrc p15, 0, %0, c0, c0, 4" : "=r" (num));
89 num = (num & MPUIR_DREGION_MASK) >> MPUIR_DREGION_SHIFT;
90 /* Regions to be configured cannot be greater than available regions */
94 * Assuming dcache might not be enabled at this point, disabling
95 * and invalidating only icache.
98 invalidate_icache_all();
102 for (i = 0; i < num_rgns; i++)
103 mpu_config(&rgns[i]);
110 void enable_caches(void)
113 * setup_mpu_regions() might have enabled Icache. So add a check
114 * before enabling Icache
116 if (!icache_status())