1819833afSPeter Tyser /*
2819833afSPeter Tyser * linux/include/asm-arm/atomic.h
3819833afSPeter Tyser *
4819833afSPeter Tyser * Copyright (c) 1996 Russell King.
5819833afSPeter Tyser *
6819833afSPeter Tyser * This program is free software; you can redistribute it and/or modify
7819833afSPeter Tyser * it under the terms of the GNU General Public License version 2 as
8819833afSPeter Tyser * published by the Free Software Foundation.
9819833afSPeter Tyser *
10819833afSPeter Tyser * Changelog:
11819833afSPeter Tyser * 27-06-1996 RMK Created
12819833afSPeter Tyser * 13-04-1997 RMK Made functions atomic!
13819833afSPeter Tyser * 07-12-1997 RMK Upgraded for v2.1.
14819833afSPeter Tyser * 26-08-1998 PJB Added #ifdef __KERNEL__
15819833afSPeter Tyser */
16819833afSPeter Tyser #ifndef __ASM_ARM_ATOMIC_H
17819833afSPeter Tyser #define __ASM_ARM_ATOMIC_H
18819833afSPeter Tyser
19*2f96fde5SJoseph Chen #ifndef CONFIG_ARCH_ROCKCHIP
20819833afSPeter Tyser #ifdef CONFIG_SMP
21819833afSPeter Tyser #error SMP not supported
22819833afSPeter Tyser #endif
23*2f96fde5SJoseph Chen #endif
24819833afSPeter Tyser
25819833afSPeter Tyser typedef struct { volatile int counter; } atomic_t;
2659a51a10SAdam Oleksy #if BITS_PER_LONG == 32
2759a51a10SAdam Oleksy typedef struct { volatile long long counter; } atomic64_t;
2859a51a10SAdam Oleksy #else /* BIT_PER_LONG == 32 */
2959a51a10SAdam Oleksy typedef struct { volatile long counter; } atomic64_t;
3059a51a10SAdam Oleksy #endif
31819833afSPeter Tyser
32819833afSPeter Tyser #define ATOMIC_INIT(i) { (i) }
33819833afSPeter Tyser
34819833afSPeter Tyser #ifdef __KERNEL__
357d89982bSVasili Galka #include <asm/proc-armv/system.h>
36819833afSPeter Tyser
37819833afSPeter Tyser #define atomic_read(v) ((v)->counter)
38819833afSPeter Tyser #define atomic_set(v, i) (((v)->counter) = (i))
3959a51a10SAdam Oleksy #define atomic64_read(v) atomic_read(v)
4059a51a10SAdam Oleksy #define atomic64_set(v, i) atomic_set(v, i)
41819833afSPeter Tyser
atomic_add(int i,volatile atomic_t * v)42819833afSPeter Tyser static inline void atomic_add(int i, volatile atomic_t *v)
43819833afSPeter Tyser {
441d48ca69SHeiko Schocher unsigned long flags = 0;
45819833afSPeter Tyser
46819833afSPeter Tyser local_irq_save(flags);
47819833afSPeter Tyser v->counter += i;
48819833afSPeter Tyser local_irq_restore(flags);
49819833afSPeter Tyser }
50819833afSPeter Tyser
atomic_sub(int i,volatile atomic_t * v)51819833afSPeter Tyser static inline void atomic_sub(int i, volatile atomic_t *v)
52819833afSPeter Tyser {
531d48ca69SHeiko Schocher unsigned long flags = 0;
54819833afSPeter Tyser
55819833afSPeter Tyser local_irq_save(flags);
56819833afSPeter Tyser v->counter -= i;
57819833afSPeter Tyser local_irq_restore(flags);
58819833afSPeter Tyser }
59819833afSPeter Tyser
atomic_inc(volatile atomic_t * v)60819833afSPeter Tyser static inline void atomic_inc(volatile atomic_t *v)
61819833afSPeter Tyser {
621d48ca69SHeiko Schocher unsigned long flags = 0;
63819833afSPeter Tyser
64819833afSPeter Tyser local_irq_save(flags);
65819833afSPeter Tyser v->counter += 1;
66819833afSPeter Tyser local_irq_restore(flags);
67819833afSPeter Tyser }
68819833afSPeter Tyser
atomic_dec(volatile atomic_t * v)69819833afSPeter Tyser static inline void atomic_dec(volatile atomic_t *v)
70819833afSPeter Tyser {
711d48ca69SHeiko Schocher unsigned long flags = 0;
72819833afSPeter Tyser
73819833afSPeter Tyser local_irq_save(flags);
74819833afSPeter Tyser v->counter -= 1;
75819833afSPeter Tyser local_irq_restore(flags);
76819833afSPeter Tyser }
77819833afSPeter Tyser
atomic_dec_and_test(volatile atomic_t * v)78819833afSPeter Tyser static inline int atomic_dec_and_test(volatile atomic_t *v)
79819833afSPeter Tyser {
801d48ca69SHeiko Schocher unsigned long flags = 0;
81819833afSPeter Tyser int val;
82819833afSPeter Tyser
83819833afSPeter Tyser local_irq_save(flags);
84819833afSPeter Tyser val = v->counter;
85819833afSPeter Tyser v->counter = val -= 1;
86819833afSPeter Tyser local_irq_restore(flags);
87819833afSPeter Tyser
88819833afSPeter Tyser return val == 0;
89819833afSPeter Tyser }
90819833afSPeter Tyser
atomic_add_negative(int i,volatile atomic_t * v)91819833afSPeter Tyser static inline int atomic_add_negative(int i, volatile atomic_t *v)
92819833afSPeter Tyser {
931d48ca69SHeiko Schocher unsigned long flags = 0;
94819833afSPeter Tyser int val;
95819833afSPeter Tyser
96819833afSPeter Tyser local_irq_save(flags);
97819833afSPeter Tyser val = v->counter;
98819833afSPeter Tyser v->counter = val += i;
99819833afSPeter Tyser local_irq_restore(flags);
100819833afSPeter Tyser
101819833afSPeter Tyser return val < 0;
102819833afSPeter Tyser }
103819833afSPeter Tyser
atomic_clear_mask(unsigned long mask,unsigned long * addr)104819833afSPeter Tyser static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
105819833afSPeter Tyser {
1061d48ca69SHeiko Schocher unsigned long flags = 0;
107819833afSPeter Tyser
108819833afSPeter Tyser local_irq_save(flags);
109819833afSPeter Tyser *addr &= ~mask;
110819833afSPeter Tyser local_irq_restore(flags);
111819833afSPeter Tyser }
112819833afSPeter Tyser
11359a51a10SAdam Oleksy #if BITS_PER_LONG == 32
11459a51a10SAdam Oleksy
atomic64_add(long long i,volatile atomic64_t * v)11559a51a10SAdam Oleksy static inline void atomic64_add(long long i, volatile atomic64_t *v)
11659a51a10SAdam Oleksy {
11759a51a10SAdam Oleksy unsigned long flags = 0;
11859a51a10SAdam Oleksy
11959a51a10SAdam Oleksy local_irq_save(flags);
12059a51a10SAdam Oleksy v->counter += i;
12159a51a10SAdam Oleksy local_irq_restore(flags);
12259a51a10SAdam Oleksy }
12359a51a10SAdam Oleksy
atomic64_sub(long long i,volatile atomic64_t * v)12459a51a10SAdam Oleksy static inline void atomic64_sub(long long i, volatile atomic64_t *v)
12559a51a10SAdam Oleksy {
12659a51a10SAdam Oleksy unsigned long flags = 0;
12759a51a10SAdam Oleksy
12859a51a10SAdam Oleksy local_irq_save(flags);
12959a51a10SAdam Oleksy v->counter -= i;
13059a51a10SAdam Oleksy local_irq_restore(flags);
13159a51a10SAdam Oleksy }
13259a51a10SAdam Oleksy
13359a51a10SAdam Oleksy #else /* BIT_PER_LONG == 32 */
13459a51a10SAdam Oleksy
atomic64_add(long i,volatile atomic64_t * v)13559a51a10SAdam Oleksy static inline void atomic64_add(long i, volatile atomic64_t *v)
13659a51a10SAdam Oleksy {
13759a51a10SAdam Oleksy unsigned long flags = 0;
13859a51a10SAdam Oleksy
13959a51a10SAdam Oleksy local_irq_save(flags);
14059a51a10SAdam Oleksy v->counter += i;
14159a51a10SAdam Oleksy local_irq_restore(flags);
14259a51a10SAdam Oleksy }
14359a51a10SAdam Oleksy
atomic64_sub(long i,volatile atomic64_t * v)14459a51a10SAdam Oleksy static inline void atomic64_sub(long i, volatile atomic64_t *v)
14559a51a10SAdam Oleksy {
14659a51a10SAdam Oleksy unsigned long flags = 0;
14759a51a10SAdam Oleksy
14859a51a10SAdam Oleksy local_irq_save(flags);
14959a51a10SAdam Oleksy v->counter -= i;
15059a51a10SAdam Oleksy local_irq_restore(flags);
15159a51a10SAdam Oleksy }
15259a51a10SAdam Oleksy #endif
15359a51a10SAdam Oleksy
atomic64_inc(volatile atomic64_t * v)15459a51a10SAdam Oleksy static inline void atomic64_inc(volatile atomic64_t *v)
15559a51a10SAdam Oleksy {
15659a51a10SAdam Oleksy unsigned long flags = 0;
15759a51a10SAdam Oleksy
15859a51a10SAdam Oleksy local_irq_save(flags);
15959a51a10SAdam Oleksy v->counter += 1;
16059a51a10SAdam Oleksy local_irq_restore(flags);
16159a51a10SAdam Oleksy }
16259a51a10SAdam Oleksy
atomic64_dec(volatile atomic64_t * v)16359a51a10SAdam Oleksy static inline void atomic64_dec(volatile atomic64_t *v)
16459a51a10SAdam Oleksy {
16559a51a10SAdam Oleksy unsigned long flags = 0;
16659a51a10SAdam Oleksy
16759a51a10SAdam Oleksy local_irq_save(flags);
16859a51a10SAdam Oleksy v->counter -= 1;
16959a51a10SAdam Oleksy local_irq_restore(flags);
17059a51a10SAdam Oleksy }
17159a51a10SAdam Oleksy
172819833afSPeter Tyser /* Atomic operations are already serializing on ARM */
173819833afSPeter Tyser #define smp_mb__before_atomic_dec() barrier()
174819833afSPeter Tyser #define smp_mb__after_atomic_dec() barrier()
175819833afSPeter Tyser #define smp_mb__before_atomic_inc() barrier()
176819833afSPeter Tyser #define smp_mb__after_atomic_inc() barrier()
177819833afSPeter Tyser
178819833afSPeter Tyser #endif
179819833afSPeter Tyser #endif
180