source: rtems/c/src/lib/libcpu/arm/shared/include/arm-cp15.h @ 0a9533fc

4.11
Last change on this file since 0a9533fc was 0a9533fc, checked in by Hesham AL-Matary <heshamelmatary@…>, on Sep 28, 2013 at 8:08:24 AM

Add a new necessary definition needed for raspberrypi MMU support

The new ARM_CP15_CTRL_XP is necessary to share ARMv6 and ARMv7
page-table formats and definitions.
It enables the extended page tables (introduced in ARMv6)
to be configured for the hardware page translation mechanism. This way
we can share ARMv6 and ARMv7 page tables entry formats.

Other Fault Status Register Definitions can be useful for debugging or
excpetion handlers.

  • Property mode set to 100644
File size: 21.7 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPUARMCP15
5 *
6 * @brief ARM co-processor 15 (CP15) API.
7 */
8
9/*
10 * Copyright (c) 2013 Hesham AL-Matary
11 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
12 *
13 *  embedded brains GmbH
14 *  Dornierstr. 4
15 *  82178 Puchheim
16 *  Germany
17 *  <info@embedded-brains.de>
18 *
19 * The license and distribution terms for this file may be
20 * found in the file LICENSE in this distribution or at
21 * http://www.rtems.com/license/LICENSE.
22 */
23
24#ifndef LIBCPU_SHARED_ARM_CP15_H
25#define LIBCPU_SHARED_ARM_CP15_H
26
27#include <rtems.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif /* __cplusplus */
32
33#define ARM_CP15_CACHE_PREPARE_MVA(mva) \
34  ((const void *) (((uint32_t) (mva)) & ~0x1fU))
35
36#define ARM_CP15_TLB_PREPARE_MVA(mva) \
37  ((const void *) (((uint32_t) (mva)) & ~0x3fU))
38
39/**
40 * @defgroup ScoreCPUARMCP15 ARM Co-Processor 15 Support
41 *
42 * @ingroup ScoreCPUARM
43 *
44 * @brief ARM co-processor 15 (CP15) support.
45 *
46 * @{
47 */
48
49/**
50 * @name MMU Defines
51 *
52 * @{
53 */
54
55#define ARM_MMU_SECT_BASE_SHIFT 20
56#define ARM_MMU_SECT_BASE_MASK (0xfffU << ARM_MMU_SECT_BASE_SHIFT)
57#define ARM_MMU_SECT_NS (1U << 19)
58#define ARM_MMU_SECT_NG (1U << 17)
59#define ARM_MMU_SECT_S (1U << 16)
60#define ARM_MMU_SECT_AP_2 (1U << 15)
61#define ARM_MMU_SECT_TEX_2 (1U << 14)
62#define ARM_MMU_SECT_TEX_1 (1U << 13)
63#define ARM_MMU_SECT_TEX_0 (1U << 12)
64#define ARM_MMU_SECT_TEX_SHIFT 12
65#define ARM_MMU_SECT_TEX_MASK (0x3U << ARM_MMU_SECT_TEX_SHIFT)
66#define ARM_MMU_SECT_AP_1 (1U << 11)
67#define ARM_MMU_SECT_AP_0 (1U << 10)
68#define ARM_MMU_SECT_AP_SHIFT 10
69#define ARM_MMU_SECT_AP_MASK (0x23U << ARM_MMU_SECT_AP_SHIFT)
70#define ARM_MMU_SECT_DOMAIN_SHIFT 5
71#define ARM_MMU_SECT_DOMAIN_MASK (0xfU << ARM_MMU_SECT_DOMAIN_SHIFT)
72#define ARM_MMU_SECT_XN (1U << 4)
73#define ARM_MMU_SECT_C (1U << 3)
74#define ARM_MMU_SECT_B (1U << 2)
75#define ARM_MMU_SECT_PXN (1U << 0)
76#define ARM_MMU_SECT_DEFAULT 0x2U
77#define ARM_MMU_SECT_GET_INDEX(mva) \
78  (((uint32_t) (mva)) >> ARM_MMU_SECT_BASE_SHIFT)
79#define ARM_MMU_SECT_MVA_ALIGN_UP(mva) \
80  ((1U << ARM_MMU_SECT_BASE_SHIFT) \
81    + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SECT_BASE_SHIFT) - 1U)))
82
83#define ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE 4U
84#define ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT 4096U
85
86#define ARM_MMU_DEFAULT_CLIENT_DOMAIN 15U
87
88#define ARMV7_MMU_READ_ONLY \
89  ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
90    | ARM_MMU_SECT_AP_0 \
91    | ARM_MMU_SECT_AP_2 \
92    | ARM_MMU_SECT_DEFAULT)
93
94#define ARMV7_MMU_READ_ONLY_CACHED \
95  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
96
97#define ARMV7_MMU_READ_WRITE \
98  ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
99    | ARM_MMU_SECT_AP_0 \
100    | ARM_MMU_SECT_DEFAULT)
101
102#define ARMV7_MMU_READ_WRITE_CACHED \
103  (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
104
105#define ARMV7_MMU_DATA_READ_ONLY \
106  ARMV7_MMU_READ_ONLY
107
108#define ARMV7_MMU_DATA_READ_ONLY_CACHED \
109  ARMV7_MMU_READ_ONLY_CACHED
110
111#define ARMV7_MMU_DATA_READ_WRITE \
112  ARMV7_MMU_READ_WRITE
113
114#define ARMV7_MMU_DATA_READ_WRITE_CACHED \
115  ARMV7_MMU_READ_WRITE_CACHED
116
117#define ARMV7_MMU_DATA_READ_WRITE_SHAREABLE \
118  (ARMV7_MMU_READ_WRITE_CACHED | ARM_MMU_SECT_S)
119
120#define ARMV7_MMU_CODE \
121  ARMV7_MMU_READ_ONLY
122
123#define ARMV7_MMU_CODE_CACHED \
124  ARMV7_MMU_READ_ONLY_CACHED
125
126#define ARMV7_MMU_DEVICE \
127  (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_B)
128
129/** @} */
130
131/**
132 * @name Control Register Defines
133 *
134 * @{
135 */
136
137#define ARM_CP15_CTRL_TE (1U << 30)
138#define ARM_CP15_CTRL_AFE (1U << 29)
139#define ARM_CP15_CTRL_TRE (1U << 28)
140#define ARM_CP15_CTRL_NMFI (1U << 27)
141#define ARM_CP15_CTRL_EE (1U << 25)
142#define ARM_CP15_CTRL_VE (1U << 24)
143#define ARM_CP15_CTRL_XP (1U << 23)
144#define ARM_CP15_CTRL_U (1U << 22)
145#define ARM_CP15_CTRL_FI (1U << 21)
146#define ARM_CP15_CTRL_UWXN (1U << 20)
147#define ARM_CP15_CTRL_WXN (1U << 19)
148#define ARM_CP15_CTRL_HA (1U << 17)
149#define ARM_CP15_CTRL_L4 (1U << 15)
150#define ARM_CP15_CTRL_RR (1U << 14)
151#define ARM_CP15_CTRL_V (1U << 13)
152#define ARM_CP15_CTRL_I (1U << 12)
153#define ARM_CP15_CTRL_Z (1U << 11)
154#define ARM_CP15_CTRL_SW (1U << 10)
155#define ARM_CP15_CTRL_R (1U << 9)
156#define ARM_CP15_CTRL_S (1U << 8)
157#define ARM_CP15_CTRL_B (1U << 7)
158#define ARM_CP15_CTRL_CP15BEN (1U << 5)
159#define ARM_CP15_CTRL_C (1U << 2)
160#define ARM_CP15_CTRL_A (1U << 1)
161#define ARM_CP15_CTRL_M (1U << 0)
162
163/** @} */
164
165/**
166 * @name Domain Access Control Defines
167 *
168 * @{
169 */
170
171#define ARM_CP15_DAC_NO_ACCESS 0x0U
172#define ARM_CP15_DAC_CLIENT 0x1U
173#define ARM_CP15_DAC_MANAGER 0x3U
174#define ARM_CP15_DAC_DOMAIN(index, val) ((val) << (2 * index))
175
176/** @} */
177
178/**
179 * @name Fault Status Register Defines
180 *
181 * @{
182 */
183
184#define ARM_CP15_FAULT_STATUS_MASK 0x040F
185
186#define ARM_CP15_FSR_ALIGNMENT_FAULT   0x00000001
187#define ARM_CP15_FSR_BACKGROUND_FAULT  0x0000
188#define ARM_CP15_FSR_ACCESS_PERMISSION_FAULT 0x000D
189#define ARM_CP15_FSR_PRECISE_EXTERNAL_ABORT_FAULT 0x0008
190#define ARM_CP15_FSR_IMPRECISE_EXTERNAL_ABORT_FAULT 0x0406
191#define ARM_CP15_FSR_PRECISE_PARITY_ERROR_EXCEPTION 0x0006
192#define ARM_CP15_FSR_IMPRECISE_PARITY_ERROR_EXCEPTION 0x0408
193#define ARM_CP15_FSR_DEBUG_EVENT 0x0002
194
195/** @} */
196
197static inline uint32_t arm_cp15_get_id_code(void)
198{
199  ARM_SWITCH_REGISTERS;
200  uint32_t val;
201
202  __asm__ volatile (
203    ARM_SWITCH_TO_ARM
204    "mrc p15, 0, %[val], c0, c0, 0\n"
205    ARM_SWITCH_BACK
206    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
207  );
208
209  return val;
210}
211
212static inline uint32_t arm_cp15_get_tcm_status(void)
213{
214  ARM_SWITCH_REGISTERS;
215  uint32_t val;
216
217  __asm__ volatile (
218    ARM_SWITCH_TO_ARM
219    "mrc p15, 0, %[val], c0, c0, 2\n"
220    ARM_SWITCH_BACK
221    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
222  );
223
224  return val;
225}
226
227static inline uint32_t arm_cp15_get_control(void)
228{
229  ARM_SWITCH_REGISTERS;
230  uint32_t val;
231
232  __asm__ volatile (
233    ARM_SWITCH_TO_ARM
234    "mrc p15, 0, %[val], c1, c0, 0\n"
235    ARM_SWITCH_BACK
236    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
237  );
238
239  return val;
240}
241
242static inline void arm_cp15_set_control(uint32_t val)
243{
244  ARM_SWITCH_REGISTERS;
245
246  __asm__ volatile (
247    ARM_SWITCH_TO_ARM
248    "mcr p15, 0, %[val], c1, c0, 0\n"
249    "nop\n"
250    "nop\n"
251    ARM_SWITCH_BACK
252    : ARM_SWITCH_OUTPUT
253    : [val] "r" (val)
254    : "memory"
255  );
256}
257
258/**
259 * @name MMU Functions
260 *
261 * @{
262 */
263
264/**
265 * @brief Disable the MMU.
266 *
267 * This function will clean and invalidate eight cache lines before and after
268 * the current stack pointer.
269 *
270 * @param[in] cls The data cache line size.
271 *
272 * @return The current control register value.
273 */
274static inline uint32_t arm_cp15_mmu_disable(uint32_t cls)
275{
276  ARM_SWITCH_REGISTERS;
277  uint32_t ctrl;
278  uint32_t tmp_0;
279  uint32_t tmp_1;
280
281  __asm__ volatile (
282    ARM_SWITCH_TO_ARM
283    "mrc p15, 0, %[ctrl], c1, c0, 0\n"
284    "bic %[tmp_0], %[ctrl], #1\n"
285    "mcr p15, 0, %[tmp_0], c1, c0, 0\n"
286    "nop\n"
287    "nop\n"
288    "mov %[tmp_1], sp\n"
289    "rsb %[tmp_0], %[cls], #0\n"
290    "and %[tmp_0], %[tmp_0], %[tmp_1]\n"
291    "sub %[tmp_0], %[tmp_0], %[cls], asl #3\n"
292    "add %[tmp_1], %[tmp_0], %[cls], asl #4\n"
293    "1:\n"
294    "mcr p15, 0, %[tmp_0], c7, c14, 1\n"
295    "add %[tmp_0], %[tmp_0], %[cls]\n"
296    "cmp %[tmp_1], %[tmp_0]\n"
297    "bne 1b\n"
298    ARM_SWITCH_BACK
299    : [ctrl] "=&r" (ctrl),
300      [tmp_0] "=&r" (tmp_0),
301      [tmp_1] "=&r" (tmp_1)
302      ARM_SWITCH_ADDITIONAL_OUTPUT
303    : [cls] "r" (cls)
304    : "memory", "cc"
305  );
306
307  return ctrl;
308}
309
310static inline uint32_t *arm_cp15_get_translation_table_base(void)
311{
312  ARM_SWITCH_REGISTERS;
313  uint32_t *base;
314
315  __asm__ volatile (
316    ARM_SWITCH_TO_ARM
317    "mrc p15, 0, %[base], c2, c0, 0\n"
318    ARM_SWITCH_BACK
319    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
320  );
321
322  return base;
323}
324
325static inline void arm_cp15_set_translation_table_base(uint32_t *base)
326{
327  ARM_SWITCH_REGISTERS;
328
329  __asm__ volatile (
330    ARM_SWITCH_TO_ARM
331    "mcr p15, 0, %[base], c2, c0, 0\n"
332    ARM_SWITCH_BACK
333    : ARM_SWITCH_OUTPUT
334    : [base] "r" (base)
335  );
336}
337
338static inline uint32_t arm_cp15_get_domain_access_control(void)
339{
340  ARM_SWITCH_REGISTERS;
341  uint32_t val;
342
343  __asm__ volatile (
344    ARM_SWITCH_TO_ARM
345    "mrc p15, 0, %[val], c3, c0, 0\n"
346    ARM_SWITCH_BACK
347    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
348  );
349
350  return val;
351}
352
353static inline void arm_cp15_set_domain_access_control(uint32_t val)
354{
355  ARM_SWITCH_REGISTERS;
356
357  __asm__ volatile (
358    ARM_SWITCH_TO_ARM
359    "mcr p15, 0, %[val], c3, c0, 0\n"
360    ARM_SWITCH_BACK
361    : ARM_SWITCH_OUTPUT
362    : [val] "r" (val)
363  );
364}
365
366static inline uint32_t arm_cp15_get_data_fault_status(void)
367{
368  ARM_SWITCH_REGISTERS;
369  uint32_t val;
370
371  __asm__ volatile (
372    ARM_SWITCH_TO_ARM
373    "mrc p15, 0, %[val], c5, c0, 0\n"
374    ARM_SWITCH_BACK
375    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
376  );
377
378  return val;
379}
380
381static inline void arm_cp15_set_data_fault_status(uint32_t val)
382{
383  ARM_SWITCH_REGISTERS;
384
385  __asm__ volatile (
386    ARM_SWITCH_TO_ARM
387    "mcr p15, 0, %[val], c5, c0, 0\n"
388    ARM_SWITCH_BACK
389    : ARM_SWITCH_OUTPUT
390    : [val] "r" (val)
391  );
392}
393
394static inline uint32_t arm_cp15_get_instruction_fault_status(void)
395{
396  ARM_SWITCH_REGISTERS;
397  uint32_t val;
398
399  __asm__ volatile (
400    ARM_SWITCH_TO_ARM
401    "mrc p15, 0, %[val], c5, c0, 1\n"
402    ARM_SWITCH_BACK
403    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
404  );
405
406  return val;
407}
408
409static inline void arm_cp15_set_instruction_fault_status(uint32_t val)
410{
411  ARM_SWITCH_REGISTERS;
412
413  __asm__ volatile (
414    ARM_SWITCH_TO_ARM
415    "mcr p15, 0, %[val], c5, c0, 1\n"
416    ARM_SWITCH_BACK
417    : ARM_SWITCH_OUTPUT
418    : [val] "r" (val)
419  );
420}
421
422static inline void *arm_cp15_get_fault_address(void)
423{
424  ARM_SWITCH_REGISTERS;
425  void *mva;
426
427  __asm__ volatile (
428    ARM_SWITCH_TO_ARM
429    "mrc p15, 0, %[mva], c6, c0, 0\n"
430    ARM_SWITCH_BACK
431    : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
432  );
433
434  return mva;
435}
436
437static inline void arm_cp15_set_fault_address(const void *mva)
438{
439  ARM_SWITCH_REGISTERS;
440
441  __asm__ volatile (
442    ARM_SWITCH_TO_ARM
443    "mcr p15, 0, %[mva], c6, c0, 0\n"
444    ARM_SWITCH_BACK
445    : ARM_SWITCH_OUTPUT
446    : [mva] "r" (mva)
447  );
448}
449
450static inline void arm_cp15_tlb_invalidate(void)
451{
452  ARM_SWITCH_REGISTERS;
453  uint32_t sbz = 0;
454
455  __asm__ volatile (
456    ARM_SWITCH_TO_ARM
457    "mcr p15, 0, %[sbz], c8, c7, 0\n"
458    ARM_SWITCH_BACK
459    : ARM_SWITCH_OUTPUT
460    : [sbz] "r" (sbz)
461  );
462}
463
464static inline void arm_cp15_tlb_invalidate_entry(const void *mva)
465{
466  ARM_SWITCH_REGISTERS;
467
468  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
469
470  __asm__ volatile (
471    ARM_SWITCH_TO_ARM
472    "mcr p15, 0, %[mva], c8, c7, 1\n"
473    ARM_SWITCH_BACK
474    : ARM_SWITCH_OUTPUT
475    : [mva] "r" (mva)
476  );
477}
478
479static inline void arm_cp15_tlb_instruction_invalidate(void)
480{
481  ARM_SWITCH_REGISTERS;
482  uint32_t sbz = 0;
483
484  __asm__ volatile (
485    ARM_SWITCH_TO_ARM
486    "mcr p15, 0, %[sbz], c8, c5, 0\n"
487    ARM_SWITCH_BACK
488    : ARM_SWITCH_OUTPUT
489    : [sbz] "r" (sbz)
490  );
491}
492
493static inline void arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
494{
495  ARM_SWITCH_REGISTERS;
496
497  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
498
499  __asm__ volatile (
500    ARM_SWITCH_TO_ARM
501    "mcr p15, 0, %[mva], c8, c5, 1\n"
502    ARM_SWITCH_BACK
503    : ARM_SWITCH_OUTPUT
504    : [mva] "r" (mva)
505  );
506}
507
508static inline void arm_cp15_tlb_data_invalidate(void)
509{
510  ARM_SWITCH_REGISTERS;
511  uint32_t sbz = 0;
512
513  __asm__ volatile (
514    ARM_SWITCH_TO_ARM
515    "mcr p15, 0, %[sbz], c8, c6, 0\n"
516    ARM_SWITCH_BACK
517    : ARM_SWITCH_OUTPUT
518    : [sbz] "r" (sbz)
519  );
520}
521
522static inline void arm_cp15_tlb_data_invalidate_entry(const void *mva)
523{
524  ARM_SWITCH_REGISTERS;
525
526  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
527
528  __asm__ volatile (
529    ARM_SWITCH_TO_ARM
530    "mcr p15, 0, %[mva], c8, c6, 1\n"
531    ARM_SWITCH_BACK
532    : ARM_SWITCH_OUTPUT
533    : [mva] "r" (mva)
534  );
535}
536
537static inline void arm_cp15_tlb_lockdown_entry(const void *mva)
538{
539  uint32_t arm_switch_reg;
540
541  __asm__ volatile (
542    ARM_SWITCH_TO_ARM
543    "add %[arm_switch_reg], pc, #16\n"
544    "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
545    "mcr p15, 0, %[mva], c8, c7, 1\n"
546    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
547    "orr %[arm_switch_reg], #0x1\n"
548    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
549    "ldr %[mva], [%[mva]]\n"
550    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
551    "bic %[arm_switch_reg], #0x1\n"
552    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
553    ARM_SWITCH_BACK
554    : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
555    : "[mva]" (mva)
556  );
557}
558
559/** @} */
560
561/**
562 * @name Cache Functions
563 *
564 * @{
565 */
566
567static inline uint32_t arm_cp15_get_cache_type(void)
568{
569  ARM_SWITCH_REGISTERS;
570  uint32_t val;
571
572  __asm__ volatile (
573    ARM_SWITCH_TO_ARM
574    "mrc p15, 0, %[val], c0, c0, 1\n"
575    ARM_SWITCH_BACK
576    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
577  );
578
579  return val;
580}
581
582static inline uint32_t arm_cp15_get_min_cache_line_size(void)
583{
584  uint32_t mcls = 0;
585  uint32_t ct = arm_cp15_get_cache_type();
586  uint32_t format = (ct >> 29) & 0x7U;
587
588  if (format == 0x4) {
589    mcls = (1U << (ct & 0xf)) * 4;
590  } else if (format == 0x0) {
591    uint32_t mask = (1U << 12) - 1;
592    uint32_t dcls = (ct >> 12) & mask;
593    uint32_t icls = ct & mask;
594
595    mcls = dcls <= icls ? dcls : icls;
596  }
597
598  return mcls;
599}
600
601/* CCSIDR, Cache Size ID Register */
602
603static inline uint32_t arm_cp15_get_cache_size_id(void)
604{
605  ARM_SWITCH_REGISTERS;
606  uint32_t val;
607
608  __asm__ volatile (
609    ARM_SWITCH_TO_ARM
610    "mrc p15, 1, %[val], c0, c0, 0\n"
611     ARM_SWITCH_BACK
612    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
613  );
614
615  return val;
616}
617
618/* CLIDR, Cache Level ID Register */
619
620static inline uint32_t arm_cp15_get_cache_level_id(void)
621{
622  ARM_SWITCH_REGISTERS;
623  uint32_t val;
624
625  __asm__ volatile (
626    ARM_SWITCH_TO_ARM
627    "mrc p15, 1, %[val], c0, c0, 1\n"
628     ARM_SWITCH_BACK
629    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
630  );
631
632  return val;
633}
634
635/* CSSELR, Cache Size Selection Register */
636
637static inline uint32_t arm_cp15_get_cache_size_selection(void)
638{
639  ARM_SWITCH_REGISTERS;
640  uint32_t val;
641
642  __asm__ volatile (
643    ARM_SWITCH_TO_ARM
644    "mrc p15, 2, %[val], c0, c0, 0\n"
645     ARM_SWITCH_BACK
646    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
647  );
648
649  return val;
650}
651
652static inline void arm_cp15_set_cache_size_selection(uint32_t val)
653{
654  ARM_SWITCH_REGISTERS;
655
656  __asm__ volatile (
657    ARM_SWITCH_TO_ARM
658    "mcr p15, 2, %[val], c0, c0, 0\n"
659     ARM_SWITCH_BACK
660    : ARM_SWITCH_OUTPUT
661    : [val] "r" (val)
662    : "memory"
663  );
664}
665
666static inline void arm_cp15_cache_invalidate(void)
667{
668  ARM_SWITCH_REGISTERS;
669  uint32_t sbz = 0;
670
671  __asm__ volatile (
672    ARM_SWITCH_TO_ARM
673    "mcr p15, 0, %[sbz], c7, c7, 0\n"
674    ARM_SWITCH_BACK
675    : ARM_SWITCH_OUTPUT
676    : [sbz] "r" (sbz)
677    : "memory"
678  );
679}
680
681static inline void arm_cp15_instruction_cache_invalidate(void)
682{
683  ARM_SWITCH_REGISTERS;
684  uint32_t sbz = 0;
685
686  __asm__ volatile (
687    ARM_SWITCH_TO_ARM
688    "mcr p15, 0, %[sbz], c7, c5, 0\n"
689    ARM_SWITCH_BACK
690    : ARM_SWITCH_OUTPUT
691    : [sbz] "r" (sbz)
692    : "memory"
693  );
694}
695
696static inline void arm_cp15_instruction_cache_invalidate_line(const void *mva)
697{
698  ARM_SWITCH_REGISTERS;
699
700  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
701
702  __asm__ volatile (
703    ARM_SWITCH_TO_ARM
704    "mcr p15, 0, %[mva], c7, c5, 1\n"
705    ARM_SWITCH_BACK
706    : ARM_SWITCH_OUTPUT
707    : [mva] "r" (mva)
708    : "memory"
709  );
710}
711
712static inline void arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
713{
714  ARM_SWITCH_REGISTERS;
715
716  __asm__ volatile (
717    ARM_SWITCH_TO_ARM
718    "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
719    ARM_SWITCH_BACK
720    : ARM_SWITCH_OUTPUT
721    : [set_and_way] "r" (set_and_way)
722    : "memory"
723  );
724}
725
726static inline void arm_cp15_instruction_cache_prefetch_line(const void *mva)
727{
728  ARM_SWITCH_REGISTERS;
729
730  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
731
732  __asm__ volatile (
733    ARM_SWITCH_TO_ARM
734    "mcr p15, 0, %[mva], c7, c13, 1\n"
735    ARM_SWITCH_BACK
736    : ARM_SWITCH_OUTPUT
737    : [mva] "r" (mva)
738  );
739}
740
741static inline void arm_cp15_data_cache_invalidate(void)
742{
743  ARM_SWITCH_REGISTERS;
744  uint32_t sbz = 0;
745
746  __asm__ volatile (
747    ARM_SWITCH_TO_ARM
748    "mcr p15, 0, %[sbz], c7, c6, 0\n"
749    ARM_SWITCH_BACK
750    : ARM_SWITCH_OUTPUT
751    : [sbz] "r" (sbz)
752    : "memory"
753  );
754}
755
756static inline void arm_cp15_data_cache_invalidate_line(const void *mva)
757{
758  ARM_SWITCH_REGISTERS;
759
760  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
761
762  __asm__ volatile (
763    ARM_SWITCH_TO_ARM
764    "mcr p15, 0, %[mva], c7, c6, 1\n"
765    ARM_SWITCH_BACK
766    : ARM_SWITCH_OUTPUT
767    : [mva] "r" (mva)
768    : "memory"
769  );
770}
771
772static inline void arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
773{
774  ARM_SWITCH_REGISTERS;
775
776  __asm__ volatile (
777    ARM_SWITCH_TO_ARM
778    "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
779    ARM_SWITCH_BACK
780    : ARM_SWITCH_OUTPUT
781    : [set_and_way] "r" (set_and_way)
782    : "memory"
783  );
784}
785
786static inline void arm_cp15_data_cache_clean_line(const void *mva)
787{
788  ARM_SWITCH_REGISTERS;
789
790  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
791
792  __asm__ volatile (
793    ARM_SWITCH_TO_ARM
794    "mcr p15, 0, %[mva], c7, c10, 1\n"
795    ARM_SWITCH_BACK
796    : ARM_SWITCH_OUTPUT
797    : [mva] "r" (mva)
798    : "memory"
799  );
800}
801
802static inline void arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
803{
804  ARM_SWITCH_REGISTERS;
805
806  __asm__ volatile (
807    ARM_SWITCH_TO_ARM
808    "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
809    ARM_SWITCH_BACK
810    : ARM_SWITCH_OUTPUT
811    : [set_and_way] "r" (set_and_way)
812    : "memory"
813  );
814}
815
816static inline void arm_cp15_data_cache_test_and_clean(void)
817{
818  ARM_SWITCH_REGISTERS;
819
820  __asm__ volatile (
821    ARM_SWITCH_TO_ARM
822    "1:\n"
823    "mrc p15, 0, r15, c7, c10, 3\n"
824    "bne 1b\n"
825    ARM_SWITCH_BACK
826    : ARM_SWITCH_OUTPUT
827    :
828    : "memory"
829  );
830}
831
832/*      In DDI0301H_arm1176jzfs_r0p7_trm
833 *      'MCR p15, 0, <Rd>, c7, c14, 0' means
834 *      Clean and Invalidate Entire Data Cache
835 */
836static inline void arm_cp15_data_cache_clean_and_invalidate(void)
837{
838  ARM_SWITCH_REGISTERS;
839
840  uint32_t sbz = 0;
841
842  __asm__ volatile (
843    ARM_SWITCH_TO_ARM
844    "mcr p15, 0, %[sbz], c7, c14, 0\n"
845    ARM_SWITCH_BACK
846    : ARM_SWITCH_OUTPUT
847    : [sbz] "r" (sbz)
848    : "memory"
849  );
850
851}
852
853static inline void arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
854{
855  ARM_SWITCH_REGISTERS;
856
857  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
858
859  __asm__ volatile (
860    ARM_SWITCH_TO_ARM
861    "mcr p15, 0, %[mva], c7, c14, 1\n"
862    ARM_SWITCH_BACK
863    : ARM_SWITCH_OUTPUT
864    : [mva] "r" (mva)
865    : "memory"
866  );
867}
868
869static inline void arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
870{
871  ARM_SWITCH_REGISTERS;
872
873  __asm__ volatile (
874    ARM_SWITCH_TO_ARM
875    "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
876    ARM_SWITCH_BACK
877    : ARM_SWITCH_OUTPUT
878    : [set_and_way] "r" (set_and_way)
879    : "memory"
880  );
881}
882
883static inline void arm_cp15_data_cache_test_and_clean_and_invalidate(void)
884{
885  ARM_SWITCH_REGISTERS;
886
887  __asm__ volatile (
888    ARM_SWITCH_TO_ARM
889    "1:\n"
890    "mrc p15, 0, r15, c7, c14, 3\n"
891    "bne 1b\n"
892    ARM_SWITCH_BACK
893    : ARM_SWITCH_OUTPUT
894    :
895    : "memory"
896  );
897}
898
899/** @} */
900
901static inline void arm_cp15_drain_write_buffer(void)
902{
903  ARM_SWITCH_REGISTERS;
904  uint32_t sbz = 0;
905
906  __asm__ volatile (
907    ARM_SWITCH_TO_ARM
908    "mcr p15, 0, %[sbz], c7, c10, 4\n"
909    ARM_SWITCH_BACK
910    : ARM_SWITCH_OUTPUT
911    : [sbz] "r" (sbz)
912    : "memory"
913  );
914}
915
916static inline void arm_cp15_wait_for_interrupt(void)
917{
918  ARM_SWITCH_REGISTERS;
919  uint32_t sbz = 0;
920
921  __asm__ volatile (
922    ARM_SWITCH_TO_ARM
923    "mcr p15, 0, %[sbz], c7, c0, 4\n"
924    ARM_SWITCH_BACK
925    : ARM_SWITCH_OUTPUT
926    : [sbz] "r" (sbz)
927    : "memory"
928  );
929}
930
931static inline uint32_t arm_cp15_get_multiprocessor_affinity(void)
932{
933  ARM_SWITCH_REGISTERS;
934  uint32_t mpidr;
935
936  __asm__ volatile (
937    ARM_SWITCH_TO_ARM
938          "mrc p15, 0, %[mpidr], c0, c0, 5\n"
939    ARM_SWITCH_BACK
940    : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
941  );
942
943  return mpidr & 0xff;
944}
945
946static inline uint32_t arm_cortex_a9_get_multiprocessor_cpu_id(void)
947{
948  return arm_cp15_get_multiprocessor_affinity() & 0xff;
949}
950
951#define ARM_CORTEX_A9_ACTL_FW (1U << 0)
952#define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
953#define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
954#define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
955#define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
956#define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
957#define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
958#define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
959
960static inline uint32_t arm_cp15_get_auxiliary_control(void)
961{
962  ARM_SWITCH_REGISTERS;
963  uint32_t val;
964
965  __asm__ volatile (
966    ARM_SWITCH_TO_ARM
967    "mrc p15, 0, %[val], c1, c0, 1\n"
968    ARM_SWITCH_BACK
969    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
970  );
971
972  return val;
973}
974
975static inline void arm_cp15_set_auxiliary_control(uint32_t val)
976{
977  ARM_SWITCH_REGISTERS;
978
979  __asm__ volatile (
980    ARM_SWITCH_TO_ARM
981    "mcr p15, 0, %[val], c1, c0, 1\n"
982    ARM_SWITCH_BACK
983    : ARM_SWITCH_OUTPUT
984    : [val] "r" (val)
985  );
986}
987
988/* ID_PFR1, Processor Feature Register 1 */
989
990static inline uint32_t arm_cp15_get_processor_feature_1(void)
991{
992  ARM_SWITCH_REGISTERS;
993  uint32_t val;
994
995  __asm__ volatile (
996    ARM_SWITCH_TO_ARM
997    "mrc p15, 0, %[val], c0, c1, 1\n"
998    ARM_SWITCH_BACK
999    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1000  );
1001
1002  return val;
1003}
1004
1005/* VBAR, Vector Base Address Register, Security Extensions */
1006
1007static inline void *arm_cp15_get_vector_base_address(void)
1008{
1009  ARM_SWITCH_REGISTERS;
1010  void *base;
1011
1012  __asm__ volatile (
1013    ARM_SWITCH_TO_ARM
1014    "mrc p15, 0, %[base], c12, c0, 0\n"
1015    ARM_SWITCH_BACK
1016    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1017  );
1018
1019  return base;
1020}
1021
1022static inline void arm_cp15_set_vector_base_address(void *base)
1023{
1024  ARM_SWITCH_REGISTERS;
1025
1026  __asm__ volatile (
1027    ARM_SWITCH_TO_ARM
1028    "mcr p15, 0, %[base], c12, c0, 0\n"
1029    ARM_SWITCH_BACK
1030    : ARM_SWITCH_OUTPUT
1031    : [base] "r" (base)
1032  );
1033}
1034
1035/**
1036 * @brief Sets the @a section_flags for the address range [@a begin, @a end).
1037 *
1038 * @return Previous section flags of the first modified entry.
1039 */
1040uint32_t arm_cp15_set_translation_table_entries(
1041  const void *begin,
1042  const void *end,
1043  uint32_t section_flags
1044);
1045
1046void arm_cp15_set_exception_handler(
1047  Arm_symbolic_exception_name exception,
1048  void (*handler)(void)
1049);
1050
1051/** @} */
1052
1053#ifdef __cplusplus
1054}
1055#endif /* __cplusplus */
1056
1057#endif /* LIBCPU_SHARED_ARM_CP15_H */
Note: See TracBrowser for help on using the repository browser.