diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2012-01-25 23:38:16 +0000 |
---|---|---|
committer | Vincent Palatin <vpalatin@chromium.org> | 2012-01-26 01:29:48 +0000 |
commit | 4cca2932efc82208b93c7b02fae4ea6c2e4944cd (patch) | |
tree | 5164f354ac39b5bf5db3c81acbe850b59fc1162d /core/cortex-m/atomic.h | |
parent | 9a465855f899b42d91b0ca0b8d3baeabfccce6cf (diff) | |
download | chrome-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.h | 65 |
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 */ |