Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
[platform/kernel/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 #include <linux/config.h>
20
21 #ifdef CONFIG_SMP
22 #error SMP not supported
23 #endif
24
25 typedef struct { volatile int counter; } atomic_t;
26
27 #define ATOMIC_INIT(i)  { (i) }
28
29 #ifdef __KERNEL__
30 #include <asm/proc/system.h>
31
32 #define atomic_read(v)  ((v)->counter)
33 #define atomic_set(v,i) (((v)->counter) = (i))
34
35 static inline void atomic_add(int i, volatile atomic_t *v)
36 {
37         unsigned long flags;
38
39         local_irq_save(flags);
40         v->counter += i;
41         local_irq_restore(flags);
42 }
43
44 static inline void atomic_sub(int i, volatile atomic_t *v)
45 {
46         unsigned long flags;
47
48         local_irq_save(flags);
49         v->counter -= i;
50         local_irq_restore(flags);
51 }
52
53 static inline void atomic_inc(volatile atomic_t *v)
54 {
55         unsigned long flags;
56
57         local_irq_save(flags);
58         v->counter += 1;
59         local_irq_restore(flags);
60 }
61
62 static inline void atomic_dec(volatile atomic_t *v)
63 {
64         unsigned long flags;
65
66         local_irq_save(flags);
67         v->counter -= 1;
68         local_irq_restore(flags);
69 }
70
71 static inline int atomic_dec_and_test(volatile atomic_t *v)
72 {
73         unsigned long flags;
74         int val;
75
76         local_irq_save(flags);
77         val = v->counter;
78         v->counter = val -= 1;
79         local_irq_restore(flags);
80
81         return val == 0;
82 }
83
84 static inline int atomic_add_negative(int i, volatile atomic_t *v)
85 {
86         unsigned long flags;
87         int val;
88
89         local_irq_save(flags);
90         val = v->counter;
91         v->counter = val += i;
92         local_irq_restore(flags);
93
94         return val < 0;
95 }
96
97 static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
98 {
99         unsigned long flags;
100
101         local_irq_save(flags);
102         *addr &= ~mask;
103         local_irq_restore(flags);
104 }
105
106 /* Atomic operations are already serializing on ARM */
107 #define smp_mb__before_atomic_dec()     barrier()
108 #define smp_mb__after_atomic_dec()      barrier()
109 #define smp_mb__before_atomic_inc()     barrier()
110 #define smp_mb__after_atomic_inc()      barrier()
111
112 #endif
113 #endif