summaryrefslogtreecommitdiff
path: root/core/cortex-m0/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/cortex-m0/atomic.h')
-rw-r--r--core/cortex-m0/atomic.h64
1 files changed, 64 insertions, 0 deletions
diff --git a/core/cortex-m0/atomic.h b/core/cortex-m0/atomic.h
new file mode 100644
index 0000000000..ca3d3d47ba
--- /dev/null
+++ b/core/cortex-m0/atomic.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Atomic operations for ARMv6-M */
+
+#ifndef __CROS_EC_ATOMIC_H
+#define __CROS_EC_ATOMIC_H
+
+#include "common.h"
+
+/**
+ * Implements atomic arithmetic operations on 32-bit integers.
+ *
+ * There is no load/store exclusive on ARMv6-M, just disable interrupts
+ */
+#define ATOMIC_OP(asm_op, a, v) do { \
+ uint32_t reg0; \
+ \
+ __asm__ __volatile__(" cpsid i\n" \
+ " ldr %0, [%1]\n" \
+ #asm_op" %0, %0, %2\n" \
+ " str %0, [%1]\n" \
+ " cpsie i\n" \
+ : "=&r" (reg0) \
+ : "r" (a), "r" (v) : "cc"); \
+} while (0)
+
+static inline void atomic_clear(uint32_t *addr, uint32_t bits)
+{
+ ATOMIC_OP(bic, addr, bits);
+}
+
+static inline void atomic_or(uint32_t *addr, uint32_t bits)
+{
+ ATOMIC_OP(orr, addr, bits);
+}
+
+static inline void atomic_add(uint32_t *addr, uint32_t value)
+{
+ ATOMIC_OP(add, addr, value);
+}
+
+static inline void atomic_sub(uint32_t *addr, uint32_t value)
+{
+ ATOMIC_OP(sub, addr, value);
+}
+
+static inline uint32_t atomic_read_clear(uint32_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__(" mov %2, #0\n"
+ " cpsid i\n"
+ " ldr %0, [%1]\n"
+ " str %2, [%1]\n"
+ " cpsie i\n"
+ : "=&r" (ret)
+ : "r" (addr), "r" (0) : "cc");
+
+ return ret;
+}
+#endif /* __CROS_EC_ATOMIC_H */