blob: e2aa506c50607ee8022e8750ba6f46e500c98389 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <asm.h>
24
25.text
26
27/* void arch_enable_ints(void); */
28FUNCTION(arch_enable_ints)
29 mrs r0, cpsr
30 bic r0, r0, #(1<<7) /* clear the I bit */
31 msr cpsr_c, r0
32 bx lr
33
34/* void arch_disable_ints(void); */
35FUNCTION(arch_disable_ints)
36 mrs r0, cpsr
37 orr r0, r0, #(1<<7)
38 msr cpsr_c, r0
39 bx lr
40
41/* int atomic_swap(int *ptr, int val); */
42FUNCTION(atomic_swap)
43 swp r0, r2, [r1]
44 bx lr
45
46/* int atomic_add(int *ptr, int val); */
47FUNCTION(atomic_add)
Travis Geiselbrecht8d529ef2008-09-13 15:13:21 -070048#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
49 /* use load/store exclusive */
50.L_loop_add:
51 ldrex r12, [r0]
52 add r2, r12, r1
53 strex r3, r2, [r0]
54 cmp r3, #0
55 bne .L_loop_add
56
57 /* save old value */
58 mov r0, r12
59 bx lr
60#else
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070061 /* disable interrupts, do the add, and reenable */
62 mrs r2, cpsr
63 mov r12, r2
64 orr r2, r2, #(3<<6)
65 msr cpsr_c, r2
66
67 /* ints disabled, old cpsr state in r12 */
68
69 /* do the add, leave the previous value in r0 */
70 mov r3, r0
71 ldr r0, [r3]
72 add r2, r0, r1
73 str r2, [r3]
74
75 /* restore interrupts and exit */
76 msr cpsr_c, r12
77 bx lr
Travis Geiselbrecht8d529ef2008-09-13 15:13:21 -070078#endif
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070079
80/* int atomic_and(int *ptr, int val); */
81FUNCTION(atomic_and)
Travis Geiselbrecht8d529ef2008-09-13 15:13:21 -070082#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
83 /* use load/store exclusive */
84.L_loop_and:
85 ldrex r12, [r0]
86 and r2, r12, r1
87 strex r3, r2, [r0]
88 cmp r3, #0
89 bne .L_loop_and
90
91 /* save old value */
92 mov r0, r12
93 bx lr
94#else
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070095 /* disable interrupts, do the and, and reenable */
96 mrs r2, cpsr
97 mov r12, r2
98 orr r2, r2, #(3<<6)
99 msr cpsr_c, r2
100
101 /* ints disabled, old cpsr state in r12 */
102
103 /* do the and, leave the previous value in r0 */
104 mov r3, r0
105 ldr r0, [r3]
106 and r2, r0, r1
107 str r2, [r3]
108
109 /* restore interrupts and exit */
110 msr cpsr_c, r12
111 bx lr
Travis Geiselbrecht8d529ef2008-09-13 15:13:21 -0700112#endif
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700113
114/* int atomic_or(int *ptr, int val); */
115FUNCTION(atomic_or)
Travis Geiselbrecht8d529ef2008-09-13 15:13:21 -0700116#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
117 /* use load/store exclusive */
118.L_loop_or:
119 ldrex r12, [r0]
120 orr r2, r12, r1
121 strex r3, r2, [r0]
122 cmp r3, #0
123 bne .L_loop_or
124
125 /* save old value */
126 mov r0, r12
127 bx lr
128#else
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700129 /* disable interrupts, do the or, and reenable */
130 mrs r2, cpsr
131 mov r12, r2
132 orr r2, r2, #(3<<6)
133 msr cpsr_c, r2
134
135 /* ints disabled, old cpsr state in r12 */
136
137 /* do the or, leave the previous value in r0 */
138 mov r3, r0
139 ldr r0, [r3]
140 orr r2, r0, r1
141 str r2, [r3]
142
143 /* restore interrupts and exit */
144 msr cpsr_c, r12
145 bx lr
Travis Geiselbrecht8d529ef2008-09-13 15:13:21 -0700146#endif
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700147
148/* void arch_idle(); */
149FUNCTION(arch_idle)
150#if ARM_CPU_CORTEX_A8
151 .word 0xe320f003 /* wfi */
Brian Swetlandaf7dab42008-09-07 02:49:51 -0700152#elif PLATFORM_MSM7K
153 /* TODO: safely handle wfi */
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700154#elif ARM_CPU_ARM1136 || ARM_CPU_ARM926
155 mov r0, #0
156 mcr p15, 0, r0, c7, c0, #4
157#elif ARM_CPU_ARM7
158 /* nothing to do here */
159#else
160#error unknown cpu
161#endif
162 bx lr
163
164/* uint32_t arm_read_cr1(void) */
165FUNCTION(arm_read_cr1)
166 mrc p15, 0, r0, c1, c0, 0
167 bx lr
168
169/* void arm_write_cr1(uint32_t val) */
170FUNCTION(arm_write_cr1)
171 mcr p15, 0, r0, c1, c0, 0
172 bx lr
173
174/* uint32_t arm_read_cr1_aux(void) */
175FUNCTION(arm_read_cr1_aux)
176 mrc p15, 0, r0, c1, c0, 1
177 bx lr
178
179/* void arm_write_cr1_aux(uint32_t val) */
180FUNCTION(arm_write_cr1_aux)
181 mcr p15, 0, r0, c1, c0, 1
182 bx lr
183
184/* void arm_write_ttbr(uint32_t val) */
185FUNCTION(arm_write_ttbr)
186 mcr p15, 0, r0, c2, c0, 0
187 bx lr
188
189/* void arm_write_dacr(uint32_t val) */
190FUNCTION(arm_write_dacr)
191 mcr p15, 0, r0, c3, c0, 0
192 bx lr
193
194/* void arm_invalidate_tlb(void) */
195FUNCTION(arm_invalidate_tlb)
196 mov r0, #0
197 mcr p15, 0, r0, c8, c7, 0
198 bx lr
199
200/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
201FUNCTION(arch_switch_stacks_and_call)
202 mov sp, r1
203 bx r0