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

5
Last change on this file since 0616555 was 0616555, checked in by Pavel Pisa <pisa@…>, on 07/03/16 at 23:30:05

bsps/arm: basic on core cache support changed to use l1 functions.

The basic data and instruction rage functions should be compatible
for all ARMv4,5,6,7 functions. On the other hand, some functions
are not portable, for example arm_cp15_data_cache_test_and_clean()
and arm_cp15_data_cache_invalidate() for all versions and there
has to be specialized version for newer cores.
arm_cache_l1_properties_for_level uses CCSIDR which is not present
on older chips.

Actual version is only experimental, needs more changes
and problem has been found on RPi1 with dlopen so there seems
to be real problem.

  • Property mode set to 100644
File size: 29.8 KB
RevLine 
[39c8fdb]1/**
2 * @file
3 *
[5e657e2]4 * @ingroup ScoreCPUARMCP15
[39c8fdb]5 *
6 * @brief ARM co-processor 15 (CP15) API.
7 */
8
9/*
[0a9533fc]10 * Copyright (c) 2013 Hesham AL-Matary
[d2d02961]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>
[39c8fdb]18 *
19 * The license and distribution terms for this file may be
20 * found in the file LICENSE in this distribution or at
[c499856]21 * http://www.rtems.org/license/LICENSE.
[39c8fdb]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
[66a2409d]33/*
34 * Allow users of this header file to optionally place the inline functions
35 * into a non-standard section.
36 */
37#ifndef ARM_CP15_TEXT_SECTION
38  #define ARM_CP15_TEXT_SECTION
39#endif
40
[5e657e2]41#define ARM_CP15_CACHE_PREPARE_MVA(mva) \
42  ((const void *) (((uint32_t) (mva)) & ~0x1fU))
43
44#define ARM_CP15_TLB_PREPARE_MVA(mva) \
45  ((const void *) (((uint32_t) (mva)) & ~0x3fU))
46
47/**
48 * @defgroup ScoreCPUARMCP15 ARM Co-Processor 15 Support
49 *
50 * @ingroup ScoreCPUARM
51 *
52 * @brief ARM co-processor 15 (CP15) support.
53 *
54 * @{
55 */
56
57/**
58 * @name MMU Defines
59 *
[eba0626]60 * See section B3.8.2, "Short-descriptor format memory region attributes,
61 * without TEX remap" in the "ARM Architecture Reference Manual ARMv7-A and
62 * ARMv7-R edition".
63 *
[5e657e2]64 * @{
65 */
66
[39c8fdb]67#define ARM_MMU_SECT_BASE_SHIFT 20
[5e657e2]68#define ARM_MMU_SECT_BASE_MASK (0xfffU << ARM_MMU_SECT_BASE_SHIFT)
[fd51f7e]69#define ARM_MMU_SECT_NS (1U << 19)
70#define ARM_MMU_SECT_NG (1U << 17)
71#define ARM_MMU_SECT_S (1U << 16)
72#define ARM_MMU_SECT_AP_2 (1U << 15)
73#define ARM_MMU_SECT_TEX_2 (1U << 14)
74#define ARM_MMU_SECT_TEX_1 (1U << 13)
75#define ARM_MMU_SECT_TEX_0 (1U << 12)
76#define ARM_MMU_SECT_TEX_SHIFT 12
77#define ARM_MMU_SECT_TEX_MASK (0x3U << ARM_MMU_SECT_TEX_SHIFT)
[39c8fdb]78#define ARM_MMU_SECT_AP_1 (1U << 11)
79#define ARM_MMU_SECT_AP_0 (1U << 10)
80#define ARM_MMU_SECT_AP_SHIFT 10
[fd51f7e]81#define ARM_MMU_SECT_AP_MASK (0x23U << ARM_MMU_SECT_AP_SHIFT)
82#define ARM_MMU_SECT_DOMAIN_SHIFT 5
83#define ARM_MMU_SECT_DOMAIN_MASK (0xfU << ARM_MMU_SECT_DOMAIN_SHIFT)
84#define ARM_MMU_SECT_XN (1U << 4)
[39c8fdb]85#define ARM_MMU_SECT_C (1U << 3)
86#define ARM_MMU_SECT_B (1U << 2)
[fd51f7e]87#define ARM_MMU_SECT_PXN (1U << 0)
88#define ARM_MMU_SECT_DEFAULT 0x2U
[39c8fdb]89#define ARM_MMU_SECT_GET_INDEX(mva) \
90  (((uint32_t) (mva)) >> ARM_MMU_SECT_BASE_SHIFT)
91#define ARM_MMU_SECT_MVA_ALIGN_UP(mva) \
92  ((1U << ARM_MMU_SECT_BASE_SHIFT) \
93    + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SECT_BASE_SHIFT) - 1U)))
94
95#define ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE 4U
96#define ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT 4096U
97
[1dcf5fe]98#define ARM_MMU_DEFAULT_CLIENT_DOMAIN 15U
99
100#define ARMV7_MMU_READ_ONLY \
101  ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
102    | ARM_MMU_SECT_AP_0 \
103    | ARM_MMU_SECT_AP_2 \
104    | ARM_MMU_SECT_DEFAULT)
105
106#define ARMV7_MMU_READ_ONLY_CACHED \
[5b391f85]107  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
[1dcf5fe]108
109#define ARMV7_MMU_READ_WRITE \
110  ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
111    | ARM_MMU_SECT_AP_0 \
112    | ARM_MMU_SECT_DEFAULT)
113
[f074a4d]114#ifdef RTEMS_SMP
115  #define ARMV7_MMU_READ_WRITE_CACHED \
116    (ARMV7_MMU_READ_WRITE \
117      | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B | ARM_MMU_SECT_S)
118#else
119  #define ARMV7_MMU_READ_WRITE_CACHED \
120    (ARMV7_MMU_READ_WRITE \
121      | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
122#endif
[1dcf5fe]123
124#define ARMV7_MMU_DATA_READ_ONLY \
[eba0626]125  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
[1dcf5fe]126
127#define ARMV7_MMU_DATA_READ_ONLY_CACHED \
128  ARMV7_MMU_READ_ONLY_CACHED
129
130#define ARMV7_MMU_DATA_READ_WRITE \
[eba0626]131  (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_TEX_0)
[1dcf5fe]132
133#define ARMV7_MMU_DATA_READ_WRITE_CACHED \
134  ARMV7_MMU_READ_WRITE_CACHED
135
136#define ARMV7_MMU_CODE \
[eba0626]137  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
[1dcf5fe]138
139#define ARMV7_MMU_CODE_CACHED \
140  ARMV7_MMU_READ_ONLY_CACHED
141
142#define ARMV7_MMU_DEVICE \
143  (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_B)
144
[5e657e2]145/** @} */
[39c8fdb]146
[5e657e2]147/**
148 * @name Control Register Defines
149 *
150 * @{
151 */
[39c8fdb]152
[fd51f7e]153#define ARM_CP15_CTRL_TE (1U << 30)
154#define ARM_CP15_CTRL_AFE (1U << 29)
155#define ARM_CP15_CTRL_TRE (1U << 28)
156#define ARM_CP15_CTRL_NMFI (1U << 27)
157#define ARM_CP15_CTRL_EE (1U << 25)
158#define ARM_CP15_CTRL_VE (1U << 24)
[0a9533fc]159#define ARM_CP15_CTRL_XP (1U << 23)
[fd51f7e]160#define ARM_CP15_CTRL_U (1U << 22)
161#define ARM_CP15_CTRL_FI (1U << 21)
162#define ARM_CP15_CTRL_UWXN (1U << 20)
163#define ARM_CP15_CTRL_WXN (1U << 19)
164#define ARM_CP15_CTRL_HA (1U << 17)
[5e657e2]165#define ARM_CP15_CTRL_L4 (1U << 15)
166#define ARM_CP15_CTRL_RR (1U << 14)
167#define ARM_CP15_CTRL_V (1U << 13)
168#define ARM_CP15_CTRL_I (1U << 12)
[fd51f7e]169#define ARM_CP15_CTRL_Z (1U << 11)
170#define ARM_CP15_CTRL_SW (1U << 10)
[5e657e2]171#define ARM_CP15_CTRL_R (1U << 9)
172#define ARM_CP15_CTRL_S (1U << 8)
173#define ARM_CP15_CTRL_B (1U << 7)
[fd51f7e]174#define ARM_CP15_CTRL_CP15BEN (1U << 5)
[5e657e2]175#define ARM_CP15_CTRL_C (1U << 2)
176#define ARM_CP15_CTRL_A (1U << 1)
177#define ARM_CP15_CTRL_M (1U << 0)
[39c8fdb]178
[5e657e2]179/** @} */
180
181/**
182 * @name Domain Access Control Defines
183 *
184 * @{
185 */
186
187#define ARM_CP15_DAC_NO_ACCESS 0x0U
188#define ARM_CP15_DAC_CLIENT 0x1U
189#define ARM_CP15_DAC_MANAGER 0x3U
190#define ARM_CP15_DAC_DOMAIN(index, val) ((val) << (2 * index))
191
192/** @} */
193
[0a9533fc]194/**
195 * @name Fault Status Register Defines
196 *
197 * @{
198 */
199
200#define ARM_CP15_FAULT_STATUS_MASK 0x040F
201
202#define ARM_CP15_FSR_ALIGNMENT_FAULT   0x00000001
203#define ARM_CP15_FSR_BACKGROUND_FAULT  0x0000
204#define ARM_CP15_FSR_ACCESS_PERMISSION_FAULT 0x000D
205#define ARM_CP15_FSR_PRECISE_EXTERNAL_ABORT_FAULT 0x0008
206#define ARM_CP15_FSR_IMPRECISE_EXTERNAL_ABORT_FAULT 0x0406
207#define ARM_CP15_FSR_PRECISE_PARITY_ERROR_EXCEPTION 0x0006
208#define ARM_CP15_FSR_IMPRECISE_PARITY_ERROR_EXCEPTION 0x0408
209#define ARM_CP15_FSR_DEBUG_EVENT 0x0002
210
211/** @} */
212
[0616555]213/**
214 * @name CCSIDR, Cache Size ID Register Defines
215 *
216 * @{
217 */
218
219#define ARM_CP15_CACHE_CSS_ID_DATA 0
220#define ARM_CP15_CACHE_CSS_ID_INSTRUCTION 1
221#define ARM_CP15_CACHE_CSS_LEVEL(level) ((level) << 1)
222
223/** @} */
224
[66a2409d]225ARM_CP15_TEXT_SECTION static inline uint32_t
226arm_cp15_get_id_code(void)
[39c8fdb]227{
228  ARM_SWITCH_REGISTERS;
229  uint32_t val;
230
[139ec149]231  __asm__ volatile (
[39c8fdb]232    ARM_SWITCH_TO_ARM
[5e657e2]233    "mrc p15, 0, %[val], c0, c0, 0\n"
[39c8fdb]234    ARM_SWITCH_BACK
235    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
236  );
237
238  return val;
239}
240
[66a2409d]241ARM_CP15_TEXT_SECTION static inline uint32_t
242arm_cp15_get_tcm_status(void)
[39c8fdb]243{
244  ARM_SWITCH_REGISTERS;
245  uint32_t val;
246
[139ec149]247  __asm__ volatile (
[39c8fdb]248    ARM_SWITCH_TO_ARM
249    "mrc p15, 0, %[val], c0, c0, 2\n"
250    ARM_SWITCH_BACK
251    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
252  );
253
254  return val;
255}
256
[66a2409d]257ARM_CP15_TEXT_SECTION static inline uint32_t
258arm_cp15_get_control(void)
[39c8fdb]259{
260  ARM_SWITCH_REGISTERS;
261  uint32_t val;
262
[139ec149]263  __asm__ volatile (
[39c8fdb]264    ARM_SWITCH_TO_ARM
265    "mrc p15, 0, %[val], c1, c0, 0\n"
266    ARM_SWITCH_BACK
267    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
268  );
269
270  return val;
271}
272
[66a2409d]273ARM_CP15_TEXT_SECTION static inline void
274arm_cp15_set_control(uint32_t val)
[39c8fdb]275{
276  ARM_SWITCH_REGISTERS;
277
[139ec149]278  __asm__ volatile (
[39c8fdb]279    ARM_SWITCH_TO_ARM
280    "mcr p15, 0, %[val], c1, c0, 0\n"
281    "nop\n"
282    "nop\n"
283    ARM_SWITCH_BACK
284    : ARM_SWITCH_OUTPUT
285    : [val] "r" (val)
286    : "memory"
287  );
288}
289
[5e657e2]290/**
291 * @name MMU Functions
292 *
293 * @{
294 */
295
[544615d]296/**
297 * @brief Disable the MMU.
298 *
299 * This function will clean and invalidate eight cache lines before and after
300 * the current stack pointer.
301 *
302 * @param[in] cls The data cache line size.
303 *
304 * @return The current control register value.
305 */
[66a2409d]306ARM_CP15_TEXT_SECTION static inline uint32_t
307arm_cp15_mmu_disable(uint32_t cls)
[544615d]308{
309  ARM_SWITCH_REGISTERS;
310  uint32_t ctrl;
311  uint32_t tmp_0;
312  uint32_t tmp_1;
313
314  __asm__ volatile (
315    ARM_SWITCH_TO_ARM
316    "mrc p15, 0, %[ctrl], c1, c0, 0\n"
317    "bic %[tmp_0], %[ctrl], #1\n"
318    "mcr p15, 0, %[tmp_0], c1, c0, 0\n"
319    "nop\n"
320    "nop\n"
321    "mov %[tmp_1], sp\n"
322    "rsb %[tmp_0], %[cls], #0\n"
323    "and %[tmp_0], %[tmp_0], %[tmp_1]\n"
324    "sub %[tmp_0], %[tmp_0], %[cls], asl #3\n"
325    "add %[tmp_1], %[tmp_0], %[cls], asl #4\n"
326    "1:\n"
327    "mcr p15, 0, %[tmp_0], c7, c14, 1\n"
328    "add %[tmp_0], %[tmp_0], %[cls]\n"
329    "cmp %[tmp_1], %[tmp_0]\n"
330    "bne 1b\n"
331    ARM_SWITCH_BACK
332    : [ctrl] "=&r" (ctrl),
333      [tmp_0] "=&r" (tmp_0),
334      [tmp_1] "=&r" (tmp_1)
335      ARM_SWITCH_ADDITIONAL_OUTPUT
336    : [cls] "r" (cls)
337    : "memory", "cc"
338  );
339
340  return ctrl;
341}
342
[66a2409d]343ARM_CP15_TEXT_SECTION static inline uint32_t
344*arm_cp15_get_translation_table_base(void)
[39c8fdb]345{
346  ARM_SWITCH_REGISTERS;
347  uint32_t *base;
348
[139ec149]349  __asm__ volatile (
[39c8fdb]350    ARM_SWITCH_TO_ARM
351    "mrc p15, 0, %[base], c2, c0, 0\n"
352    ARM_SWITCH_BACK
353    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
354  );
355
356  return base;
357}
358
[66a2409d]359ARM_CP15_TEXT_SECTION static inline void
360arm_cp15_set_translation_table_base(uint32_t *base)
[39c8fdb]361{
362  ARM_SWITCH_REGISTERS;
363
[139ec149]364  __asm__ volatile (
[39c8fdb]365    ARM_SWITCH_TO_ARM
366    "mcr p15, 0, %[base], c2, c0, 0\n"
367    ARM_SWITCH_BACK
368    : ARM_SWITCH_OUTPUT
369    : [base] "r" (base)
370  );
371}
372
[6fbc692]373/* Translation Table Base Control Register - DDI0301H arm1176jzfs TRM 3.2.15 */
374ARM_CP15_TEXT_SECTION static inline uint32_t
375*arm_cp15_get_translation_table_base_control_register(void)
376{
377  ARM_SWITCH_REGISTERS;
378  uint32_t ttb_cr;
379
380  __asm__ volatile (
381    ARM_SWITCH_TO_ARM
382    "mrc p15, 0, %[ttb_cr], c2, c0, 2\n"
383    ARM_SWITCH_BACK
384    : [ttb_cr] "=&r" (ttb_cr) ARM_SWITCH_ADDITIONAL_OUTPUT
385  );
386
387  return ttb_cr;
388}
389
390ARM_CP15_TEXT_SECTION static inline void
391arm_cp15_set_translation_table_base_control_register(uint32_t ttb_cr)
392{
393  ARM_SWITCH_REGISTERS;
394
395  __asm__ volatile (
396    ARM_SWITCH_TO_ARM
397    "mcr p15, 0, %[ttb_cr], c2, c0, 2\n"
398    ARM_SWITCH_BACK
399    : ARM_SWITCH_OUTPUT
400    : [ttb_cr] "r" (ttb_cr)
401  );
402}
403
[66a2409d]404ARM_CP15_TEXT_SECTION static inline uint32_t
405arm_cp15_get_domain_access_control(void)
[39c8fdb]406{
407  ARM_SWITCH_REGISTERS;
408  uint32_t val;
409
[139ec149]410  __asm__ volatile (
[39c8fdb]411    ARM_SWITCH_TO_ARM
412    "mrc p15, 0, %[val], c3, c0, 0\n"
413    ARM_SWITCH_BACK
414    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
415  );
416
417  return val;
418}
419
[66a2409d]420ARM_CP15_TEXT_SECTION static inline void
421arm_cp15_set_domain_access_control(uint32_t val)
[39c8fdb]422{
423  ARM_SWITCH_REGISTERS;
424
[139ec149]425  __asm__ volatile (
[39c8fdb]426    ARM_SWITCH_TO_ARM
427    "mcr p15, 0, %[val], c3, c0, 0\n"
428    ARM_SWITCH_BACK
429    : ARM_SWITCH_OUTPUT
430    : [val] "r" (val)
431  );
432}
433
[66a2409d]434ARM_CP15_TEXT_SECTION static inline uint32_t
435arm_cp15_get_data_fault_status(void)
[39c8fdb]436{
437  ARM_SWITCH_REGISTERS;
438  uint32_t val;
439
[139ec149]440  __asm__ volatile (
[39c8fdb]441    ARM_SWITCH_TO_ARM
442    "mrc p15, 0, %[val], c5, c0, 0\n"
443    ARM_SWITCH_BACK
444    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
445  );
446
447  return val;
448}
449
[66a2409d]450ARM_CP15_TEXT_SECTION static inline void
451arm_cp15_set_data_fault_status(uint32_t val)
[39c8fdb]452{
453  ARM_SWITCH_REGISTERS;
454
[139ec149]455  __asm__ volatile (
[39c8fdb]456    ARM_SWITCH_TO_ARM
457    "mcr p15, 0, %[val], c5, c0, 0\n"
458    ARM_SWITCH_BACK
459    : ARM_SWITCH_OUTPUT
460    : [val] "r" (val)
461  );
462}
463
[66a2409d]464ARM_CP15_TEXT_SECTION static inline uint32_t
465arm_cp15_get_instruction_fault_status(void)
[39c8fdb]466{
467  ARM_SWITCH_REGISTERS;
468  uint32_t val;
469
[139ec149]470  __asm__ volatile (
[39c8fdb]471    ARM_SWITCH_TO_ARM
472    "mrc p15, 0, %[val], c5, c0, 1\n"
473    ARM_SWITCH_BACK
474    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
475  );
476
477  return val;
478}
479
[66a2409d]480ARM_CP15_TEXT_SECTION static inline void
481arm_cp15_set_instruction_fault_status(uint32_t val)
[39c8fdb]482{
483  ARM_SWITCH_REGISTERS;
484
[139ec149]485  __asm__ volatile (
[39c8fdb]486    ARM_SWITCH_TO_ARM
487    "mcr p15, 0, %[val], c5, c0, 1\n"
488    ARM_SWITCH_BACK
489    : ARM_SWITCH_OUTPUT
490    : [val] "r" (val)
491  );
492}
493
[66a2409d]494ARM_CP15_TEXT_SECTION static inline void
495*arm_cp15_get_fault_address(void)
[39c8fdb]496{
497  ARM_SWITCH_REGISTERS;
498  void *mva;
499
[139ec149]500  __asm__ volatile (
[39c8fdb]501    ARM_SWITCH_TO_ARM
502    "mrc p15, 0, %[mva], c6, c0, 0\n"
503    ARM_SWITCH_BACK
504    : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
505  );
506
507  return mva;
508}
509
[66a2409d]510ARM_CP15_TEXT_SECTION static inline void
511arm_cp15_set_fault_address(const void *mva)
[39c8fdb]512{
513  ARM_SWITCH_REGISTERS;
514
[139ec149]515  __asm__ volatile (
[39c8fdb]516    ARM_SWITCH_TO_ARM
517    "mcr p15, 0, %[mva], c6, c0, 0\n"
518    ARM_SWITCH_BACK
519    : ARM_SWITCH_OUTPUT
520    : [mva] "r" (mva)
521  );
522}
523
[66a2409d]524ARM_CP15_TEXT_SECTION static inline void
525arm_cp15_tlb_invalidate(void)
[39c8fdb]526{
527  ARM_SWITCH_REGISTERS;
528  uint32_t sbz = 0;
529
[139ec149]530  __asm__ volatile (
[39c8fdb]531    ARM_SWITCH_TO_ARM
[5e657e2]532    "mcr p15, 0, %[sbz], c8, c7, 0\n"
[39c8fdb]533    ARM_SWITCH_BACK
534    : ARM_SWITCH_OUTPUT
535    : [sbz] "r" (sbz)
536  );
[dc44de7]537
538  /*
539   * ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, Issue C,
540   * B3.10.1 General TLB maintenance requirements.
541   */
542  _ARM_Data_synchronization_barrier();
543  _ARM_Instruction_synchronization_barrier();
[39c8fdb]544}
545
[66a2409d]546ARM_CP15_TEXT_SECTION static inline void
547arm_cp15_tlb_invalidate_entry(const void *mva)
[5e657e2]548{
549  ARM_SWITCH_REGISTERS;
550
551  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
552
[139ec149]553  __asm__ volatile (
[5e657e2]554    ARM_SWITCH_TO_ARM
555    "mcr p15, 0, %[mva], c8, c7, 1\n"
556    ARM_SWITCH_BACK
557    : ARM_SWITCH_OUTPUT
558    : [mva] "r" (mva)
559  );
560}
561
[66a2409d]562ARM_CP15_TEXT_SECTION static inline void
563arm_cp15_tlb_instruction_invalidate(void)
[39c8fdb]564{
565  ARM_SWITCH_REGISTERS;
566  uint32_t sbz = 0;
567
[139ec149]568  __asm__ volatile (
[39c8fdb]569    ARM_SWITCH_TO_ARM
[5e657e2]570    "mcr p15, 0, %[sbz], c8, c5, 0\n"
[39c8fdb]571    ARM_SWITCH_BACK
572    : ARM_SWITCH_OUTPUT
573    : [sbz] "r" (sbz)
574  );
575}
576
[66a2409d]577ARM_CP15_TEXT_SECTION static inline void
578arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
[39c8fdb]579{
580  ARM_SWITCH_REGISTERS;
581
[5e657e2]582  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
[39c8fdb]583
[139ec149]584  __asm__ volatile (
[39c8fdb]585    ARM_SWITCH_TO_ARM
[5e657e2]586    "mcr p15, 0, %[mva], c8, c5, 1\n"
[39c8fdb]587    ARM_SWITCH_BACK
588    : ARM_SWITCH_OUTPUT
589    : [mva] "r" (mva)
590  );
591}
592
[66a2409d]593ARM_CP15_TEXT_SECTION static inline void
594arm_cp15_tlb_data_invalidate(void)
[39c8fdb]595{
596  ARM_SWITCH_REGISTERS;
[5e657e2]597  uint32_t sbz = 0;
[39c8fdb]598
[139ec149]599  __asm__ volatile (
[39c8fdb]600    ARM_SWITCH_TO_ARM
[5e657e2]601    "mcr p15, 0, %[sbz], c8, c6, 0\n"
[39c8fdb]602    ARM_SWITCH_BACK
603    : ARM_SWITCH_OUTPUT
[5e657e2]604    : [sbz] "r" (sbz)
[39c8fdb]605  );
606}
607
[66a2409d]608ARM_CP15_TEXT_SECTION static inline void
609arm_cp15_tlb_data_invalidate_entry(const void *mva)
[39c8fdb]610{
611  ARM_SWITCH_REGISTERS;
612
[5e657e2]613  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
[39c8fdb]614
[139ec149]615  __asm__ volatile (
[39c8fdb]616    ARM_SWITCH_TO_ARM
[5e657e2]617    "mcr p15, 0, %[mva], c8, c6, 1\n"
[39c8fdb]618    ARM_SWITCH_BACK
619    : ARM_SWITCH_OUTPUT
620    : [mva] "r" (mva)
621  );
622}
623
[66a2409d]624ARM_CP15_TEXT_SECTION static inline void
625arm_cp15_tlb_lockdown_entry(const void *mva)
[39c8fdb]626{
[5e657e2]627  uint32_t arm_switch_reg;
[39c8fdb]628
[139ec149]629  __asm__ volatile (
[39c8fdb]630    ARM_SWITCH_TO_ARM
[5e657e2]631    "add %[arm_switch_reg], pc, #16\n"
632    "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
633    "mcr p15, 0, %[mva], c8, c7, 1\n"
634    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
635    "orr %[arm_switch_reg], #0x1\n"
636    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
637    "ldr %[mva], [%[mva]]\n"
638    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
639    "bic %[arm_switch_reg], #0x1\n"
640    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
[39c8fdb]641    ARM_SWITCH_BACK
[5e657e2]642    : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
643    : "[mva]" (mva)
[39c8fdb]644  );
645}
646
[5e657e2]647/** @} */
648
649/**
650 * @name Cache Functions
651 *
652 * @{
653 */
654
[0656a00a]655/* Read cache type register CTR */
[66a2409d]656ARM_CP15_TEXT_SECTION static inline uint32_t
657arm_cp15_get_cache_type(void)
[39c8fdb]658{
659  ARM_SWITCH_REGISTERS;
[5e657e2]660  uint32_t val;
[39c8fdb]661
[139ec149]662  __asm__ volatile (
[5e657e2]663    ARM_SWITCH_TO_ARM
664    "mrc p15, 0, %[val], c0, c0, 1\n"
665    ARM_SWITCH_BACK
666    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
667  );
668
669  return val;
670}
671
[0656a00a]672/* Read size of smallest cache line of all instruction/data caches controlled by the processor */
[66a2409d]673ARM_CP15_TEXT_SECTION static inline uint32_t
674arm_cp15_get_min_cache_line_size(void)
[d2d02961]675{
676  uint32_t mcls = 0;
677  uint32_t ct = arm_cp15_get_cache_type();
678  uint32_t format = (ct >> 29) & 0x7U;
679
680  if (format == 0x4) {
[0656a00a]681    /* ARMv7 format */
[d2d02961]682    mcls = (1U << (ct & 0xf)) * 4;
683  } else if (format == 0x0) {
[0656a00a]684    /* ARMv6 format */
[d2d02961]685    uint32_t mask = (1U << 12) - 1;
686    uint32_t dcls = (ct >> 12) & mask;
687    uint32_t icls = ct & mask;
688
689    mcls = dcls <= icls ? dcls : icls;
690  }
691
692  return mcls;
693}
694
[0656a00a]695/* Read size of smallest data cache lines */
[66a2409d]696ARM_CP15_TEXT_SECTION static inline uint32_t
697arm_cp15_get_data_cache_line_size(void)
[0656a00a]698{
699  uint32_t mcls = 0;
700  uint32_t ct = arm_cp15_get_cache_type();
701  uint32_t format = (ct >> 29) & 0x7U;
702
703  if (format == 0x4) {
704    /* ARMv7 format */
705    mcls = (1U << ((ct & 0xf0000) >> 16)) * 4;
706  } else if (format == 0x0) {
707    /* ARMv6 format */
708    uint32_t mask = (1U << 12) - 1;
709    mcls = (ct >> 12) & mask;
710  }
711
712  return mcls;
713}
714
715/* Read size of smallest instruction cache lines */
[66a2409d]716ARM_CP15_TEXT_SECTION static inline uint32_t
717arm_cp15_get_instruction_cache_line_size(void)
[0656a00a]718{
719  uint32_t mcls = 0;
720  uint32_t ct = arm_cp15_get_cache_type();
721  uint32_t format = (ct >> 29) & 0x7U;
722
723  if (format == 0x4) {
724    /* ARMv7 format */
725    mcls = (1U << (ct & 0x0000f)) * 4;
726  } else if (format == 0x0) {
727    /* ARMv6 format */
728    uint32_t mask = (1U << 12) - 1;
729    mcls = ct & mask;;
730  }
731
732  return mcls;
733}
734
[c9b66f5]735/* CCSIDR, Cache Size ID Register */
736
[66a2409d]737ARM_CP15_TEXT_SECTION static inline uint32_t
738arm_cp15_get_cache_size_id(void)
[c9b66f5]739{
740  ARM_SWITCH_REGISTERS;
741  uint32_t val;
742
743  __asm__ volatile (
744    ARM_SWITCH_TO_ARM
[d157a4fd]745    "mrc p15, 1, %[val], c0, c0, 0\n"
[c9b66f5]746     ARM_SWITCH_BACK
747    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
748  );
749
750  return val;
751}
752
[66a2409d]753ARM_CP15_TEXT_SECTION static inline uint32_t
754arm_ccsidr_get_line_power(uint32_t ccsidr)
[d0a8f513]755{
756  return (ccsidr & 0x7) + 4;
757}
758
[66a2409d]759ARM_CP15_TEXT_SECTION static inline uint32_t
760arm_ccsidr_get_associativity(uint32_t ccsidr)
[d0a8f513]761{
762  return ((ccsidr >> 3) & 0x3ff) + 1;
763}
764
[66a2409d]765ARM_CP15_TEXT_SECTION static inline uint32_t
766arm_ccsidr_get_num_sets(uint32_t ccsidr)
[d0a8f513]767{
768  return ((ccsidr >> 13) & 0x7fff) + 1;
769}
770
[c9b66f5]771/* CLIDR, Cache Level ID Register */
772
[66a2409d]773ARM_CP15_TEXT_SECTION static inline uint32_t
774arm_cp15_get_cache_level_id(void)
[c9b66f5]775{
776  ARM_SWITCH_REGISTERS;
777  uint32_t val;
778
779  __asm__ volatile (
780    ARM_SWITCH_TO_ARM
[d157a4fd]781    "mrc p15, 1, %[val], c0, c0, 1\n"
[c9b66f5]782     ARM_SWITCH_BACK
783    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
784  );
785
786  return val;
787}
788
[66a2409d]789ARM_CP15_TEXT_SECTION static inline uint32_t
790arm_clidr_get_level_of_coherency(uint32_t clidr)
[d0a8f513]791{
792  return (clidr >> 24) & 0x7;
793}
794
[66a2409d]795ARM_CP15_TEXT_SECTION static inline uint32_t
796arm_clidr_get_cache_type(uint32_t clidr, uint32_t level)
[0656a00a]797{
[d0a8f513]798  return (clidr >> (3 * level)) & 0x7;
[0656a00a]799}
800
[c9b66f5]801/* CSSELR, Cache Size Selection Register */
802
[66a2409d]803ARM_CP15_TEXT_SECTION static inline uint32_t
804arm_cp15_get_cache_size_selection(void)
[c9b66f5]805{
806  ARM_SWITCH_REGISTERS;
807  uint32_t val;
808
809  __asm__ volatile (
810    ARM_SWITCH_TO_ARM
[d157a4fd]811    "mrc p15, 2, %[val], c0, c0, 0\n"
[c9b66f5]812     ARM_SWITCH_BACK
813    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
814  );
815
816  return val;
817}
818
[66a2409d]819ARM_CP15_TEXT_SECTION static inline void
820arm_cp15_set_cache_size_selection(uint32_t val)
[c9b66f5]821{
822  ARM_SWITCH_REGISTERS;
823
824  __asm__ volatile (
825    ARM_SWITCH_TO_ARM
826    "mcr p15, 2, %[val], c0, c0, 0\n"
827     ARM_SWITCH_BACK
828    : ARM_SWITCH_OUTPUT
829    : [val] "r" (val)
830    : "memory"
831  );
832}
833
[0616555]834ARM_CP15_TEXT_SECTION static inline uint32_t
835arm_cp15_get_cache_size_id_for_level(uint32_t level_and_inst_dat)
836{
837  rtems_interrupt_level irq_level;
838  uint32_t ccsidr;
839
840  rtems_interrupt_local_disable(irq_level);
841  arm_cp15_set_cache_size_selection(level_and_inst_dat);
842  _ARM_Instruction_synchronization_barrier();
843  ccsidr = arm_cp15_get_cache_size_id();
844  rtems_interrupt_local_enable(irq_level);
845
846  return ccsidr;
847}
848
[66a2409d]849ARM_CP15_TEXT_SECTION static inline void
850arm_cp15_cache_invalidate(void)
[5e657e2]851{
852  ARM_SWITCH_REGISTERS;
853  uint32_t sbz = 0;
[39c8fdb]854
[139ec149]855  __asm__ volatile (
[39c8fdb]856    ARM_SWITCH_TO_ARM
[5e657e2]857    "mcr p15, 0, %[sbz], c7, c7, 0\n"
[39c8fdb]858    ARM_SWITCH_BACK
859    : ARM_SWITCH_OUTPUT
[5e657e2]860    : [sbz] "r" (sbz)
[39c8fdb]861    : "memory"
862  );
863}
864
[0656a00a]865/* ICIALLUIS, Instruction Cache Invalidate All to PoU, Inner Shareable */
866
[66a2409d]867ARM_CP15_TEXT_SECTION static inline void
868arm_cp15_instruction_cache_inner_shareable_invalidate_all(void)
[0656a00a]869{
870  ARM_SWITCH_REGISTERS;
871  uint32_t sbz = 0;
872
873  __asm__ volatile (
874    ARM_SWITCH_TO_ARM
875    "mcr p15, 0, %[sbz], c7, c1, 0\n"
876    ARM_SWITCH_BACK
877    : ARM_SWITCH_OUTPUT
878    : [sbz] "r" (sbz)
879    : "memory"
880  );
881}
882
883/* BPIALLIS, Branch Predictor Invalidate All, Inner Shareable */
884
[66a2409d]885ARM_CP15_TEXT_SECTION static inline void
886arm_cp15_branch_predictor_inner_shareable_invalidate_all(void)
[0656a00a]887{
888  ARM_SWITCH_REGISTERS;
889  uint32_t sbz = 0;
890
891  __asm__ volatile (
892    ARM_SWITCH_TO_ARM
893    "mcr p15, 0, %[sbz], c7, c1, 6\n"
894    ARM_SWITCH_BACK
895    : ARM_SWITCH_OUTPUT
896    : [sbz] "r" (sbz)
897    : "memory"
898  );
899}
900
901/* BPIALL, Branch Predictor Invalidate All */
902
[66a2409d]903ARM_CP15_TEXT_SECTION static inline void
904arm_cp15_branch_predictor_invalidate_all(void)
[0656a00a]905{
906  ARM_SWITCH_REGISTERS;
907  uint32_t sbz = 0;
908
909  __asm__ volatile (
910    ARM_SWITCH_TO_ARM
911    "mcr p15, 0, %[sbz], c7, c5, 6\n"
912    ARM_SWITCH_BACK
913    : ARM_SWITCH_OUTPUT
914    : [sbz] "r" (sbz)
915    : "memory"
916  );
917}
918
[6fbc692]919/* Flush Prefetch Buffer - DDI0301H arm1176jzfs TRM 3.2.22 */
920ARM_CP15_TEXT_SECTION static inline void
921arm_cp15_flush_prefetch_buffer(void)
922{
923  ARM_SWITCH_REGISTERS;
924  uint32_t sbz = 0;
925
926  __asm__ volatile (
927    ARM_SWITCH_TO_ARM
928    "mcr p15, 0, %[sbz], c7, c5, 4\n"
929    ARM_SWITCH_BACK
930    : ARM_SWITCH_OUTPUT
931    : [sbz] "r" (sbz)
932    : "memory"
933  );
934}
935
[66a2409d]936ARM_CP15_TEXT_SECTION static inline void
937arm_cp15_instruction_cache_invalidate(void)
[39c8fdb]938{
939  ARM_SWITCH_REGISTERS;
[5e657e2]940  uint32_t sbz = 0;
[39c8fdb]941
[139ec149]942  __asm__ volatile (
[39c8fdb]943    ARM_SWITCH_TO_ARM
[5e657e2]944    "mcr p15, 0, %[sbz], c7, c5, 0\n"
[39c8fdb]945    ARM_SWITCH_BACK
946    : ARM_SWITCH_OUTPUT
[5e657e2]947    : [sbz] "r" (sbz)
[39c8fdb]948    : "memory"
949  );
950}
951
[66a2409d]952ARM_CP15_TEXT_SECTION static inline void
953arm_cp15_instruction_cache_invalidate_line(const void *mva)
[39c8fdb]954{
955  ARM_SWITCH_REGISTERS;
956
957  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
958
[139ec149]959  __asm__ volatile (
[39c8fdb]960    ARM_SWITCH_TO_ARM
[5e657e2]961    "mcr p15, 0, %[mva], c7, c5, 1\n"
[39c8fdb]962    ARM_SWITCH_BACK
963    : ARM_SWITCH_OUTPUT
964    : [mva] "r" (mva)
965    : "memory"
966  );
967}
968
[66a2409d]969ARM_CP15_TEXT_SECTION static inline void
970arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
[39c8fdb]971{
972  ARM_SWITCH_REGISTERS;
973
[139ec149]974  __asm__ volatile (
[39c8fdb]975    ARM_SWITCH_TO_ARM
[5e657e2]976    "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
[39c8fdb]977    ARM_SWITCH_BACK
978    : ARM_SWITCH_OUTPUT
979    : [set_and_way] "r" (set_and_way)
980    : "memory"
981  );
982}
983
[66a2409d]984ARM_CP15_TEXT_SECTION static inline void
985arm_cp15_instruction_cache_prefetch_line(const void *mva)
[39c8fdb]986{
987  ARM_SWITCH_REGISTERS;
988
[5e657e2]989  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
990
[139ec149]991  __asm__ volatile (
[39c8fdb]992    ARM_SWITCH_TO_ARM
[5e657e2]993    "mcr p15, 0, %[mva], c7, c13, 1\n"
[39c8fdb]994    ARM_SWITCH_BACK
995    : ARM_SWITCH_OUTPUT
[5e657e2]996    : [mva] "r" (mva)
[39c8fdb]997  );
998}
999
[66a2409d]1000ARM_CP15_TEXT_SECTION static inline void
1001arm_cp15_data_cache_invalidate(void)
[39c8fdb]1002{
1003  ARM_SWITCH_REGISTERS;
[5e657e2]1004  uint32_t sbz = 0;
[39c8fdb]1005
[139ec149]1006  __asm__ volatile (
[39c8fdb]1007    ARM_SWITCH_TO_ARM
[5e657e2]1008    "mcr p15, 0, %[sbz], c7, c6, 0\n"
[39c8fdb]1009    ARM_SWITCH_BACK
1010    : ARM_SWITCH_OUTPUT
[5e657e2]1011    : [sbz] "r" (sbz)
[39c8fdb]1012    : "memory"
1013  );
1014}
1015
[66a2409d]1016ARM_CP15_TEXT_SECTION static inline void
1017arm_cp15_data_cache_invalidate_line(const void *mva)
[39c8fdb]1018{
1019  ARM_SWITCH_REGISTERS;
1020
[5e657e2]1021  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1022
[139ec149]1023  __asm__ volatile (
[39c8fdb]1024    ARM_SWITCH_TO_ARM
[5e657e2]1025    "mcr p15, 0, %[mva], c7, c6, 1\n"
[39c8fdb]1026    ARM_SWITCH_BACK
1027    : ARM_SWITCH_OUTPUT
[5e657e2]1028    : [mva] "r" (mva)
[39c8fdb]1029    : "memory"
1030  );
1031}
1032
[66a2409d]1033ARM_CP15_TEXT_SECTION static inline void
1034arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
[39c8fdb]1035{
1036  ARM_SWITCH_REGISTERS;
1037
[139ec149]1038  __asm__ volatile (
[39c8fdb]1039    ARM_SWITCH_TO_ARM
[5e657e2]1040    "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
[39c8fdb]1041    ARM_SWITCH_BACK
1042    : ARM_SWITCH_OUTPUT
[5e657e2]1043    : [set_and_way] "r" (set_and_way)
[39c8fdb]1044    : "memory"
1045  );
1046}
1047
[66a2409d]1048ARM_CP15_TEXT_SECTION static inline void
1049arm_cp15_data_cache_invalidate_all_levels(void)
[d0a8f513]1050{
1051  uint32_t clidr = arm_cp15_get_cache_level_id();
1052  uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1053  uint32_t level = 0;
1054
1055  for (level = 0; level < loc; ++level) {
1056    uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1057
1058    /* Check if this level has a data cache */
1059    if ((ctype & 0x2) != 0) {
1060      uint32_t ccsidr;
1061      uint32_t line_power;
1062      uint32_t associativity;
1063      uint32_t way;
1064      uint32_t way_shift;
1065
[0616555]1066      ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
[d0a8f513]1067
1068      line_power = arm_ccsidr_get_line_power(ccsidr);
1069      associativity = arm_ccsidr_get_associativity(ccsidr);
1070      way_shift = __builtin_clz(associativity - 1);
1071
1072      for (way = 0; way < associativity; ++way) {
1073        uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1074        uint32_t set;
1075
1076        for (set = 0; set < num_sets; ++set) {
1077          uint32_t set_way = (way << way_shift)
1078            | (set << line_power)
1079            | (level << 1);
1080
1081          arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
1082        }
1083      }
1084    }
1085  }
1086}
1087
[66a2409d]1088ARM_CP15_TEXT_SECTION static inline void
1089arm_cp15_data_cache_clean_line(const void *mva)
[39c8fdb]1090{
1091  ARM_SWITCH_REGISTERS;
[5e657e2]1092
1093  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
[39c8fdb]1094
[139ec149]1095  __asm__ volatile (
[39c8fdb]1096    ARM_SWITCH_TO_ARM
[5e657e2]1097    "mcr p15, 0, %[mva], c7, c10, 1\n"
[39c8fdb]1098    ARM_SWITCH_BACK
1099    : ARM_SWITCH_OUTPUT
[5e657e2]1100    : [mva] "r" (mva)
[39c8fdb]1101    : "memory"
1102  );
1103}
1104
[66a2409d]1105ARM_CP15_TEXT_SECTION static inline void
1106arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
[39c8fdb]1107{
1108  ARM_SWITCH_REGISTERS;
1109
[139ec149]1110  __asm__ volatile (
[39c8fdb]1111    ARM_SWITCH_TO_ARM
[5e657e2]1112    "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
[39c8fdb]1113    ARM_SWITCH_BACK
1114    : ARM_SWITCH_OUTPUT
[5e657e2]1115    : [set_and_way] "r" (set_and_way)
[39c8fdb]1116    : "memory"
1117  );
1118}
1119
[66a2409d]1120ARM_CP15_TEXT_SECTION static inline void
1121arm_cp15_data_cache_test_and_clean(void)
[39c8fdb]1122{
1123  ARM_SWITCH_REGISTERS;
1124
[139ec149]1125  __asm__ volatile (
[39c8fdb]1126    ARM_SWITCH_TO_ARM
[5e657e2]1127    "1:\n"
1128    "mrc p15, 0, r15, c7, c10, 3\n"
1129    "bne 1b\n"
[39c8fdb]1130    ARM_SWITCH_BACK
1131    : ARM_SWITCH_OUTPUT
[5e657e2]1132    :
1133    : "memory"
[39c8fdb]1134  );
1135}
1136
[76de8a8e]1137/*      In DDI0301H_arm1176jzfs_r0p7_trm
1138 *      'MCR p15, 0, <Rd>, c7, c14, 0' means
1139 *      Clean and Invalidate Entire Data Cache
1140 */
[66a2409d]1141ARM_CP15_TEXT_SECTION static inline void
1142arm_cp15_data_cache_clean_and_invalidate(void)
[76de8a8e]1143{
1144  ARM_SWITCH_REGISTERS;
1145
1146  uint32_t sbz = 0;
1147
1148  __asm__ volatile (
1149    ARM_SWITCH_TO_ARM
1150    "mcr p15, 0, %[sbz], c7, c14, 0\n"
1151    ARM_SWITCH_BACK
1152    : ARM_SWITCH_OUTPUT
1153    : [sbz] "r" (sbz)
1154    : "memory"
1155  );
1156}
1157
[66a2409d]1158ARM_CP15_TEXT_SECTION static inline void
1159arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
[39c8fdb]1160{
1161  ARM_SWITCH_REGISTERS;
1162
[5e657e2]1163  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
[39c8fdb]1164
[139ec149]1165  __asm__ volatile (
[39c8fdb]1166    ARM_SWITCH_TO_ARM
[5e657e2]1167    "mcr p15, 0, %[mva], c7, c14, 1\n"
[39c8fdb]1168    ARM_SWITCH_BACK
1169    : ARM_SWITCH_OUTPUT
1170    : [mva] "r" (mva)
[5e657e2]1171    : "memory"
[39c8fdb]1172  );
1173}
1174
[66a2409d]1175ARM_CP15_TEXT_SECTION static inline void
1176arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
[39c8fdb]1177{
1178  ARM_SWITCH_REGISTERS;
1179
[139ec149]1180  __asm__ volatile (
[39c8fdb]1181    ARM_SWITCH_TO_ARM
[5e657e2]1182    "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
[39c8fdb]1183    ARM_SWITCH_BACK
1184    : ARM_SWITCH_OUTPUT
[5e657e2]1185    : [set_and_way] "r" (set_and_way)
1186    : "memory"
[39c8fdb]1187  );
1188}
1189
[66a2409d]1190ARM_CP15_TEXT_SECTION static inline void
1191arm_cp15_data_cache_test_and_clean_and_invalidate(void)
[39c8fdb]1192{
1193  ARM_SWITCH_REGISTERS;
1194
[139ec149]1195  __asm__ volatile (
[39c8fdb]1196    ARM_SWITCH_TO_ARM
[5e657e2]1197    "1:\n"
1198    "mrc p15, 0, r15, c7, c14, 3\n"
1199    "bne 1b\n"
[39c8fdb]1200    ARM_SWITCH_BACK
1201    : ARM_SWITCH_OUTPUT
[5e657e2]1202    :
1203    : "memory"
[39c8fdb]1204  );
1205}
1206
[5e657e2]1207/** @} */
1208
[66a2409d]1209ARM_CP15_TEXT_SECTION static inline void
1210arm_cp15_drain_write_buffer(void)
[39c8fdb]1211{
1212  ARM_SWITCH_REGISTERS;
1213  uint32_t sbz = 0;
1214
[139ec149]1215  __asm__ volatile (
[39c8fdb]1216    ARM_SWITCH_TO_ARM
[5e657e2]1217    "mcr p15, 0, %[sbz], c7, c10, 4\n"
[39c8fdb]1218    ARM_SWITCH_BACK
1219    : ARM_SWITCH_OUTPUT
1220    : [sbz] "r" (sbz)
[5e657e2]1221    : "memory"
[39c8fdb]1222  );
1223}
1224
[66a2409d]1225ARM_CP15_TEXT_SECTION static inline void
1226arm_cp15_wait_for_interrupt(void)
[39c8fdb]1227{
1228  ARM_SWITCH_REGISTERS;
[5e657e2]1229  uint32_t sbz = 0;
[39c8fdb]1230
[139ec149]1231  __asm__ volatile (
[39c8fdb]1232    ARM_SWITCH_TO_ARM
[5e657e2]1233    "mcr p15, 0, %[sbz], c7, c0, 4\n"
[39c8fdb]1234    ARM_SWITCH_BACK
1235    : ARM_SWITCH_OUTPUT
[5e657e2]1236    : [sbz] "r" (sbz)
1237    : "memory"
[39c8fdb]1238  );
1239}
1240
[66a2409d]1241ARM_CP15_TEXT_SECTION static inline uint32_t
1242arm_cp15_get_multiprocessor_affinity(void)
[db42c079]1243{
1244  ARM_SWITCH_REGISTERS;
1245  uint32_t mpidr;
1246
1247  __asm__ volatile (
1248    ARM_SWITCH_TO_ARM
1249          "mrc p15, 0, %[mpidr], c0, c0, 5\n"
1250    ARM_SWITCH_BACK
1251    : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
1252  );
1253
1254  return mpidr & 0xff;
1255}
1256
[66a2409d]1257ARM_CP15_TEXT_SECTION static inline uint32_t
1258arm_cortex_a9_get_multiprocessor_cpu_id(void)
[db42c079]1259{
1260  return arm_cp15_get_multiprocessor_affinity() & 0xff;
1261}
1262
1263#define ARM_CORTEX_A9_ACTL_FW (1U << 0)
1264#define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
1265#define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
1266#define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
1267#define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
1268#define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
1269#define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
1270#define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
1271
[66a2409d]1272ARM_CP15_TEXT_SECTION static inline uint32_t
1273arm_cp15_get_auxiliary_control(void)
[db42c079]1274{
1275  ARM_SWITCH_REGISTERS;
1276  uint32_t val;
1277
1278  __asm__ volatile (
1279    ARM_SWITCH_TO_ARM
1280    "mrc p15, 0, %[val], c1, c0, 1\n"
1281    ARM_SWITCH_BACK
1282    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1283  );
1284
1285  return val;
1286}
1287
[66a2409d]1288ARM_CP15_TEXT_SECTION static inline void
1289arm_cp15_set_auxiliary_control(uint32_t val)
[db42c079]1290{
1291  ARM_SWITCH_REGISTERS;
1292
1293  __asm__ volatile (
1294    ARM_SWITCH_TO_ARM
1295    "mcr p15, 0, %[val], c1, c0, 1\n"
1296    ARM_SWITCH_BACK
1297    : ARM_SWITCH_OUTPUT
1298    : [val] "r" (val)
1299  );
1300}
1301
[9a037da9]1302/* ID_PFR1, Processor Feature Register 1 */
1303
[66a2409d]1304ARM_CP15_TEXT_SECTION static inline uint32_t
1305arm_cp15_get_processor_feature_1(void)
[9a037da9]1306{
1307  ARM_SWITCH_REGISTERS;
1308  uint32_t val;
1309
1310  __asm__ volatile (
1311    ARM_SWITCH_TO_ARM
1312    "mrc p15, 0, %[val], c0, c1, 1\n"
1313    ARM_SWITCH_BACK
1314    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1315  );
1316
1317  return val;
1318}
1319
1320/* VBAR, Vector Base Address Register, Security Extensions */
1321
[66a2409d]1322ARM_CP15_TEXT_SECTION static inline void
1323*arm_cp15_get_vector_base_address(void)
[9a037da9]1324{
1325  ARM_SWITCH_REGISTERS;
1326  void *base;
1327
1328  __asm__ volatile (
1329    ARM_SWITCH_TO_ARM
1330    "mrc p15, 0, %[base], c12, c0, 0\n"
1331    ARM_SWITCH_BACK
1332    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1333  );
1334
1335  return base;
1336}
1337
[66a2409d]1338ARM_CP15_TEXT_SECTION static inline void
1339arm_cp15_set_vector_base_address(void *base)
[9a037da9]1340{
1341  ARM_SWITCH_REGISTERS;
1342
1343  __asm__ volatile (
1344    ARM_SWITCH_TO_ARM
1345    "mcr p15, 0, %[base], c12, c0, 0\n"
1346    ARM_SWITCH_BACK
1347    : ARM_SWITCH_OUTPUT
1348    : [base] "r" (base)
1349  );
1350}
1351
[19a9090]1352ARM_CP15_TEXT_SECTION static inline void
1353*arm_cp15_get_hyp_vector_base_address(void)
1354{
1355  ARM_SWITCH_REGISTERS;
1356  void *base;
1357
1358  __asm__ volatile (
1359    ARM_SWITCH_TO_ARM
1360    "mrc p15, 4, %[base], c12, c0, 0\n"
1361    ARM_SWITCH_BACK
1362    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1363  );
1364
1365  return base;
1366}
1367
1368ARM_CP15_TEXT_SECTION static inline void
1369arm_cp15_set_hyp_vector_base_address(void *base)
1370{
1371  ARM_SWITCH_REGISTERS;
1372
1373  __asm__ volatile (
1374    ARM_SWITCH_TO_ARM
1375    "mcr p15, 4, %[base], c12, c0, 0\n"
1376    ARM_SWITCH_BACK
1377    : ARM_SWITCH_OUTPUT
1378    : [base] "r" (base)
1379  );
1380}
1381
[037e8ae5]1382/**
1383 * @brief Sets the @a section_flags for the address range [@a begin, @a end).
1384 *
1385 * @return Previous section flags of the first modified entry.
1386 */
1387uint32_t arm_cp15_set_translation_table_entries(
1388  const void *begin,
1389  const void *end,
1390  uint32_t section_flags
1391);
1392
[88cf23f8]1393void arm_cp15_set_exception_handler(
1394  Arm_symbolic_exception_name exception,
[33c98fd]1395  void (*handler)(void)
[88cf23f8]1396);
1397
[5e657e2]1398/** @} */
[39c8fdb]1399
1400#ifdef __cplusplus
1401}
1402#endif /* __cplusplus */
1403
1404#endif /* LIBCPU_SHARED_ARM_CP15_H */
Note: See TracBrowser for help on using the repository browser.