Files
OpenCellular/core/nds32/atomic.h
Dino Li 911de4d175 nds32: use INT_MASK instead of GIE
When there is an interrupt event, N8 CPU will save PSW register to IPSW
register and clear GIE then jump to interrupt service routine. N8 will
restore PSW from IPSW after "iret" instruction (the above are purely
hardware mechanism).

Nested interrupt will occur if we set GIE again in interrupt context.

symptom:
    power button pressed while LID open -> exception or unknown reset.

Signed-off-by: Dino Li <dino.li@ite.com.tw>

BRANCH=none
BUG=none
TEST=1. Manually pressed power button x200.
     2. Console "eflash" erase and write eflash OK.

Change-Id: Ic04a23d473ebc6417dffea814a27583cb8d63a1f
Reviewed-on: https://chromium-review.googlesource.com/289437
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Commit-Queue: Dino Li <dino.li@ite.com.tw>
Tested-by: Dino Li <dino.li@ite.com.tw>
2015-08-20 01:37:56 +00:00

58 lines
1.2 KiB
C

/* Copyright (c) 2013 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 Andes */
#ifndef __CROS_EC_ATOMIC_H
#define __CROS_EC_ATOMIC_H
#include "common.h"
#include "cpu.h"
#include "task.h"
static inline void atomic_clear(uint32_t volatile *addr, uint32_t bits)
{
uint32_t int_mask = get_int_mask();
interrupt_disable();
*addr &= ~bits;
set_int_mask(int_mask);
}
static inline void atomic_or(uint32_t volatile *addr, uint32_t bits)
{
uint32_t int_mask = get_int_mask();
interrupt_disable();
*addr |= bits;
set_int_mask(int_mask);
}
static inline void atomic_add(uint32_t volatile *addr, uint32_t value)
{
uint32_t int_mask = get_int_mask();
interrupt_disable();
*addr += value;
set_int_mask(int_mask);
}
static inline void atomic_sub(uint32_t volatile *addr, uint32_t value)
{
uint32_t int_mask = get_int_mask();
interrupt_disable();
*addr -= value;
set_int_mask(int_mask);
}
static inline uint32_t atomic_read_clear(uint32_t volatile *addr)
{
uint32_t val;
uint32_t int_mask = get_int_mask();
interrupt_disable();
val = *addr;
*addr = 0;
set_int_mask(int_mask);
return val;
}
#endif /* __CROS_EC_ATOMIC_H */