18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * include/asm/irqflags.h
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * IRQ flags handling
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This file gets included from lowlevel asm headers too, to provide
88c2ecf20Sopenharmony_ci * wrapped versions of the local_irq_*() APIs, based on the
98c2ecf20Sopenharmony_ci * arch_local_irq_*() functions from the lowlevel headers.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#ifndef _ASM_IRQFLAGS_H
128c2ecf20Sopenharmony_ci#define _ASM_IRQFLAGS_H
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <asm/pil.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic inline notrace unsigned long arch_local_save_flags(void)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	unsigned long flags;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	__asm__ __volatile__(
238c2ecf20Sopenharmony_ci		"rdpr	%%pil, %0"
248c2ecf20Sopenharmony_ci		: "=r" (flags)
258c2ecf20Sopenharmony_ci	);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	return flags;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic inline notrace void arch_local_irq_restore(unsigned long flags)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	__asm__ __volatile__(
338c2ecf20Sopenharmony_ci		"wrpr	%0, %%pil"
348c2ecf20Sopenharmony_ci		: /* no output */
358c2ecf20Sopenharmony_ci		: "r" (flags)
368c2ecf20Sopenharmony_ci		: "memory"
378c2ecf20Sopenharmony_ci	);
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic inline notrace void arch_local_irq_disable(void)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	__asm__ __volatile__(
438c2ecf20Sopenharmony_ci		"wrpr	%0, %%pil"
448c2ecf20Sopenharmony_ci		: /* no outputs */
458c2ecf20Sopenharmony_ci		: "i" (PIL_NORMAL_MAX)
468c2ecf20Sopenharmony_ci		: "memory"
478c2ecf20Sopenharmony_ci	);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic inline notrace void arch_local_irq_enable(void)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	__asm__ __volatile__(
538c2ecf20Sopenharmony_ci		"wrpr	0, %%pil"
548c2ecf20Sopenharmony_ci		: /* no outputs */
558c2ecf20Sopenharmony_ci		: /* no inputs */
568c2ecf20Sopenharmony_ci		: "memory"
578c2ecf20Sopenharmony_ci	);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic inline notrace int arch_irqs_disabled_flags(unsigned long flags)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	return (flags > 0);
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic inline notrace int arch_irqs_disabled(void)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	return arch_irqs_disabled_flags(arch_local_save_flags());
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic inline notrace unsigned long arch_local_irq_save(void)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	unsigned long flags, tmp;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* Disable interrupts to PIL_NORMAL_MAX unless we already
758c2ecf20Sopenharmony_ci	 * are using PIL_NMI, in which case PIL_NMI is retained.
768c2ecf20Sopenharmony_ci	 *
778c2ecf20Sopenharmony_ci	 * The only values we ever program into the %pil are 0,
788c2ecf20Sopenharmony_ci	 * PIL_NORMAL_MAX and PIL_NMI.
798c2ecf20Sopenharmony_ci	 *
808c2ecf20Sopenharmony_ci	 * Since PIL_NMI is the largest %pil value and all bits are
818c2ecf20Sopenharmony_ci	 * set in it (0xf), it doesn't matter what PIL_NORMAL_MAX
828c2ecf20Sopenharmony_ci	 * actually is.
838c2ecf20Sopenharmony_ci	 */
848c2ecf20Sopenharmony_ci	__asm__ __volatile__(
858c2ecf20Sopenharmony_ci		"rdpr	%%pil, %0\n\t"
868c2ecf20Sopenharmony_ci		"or	%0, %2, %1\n\t"
878c2ecf20Sopenharmony_ci		"wrpr	%1, 0x0, %%pil"
888c2ecf20Sopenharmony_ci		: "=r" (flags), "=r" (tmp)
898c2ecf20Sopenharmony_ci		: "i" (PIL_NORMAL_MAX)
908c2ecf20Sopenharmony_ci		: "memory"
918c2ecf20Sopenharmony_ci	);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	return flags;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#endif /* (__ASSEMBLY__) */
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#endif /* !(_ASM_IRQFLAGS_H) */
99