summaryrefslogtreecommitdiff
path: root/core/cortex-m/atomic.h
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-01-25 23:38:16 +0000
committerVincent Palatin <vpalatin@chromium.org>2012-01-26 01:29:48 +0000
commit4cca2932efc82208b93c7b02fae4ea6c2e4944cd (patch)
tree5164f354ac39b5bf5db3c81acbe850b59fc1162d /core/cortex-m/atomic.h
parent9a465855f899b42d91b0ca0b8d3baeabfccce6cf (diff)
downloadchrome-ec-4cca2932efc82208b93c7b02fae4ea6c2e4944cd.tar.gz
Move SoC-independant headers to another directory
Preparatory work to introduce a second SoC : 2nd series 1/4 The atomic operations are SoC independant since they are only using LDREX/STREX instructions which are just core specific ARMv7-M). The watchdog header defines the API which is common to all platforms. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BUG=None TEST=run EC firmware on BDS and check a few console commands
Diffstat (limited to 'core/cortex-m/atomic.h')
-rw-r--r--core/cortex-m/atomic.h65
1 files changed, 65 insertions, 0 deletions
diff --git a/core/cortex-m/atomic.h b/core/cortex-m/atomic.h
new file mode 100644
index 0000000000..a6fff4be08
--- /dev/null
+++ b/core/cortex-m/atomic.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2011 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 ARMv7 */
+
+#ifndef __ATOMIC_H
+#define __ATOMIC_H
+
+/**
+ * Implements atomic arithmetic operations on 32-bit integers.
+ *
+ * It used load/store exclusive.
+ * If you write directly the integer used as an atomic variable,
+ * you must either clear explicitly the exclusive monitor (using clrex)
+ * or do it in exception context (which clears the monitor).
+ */
+#define ATOMIC_OP(asm_op,a,v) do { \
+ uint32_t reg0, reg1; \
+ \
+ __asm__ __volatile__("1: ldrex %0, [%2]\n" \
+ #asm_op" %0, %0, %3\n" \
+ " strex %1, %0, [%2]\n" \
+ " teq %1, #0\n" \
+ " bne 1b" \
+ : "=&r" (reg0), "=&r" (reg1) \
+ : "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, tmp;
+
+ __asm__ __volatile__(" mov %3, #0\n"
+ "1: ldrex %0, [%2]\n"
+ " strex %1, %3, [%2]\n"
+ " teq %1, #0\n"
+ " bne 1b"
+ : "=&r" (ret), "=&r" (tmp)
+ : "r" (addr), "r" (0) : "cc");
+
+ return ret;
+}
+#endif /* __ATOMIC_H */