Merge tag 'xilinx-for-v2017.09' of git://www.denx.de/git/u-boot-microblaze
[oweals/u-boot.git] / arch / arm / include / asm / atomic.h
1 /*
2  *  linux/include/asm-arm/atomic.h
3  *
4  *  Copyright (c) 1996 Russell King.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  *  Changelog:
11  *   27-06-1996 RMK     Created
12  *   13-04-1997 RMK     Made functions atomic!
13  *   07-12-1997 RMK     Upgraded for v2.1.
14  *   26-08-1998 PJB     Added #ifdef __KERNEL__
15  */
16 #ifndef __ASM_ARM_ATOMIC_H
17 #define __ASM_ARM_ATOMIC_H
18
19 #ifdef CONFIG_SMP
20 #error SMP not supported
21 #endif
22
23 typedef struct { volatile int counter; } atomic_t;
24 #if BITS_PER_LONG == 32
25 typedef struct { volatile long long counter; } atomic64_t;
26 #else /* BIT_PER_LONG == 32 */
27 typedef struct { volatile long counter; } atomic64_t;
28 #endif
29
30 #define ATOMIC_INIT(i)  { (i) }
31
32 #ifdef __KERNEL__
33 #include <asm/proc-armv/system.h>
34
35 #define atomic_read(v)  ((v)->counter)
36 #define atomic_set(v, i)        (((v)->counter) = (i))
37 #define atomic64_read(v)        atomic_read(v)
38 #define atomic64_set(v, i)      atomic_set(v, i)
39
40 static inline void atomic_add(int i, volatile atomic_t *v)
41 {
42         unsigned long flags = 0;
43
44         local_irq_save(flags);
45         v->counter += i;
46         local_irq_restore(flags);
47 }
48
49 static inline void atomic_sub(int i, volatile atomic_t *v)
50 {
51         unsigned long flags = 0;
52
53         local_irq_save(flags);
54         v->counter -= i;
55         local_irq_restore(flags);
56 }
57
58 static inline void atomic_inc(volatile atomic_t *v)
59 {
60         unsigned long flags = 0;
61
62         local_irq_save(flags);
63         v->counter += 1;
64         local_irq_restore(flags);
65 }
66
67 static inline void atomic_dec(volatile atomic_t *v)
68 {
69         unsigned long flags = 0;
70
71         local_irq_save(flags);
72         v->counter -= 1;
73         local_irq_restore(flags);
74 }
75
76 static inline int atomic_dec_and_test(volatile atomic_t *v)
77 {
78         unsigned long flags = 0;
79         int val;
80
81         local_irq_save(flags);
82         val = v->counter;
83         v->counter = val -= 1;
84         local_irq_restore(flags);
85
86         return val == 0;
87 }
88
89 static inline int atomic_add_negative(int i, volatile atomic_t *v)
90 {
91         unsigned long flags = 0;
92         int val;
93
94         local_irq_save(flags);
95         val = v->counter;
96         v->counter = val += i;
97         local_irq_restore(flags);
98
99         return val < 0;
100 }
101
102 static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
103 {
104         unsigned long flags = 0;
105
106         local_irq_save(flags);
107         *addr &= ~mask;
108         local_irq_restore(flags);
109 }
110
111 #if BITS_PER_LONG == 32
112
113 static inline void atomic64_add(long long i, volatile atomic64_t *v)
114 {
115         unsigned long flags = 0;
116
117         local_irq_save(flags);
118         v->counter += i;
119         local_irq_restore(flags);
120 }
121
122 static inline void atomic64_sub(long long i, volatile atomic64_t *v)
123 {
124         unsigned long flags = 0;
125
126         local_irq_save(flags);
127         v->counter -= i;
128         local_irq_restore(flags);
129 }
130
131 #else /* BIT_PER_LONG == 32 */
132
133 static inline void atomic64_add(long i, volatile atomic64_t *v)
134 {
135         unsigned long flags = 0;
136
137         local_irq_save(flags);
138         v->counter += i;
139         local_irq_restore(flags);
140 }
141
142 static inline void atomic64_sub(long i, volatile atomic64_t *v)
143 {
144         unsigned long flags = 0;
145
146         local_irq_save(flags);
147         v->counter -= i;
148         local_irq_restore(flags);
149 }
150 #endif
151
152 static inline void atomic64_inc(volatile atomic64_t *v)
153 {
154         unsigned long flags = 0;
155
156         local_irq_save(flags);
157         v->counter += 1;
158         local_irq_restore(flags);
159 }
160
161 static inline void atomic64_dec(volatile atomic64_t *v)
162 {
163         unsigned long flags = 0;
164
165         local_irq_save(flags);
166         v->counter -= 1;
167         local_irq_restore(flags);
168 }
169
170 /* Atomic operations are already serializing on ARM */
171 #define smp_mb__before_atomic_dec()     barrier()
172 #define smp_mb__after_atomic_dec()      barrier()
173 #define smp_mb__before_atomic_inc()     barrier()
174 #define smp_mb__after_atomic_inc()      barrier()
175
176 #endif
177 #endif