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