18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __ASM_LSE_H
38c2ecf20Sopenharmony_ci#define __ASM_LSE_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <asm/atomic_ll_sc.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_LSE_ATOMICS
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define __LSE_PREAMBLE	".arch_extension lse\n"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/compiler_types.h>
128c2ecf20Sopenharmony_ci#include <linux/export.h>
138c2ecf20Sopenharmony_ci#include <linux/jump_label.h>
148c2ecf20Sopenharmony_ci#include <linux/stringify.h>
158c2ecf20Sopenharmony_ci#include <asm/alternative.h>
168c2ecf20Sopenharmony_ci#include <asm/atomic_lse.h>
178c2ecf20Sopenharmony_ci#include <asm/cpucaps.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciextern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
208c2ecf20Sopenharmony_ciextern struct static_key_false arm64_const_caps_ready;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic inline bool system_uses_lse_atomics(void)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	return (static_branch_likely(&arm64_const_caps_ready)) &&
258c2ecf20Sopenharmony_ci		static_branch_likely(&cpu_hwcap_keys[ARM64_HAS_LSE_ATOMICS]);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define __lse_ll_sc_body(op, ...)					\
298c2ecf20Sopenharmony_ci({									\
308c2ecf20Sopenharmony_ci	system_uses_lse_atomics() ?					\
318c2ecf20Sopenharmony_ci		__lse_##op(__VA_ARGS__) :				\
328c2ecf20Sopenharmony_ci		__ll_sc_##op(__VA_ARGS__);				\
338c2ecf20Sopenharmony_ci})
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* In-line patching at runtime */
368c2ecf20Sopenharmony_ci#define ARM64_LSE_ATOMIC_INSN(llsc, lse)				\
378c2ecf20Sopenharmony_ci	ALTERNATIVE(llsc, __LSE_PREAMBLE lse, ARM64_HAS_LSE_ATOMICS)
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#else	/* CONFIG_ARM64_LSE_ATOMICS */
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic inline bool system_uses_lse_atomics(void) { return false; }
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define __lse_ll_sc_body(op, ...)		__ll_sc_##op(__VA_ARGS__)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define ARM64_LSE_ATOMIC_INSN(llsc, lse)	llsc
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#endif	/* CONFIG_ARM64_LSE_ATOMICS */
488c2ecf20Sopenharmony_ci#endif	/* __ASM_LSE_H */
49