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