18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __ASM_SH_ATOMIC_IRQ_H
38c2ecf20Sopenharmony_ci#define __ASM_SH_ATOMIC_IRQ_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/irqflags.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci/*
88c2ecf20Sopenharmony_ci * To get proper branch prediction for the main line, we must branch
98c2ecf20Sopenharmony_ci * forward to code at the end of this object's .text section, then
108c2ecf20Sopenharmony_ci * branch back to restart the operation.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define ATOMIC_OP(op, c_op)						\
148c2ecf20Sopenharmony_cistatic inline void atomic_##op(int i, atomic_t *v)			\
158c2ecf20Sopenharmony_ci{									\
168c2ecf20Sopenharmony_ci	unsigned long flags;						\
178c2ecf20Sopenharmony_ci									\
188c2ecf20Sopenharmony_ci	raw_local_irq_save(flags);					\
198c2ecf20Sopenharmony_ci	v->counter c_op i;						\
208c2ecf20Sopenharmony_ci	raw_local_irq_restore(flags);					\
218c2ecf20Sopenharmony_ci}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define ATOMIC_OP_RETURN(op, c_op)					\
248c2ecf20Sopenharmony_cistatic inline int atomic_##op##_return(int i, atomic_t *v)		\
258c2ecf20Sopenharmony_ci{									\
268c2ecf20Sopenharmony_ci	unsigned long temp, flags;					\
278c2ecf20Sopenharmony_ci									\
288c2ecf20Sopenharmony_ci	raw_local_irq_save(flags);					\
298c2ecf20Sopenharmony_ci	temp = v->counter;						\
308c2ecf20Sopenharmony_ci	temp c_op i;							\
318c2ecf20Sopenharmony_ci	v->counter = temp;						\
328c2ecf20Sopenharmony_ci	raw_local_irq_restore(flags);					\
338c2ecf20Sopenharmony_ci									\
348c2ecf20Sopenharmony_ci	return temp;							\
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define ATOMIC_FETCH_OP(op, c_op)					\
388c2ecf20Sopenharmony_cistatic inline int atomic_fetch_##op(int i, atomic_t *v)			\
398c2ecf20Sopenharmony_ci{									\
408c2ecf20Sopenharmony_ci	unsigned long temp, flags;					\
418c2ecf20Sopenharmony_ci									\
428c2ecf20Sopenharmony_ci	raw_local_irq_save(flags);					\
438c2ecf20Sopenharmony_ci	temp = v->counter;						\
448c2ecf20Sopenharmony_ci	v->counter c_op i;						\
458c2ecf20Sopenharmony_ci	raw_local_irq_restore(flags);					\
468c2ecf20Sopenharmony_ci									\
478c2ecf20Sopenharmony_ci	return temp;							\
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, c_op)						\
518c2ecf20Sopenharmony_ci	ATOMIC_OP(op, c_op)						\
528c2ecf20Sopenharmony_ci	ATOMIC_OP_RETURN(op, c_op)					\
538c2ecf20Sopenharmony_ci	ATOMIC_FETCH_OP(op, c_op)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciATOMIC_OPS(add, +=)
568c2ecf20Sopenharmony_ciATOMIC_OPS(sub, -=)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#undef ATOMIC_OPS
598c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, c_op)						\
608c2ecf20Sopenharmony_ci	ATOMIC_OP(op, c_op)						\
618c2ecf20Sopenharmony_ci	ATOMIC_FETCH_OP(op, c_op)
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciATOMIC_OPS(and, &=)
648c2ecf20Sopenharmony_ciATOMIC_OPS(or, |=)
658c2ecf20Sopenharmony_ciATOMIC_OPS(xor, ^=)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#undef ATOMIC_OPS
688c2ecf20Sopenharmony_ci#undef ATOMIC_FETCH_OP
698c2ecf20Sopenharmony_ci#undef ATOMIC_OP_RETURN
708c2ecf20Sopenharmony_ci#undef ATOMIC_OP
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#endif /* __ASM_SH_ATOMIC_IRQ_H */
73