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

4.115
Last change on this file since f241977 was 0656a00a, checked in by Ralf Kirchner <ralf.kirchner@…>, on 01/23/14 at 09:56:31

bsp/arm: Add CP15 methods

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