summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/system-arm.h241
1 files changed, 157 insertions, 84 deletions
diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h
index c383121b46..0608f50a02 100644
--- a/firmware/target/arm/system-arm.h
+++ b/firmware/target/arm/system-arm.h
@@ -21,29 +21,85 @@
21#ifndef SYSTEM_ARM_H 21#ifndef SYSTEM_ARM_H
22#define SYSTEM_ARM_H 22#define SYSTEM_ARM_H
23 23
24/* Common to all ARM_ARCH */
24#define nop \ 25#define nop \
25 asm volatile ("nop") 26 asm volatile ("nop")
26 27
27void __div0(void); 28void __div0(void);
28 29
29/* This gets too complicated otherwise with all the ARM variation and would 30#define IRQ_ENABLED 0x00
30 have conflicts with another system-target.h elsewhere so include a 31#define IRQ_DISABLED 0x80
31 subheader from here. */ 32#define IRQ_STATUS 0x80
33#define FIQ_ENABLED 0x00
34#define FIQ_DISABLED 0x40
35#define FIQ_STATUS 0x40
36#define IRQ_FIQ_ENABLED 0x00
37#define IRQ_FIQ_DISABLED 0xc0
38#define IRQ_FIQ_STATUS 0xc0
39#define HIGHEST_IRQ_LEVEL IRQ_DISABLED
40
41#define set_irq_level(status) \
42 set_interrupt_status((status), IRQ_STATUS)
43#define set_fiq_status(status) \
44 set_interrupt_status((status), FIQ_STATUS)
45
46#define disable_irq_save() \
47 disable_interrupt_save(IRQ_STATUS)
48#define disable_fiq_save() \
49 disable_interrupt_save(FIQ_STATUS)
50
51#define restore_irq(cpsr) \
52 restore_interrupt(cpsr)
53#define restore_fiq(cpsr) \
54 restore_interrupt(cpsr)
55
56#define disable_irq() \
57 disable_interrupt(IRQ_STATUS)
58#define enable_irq() \
59 enable_interrupt(IRQ_STATUS)
60#define disable_fiq() \
61 disable_interrupt(FIQ_STATUS)
62#define enable_fiq() \
63 enable_interrupt(FIQ_STATUS)
64
65/* Core-level interrupt masking */
66
67static inline int set_interrupt_status(int status, int mask)
68{
69 unsigned long cpsr;
70 int oldstatus;
71 /* Read the old levels and set the new ones */
72 asm volatile (
73 "mrs %1, cpsr \n"
74 "bic %0, %1, %[mask] \n"
75 "orr %0, %0, %2 \n"
76 "msr cpsr_c, %0 \n"
77 : "=&r,r"(cpsr), "=&r,r"(oldstatus)
78 : "r,i"(status & mask), [mask]"i,i"(mask));
79
80 return oldstatus;
81}
32 82
83static inline void restore_interrupt(int cpsr)
84{
85 /* Set cpsr_c from value returned by disable_interrupt_save
86 * or set_interrupt_status */
87 asm volatile ("msr cpsr_c, %0" : : "r"(cpsr));
88}
89
90/* ARM_ARCH version section for architecture*/
91
92#if ARM_ARCH >= 6
33static inline uint16_t swap16(uint16_t value) 93static inline uint16_t swap16(uint16_t value)
34 /* 94 /*
35 result[15..8] = value[ 7..0]; 95 result[15..8] = value[ 7..0];
36 result[ 7..0] = value[15..8]; 96 result[ 7..0] = value[15..8];
37 */ 97 */
38{ 98{
39#if ARM_ARCH >= 6
40 uint32_t retval; 99 uint32_t retval;
41 asm volatile ("revsh %0, %1" /* xxAB */ 100 asm volatile ("revsh %0, %1" /* xxAB */
42 : "=r"(retval) : "r"((uint32_t)value)); /* xxBA */ 101 : "=r"(retval) : "r"((uint32_t)value)); /* xxBA */
43 return retval; 102 return retval;
44#else
45 return (value >> 8) | (value << 8);
46#endif
47} 103}
48 104
49static inline uint32_t swap32(uint32_t value) 105static inline uint32_t swap32(uint32_t value)
@@ -54,14 +110,104 @@ static inline uint32_t swap32(uint32_t value)
54 result[ 7.. 0] = value[31..24]; 110 result[ 7.. 0] = value[31..24];
55 */ 111 */
56{ 112{
57#if ARM_ARCH >= 6
58 uint32_t retval; 113 uint32_t retval;
59 asm volatile ("rev %0, %1" /* ABCD */ 114 asm volatile ("rev %0, %1" /* ABCD */
60 : "=r"(retval) : "r"(value)); /* DCBA */ 115 : "=r"(retval) : "r"(value)); /* DCBA */
61 return retval; 116 return retval;
62#else 117}
63 uint32_t tmp; 118
119static inline uint32_t swap_odd_even32(uint32_t value)
120{
121 /*
122 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
123 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
124 */
125 uint32_t retval;
126 asm volatile ("rev16 %0, %1" /* ABCD */
127 : "=r"(retval) : "r"(value)); /* BADC */
128 return retval;
129}
64 130
131static inline void enable_interrupt(int mask)
132{
133 /* Clear I and/or F disable bit */
134 /* mask is expected to be constant and so only relevent branch
135 * is preserved */
136 switch (mask & IRQ_FIQ_STATUS)
137 {
138 case IRQ_STATUS:
139 asm volatile ("cpsie i");
140 break;
141 case FIQ_STATUS:
142 asm volatile ("cpsie f");
143 break;
144 case IRQ_FIQ_STATUS:
145 asm volatile ("cpsie if");
146 break;
147 }
148}
149
150static inline void disable_interrupt(int mask)
151{
152 /* Set I and/or F disable bit */
153 /* mask is expected to be constant and so only relevent branch
154 * is preserved */
155 switch (mask & IRQ_FIQ_STATUS)
156 {
157 case IRQ_STATUS:
158 asm volatile ("cpsid i");
159 break;
160 case FIQ_STATUS:
161 asm volatile ("cpsid f");
162 break;
163 case IRQ_FIQ_STATUS:
164 asm volatile ("cpsid if");
165 break;
166 }
167}
168
169static inline int disable_interrupt_save(int mask)
170{
171 /* Set I and/or F disable bit and return old cpsr value */
172 int cpsr;
173 /* mask is expected to be constant and so only relevent branch
174 * is preserved */
175 asm volatile("mrs %0, cpsr" : "=r"(cpsr));
176 switch (mask & IRQ_FIQ_STATUS)
177 {
178 case IRQ_STATUS:
179 asm volatile ("cpsid i");
180 break;
181 case FIQ_STATUS:
182 asm volatile ("cpsid f");
183 break;
184 case IRQ_FIQ_STATUS:
185 asm volatile ("cpsid if");
186 break;
187 }
188 return cpsr;
189}
190
191#else /* ARM_ARCH < 6 */
192
193static inline uint16_t swap16(uint16_t value)
194 /*
195 result[15..8] = value[ 7..0];
196 result[ 7..0] = value[15..8];
197 */
198{
199 return (value >> 8) | (value << 8);
200}
201
202static inline uint32_t swap32(uint32_t value)
203 /*
204 result[31..24] = value[ 7.. 0];
205 result[23..16] = value[15.. 8];
206 result[15.. 8] = value[23..16];
207 result[ 7.. 0] = value[31..24];
208 */
209{
210 uint32_t tmp;
65 asm volatile ( 211 asm volatile (
66 "eor %1, %0, %0, ror #16 \n\t" 212 "eor %1, %0, %0, ror #16 \n\t"
67 "bic %1, %1, #0xff0000 \n\t" 213 "bic %1, %1, #0xff0000 \n\t"
@@ -70,7 +216,6 @@ static inline uint32_t swap32(uint32_t value)
70 : "+r" (value), "=r" (tmp) 216 : "+r" (value), "=r" (tmp)
71 ); 217 );
72 return value; 218 return value;
73#endif
74} 219}
75 220
76static inline uint32_t swap_odd_even32(uint32_t value) 221static inline uint32_t swap_odd_even32(uint32_t value)
@@ -79,14 +224,7 @@ static inline uint32_t swap_odd_even32(uint32_t value)
79 result[31..24],[15.. 8] = value[23..16],[ 7.. 0] 224 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
80 result[23..16],[ 7.. 0] = value[31..24],[15.. 8] 225 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
81 */ 226 */
82#if ARM_ARCH >= 6
83 uint32_t retval;
84 asm volatile ("rev16 %0, %1" /* ABCD */
85 : "=r"(retval) : "r"(value)); /* BADC */
86 return retval;
87#else
88 uint32_t tmp; 227 uint32_t tmp;
89
90 asm volatile ( /* ABCD */ 228 asm volatile ( /* ABCD */
91 "bic %1, %0, #0x00ff00 \n\t" /* AB.D */ 229 "bic %1, %0, #0x00ff00 \n\t" /* AB.D */
92 "bic %0, %0, #0xff0000 \n\t" /* A.CD */ 230 "bic %0, %0, #0xff0000 \n\t" /* A.CD */
@@ -95,42 +233,6 @@ static inline uint32_t swap_odd_even32(uint32_t value)
95 : "+r" (value), "=r" (tmp) /* BADC */ 233 : "+r" (value), "=r" (tmp) /* BADC */
96 ); 234 );
97 return value; 235 return value;
98#endif
99}
100
101/* Core-level interrupt masking */
102
103/* This one returns the old status */
104#define IRQ_ENABLED 0x00
105#define IRQ_DISABLED 0x80
106#define IRQ_STATUS 0x80
107#define FIQ_ENABLED 0x00
108#define FIQ_DISABLED 0x40
109#define FIQ_STATUS 0x40
110#define IRQ_FIQ_ENABLED 0x00
111#define IRQ_FIQ_DISABLED 0xc0
112#define IRQ_FIQ_STATUS 0xc0
113#define HIGHEST_IRQ_LEVEL IRQ_DISABLED
114
115#define set_irq_level(status) \
116 set_interrupt_status((status), IRQ_STATUS)
117#define set_fiq_status(status) \
118 set_interrupt_status((status), FIQ_STATUS)
119
120static inline int set_interrupt_status(int status, int mask)
121{
122 unsigned long cpsr;
123 int oldstatus;
124 /* Read the old levels and set the new ones */
125 asm volatile (
126 "mrs %1, cpsr \n"
127 "bic %0, %1, %[mask] \n"
128 "orr %0, %0, %2 \n"
129 "msr cpsr_c, %0 \n"
130 : "=&r,r"(cpsr), "=&r,r"(oldstatus)
131 : "r,i"(status & mask), [mask]"i,i"(mask));
132
133 return oldstatus;
134} 236}
135 237
136static inline void enable_interrupt(int mask) 238static inline void enable_interrupt(int mask)
@@ -155,18 +257,6 @@ static inline void disable_interrupt(int mask)
155 : "=&r"(tmp) : "i"(mask)); 257 : "=&r"(tmp) : "i"(mask));
156} 258}
157 259
158#define disable_irq() \
159 disable_interrupt(IRQ_STATUS)
160
161#define enable_irq() \
162 enable_interrupt(IRQ_STATUS)
163
164#define disable_fiq() \
165 disable_interrupt(FIQ_STATUS)
166
167#define enable_fiq() \
168 enable_interrupt(FIQ_STATUS)
169
170static inline int disable_interrupt_save(int mask) 260static inline int disable_interrupt_save(int mask)
171{ 261{
172 /* Set I and/or F disable bit and return old cpsr value */ 262 /* Set I and/or F disable bit and return old cpsr value */
@@ -180,23 +270,6 @@ static inline int disable_interrupt_save(int mask)
180 return cpsr; 270 return cpsr;
181} 271}
182 272
183#define disable_irq_save() \ 273#endif /* ARM_ARCH */
184 disable_interrupt_save(IRQ_STATUS)
185
186#define disable_fiq_save() \
187 disable_interrupt_save(FIQ_STATUS)
188
189static inline void restore_interrupt(int cpsr)
190{
191 /* Set cpsr_c from value returned by disable_interrupt_save
192 * or set_interrupt_status */
193 asm volatile ("msr cpsr_c, %0" : : "r"(cpsr));
194}
195
196#define restore_irq(cpsr) \
197 restore_interrupt(cpsr)
198
199#define restore_fiq(cpsr) \
200 restore_interrupt(cpsr)
201 274
202#endif /* SYSTEM_ARM_H */ 275#endif /* SYSTEM_ARM_H */