Linux 4.5-rc1
[linux-drm-fsl-dcu.git] / arch / mips / lib / bitops.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org)
7  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
8  */
9 #include <linux/bitops.h>
10 #include <linux/irqflags.h>
11 #include <linux/export.h>
12
13
14 /**
15  * __mips_set_bit - Atomically set a bit in memory.  This is called by
16  * set_bit() if it cannot find a faster solution.
17  * @nr: the bit to set
18  * @addr: the address to start counting from
19  */
20 void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
21 {
22         unsigned long *a = (unsigned long *)addr;
23         unsigned bit = nr & SZLONG_MASK;
24         unsigned long mask;
25         unsigned long flags;
26
27         a += nr >> SZLONG_LOG;
28         mask = 1UL << bit;
29         raw_local_irq_save(flags);
30         *a |= mask;
31         raw_local_irq_restore(flags);
32 }
33 EXPORT_SYMBOL(__mips_set_bit);
34
35
36 /**
37  * __mips_clear_bit - Clears a bit in memory.  This is called by clear_bit() if
38  * it cannot find a faster solution.
39  * @nr: Bit to clear
40  * @addr: Address to start counting from
41  */
42 void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
43 {
44         unsigned long *a = (unsigned long *)addr;
45         unsigned bit = nr & SZLONG_MASK;
46         unsigned long mask;
47         unsigned long flags;
48
49         a += nr >> SZLONG_LOG;
50         mask = 1UL << bit;
51         raw_local_irq_save(flags);
52         *a &= ~mask;
53         raw_local_irq_restore(flags);
54 }
55 EXPORT_SYMBOL(__mips_clear_bit);
56
57
58 /**
59  * __mips_change_bit - Toggle a bit in memory.  This is called by change_bit()
60  * if it cannot find a faster solution.
61  * @nr: Bit to change
62  * @addr: Address to start counting from
63  */
64 void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
65 {
66         unsigned long *a = (unsigned long *)addr;
67         unsigned bit = nr & SZLONG_MASK;
68         unsigned long mask;
69         unsigned long flags;
70
71         a += nr >> SZLONG_LOG;
72         mask = 1UL << bit;
73         raw_local_irq_save(flags);
74         *a ^= mask;
75         raw_local_irq_restore(flags);
76 }
77 EXPORT_SYMBOL(__mips_change_bit);
78
79
80 /**
81  * __mips_test_and_set_bit - Set a bit and return its old value.  This is
82  * called by test_and_set_bit() if it cannot find a faster solution.
83  * @nr: Bit to set
84  * @addr: Address to count from
85  */
86 int __mips_test_and_set_bit(unsigned long nr,
87                             volatile unsigned long *addr)
88 {
89         unsigned long *a = (unsigned long *)addr;
90         unsigned bit = nr & SZLONG_MASK;
91         unsigned long mask;
92         unsigned long flags;
93         int res;
94
95         a += nr >> SZLONG_LOG;
96         mask = 1UL << bit;
97         raw_local_irq_save(flags);
98         res = (mask & *a) != 0;
99         *a |= mask;
100         raw_local_irq_restore(flags);
101         return res;
102 }
103 EXPORT_SYMBOL(__mips_test_and_set_bit);
104
105
106 /**
107  * __mips_test_and_set_bit_lock - Set a bit and return its old value.  This is
108  * called by test_and_set_bit_lock() if it cannot find a faster solution.
109  * @nr: Bit to set
110  * @addr: Address to count from
111  */
112 int __mips_test_and_set_bit_lock(unsigned long nr,
113                                  volatile unsigned long *addr)
114 {
115         unsigned long *a = (unsigned long *)addr;
116         unsigned bit = nr & SZLONG_MASK;
117         unsigned long mask;
118         unsigned long flags;
119         int res;
120
121         a += nr >> SZLONG_LOG;
122         mask = 1UL << bit;
123         raw_local_irq_save(flags);
124         res = (mask & *a) != 0;
125         *a |= mask;
126         raw_local_irq_restore(flags);
127         return res;
128 }
129 EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
130
131
132 /**
133  * __mips_test_and_clear_bit - Clear a bit and return its old value.  This is
134  * called by test_and_clear_bit() if it cannot find a faster solution.
135  * @nr: Bit to clear
136  * @addr: Address to count from
137  */
138 int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
139 {
140         unsigned long *a = (unsigned long *)addr;
141         unsigned bit = nr & SZLONG_MASK;
142         unsigned long mask;
143         unsigned long flags;
144         int res;
145
146         a += nr >> SZLONG_LOG;
147         mask = 1UL << bit;
148         raw_local_irq_save(flags);
149         res = (mask & *a) != 0;
150         *a &= ~mask;
151         raw_local_irq_restore(flags);
152         return res;
153 }
154 EXPORT_SYMBOL(__mips_test_and_clear_bit);
155
156
157 /**
158  * __mips_test_and_change_bit - Change a bit and return its old value.  This is
159  * called by test_and_change_bit() if it cannot find a faster solution.
160  * @nr: Bit to change
161  * @addr: Address to count from
162  */
163 int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
164 {
165         unsigned long *a = (unsigned long *)addr;
166         unsigned bit = nr & SZLONG_MASK;
167         unsigned long mask;
168         unsigned long flags;
169         int res;
170
171         a += nr >> SZLONG_LOG;
172         mask = 1UL << bit;
173         raw_local_irq_save(flags);
174         res = (mask & *a) != 0;
175         *a ^= mask;
176         raw_local_irq_restore(flags);
177         return res;
178 }
179 EXPORT_SYMBOL(__mips_test_and_change_bit);