Skip to content

Commit 9fcb01a

Browse files
murzinvRussell King
authored andcommitted
ARM: 8711/1: V7M: Add support for MPU to M-class
This patch makes it possible to use MPU with v7M cores. Tested-by: Szemző András <[email protected]> Tested-by: Alexandre TORGUE <[email protected]> Tested-by: Benjamin Gaignard <[email protected]> Signed-off-by: Vladimir Murzin <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent 89a6daf commit 9fcb01a

File tree

5 files changed

+113
-20
lines changed

5 files changed

+113
-20
lines changed

arch/arm/Kconfig-nommu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ config REMAP_VECTORS_TO_RAM
5252

5353
config ARM_MPU
5454
bool 'Use the ARM v7 PMSA Compliant MPU'
55-
depends on !XIP_KERNEL && CPU_V7
56-
default y
55+
depends on !XIP_KERNEL && (CPU_V7 || CPU_V7M)
56+
default y if CPU_V7
5757
help
5858
Some ARM systems without an MMU have instead a Memory Protection
5959
Unit (MPU) that defines the type and permissions for regions of

arch/arm/include/asm/cputype.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
173173
return read_cpuid(CPUID_CACHETYPE);
174174
}
175175

176+
static inline unsigned int __attribute_const__ read_cpuid_mputype(void)
177+
{
178+
return read_cpuid(CPUID_MPUIR);
179+
}
180+
176181
#elif defined(CONFIG_CPU_V7M)
177182

178183
static inline unsigned int __attribute_const__ read_cpuid_id(void)
@@ -185,6 +190,11 @@ static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
185190
return readl(BASEADDR_V7M_SCB + V7M_SCB_CTR);
186191
}
187192

193+
static inline unsigned int __attribute_const__ read_cpuid_mputype(void)
194+
{
195+
return readl(BASEADDR_V7M_SCB + MPU_TYPE);
196+
}
197+
188198
#else /* ifdef CONFIG_CPU_CP15 / elif defined(CONFIG_CPU_V7M) */
189199

190200
static inline unsigned int __attribute_const__ read_cpuid_id(void)

arch/arm/include/asm/v7m.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@
5757
#define V7M_SCB_CCSIDR 0x80 /* Cache size ID register */
5858
#define V7M_SCB_CSSELR 0x84 /* Cache size selection register */
5959

60+
/* Memory-mapped MPU registers for M-class */
61+
#define MPU_TYPE 0x90
62+
#define MPU_CTRL 0x94
63+
#define MPU_CTRL_ENABLE 1
64+
#define MPU_CTRL_PRIVDEFENA (1 << 2)
65+
66+
#define MPU_RNR 0x98
67+
#define MPU_RBAR 0x9c
68+
#define MPU_RASR 0xa0
69+
6070
/* Cache opeartions */
6171
#define V7M_SCB_ICIALLU 0x250 /* I-cache invalidate all to PoU */
6272
#define V7M_SCB_ICIMVAU 0x258 /* I-cache invalidate by MVA to PoU */

arch/arm/kernel/head-nommu.S

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,33 @@ ENDPROC(__after_proc_init)
176176
#ifdef CONFIG_ARM_MPU
177177

178178

179+
#ifndef CONFIG_CPU_V7M
179180
/* Set which MPU region should be programmed */
180-
.macro set_region_nr tmp, rgnr
181+
.macro set_region_nr tmp, rgnr, unused
181182
mov \tmp, \rgnr @ Use static region numbers
182183
mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR
183184
.endm
184185

