1 /* 2 ** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 ** Distributed under the terms of the MIT License. 4 */ 5 #ifndef _KERNEL_ARCH_ARM_CPU_H 6 #define _KERNEL_ARCH_ARM_CPU_H 7 8 9 #define CPU_MAX_CACHE_LEVEL 8 10 #define CACHE_LINE_SIZE 64 11 // TODO: Could be 32-bits sometimes? 12 13 14 #define isb() __asm__ __volatile__("isb" : : : "memory") 15 #define dsb() __asm__ __volatile__("dsb" : : : "memory") 16 #define dmb() __asm__ __volatile__("dmb" : : : "memory") 17 18 #define set_ac() 19 #define clear_ac() 20 21 22 #ifndef _ASSEMBLER 23 24 #include <arch/arm/arch_thread_types.h> 25 #include <kernel.h> 26 27 /**! Values for arch_cpu_info.arch */ 28 enum { 29 ARCH_ARM_PRE_ARM7, 30 ARCH_ARM_v3, 31 ARCH_ARM_v4, 32 ARCH_ARM_v4T, 33 ARCH_ARM_v5, 34 ARCH_ARM_v5T, 35 ARCH_ARM_v5TE, 36 ARCH_ARM_v5TEJ, 37 ARCH_ARM_v6, 38 ARCH_ARM_v7 39 }; 40 41 typedef struct arch_cpu_info { 42 /* For a detailed interpretation of these values, 43 see "The System Control coprocessor", 44 "Main ID register" in your ARM ARM */ 45 int implementor; 46 int part_number; 47 int revision; 48 int variant; 49 int arch; 50 } arch_cpu_info; 51 52 #ifdef __cplusplus 53 extern "C" { 54 #endif 55 56 57 #define DEFINE_ARM_GET_REG(name, cp, opc1, crn, crm, opc2) \ 58 static inline uint32 \ 59 arm_get_##name(void) \ 60 { \ 61 uint32 res; \ 62 asm volatile ("mrc " #cp ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 : "=r" (res)); \ 63 return res; \ 64 } 65 66 67 #define DEFINE_ARM_SET_REG(name, cp, opc1, crn, crm, opc2) \ 68 static inline void \ 69 arm_set_##name(uint32 val) \ 70 { \ 71 asm volatile ("mcr " #cp ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 :: "r" (val)); \ 72 } 73 74 75 /* CP15 c1, System Control Register */ 76 DEFINE_ARM_GET_REG(sctlr, p15, 0, c1, c0, 0) 77 DEFINE_ARM_SET_REG(sctlr, p15, 0, c1, c0, 0) 78 79 /* CP15 c2, Translation table support registers */ 80 DEFINE_ARM_GET_REG(ttbr0, p15, 0, c2, c0, 0) 81 DEFINE_ARM_SET_REG(ttbr0, p15, 0, c2, c0, 0) 82 DEFINE_ARM_GET_REG(ttbr1, p15, 0, c2, c0, 1) 83 DEFINE_ARM_SET_REG(ttbr1, p15, 0, c2, c0, 1) 84 DEFINE_ARM_GET_REG(ttbcr, p15, 0, c2, c0, 2) 85 DEFINE_ARM_SET_REG(ttbcr, p15, 0, c2, c0, 2) 86 87 /* CP15 c5 and c6, Memory system fault registers */ 88 DEFINE_ARM_GET_REG(dfsr, p15, 0, c5, c0, 0) 89 DEFINE_ARM_GET_REG(ifsr, p15, 0, c5, c0, 1) 90 DEFINE_ARM_GET_REG(dfar, p15, 0, c6, c0, 0) 91 DEFINE_ARM_GET_REG(ifar, p15, 0, c6, c0, 2) 92 93 /* CP15 c13, Process, context and thread ID registers */ 94 DEFINE_ARM_GET_REG(tpidruro, p15, 0, c13, c0, 3) 95 DEFINE_ARM_SET_REG(tpidruro, p15, 0, c13, c0, 3) 96 DEFINE_ARM_GET_REG(tpidrprw, p15, 0, c13, c0, 4) 97 DEFINE_ARM_SET_REG(tpidrprw, p15, 0, c13, c0, 4) 98 99 100 #undef DEFINE_ARM_GET_REG 101 #undef DEFINE_ARM_SET_REG 102 103 104 static inline addr_t 105 arm_get_fp(void) 106 { 107 uint32 res; 108 asm volatile ("mov %0, fp": "=r" (res)); 109 return res; 110 } 111 112 113 void arch_cpu_invalidate_TLB_page(addr_t page); 114 115 static inline void 116 arch_cpu_pause(void) 117 { 118 // TODO: ARM Priority pause call 119 } 120 121 122 static inline void 123 arch_cpu_idle(void) 124 { 125 uint32 Rd = 0; 126 asm volatile("mcr p15, 0, %[c7format], c7, c0, 4" 127 : : [c7format] "r" (Rd) ); 128 } 129 130 131 #ifdef __cplusplus 132 }; 133 #endif 134 135 #endif // !_ASSEMBLER 136 137 #endif /* _KERNEL_ARCH_ARM_CPU_H */ 138