18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __ARCH_H8300_ATOMIC__ 38c2ecf20Sopenharmony_ci#define __ARCH_H8300_ATOMIC__ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/compiler.h> 68c2ecf20Sopenharmony_ci#include <linux/types.h> 78c2ecf20Sopenharmony_ci#include <asm/cmpxchg.h> 88c2ecf20Sopenharmony_ci#include <asm/irqflags.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* 118c2ecf20Sopenharmony_ci * Atomic operations that C can't guarantee us. Useful for 128c2ecf20Sopenharmony_ci * resource counting etc.. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define atomic_read(v) READ_ONCE((v)->counter) 168c2ecf20Sopenharmony_ci#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define ATOMIC_OP_RETURN(op, c_op) \ 198c2ecf20Sopenharmony_cistatic inline int atomic_##op##_return(int i, atomic_t *v) \ 208c2ecf20Sopenharmony_ci{ \ 218c2ecf20Sopenharmony_ci h8300flags flags; \ 228c2ecf20Sopenharmony_ci int ret; \ 238c2ecf20Sopenharmony_ci \ 248c2ecf20Sopenharmony_ci flags = arch_local_irq_save(); \ 258c2ecf20Sopenharmony_ci ret = v->counter c_op i; \ 268c2ecf20Sopenharmony_ci arch_local_irq_restore(flags); \ 278c2ecf20Sopenharmony_ci return ret; \ 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define ATOMIC_FETCH_OP(op, c_op) \ 318c2ecf20Sopenharmony_cistatic inline int atomic_fetch_##op(int i, atomic_t *v) \ 328c2ecf20Sopenharmony_ci{ \ 338c2ecf20Sopenharmony_ci h8300flags flags; \ 348c2ecf20Sopenharmony_ci int ret; \ 358c2ecf20Sopenharmony_ci \ 368c2ecf20Sopenharmony_ci flags = arch_local_irq_save(); \ 378c2ecf20Sopenharmony_ci ret = v->counter; \ 388c2ecf20Sopenharmony_ci v->counter c_op i; \ 398c2ecf20Sopenharmony_ci arch_local_irq_restore(flags); \ 408c2ecf20Sopenharmony_ci return ret; \ 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define ATOMIC_OP(op, c_op) \ 448c2ecf20Sopenharmony_cistatic inline void atomic_##op(int i, atomic_t *v) \ 458c2ecf20Sopenharmony_ci{ \ 468c2ecf20Sopenharmony_ci h8300flags flags; \ 478c2ecf20Sopenharmony_ci \ 488c2ecf20Sopenharmony_ci flags = arch_local_irq_save(); \ 498c2ecf20Sopenharmony_ci v->counter c_op i; \ 508c2ecf20Sopenharmony_ci arch_local_irq_restore(flags); \ 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciATOMIC_OP_RETURN(add, +=) 548c2ecf20Sopenharmony_ciATOMIC_OP_RETURN(sub, -=) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, c_op) \ 578c2ecf20Sopenharmony_ci ATOMIC_OP(op, c_op) \ 588c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP(op, c_op) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ciATOMIC_OPS(and, &=) 618c2ecf20Sopenharmony_ciATOMIC_OPS(or, |=) 628c2ecf20Sopenharmony_ciATOMIC_OPS(xor, ^=) 638c2ecf20Sopenharmony_ciATOMIC_OPS(add, +=) 648c2ecf20Sopenharmony_ciATOMIC_OPS(sub, -=) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#undef ATOMIC_OPS 678c2ecf20Sopenharmony_ci#undef ATOMIC_OP_RETURN 688c2ecf20Sopenharmony_ci#undef ATOMIC_OP 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic inline int atomic_cmpxchg(atomic_t *v, int old, int new) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci int ret; 738c2ecf20Sopenharmony_ci h8300flags flags; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci flags = arch_local_irq_save(); 768c2ecf20Sopenharmony_ci ret = v->counter; 778c2ecf20Sopenharmony_ci if (likely(ret == old)) 788c2ecf20Sopenharmony_ci v->counter = new; 798c2ecf20Sopenharmony_ci arch_local_irq_restore(flags); 808c2ecf20Sopenharmony_ci return ret; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline int atomic_fetch_add_unless(atomic_t *v, int a, int u) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci int ret; 868c2ecf20Sopenharmony_ci h8300flags flags; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci flags = arch_local_irq_save(); 898c2ecf20Sopenharmony_ci ret = v->counter; 908c2ecf20Sopenharmony_ci if (ret != u) 918c2ecf20Sopenharmony_ci v->counter += a; 928c2ecf20Sopenharmony_ci arch_local_irq_restore(flags); 938c2ecf20Sopenharmony_ci return ret; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci#define atomic_fetch_add_unless atomic_fetch_add_unless 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#endif /* __ARCH_H8300_ATOMIC __ */ 98