0001
0002
0003
0004
0005
0006
0007 #include <linux/memblock.h>
0008 #include <linux/range.h>
0009
0010 #include <asm/cp15.h>
0011 #include <asm/cputype.h>
0012 #include <asm/mpu.h>
0013
0014 #include <asm/memory.h>
0015 #include <asm/sections.h>
0016
0017 #include "mm.h"
0018
0019 #ifndef CONFIG_CPU_V7M
0020
0021 #define PRSEL __ACCESS_CP15(c6, 0, c2, 1)
0022 #define PRBAR __ACCESS_CP15(c6, 0, c3, 0)
0023 #define PRLAR __ACCESS_CP15(c6, 0, c3, 1)
0024
0025 static inline u32 prlar_read(void)
0026 {
0027 return read_sysreg(PRLAR);
0028 }
0029
0030 static inline u32 prbar_read(void)
0031 {
0032 return read_sysreg(PRBAR);
0033 }
0034
0035 static inline void prsel_write(u32 v)
0036 {
0037 write_sysreg(v, PRSEL);
0038 }
0039
0040 static inline void prbar_write(u32 v)
0041 {
0042 write_sysreg(v, PRBAR);
0043 }
0044
0045 static inline void prlar_write(u32 v)
0046 {
0047 write_sysreg(v, PRLAR);
0048 }
0049 #else
0050
0051 static inline u32 prlar_read(void)
0052 {
0053 return readl_relaxed(BASEADDR_V7M_SCB + PMSAv8_RLAR);
0054 }
0055
0056 static inline u32 prbar_read(void)
0057 {
0058 return readl_relaxed(BASEADDR_V7M_SCB + PMSAv8_RBAR);
0059 }
0060
0061 static inline void prsel_write(u32 v)
0062 {
0063 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv8_RNR);
0064 }
0065
0066 static inline void prbar_write(u32 v)
0067 {
0068 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv8_RBAR);
0069 }
0070
0071 static inline void prlar_write(u32 v)
0072 {
0073 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv8_RLAR);
0074 }
0075
0076 #endif
0077
0078 static struct range __initdata io[MPU_MAX_REGIONS];
0079 static struct range __initdata mem[MPU_MAX_REGIONS];
0080
0081 static unsigned int __initdata mpu_max_regions;
0082
0083 static __init bool is_region_fixed(int number)
0084 {
0085 switch (number) {
0086 case PMSAv8_XIP_REGION:
0087 case PMSAv8_KERNEL_REGION:
0088 return true;
0089 default:
0090 return false;
0091 }
0092 }
0093
0094 void __init pmsav8_adjust_lowmem_bounds(void)
0095 {
0096 phys_addr_t mem_end;
0097 phys_addr_t reg_start, reg_end;
0098 bool first = true;
0099 u64 i;
0100
0101 for_each_mem_range(i, ®_start, ®_end) {
0102 if (first) {
0103 phys_addr_t phys_offset = PHYS_OFFSET;
0104
0105
0106
0107
0108 if (reg_start != phys_offset)
0109 panic("First memory bank must be contiguous from PHYS_OFFSET");
0110 mem_end = reg_end;
0111 first = false;
0112 } else {
0113
0114
0115
0116
0117
0118 pr_notice("Ignoring RAM after %pa, memory at %pa ignored\n",
0119 &mem_end, ®_start);
0120 memblock_remove(reg_start, 0 - reg_start);
0121 break;
0122 }
0123 }
0124 }
0125
0126 static int __init __mpu_max_regions(void)
0127 {
0128 static int max_regions;
0129 u32 mpuir;
0130
0131 if (max_regions)
0132 return max_regions;
0133
0134 mpuir = read_cpuid_mputype();
0135
0136 max_regions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION;
0137
0138 return max_regions;
0139 }
0140
0141 static int __init __pmsav8_setup_region(unsigned int number, u32 bar, u32 lar)
0142 {
0143 if (number > mpu_max_regions
0144 || number >= MPU_MAX_REGIONS)
0145 return -ENOENT;
0146
0147 dsb();
0148 prsel_write(number);
0149 isb();
0150 prbar_write(bar);
0151 prlar_write(lar);
0152
0153 mpu_rgn_info.rgns[number].prbar = bar;
0154 mpu_rgn_info.rgns[number].prlar = lar;
0155
0156 mpu_rgn_info.used++;
0157
0158 return 0;
0159 }
0160
0161 static int __init pmsav8_setup_ram(unsigned int number, phys_addr_t start,phys_addr_t end)
0162 {
0163 u32 bar, lar;
0164
0165 if (is_region_fixed(number))
0166 return -EINVAL;
0167
0168 bar = start;
0169 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);
0170
0171 bar |= PMSAv8_AP_PL1RW_PL0RW | PMSAv8_RGN_SHARED;
0172 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN;
0173
0174 return __pmsav8_setup_region(number, bar, lar);
0175 }
0176
0177 static int __init pmsav8_setup_io(unsigned int number, phys_addr_t start,phys_addr_t end)
0178 {
0179 u32 bar, lar;
0180
0181 if (is_region_fixed(number))
0182 return -EINVAL;
0183
0184 bar = start;
0185 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);
0186
0187 bar |= PMSAv8_AP_PL1RW_PL0RW | PMSAv8_RGN_SHARED | PMSAv8_BAR_XN;
0188 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_DEVICE_nGnRnE) | PMSAv8_LAR_EN;
0189
0190 return __pmsav8_setup_region(number, bar, lar);
0191 }
0192
0193 static int __init pmsav8_setup_fixed(unsigned int number, phys_addr_t start,phys_addr_t end)
0194 {
0195 u32 bar, lar;
0196
0197 if (!is_region_fixed(number))
0198 return -EINVAL;
0199
0200 bar = start;
0201 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);
0202
0203 bar |= PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED;
0204 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN;
0205
0206 prsel_write(number);
0207 isb();
0208
0209 if (prbar_read() != bar || prlar_read() != lar)
0210 return -EINVAL;
0211
0212
0213 mpu_rgn_info.rgns[number].prbar = bar;
0214 mpu_rgn_info.rgns[number].prlar = lar;
0215
0216 mpu_rgn_info.used++;
0217
0218 return 0;
0219 }
0220
0221 #ifndef CONFIG_CPU_V7M
0222 static int __init pmsav8_setup_vector(unsigned int number, phys_addr_t start,phys_addr_t end)
0223 {
0224 u32 bar, lar;
0225
0226 if (number == PMSAv8_KERNEL_REGION)
0227 return -EINVAL;
0228
0229 bar = start;
0230 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);
0231
0232 bar |= PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED;
0233 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN;
0234
0235 return __pmsav8_setup_region(number, bar, lar);
0236 }
0237 #endif
0238
0239 void __init pmsav8_setup(void)
0240 {
0241 int i, err = 0;
0242 int region = PMSAv8_KERNEL_REGION;
0243
0244
0245 mpu_max_regions = __mpu_max_regions();
0246
0247
0248 add_range(mem, ARRAY_SIZE(mem), 0, memblock.memory.regions[0].base,
0249 memblock.memory.regions[0].base + memblock.memory.regions[0].size);
0250
0251
0252 add_range(io, ARRAY_SIZE(io), 0, 0, 0xffffffff);
0253
0254
0255 subtract_range(mem, ARRAY_SIZE(mem), __pa(KERNEL_START), __pa(KERNEL_END));
0256 subtract_range(io, ARRAY_SIZE(io), __pa(KERNEL_START), __pa(KERNEL_END));
0257
0258 #ifdef CONFIG_XIP_KERNEL
0259
0260 subtract_range(mem, ARRAY_SIZE(mem), CONFIG_XIP_PHYS_ADDR, __pa(_exiprom));
0261 subtract_range(io, ARRAY_SIZE(io), CONFIG_XIP_PHYS_ADDR, __pa(_exiprom));
0262 #endif
0263
0264 #ifndef CONFIG_CPU_V7M
0265
0266 subtract_range(mem, ARRAY_SIZE(mem), vectors_base, vectors_base + 2 * PAGE_SIZE);
0267 subtract_range(io, ARRAY_SIZE(io), vectors_base, vectors_base + 2 * PAGE_SIZE);
0268 #endif
0269
0270 for (i = 0; i < ARRAY_SIZE(mem); i++)
0271 subtract_range(io, ARRAY_SIZE(io), mem[i].start, mem[i].end);
0272
0273
0274
0275 #ifdef CONFIG_XIP_KERNEL
0276
0277 err |= pmsav8_setup_fixed(PMSAv8_XIP_REGION, CONFIG_XIP_PHYS_ADDR, __pa(_exiprom));
0278 #endif
0279
0280 err |= pmsav8_setup_fixed(region++, __pa(KERNEL_START), __pa(KERNEL_END));
0281
0282
0283
0284 for (i = 0; i < ARRAY_SIZE(io); i++) {
0285 if (!io[i].end)
0286 continue;
0287
0288 err |= pmsav8_setup_io(region++, io[i].start, io[i].end);
0289 }
0290
0291
0292 for (i = 0; i < ARRAY_SIZE(mem); i++) {
0293 if (!mem[i].end)
0294 continue;
0295
0296 err |= pmsav8_setup_ram(region++, mem[i].start, mem[i].end);
0297 }
0298
0299
0300 #ifndef CONFIG_CPU_V7M
0301 err |= pmsav8_setup_vector(region++, vectors_base, vectors_base + 2 * PAGE_SIZE);
0302 #endif
0303 if (err)
0304 pr_warn("MPU region initialization failure! %d", err);
0305 else
0306 pr_info("Using ARM PMSAv8 Compliant MPU. Used %d of %d regions\n",
0307 mpu_rgn_info.used, mpu_max_regions);
0308 }