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