1#ifndef _ASM_M32R_BITOPS_H 2#define _ASM_M32R_BITOPS_H 3 4/* 5 * linux/include/asm-m32r/bitops.h 6 * 7 * Copyright 1992, Linus Torvalds. 8 * 9 * M32R version: 10 * Copyright (C) 2001, 2002 Hitoshi Yamamoto 11 * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org> 12 */ 13 14#ifndef _LINUX_BITOPS_H 15#error only <linux/bitops.h> can be included directly 16#endif 17 18#include <linux/compiler.h> 19#include <asm/assembler.h> 20#include <asm/system.h> 21#include <asm/byteorder.h> 22#include <asm/types.h> 23 24/* 25 * These have to be done with inline assembly: that way the bit-setting 26 * is guaranteed to be atomic. All bit operations return 0 if the bit 27 * was cleared before the operation and != 0 if it was not. 28 * 29 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 30 */ 31 32/** 33 * set_bit - Atomically set a bit in memory 34 * @nr: the bit to set 35 * @addr: the address to start counting from 36 * 37 * This function is atomic and may not be reordered. See __set_bit() 38 * if you do not require the atomic guarantees. 39 * Note that @nr may be almost arbitrarily large; this function is not 40 * restricted to acting on a single-word quantity. 41 */ 42static __inline__ void set_bit(int nr, volatile void * addr) 43{ 44 __u32 mask; 45 volatile __u32 *a = addr; 46 unsigned long flags; 47 unsigned long tmp; 48 49 a += (nr >> 5); 50 mask = (1 << (nr & 0x1F)); 51 52 local_irq_save(flags); 53 __asm__ __volatile__ ( 54 DCACHE_CLEAR("%0", "r6", "%1") 55 M32R_LOCK" %0, @%1; \n\t" 56 "or %0, %2; \n\t" 57 M32R_UNLOCK" %0, @%1; \n\t" 58 : "=&r" (tmp) 59 : "r" (a), "r" (mask) 60 : "memory" 61#ifdef CONFIG_CHIP_M32700_TS1 62 , "r6" 63#endif /* CONFIG_CHIP_M32700_TS1 */ 64 ); 65 local_irq_restore(flags); 66} 67 68/** 69 * clear_bit - Clears a bit in memory 70 * @nr: Bit to clear 71 * @addr: Address to start counting from 72 * 73 * clear_bit() is atomic and may not be reordered. However, it does 74 * not contain a memory barrier, so if it is used for locking purposes, 75 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() 76 * in order to ensure changes are visible on other processors. 77 */ 78static __inline__ void clear_bit(int nr, volatile void * addr) 79{ 80 __u32 mask; 81 volatile __u32 *a = addr; 82 unsigned long flags; 83 unsigned long tmp; 84 85 a += (nr >> 5); 86 mask = (1 << (nr & 0x1F)); 87 88 local_irq_save(flags); 89 90 __asm__ __volatile__ ( 91 DCACHE_CLEAR("%0", "r6", "%1") 92 M32R_LOCK" %0, @%1; \n\t" 93 "and %0, %2; \n\t" 94 M32R_UNLOCK" %0, @%1; \n\t" 95 : "=&r" (tmp) 96 : "r" (a), "r" (~mask) 97 : "memory" 98#ifdef CONFIG_CHIP_M32700_TS1 99 , "r6" 100#endif /* CONFIG_CHIP_M32700_TS1 */ 101 ); 102 local_irq_restore(flags); 103} 104 105#define smp_mb__before_clear_bit() barrier() 106#define smp_mb__after_clear_bit() barrier() 107 108/** 109 * change_bit - Toggle a bit in memory 110 * @nr: Bit to clear 111 * @addr: Address to start counting from 112 * 113 * change_bit() is atomic and may not be reordered. 114 * Note that @nr may be almost arbitrarily large; this function is not 115 * restricted to acting on a single-word quantity. 116 */ 117static __inline__ void change_bit(int nr, volatile void * addr) 118{ 119 __u32 mask; 120 volatile __u32 *a = addr; 121 unsigned long flags; 122 unsigned long tmp; 123 124 a += (nr >> 5); 125 mask = (1 << (nr & 0x1F)); 126 127 local_irq_save(flags); 128 __asm__ __volatile__ ( 129 DCACHE_CLEAR("%0", "r6", "%1") 130 M32R_LOCK" %0, @%1; \n\t" 131 "xor %0, %2; \n\t" 132 M32R_UNLOCK" %0, @%1; \n\t" 133 : "=&r" (tmp) 134 : "r" (a), "r" (mask) 135 : "memory" 136#ifdef CONFIG_CHIP_M32700_TS1 137 , "r6" 138#endif /* CONFIG_CHIP_M32700_TS1 */ 139 ); 140 local_irq_restore(flags); 141} 142 143/** 144 * test_and_set_bit - Set a bit and return its old value 145 * @nr: Bit to set 146 * @addr: Address to count from 147 * 148 * This operation is atomic and cannot be reordered. 149 * It also implies a memory barrier. 150 */ 151static __inline__ int test_and_set_bit(int nr, volatile void * addr) 152{ 153 __u32 mask, oldbit; 154 volatile __u32 *a = addr; 155 unsigned long flags; 156 unsigned long tmp; 157 158 a += (nr >> 5); 159 mask = (1 << (nr & 0x1F)); 160 161 local_irq_save(flags); 162 __asm__ __volatile__ ( 163 DCACHE_CLEAR("%0", "%1", "%2") 164 M32R_LOCK" %0, @%2; \n\t" 165 "mv %1, %0; \n\t" 166 "and %0, %3; \n\t" 167 "or %1, %3; \n\t" 168 M32R_UNLOCK" %1, @%2; \n\t" 169 : "=&r" (oldbit), "=&r" (tmp) 170 : "r" (a), "r" (mask) 171 : "memory" 172 ); 173 local_irq_restore(flags); 174 175 return (oldbit != 0); 176} 177 178/** 179 * test_and_clear_bit - Clear a bit and return its old value 180 * @nr: Bit to set 181 * @addr: Address to count from 182 * 183 * This operation is atomic and cannot be reordered. 184 * It also implies a memory barrier. 185 */ 186static __inline__ int test_and_clear_bit(int nr, volatile void * addr) 187{ 188 __u32 mask, oldbit; 189 volatile __u32 *a = addr; 190 unsigned long flags; 191 unsigned long tmp; 192 193 a += (nr >> 5); 194 mask = (1 << (nr & 0x1F)); 195 196 local_irq_save(flags); 197 198 __asm__ __volatile__ ( 199 DCACHE_CLEAR("%0", "%1", "%3") 200 M32R_LOCK" %0, @%3; \n\t" 201 "mv %1, %0; \n\t" 202 "and %0, %2; \n\t" 203 "not %2, %2; \n\t" 204 "and %1, %2; \n\t" 205 M32R_UNLOCK" %1, @%3; \n\t" 206 : "=&r" (oldbit), "=&r" (tmp), "+r" (mask) 207 : "r" (a) 208 : "memory" 209 ); 210 local_irq_restore(flags); 211 212 return (oldbit != 0); 213} 214 215/** 216 * test_and_change_bit - Change a bit and return its old value 217 * @nr: Bit to set 218 * @addr: Address to count from 219 * 220 * This operation is atomic and cannot be reordered. 221 * It also implies a memory barrier. 222 */ 223static __inline__ int test_and_change_bit(int nr, volatile void * addr) 224{ 225 __u32 mask, oldbit; 226 volatile __u32 *a = addr; 227 unsigned long flags; 228 unsigned long tmp; 229 230 a += (nr >> 5); 231 mask = (1 << (nr & 0x1F)); 232 233 local_irq_save(flags); 234 __asm__ __volatile__ ( 235 DCACHE_CLEAR("%0", "%1", "%2") 236 M32R_LOCK" %0, @%2; \n\t" 237 "mv %1, %0; \n\t" 238 "and %0, %3; \n\t" 239 "xor %1, %3; \n\t" 240 M32R_UNLOCK" %1, @%2; \n\t" 241 : "=&r" (oldbit), "=&r" (tmp) 242 : "r" (a), "r" (mask) 243 : "memory" 244 ); 245 local_irq_restore(flags); 246 247 return (oldbit != 0); 248} 249 250#include <asm-generic/bitops/non-atomic.h> 251#include <asm-generic/bitops/ffz.h> 252#include <asm-generic/bitops/__ffs.h> 253#include <asm-generic/bitops/fls.h> 254#include <asm-generic/bitops/__fls.h> 255#include <asm-generic/bitops/fls64.h> 256 257#ifdef __KERNEL__ 258 259#include <asm-generic/bitops/sched.h> 260#include <asm-generic/bitops/find.h> 261#include <asm-generic/bitops/ffs.h> 262#include <asm-generic/bitops/hweight.h> 263#include <asm-generic/bitops/lock.h> 264 265#endif /* __KERNEL__ */ 266 267#ifdef __KERNEL__ 268 269#include <asm-generic/bitops/ext2-non-atomic.h> 270#include <asm-generic/bitops/ext2-atomic.h> 271#include <asm-generic/bitops/minix.h> 272 273#endif /* __KERNEL__ */ 274 275#endif /* _ASM_M32R_BITOPS_H */ 276