xref: /rk3399_rockchip-uboot/arch/arm/include/asm/atomic.h (revision 1d48ca69e5cb0538b0cae8fa651d2cb2eb97b2cb)
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 
19819833afSPeter Tyser #ifdef CONFIG_SMP
20819833afSPeter Tyser #error SMP not supported
21819833afSPeter Tyser #endif
22819833afSPeter Tyser 
23819833afSPeter Tyser typedef struct { volatile int counter; } atomic_t;
24819833afSPeter Tyser 
25819833afSPeter Tyser #define ATOMIC_INIT(i)	{ (i) }
26819833afSPeter Tyser 
27819833afSPeter Tyser #ifdef __KERNEL__
287d89982bSVasili Galka #include <asm/proc-armv/system.h>
29819833afSPeter Tyser 
30819833afSPeter Tyser #define atomic_read(v)	((v)->counter)
31819833afSPeter Tyser #define atomic_set(v,i)	(((v)->counter) = (i))
32819833afSPeter Tyser 
33819833afSPeter Tyser static inline void atomic_add(int i, volatile atomic_t *v)
34819833afSPeter Tyser {
35*1d48ca69SHeiko Schocher 	unsigned long flags = 0;
36819833afSPeter Tyser 
37819833afSPeter Tyser 	local_irq_save(flags);
38819833afSPeter Tyser 	v->counter += i;
39819833afSPeter Tyser 	local_irq_restore(flags);
40819833afSPeter Tyser }
41819833afSPeter Tyser 
42819833afSPeter Tyser static inline void atomic_sub(int i, volatile atomic_t *v)
43819833afSPeter Tyser {
44*1d48ca69SHeiko 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 
51819833afSPeter Tyser static inline void atomic_inc(volatile atomic_t *v)
52819833afSPeter Tyser {
53*1d48ca69SHeiko Schocher 	unsigned long flags = 0;
54819833afSPeter Tyser 
55819833afSPeter Tyser 	local_irq_save(flags);
56819833afSPeter Tyser 	v->counter += 1;
57819833afSPeter Tyser 	local_irq_restore(flags);
58819833afSPeter Tyser }
59819833afSPeter Tyser 
60819833afSPeter Tyser static inline void atomic_dec(volatile atomic_t *v)
61819833afSPeter Tyser {
62*1d48ca69SHeiko 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 
69819833afSPeter Tyser static inline int atomic_dec_and_test(volatile atomic_t *v)
70819833afSPeter Tyser {
71*1d48ca69SHeiko Schocher 	unsigned long flags = 0;
72819833afSPeter Tyser 	int val;
73819833afSPeter Tyser 
74819833afSPeter Tyser 	local_irq_save(flags);
75819833afSPeter Tyser 	val = v->counter;
76819833afSPeter Tyser 	v->counter = val -= 1;
77819833afSPeter Tyser 	local_irq_restore(flags);
78819833afSPeter Tyser 
79819833afSPeter Tyser 	return val == 0;
80819833afSPeter Tyser }
81819833afSPeter Tyser 
82819833afSPeter Tyser static inline int atomic_add_negative(int i, volatile atomic_t *v)
83819833afSPeter Tyser {
84*1d48ca69SHeiko Schocher 	unsigned long flags = 0;
85819833afSPeter Tyser 	int val;
86819833afSPeter Tyser 
87819833afSPeter Tyser 	local_irq_save(flags);
88819833afSPeter Tyser 	val = v->counter;
89819833afSPeter Tyser 	v->counter = val += i;
90819833afSPeter Tyser 	local_irq_restore(flags);
91819833afSPeter Tyser 
92819833afSPeter Tyser 	return val < 0;
93819833afSPeter Tyser }
94819833afSPeter Tyser 
95819833afSPeter Tyser static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
96819833afSPeter Tyser {
97*1d48ca69SHeiko Schocher 	unsigned long flags = 0;
98819833afSPeter Tyser 
99819833afSPeter Tyser 	local_irq_save(flags);
100819833afSPeter Tyser 	*addr &= ~mask;
101819833afSPeter Tyser 	local_irq_restore(flags);
102819833afSPeter Tyser }
103819833afSPeter Tyser 
104819833afSPeter Tyser /* Atomic operations are already serializing on ARM */
105819833afSPeter Tyser #define smp_mb__before_atomic_dec()	barrier()
106819833afSPeter Tyser #define smp_mb__after_atomic_dec()	barrier()
107819833afSPeter Tyser #define smp_mb__before_atomic_inc()	barrier()
108819833afSPeter Tyser #define smp_mb__after_atomic_inc()	barrier()
109819833afSPeter Tyser 
110819833afSPeter Tyser #endif
111819833afSPeter Tyser #endif
112