summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAtish Patra <atish.patra@wdc.com>2019-01-21 10:23:28 +0300
committerAnup Patel <anup@brainfault.org>2019-01-22 07:33:49 +0300
commit312b6bf32f51e530dd22746fe2a36d6459e29588 (patch)
treef7f9270897139dce8886b1db11f02cc087559f9f /include
parent784a4657c0957e7f9561fd2d87930ba008643c1e (diff)
downloadopensbi-312b6bf32f51e530dd22746fe2a36d6459e29588.tar.xz
lib: Add atomic bit set/clear operations.
Add addtional functionlities for set/clear bits atomically. Signed-off-by: Atish Patra <atish.patra@wdc.com>
Diffstat (limited to 'include')
-rw-r--r--include/sbi/riscv_asm.h2
-rw-r--r--include/sbi/riscv_atomic.h28
-rw-r--r--include/sbi/sbi_bitops.h98
-rw-r--r--include/sbi/sbi_bits.h2
4 files changed, 130 insertions, 0 deletions
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
index 6e1bff7..b7a8d4e 100644
--- a/include/sbi/riscv_asm.h
+++ b/include/sbi/riscv_asm.h
@@ -30,6 +30,7 @@
#define LGREG __REG_SEL(3, 2)
#if __SIZEOF_POINTER__ == 8
+#define BITS_PER_LONG 64
#ifdef __ASSEMBLY__
#define RISCV_PTR .dword
#define RISCV_SZPTR 8
@@ -40,6 +41,7 @@
#define RISCV_LGPTR "3"
#endif
#elif __SIZEOF_POINTER__ == 4
+#define BITS_PER_LONG 32
#ifdef __ASSEMBLY__
#define RISCV_PTR .word
#define RISCV_SZPTR 4
diff --git a/include/sbi/riscv_atomic.h b/include/sbi/riscv_atomic.h
index 775cd6f..0fea6bd 100644
--- a/include/sbi/riscv_atomic.h
+++ b/include/sbi/riscv_atomic.h
@@ -34,5 +34,33 @@ long arch_atomic_xchg(atomic_t *atom, long newval);
unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr,
unsigned int newval);
+/**
+ * Set a bit in an atomic variable and return the new value.
+ * @nr : Bit to set.
+ * @atom: atomic variable to modify
+ */
+int atomic_set_bit(int nr, atomic_t *atom);
+
+/**
+ * Clear a bit in an atomic variable and return the new value.
+ * @nr : Bit to set.
+ * @atom: atomic variable to modify
+ */
+
+int atomic_clear_bit(int nr, atomic_t *atom);
+
+/**
+ * Set a bit in any address and return the new value .
+ * @nr : Bit to set.
+ * @addr: Address to modify
+ */
+int atomic_raw_set_bit(int nr, volatile unsigned long *addr);
+
+/**
+ * Clear a bit in any address and return the new value .
+ * @nr : Bit to set.
+ * @addr: Address to modify
+ */
+int atomic_raw_clear_bit(int nr, volatile unsigned long *addr);
#endif
diff --git a/include/sbi/sbi_bitops.h b/include/sbi/sbi_bitops.h
new file mode 100644
index 0000000..c7a6e88
--- /dev/null
+++ b/include/sbi/sbi_bitops.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Atish Patra<atish.patra@wdc.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SBI_BITOPS_H__
+#define __SBI_BITOPS_H__
+
+#include <sbi/sbi_bits.h>
+#include <sbi/riscv_asm.h>
+
+/**
+ * ffs - Find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline int ffs(int x)
+{
+ int r = 1;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff)) {
+ x >>= 16;
+ r += 16;
+ }
+ if (!(x & 0xff)) {
+ x >>= 8;
+ r += 8;
+ }
+ if (!(x & 0xf)) {
+ x >>= 4;
+ r += 4;
+ }
+ if (!(x & 3)) {
+ x >>= 2;
+ r += 2;
+ }
+ if (!(x & 1)) {
+ x >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline int __ffs(unsigned long word)
+{
+ int num = 0;
+
+#if BITS_PER_LONG == 64
+ if ((word & 0xffffffff) == 0) {
+ num += 32;
+ word >>= 32;
+ }
+#endif
+ if ((word & 0xffff) == 0) {
+ num += 16;
+ word >>= 16;
+ }
+ if ((word & 0xff) == 0) {
+ num += 8;
+ word >>= 8;
+ }
+ if ((word & 0xf) == 0) {
+ num += 4;
+ word >>= 4;
+ }
+ if ((word & 0x3) == 0) {
+ num += 2;
+ word >>= 2;
+ }
+ if ((word & 0x1) == 0)
+ num += 1;
+ return num;
+}
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+#define ffz(x) __ffs(~(x))
+
+#endif
diff --git a/include/sbi/sbi_bits.h b/include/sbi/sbi_bits.h
index 2a2f2a5..b9e4a1a 100644
--- a/include/sbi/sbi_bits.h
+++ b/include/sbi/sbi_bits.h
@@ -26,4 +26,6 @@
#define STR(x) XSTR(x)
#define XSTR(x) #x
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#endif