185186
/* Setup a single MPU region, either D or I side (D-side for unified) */
186-
.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE
187+
.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE, unused
187188
mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR
188189
mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR
189190
mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR
190191
.endm
192+
#else
193+
.macro set_region_nr tmp, rgnr, base
194+
mov \tmp, \rgnr
195+
str \tmp, [\base, #MPU_RNR]
196+
.endm
197+
198+
.macro setup_region bar, acr, sr, unused, base
199+
lsl \acr, \acr, #16
200+
orr \acr, \acr, \sr
201+
str \bar, [\base, #MPU_RBAR]
202+
str \acr, [\base, #MPU_RASR]
203+
.endm
191204

205+
#endif
192206
/*
193207
* Setup the MPU and initial MPU Regions. We create the following regions:
194208
* Region 0: Use this for probing the MPU details, so leave disabled.
@@ -202,48 +216,58 @@ ENDPROC(__after_proc_init)
202216
ENTRY(__setup_mpu)
203217

204218
/* Probe for v7 PMSA compliance */
205-
mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0
219+
M_CLASS(movw r12, #:lower16:BASEADDR_V7M_SCB)
220+
M_CLASS(movt r12, #:upper16:BASEADDR_V7M_SCB)
221+
222+
AR_CLASS(mrc p15, 0, r0, c0, c1, 4) @ Read ID_MMFR0
223+
M_CLASS(ldr r0, [r12, 0x50])
206224
and r0, r0, #(MMFR0_PMSA) @ PMSA field
207225
teq r0, #(MMFR0_PMSAv7) @ PMSA v7
208226
bxne lr
209227

210228
/* Determine whether the D/I-side memory map is unified. We set the
211229
* flags here and continue to use them for the rest of this function */
212-
mrc p15, 0, r0, c0, c0, 4 @ MPUIR
230+
AR_CLASS(mrc p15, 0, r0, c0, c0, 4) @ MPUIR
231+
M_CLASS(ldr r0, [r12, #MPU_TYPE])
213232
ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
214233
bxeq lr
215234
tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
216235

217236
/* Setup second region first to free up r6 */
218-
set_region_nr r0, #MPU_RAM_REGION
237+
set_region_nr r0, #MPU_RAM_REGION, r12
219238
isb
220239
/* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
221240
ldr r0, =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET
222241
ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
223242

224-
setup_region r0, r5, r6, MPU_DATA_SIDE @ PHYS_OFFSET, shared, enabled
225-
beq 1f @ Memory-map not unified
226-
setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled
243+
setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ PHYS_OFFSET, shared, enabled
244+
beq 1f @ Memory-map not unified
245+
setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ PHYS_OFFSET, shared, enabled
227246
1: isb
228247

229248
/* First/background region */
230-
set_region_nr r0, #MPU_BG_REGION
249+
set_region_nr r0, #MPU_BG_REGION, r12
231250
isb
232251
/* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
233252
mov r0, #0 @ BG region starts at 0x0
234253
ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA)
235254
mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled
236255

237-
setup_region r0, r5, r6, MPU_DATA_SIDE @ 0x0, BG region, enabled
238-
beq 2f @ Memory-map not unified
239-
setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled
256+
setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ 0x0, BG region, enabled
257+
beq 2f @ Memory-map not unified
258+
setup_region r0, r5, r6, MPU_INSTR_SIDE r12 @ 0x0, BG region, enabled
240259
2: isb
241260

242261
/* Enable the MPU */
243-
mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
244-
bic r0, r0, #CR_BR @ Disable the 'default mem-map'
245-
orr r0, r0, #CR_M @ Set SCTRL.M (MPU on)
246-
mcr p15, 0, r0, c1, c0, 0 @ Enable MPU
262+
AR_CLASS(mrc p15, 0, r0, c1, c0, 0) @ Read SCTLR
263+
AR_CLASS(bic r0, r0, #CR_BR) @ Disable the 'default mem-map'
264+
AR_CLASS(orr r0, r0, #CR_M) @ Set SCTRL.M (MPU on)
265+
AR_CLASS(mcr p15, 0, r0, c1, c0, 0) @ Enable MPU
266+
267+
M_CLASS(ldr r0, [r12, #MPU_CTRL])
268+
M_CLASS(bic r0, #MPU_CTRL_PRIVDEFENA)
269+
M_CLASS(orr r0, #MPU_CTRL_ENABLE)
270+
M_CLASS(str r0, [r12, #MPU_CTRL])
247271
isb
248272

249273
ret lr

arch/arm/mm/pmsa-v7.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
static unsigned int __initdata mpu_min_region_order;
1616
static unsigned int __initdata mpu_max_regions;
1717

18+
#ifndef CONFIG_CPU_V7M
19+
1820
#define DRBAR __ACCESS_CP15(c6, 0, c1, 0)
1921
#define IRBAR __ACCESS_CP15(c6, 0, c1, 1)
2022
#define DRSR __ACCESS_CP15(c6, 0, c1, 2)
@@ -78,6 +80,51 @@ static inline u32 irbar_read(void)
7880
return read_sysreg(IRBAR);
7981
}
8082

83+
#else
84+
85+
static inline void rgnr_write(u32 v)
86+
{
87+
writel_relaxed(v, BASEADDR_V7M_SCB + MPU_RNR);
88+
}
89+
90+
/* Data-side / unified region attributes */
91+
92+
/* Region access control register */
93+
static inline void dracr_write(u32 v)
94+
{
95+
u32 rsr = readl_relaxed(BASEADDR_V7M_SCB + MPU_RASR) & GENMASK(15, 0);
96+
97+
writel_relaxed((v << 16) | rsr, BASEADDR_V7M_SCB + MPU_RASR);
98+
}
99+
100+
/* Region size register */
101+
static inline void drsr_write(u32 v)
102+
{
103+
u32 racr = readl_relaxed(BASEADDR_V7M_SCB + MPU_RASR) & GENMASK(31, 16);
104+
105+
writel_relaxed(v | racr, BASEADDR_V7M_SCB + MPU_RASR);
106+
}
107+
108+
/* Region base address register */
109+
static inline void drbar_write(u32 v)
110+
{
111+
writel_relaxed(v, BASEADDR_V7M_SCB + MPU_RBAR);
112+
}
113+
114+
static inline u32 drbar_read(void)
115+
{
116+
return readl_relaxed(BASEADDR_V7M_SCB + MPU_RBAR);
117+
}
118+
119+
/* ARMv7-M only supports a unified MPU, so I-side operations are nop */
120+
121+
static inline void iracr_write(u32 v) {}
122+
static inline void irsr_write(u32 v) {}
123+
static inline void irbar_write(u32 v) {}
124+
static inline unsigned long irbar_read(void) {return 0;}
125+
126+
#endif
127+
81128
static int __init mpu_present(void)
82129
{
83130
return ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7);
@@ -166,7 +213,7 @@ static int __init __mpu_max_regions(void)
166213
*/
167214
u32 dregions, iregions, mpuir;
168215

169-
mpuir = read_cpuid(CPUID_MPUIR);
216+
mpuir = read_cpuid_mputype();
170217

171218
dregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION;
172219

@@ -181,7 +228,7 @@ static int __init __mpu_max_regions(void)
181228
static int __init mpu_iside_independent(void)
182229
{
183230
/* MPUIR.nU specifies whether there is *not* a unified memory map */
184-
return read_cpuid(CPUID_MPUIR) & MPUIR_nU;
231+
return read_cpuid_mputype() & MPUIR_nU;
185232
}
186233

187234
static int __init __mpu_min_region_order(void)
@@ -284,9 +331,11 @@ void __init mpu_setup(void)
284331
MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL);
285332

286333
/* Vectors */
334+
#ifndef CONFIG_CPU_V7M
287335
err |= mpu_setup_region(region++, vectors_base,
288336
ilog2(2 * PAGE_SIZE),
289337
MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL);
338+
#endif
290339
if (err) {
291340
panic("MPU region initialization failure! %d", err);
292341
} else {

0 commit comments

Comments
 (0)