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