1/* 2 * Copyright (C) 2004-2006 Atmel Corporation 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8#ifndef __ASM_AVR32_BITOPS_H 9#define __ASM_AVR32_BITOPS_H 10 11#ifndef _LINUX_BITOPS_H 12#error only <linux/bitops.h> can be included directly 13#endif 14 15#include <asm/byteorder.h> 16#include <asm/system.h> 17 18/* 19 * clear_bit() doesn't provide any barrier for the compiler 20 */ 21#define smp_mb__before_clear_bit() barrier() 22#define smp_mb__after_clear_bit() barrier() 23 24/* 25 * set_bit - Atomically set a bit in memory 26 * @nr: the bit to set 27 * @addr: the address to start counting from 28 * 29 * This function is atomic and may not be reordered. See __set_bit() 30 * if you do not require the atomic guarantees. 31 * 32 * Note that @nr may be almost arbitrarily large; this function is not 33 * restricted to acting on a single-word quantity. 34 */ 35static inline void set_bit(int nr, volatile void * addr) 36{ 37 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; 38 unsigned long tmp; 39 40 if (__builtin_constant_p(nr)) { 41 asm volatile( 42 "1: ssrf 5\n" 43 " ld.w %0, %2\n" 44 " sbr %0, %3\n" 45 " stcond %1, %0\n" 46 " brne 1b" 47 : "=&r"(tmp), "=o"(*p) 48 : "m"(*p), "i"(nr) 49 : "cc"); 50 } else { 51 unsigned long mask = 1UL << (nr % BITS_PER_LONG); 52 asm volatile( 53 "1: ssrf 5\n" 54 " ld.w %0, %2\n" 55 " or %0, %3\n" 56 " stcond %1, %0\n" 57 " brne 1b" 58 : "=&r"(tmp), "=o"(*p) 59 : "m"(*p), "r"(mask) 60 : "cc"); 61 } 62} 63 64/* 65 * clear_bit - Clears a bit in memory 66 * @nr: Bit to clear 67 * @addr: Address to start counting from 68 * 69 * clear_bit() is atomic and may not be reordered. However, it does 70 * not contain a memory barrier, so if it is used for locking purposes, 71 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() 72 * in order to ensure changes are visible on other processors. 73 */ 74static inline void clear_bit(int nr, volatile void * addr) 75{ 76 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; 77 unsigned long tmp; 78 79 if (__builtin_constant_p(nr)) { 80 asm volatile( 81 "1: ssrf 5\n" 82 " ld.w %0, %2\n" 83 " cbr %0, %3\n" 84 " stcond %1, %0\n" 85 " brne 1b" 86 : "=&r"(tmp), "=o"(*p) 87 : "m"(*p), "i"(nr) 88 : "cc"); 89 } else { 90 unsigned long mask = 1UL << (nr % BITS_PER_LONG); 91 asm volatile( 92 "1: ssrf 5\n" 93 " ld.w %0, %2\n" 94 " andn %0, %3\n" 95 " stcond %1, %0\n" 96 " brne 1b" 97 : "=&r"(tmp), "=o"(*p) 98 : "m"(*p), "r"(mask) 99 : "cc"); 100 } 101} 102 103/* 104 * change_bit - Toggle a bit in memory 105 * @nr: Bit to change 106 * @addr: Address to start counting from 107 * 108 * change_bit() is atomic and may not be reordered. 109 * Note that @nr may be almost arbitrarily large; this function is not 110 * restricted to acting on a single-word quantity. 111 */ 112static inline void change_bit(int nr, volatile void * addr) 113{ 114 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; 115 unsigned long mask = 1UL << (nr % BITS_PER_LONG); 116 unsigned long tmp; 117 118 asm volatile( 119 "1: ssrf 5\n" 120 " ld.w %0, %2\n" 121 " eor %0, %3\n" 122 " stcond %1, %0\n" 123 " brne 1b" 124 : "=&r"(tmp), "=o"(*p) 125 : "m"(*p), "r"(mask) 126 : "cc"); 127} 128 129/* 130 * test_and_set_bit - Set a bit and return its old value 131 * @nr: Bit to set 132 * @addr: Address to count from 133 * 134 * This operation is atomic and cannot be reordered. 135 * It also implies a memory barrier. 136 */ 137static inline int test_and_set_bit(int nr, volatile void * addr) 138{ 139 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; 140 unsigned long mask = 1UL << (nr % BITS_PER_LONG); 141 unsigned long tmp, old; 142 143 if (__builtin_constant_p(nr)) { 144 asm volatile( 145 "1: ssrf 5\n" 146 " ld.w %0, %3\n" 147 " mov %2, %0\n" 148 " sbr %0, %4\n" 149 " stcond %1, %0\n" 150 " brne 1b" 151 : "=&r"(tmp), "=o"(*p), "=&r"(old) 152 : "m"(*p), "i"(nr) 153 : "memory", "cc"); 154 } else { 155 asm volatile( 156 "1: ssrf 5\n" 157 " ld.w %2, %3\n" 158 " or %0, %2, %4\n" 159 " stcond %1, %0\n" 160 " brne 1b" 161 : "=&r"(tmp), "=o"(*p), "=&r"(old) 162 : "m"(*p), "r"(mask) 163 : "memory", "cc"); 164 } 165 166 return (old & mask) != 0; 167} 168 169/* 170 * test_and_clear_bit - Clear a bit and return its old value 171 * @nr: Bit to clear 172 * @addr: Address to count from 173 * 174 * This operation is atomic and cannot be reordered. 175 * It also implies a memory barrier. 176 */ 177static inline int test_and_clear_bit(int nr, volatile void * addr) 178{ 179 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; 180 unsigned long mask = 1UL << (nr % BITS_PER_LONG); 181 unsigned long tmp, old; 182 183 if (__builtin_constant_p(nr)) { 184 asm volatile( 185 "1: ssrf 5\n" 186 " ld.w %0, %3\n" 187 " mov %2, %0\n" 188 " cbr %0, %4\n" 189 " stcond %1, %0\n" 190 " brne 1b" 191 : "=&r"(tmp), "=o"(*p), "=&r"(old) 192 : "m"(*p), "i"(nr) 193 : "memory", "cc"); 194 } else { 195 asm volatile( 196 "1: ssrf 5\n" 197 " ld.w %0, %3\n" 198 " mov %2, %0\n" 199 " andn %0, %4\n" 200 " stcond %1, %0\n" 201 " brne 1b" 202 : "=&r"(tmp), "=o"(*p), "=&r"(old) 203 : "m"(*p), "r"(mask) 204 : "memory", "cc"); 205 } 206 207 return (old & mask) != 0; 208} 209 210/* 211 * test_and_change_bit - Change a bit and return its old value 212 * @nr: Bit to change 213 * @addr: Address to count from 214 * 215 * This operation is atomic and cannot be reordered. 216 * It also implies a memory barrier. 217 */ 218static inline int test_and_change_bit(int nr, volatile void * addr) 219{ 220 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; 221 unsigned long mask = 1UL << (nr % BITS_PER_LONG); 222 unsigned long tmp, old; 223 224 asm volatile( 225 "1: ssrf 5\n" 226 " ld.w %2, %3\n" 227 " eor %0, %2, %4\n" 228 " stcond %1, %0\n" 229 " brne 1b" 230 : "=&r"(tmp), "=o"(*p), "=&r"(old) 231 : "m"(*p), "r"(mask) 232 : "memory", "cc"); 233 234 return (old & mask) != 0; 235} 236 237#include <asm-generic/bitops/non-atomic.h> 238 239/* Find First bit Set */ 240static inline unsigned long __ffs(unsigned long word) 241{ 242 unsigned long result; 243 244 asm("brev %1\n\t" 245 "clz %0,%1" 246 : "=r"(result), "=&r"(word) 247 : "1"(word)); 248 return result; 249} 250 251/* Find First Zero */ 252static inline unsigned long ffz(unsigned long word) 253{ 254 return __ffs(~word); 255} 256 257/* Find Last bit Set */ 258static inline int fls(unsigned long word) 259{ 260 unsigned long result; 261 262 asm("clz %0,%1" : "=r"(result) : "r"(word)); 263 return 32 - result; 264} 265 266static inline int __fls(unsigned long word) 267{ 268 return fls(word) - 1; 269} 270 271unsigned long find_first_zero_bit(const unsigned long *addr, 272 unsigned long size); 273unsigned long find_next_zero_bit(const unsigned long *addr, 274 unsigned long size, 275 unsigned long offset); 276unsigned long find_first_bit(const unsigned long *addr, 277 unsigned long size); 278unsigned long find_next_bit(const unsigned long *addr, 279 unsigned long size, 280 unsigned long offset); 281 282/* 283 * ffs: find first bit set. This is defined the same way as 284 * the libc and compiler builtin ffs routines, therefore 285 * differs in spirit from the above ffz (man ffs). 286 * 287 * The difference is that bit numbering starts at 1, and if no bit is set, 288 * the function returns 0. 289 */ 290static inline int ffs(unsigned long word) 291{ 292 if(word == 0) 293 return 0; 294 return __ffs(word) + 1; 295} 296 297#include <asm-generic/bitops/fls64.h> 298#include <asm-generic/bitops/sched.h> 299#include <asm-generic/bitops/hweight.h> 300#include <asm-generic/bitops/lock.h> 301 302#include <asm-generic/bitops/ext2-non-atomic.h> 303#include <asm-generic/bitops/ext2-atomic.h> 304#include <asm-generic/bitops/minix-le.h> 305 306#endif /* __ASM_AVR32_BITOPS_H */ 307