1 /* 2 * Adapated from 3 * include/asm-generic/bitops/atomic.h 4 * 5 * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com> 6 * 7 * This work is licensed under the terms of the GNU LGPL, version 2. 8 */ 9 #include <bitops.h> 10 #include <asm/barrier.h> 11 #include <asm/mmu.h> 12 13 void set_bit(int nr, volatile unsigned long *addr) 14 { 15 volatile unsigned long *word = addr + BIT_WORD(nr); 16 unsigned long mask = BIT_MASK(nr); 17 18 if (mmu_enabled()) 19 ATOMIC_BITOP("orr", mask, word); 20 else 21 *word |= mask; 22 smp_mb(); 23 } 24 25 void clear_bit(int nr, volatile unsigned long *addr) 26 { 27 volatile unsigned long *word = addr + BIT_WORD(nr); 28 unsigned long mask = BIT_MASK(nr); 29 30 if (mmu_enabled()) 31 ATOMIC_BITOP("bic", mask, word); 32 else 33 *word &= ~mask; 34 smp_mb(); 35 } 36 37 int test_bit(int nr, const volatile unsigned long *addr) 38 { 39 const volatile unsigned long *word = addr + BIT_WORD(nr); 40 unsigned long mask = BIT_MASK(nr); 41 42 return (*word & mask) != 0; 43 } 44 45 int test_and_set_bit(int nr, volatile unsigned long *addr) 46 { 47 volatile unsigned long *word = addr + BIT_WORD(nr); 48 unsigned long mask = BIT_MASK(nr); 49 unsigned long old; 50 51 smp_mb(); 52 53 if (mmu_enabled()) { 54 ATOMIC_TESTOP("orr", mask, word, old); 55 } else { 56 old = *word; 57 *word = old | mask; 58 } 59 smp_mb(); 60 61 return (old & mask) != 0; 62 } 63 64 int test_and_clear_bit(int nr, volatile unsigned long *addr) 65 { 66 volatile unsigned long *word = addr + BIT_WORD(nr); 67 unsigned long mask = BIT_MASK(nr); 68 unsigned long old; 69 70 smp_mb(); 71 72 if (mmu_enabled()) { 73 ATOMIC_TESTOP("bic", mask, word, old); 74 } else { 75 old = *word; 76 *word = old & ~mask; 77 } 78 smp_mb(); 79 80 return (old & mask) != 0; 81 } 82