Merge branches 'pm-cpufreq', 'pm-sleep' and 'pm-em'
[linux-2.6-microblaze.git] / arch / arc / include / asm / atomic-llsc.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #ifndef _ASM_ARC_ATOMIC_LLSC_H
4 #define _ASM_ARC_ATOMIC_LLSC_H
5
6 #define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
7
8 #define ATOMIC_OP(op, c_op, asm_op)                                     \
9 static inline void arch_atomic_##op(int i, atomic_t *v)                 \
10 {                                                                       \
11         unsigned int val;                                               \
12                                                                         \
13         __asm__ __volatile__(                                           \
14         "1:     llock   %[val], [%[ctr]]                \n"             \
15         "       " #asm_op " %[val], %[val], %[i]        \n"             \
16         "       scond   %[val], [%[ctr]]                \n"             \
17         "       bnz     1b                              \n"             \
18         : [val] "=&r"   (val) /* Early clobber to prevent reg reuse */  \
19         : [ctr] "r"     (&v->counter), /* Not "m": llock only supports reg direct addr mode */  \
20           [i]   "ir"    (i)                                             \
21         : "cc");                                                        \
22 }                                                                       \
23
24 #define ATOMIC_OP_RETURN(op, c_op, asm_op)                              \
25 static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
26 {                                                                       \
27         unsigned int val;                                               \
28                                                                         \
29         __asm__ __volatile__(                                           \
30         "1:     llock   %[val], [%[ctr]]                \n"             \
31         "       " #asm_op " %[val], %[val], %[i]        \n"             \
32         "       scond   %[val], [%[ctr]]                \n"             \
33         "       bnz     1b                              \n"             \
34         : [val] "=&r"   (val)                                           \
35         : [ctr] "r"     (&v->counter),                                  \
36           [i]   "ir"    (i)                                             \
37         : "cc");                                                        \
38                                                                         \
39         return val;                                                     \
40 }
41
42 #define arch_atomic_add_return_relaxed          arch_atomic_add_return_relaxed
43 #define arch_atomic_sub_return_relaxed          arch_atomic_sub_return_relaxed
44
45 #define ATOMIC_FETCH_OP(op, c_op, asm_op)                               \
46 static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v)  \
47 {                                                                       \
48         unsigned int val, orig;                                         \
49                                                                         \
50         __asm__ __volatile__(                                           \
51         "1:     llock   %[orig], [%[ctr]]               \n"             \
52         "       " #asm_op " %[val], %[orig], %[i]       \n"             \
53         "       scond   %[val], [%[ctr]]                \n"             \
54         "       bnz     1b                              \n"             \
55         : [val] "=&r"   (val),                                          \
56           [orig] "=&r" (orig)                                           \
57         : [ctr] "r"     (&v->counter),                                  \
58           [i]   "ir"    (i)                                             \
59         : "cc");                                                        \
60                                                                         \
61         return orig;                                                    \
62 }
63
64 #define arch_atomic_fetch_add_relaxed           arch_atomic_fetch_add_relaxed
65 #define arch_atomic_fetch_sub_relaxed           arch_atomic_fetch_sub_relaxed
66
67 #define arch_atomic_fetch_and_relaxed           arch_atomic_fetch_and_relaxed
68 #define arch_atomic_fetch_andnot_relaxed        arch_atomic_fetch_andnot_relaxed
69 #define arch_atomic_fetch_or_relaxed            arch_atomic_fetch_or_relaxed
70 #define arch_atomic_fetch_xor_relaxed           arch_atomic_fetch_xor_relaxed
71
72 #define ATOMIC_OPS(op, c_op, asm_op)                                    \
73         ATOMIC_OP(op, c_op, asm_op)                                     \
74         ATOMIC_OP_RETURN(op, c_op, asm_op)                              \
75         ATOMIC_FETCH_OP(op, c_op, asm_op)
76
77 ATOMIC_OPS(add, +=, add)
78 ATOMIC_OPS(sub, -=, sub)
79
80 #undef ATOMIC_OPS
81 #define ATOMIC_OPS(op, c_op, asm_op)                                    \
82         ATOMIC_OP(op, c_op, asm_op)                                     \
83         ATOMIC_FETCH_OP(op, c_op, asm_op)
84
85 ATOMIC_OPS(and, &=, and)
86 ATOMIC_OPS(andnot, &= ~, bic)
87 ATOMIC_OPS(or, |=, or)
88 ATOMIC_OPS(xor, ^=, xor)
89
90 #define arch_atomic_andnot              arch_atomic_andnot
91
92 #undef ATOMIC_OPS
93 #undef ATOMIC_FETCH_OP
94 #undef ATOMIC_OP_RETURN
95 #undef ATOMIC_OP
96
97 #endif