18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_HW_IRQ_H
68c2ecf20Sopenharmony_ci#define _ASM_POWERPC_HW_IRQ_H
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifdef __KERNEL__
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/errno.h>
118c2ecf20Sopenharmony_ci#include <linux/compiler.h>
128c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
138c2ecf20Sopenharmony_ci#include <asm/processor.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * PACA flags in paca->irq_happened.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * This bits are set when interrupts occur while soft-disabled
218c2ecf20Sopenharmony_ci * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS
228c2ecf20Sopenharmony_ci * is set whenever we manually hard disable.
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_ci#define PACA_IRQ_HARD_DIS	0x01
258c2ecf20Sopenharmony_ci#define PACA_IRQ_DBELL		0x02
268c2ecf20Sopenharmony_ci#define PACA_IRQ_EE		0x04
278c2ecf20Sopenharmony_ci#define PACA_IRQ_DEC		0x08 /* Or FIT */
288c2ecf20Sopenharmony_ci#define PACA_IRQ_HMI		0x10
298c2ecf20Sopenharmony_ci#define PACA_IRQ_PMI		0x20
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * Some soft-masked interrupts must be hard masked until they are replayed
338c2ecf20Sopenharmony_ci * (e.g., because the soft-masked handler does not clear the exception).
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
368c2ecf20Sopenharmony_ci#define PACA_IRQ_MUST_HARD_MASK	(PACA_IRQ_EE|PACA_IRQ_PMI)
378c2ecf20Sopenharmony_ci#else
388c2ecf20Sopenharmony_ci#define PACA_IRQ_MUST_HARD_MASK	(PACA_IRQ_EE)
398c2ecf20Sopenharmony_ci#endif
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * flags for paca->irq_soft_mask
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_ci#define IRQS_ENABLED		0
478c2ecf20Sopenharmony_ci#define IRQS_DISABLED		1 /* local_irq_disable() interrupts */
488c2ecf20Sopenharmony_ci#define IRQS_PMI_DISABLED	2
498c2ecf20Sopenharmony_ci#define IRQS_ALL_DISABLED	(IRQS_DISABLED | IRQS_PMI_DISABLED)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ciextern void replay_system_reset(void);
548c2ecf20Sopenharmony_ciextern void replay_soft_interrupts(void);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ciextern void timer_interrupt(struct pt_regs *);
578c2ecf20Sopenharmony_ciextern void timer_broadcast_interrupt(void);
588c2ecf20Sopenharmony_ciextern void performance_monitor_exception(struct pt_regs *regs);
598c2ecf20Sopenharmony_ciextern void WatchdogException(struct pt_regs *regs);
608c2ecf20Sopenharmony_ciextern void unknown_exception(struct pt_regs *regs);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64
638c2ecf20Sopenharmony_ci#include <asm/paca.h>
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic inline notrace unsigned long irq_soft_mask_return(void)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	unsigned long flags;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	asm volatile(
708c2ecf20Sopenharmony_ci		"lbz %0,%1(13)"
718c2ecf20Sopenharmony_ci		: "=r" (flags)
728c2ecf20Sopenharmony_ci		: "i" (offsetof(struct paca_struct, irq_soft_mask)));
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	return flags;
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci/*
788c2ecf20Sopenharmony_ci * The "memory" clobber acts as both a compiler barrier
798c2ecf20Sopenharmony_ci * for the critical section and as a clobber because
808c2ecf20Sopenharmony_ci * we changed paca->irq_soft_mask
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_cistatic inline notrace void irq_soft_mask_set(unsigned long mask)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
858c2ecf20Sopenharmony_ci	/*
868c2ecf20Sopenharmony_ci	 * The irq mask must always include the STD bit if any are set.
878c2ecf20Sopenharmony_ci	 *
888c2ecf20Sopenharmony_ci	 * and interrupts don't get replayed until the standard
898c2ecf20Sopenharmony_ci	 * interrupt (local_irq_disable()) is unmasked.
908c2ecf20Sopenharmony_ci	 *
918c2ecf20Sopenharmony_ci	 * Other masks must only provide additional masking beyond
928c2ecf20Sopenharmony_ci	 * the standard, and they are also not replayed until the
938c2ecf20Sopenharmony_ci	 * standard interrupt becomes unmasked.
948c2ecf20Sopenharmony_ci	 *
958c2ecf20Sopenharmony_ci	 * This could be changed, but it will require partial
968c2ecf20Sopenharmony_ci	 * unmasks to be replayed, among other things. For now, take
978c2ecf20Sopenharmony_ci	 * the simple approach.
988c2ecf20Sopenharmony_ci	 */
998c2ecf20Sopenharmony_ci	WARN_ON(mask && !(mask & IRQS_DISABLED));
1008c2ecf20Sopenharmony_ci#endif
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	asm volatile(
1038c2ecf20Sopenharmony_ci		"stb %0,%1(13)"
1048c2ecf20Sopenharmony_ci		:
1058c2ecf20Sopenharmony_ci		: "r" (mask),
1068c2ecf20Sopenharmony_ci		  "i" (offsetof(struct paca_struct, irq_soft_mask))
1078c2ecf20Sopenharmony_ci		: "memory");
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	unsigned long flags;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
1158c2ecf20Sopenharmony_ci	WARN_ON(mask && !(mask & IRQS_DISABLED));
1168c2ecf20Sopenharmony_ci#endif
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	asm volatile(
1198c2ecf20Sopenharmony_ci		"lbz %0,%1(13); stb %2,%1(13)"
1208c2ecf20Sopenharmony_ci		: "=&r" (flags)
1218c2ecf20Sopenharmony_ci		: "i" (offsetof(struct paca_struct, irq_soft_mask)),
1228c2ecf20Sopenharmony_ci		  "r" (mask)
1238c2ecf20Sopenharmony_ci		: "memory");
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	return flags;
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	unsigned long flags, tmp;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	asm volatile(
1338c2ecf20Sopenharmony_ci		"lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)"
1348c2ecf20Sopenharmony_ci		: "=&r" (flags), "=r" (tmp)
1358c2ecf20Sopenharmony_ci		: "i" (offsetof(struct paca_struct, irq_soft_mask)),
1368c2ecf20Sopenharmony_ci		  "r" (mask)
1378c2ecf20Sopenharmony_ci		: "memory");
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
1408c2ecf20Sopenharmony_ci	WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED));
1418c2ecf20Sopenharmony_ci#endif
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return flags;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_save_flags(void)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	return irq_soft_mask_return();
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic inline void arch_local_irq_disable(void)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	irq_soft_mask_set(IRQS_DISABLED);
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ciextern void arch_local_irq_restore(unsigned long);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic inline void arch_local_irq_enable(void)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	arch_local_irq_restore(IRQS_ENABLED);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_irq_save(void)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	return irq_soft_mask_set_return(IRQS_DISABLED);
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled_flags(unsigned long flags)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	return flags & IRQS_DISABLED;
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled(void)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	return arch_irqs_disabled_flags(arch_local_save_flags());
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic inline void set_pmi_irq_pending(void)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	/*
1818c2ecf20Sopenharmony_ci	 * Invoked from PMU callback functions to set PMI bit in the paca.
1828c2ecf20Sopenharmony_ci	 * This has to be called with irq's disabled (via hard_irq_disable()).
1838c2ecf20Sopenharmony_ci	 */
1848c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
1858c2ecf20Sopenharmony_ci		WARN_ON_ONCE(mfmsr() & MSR_EE);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	get_paca()->irq_happened |= PACA_IRQ_PMI;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic inline void clear_pmi_irq_pending(void)
1918c2ecf20Sopenharmony_ci{
1928c2ecf20Sopenharmony_ci	/*
1938c2ecf20Sopenharmony_ci	 * Invoked from PMU callback functions to clear the pending PMI bit
1948c2ecf20Sopenharmony_ci	 * in the paca.
1958c2ecf20Sopenharmony_ci	 */
1968c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
1978c2ecf20Sopenharmony_ci		WARN_ON_ONCE(mfmsr() & MSR_EE);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	get_paca()->irq_happened &= ~PACA_IRQ_PMI;
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic inline bool pmi_irq_pending(void)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	/*
2058c2ecf20Sopenharmony_ci	 * Invoked from PMU callback functions to check if there is a pending
2068c2ecf20Sopenharmony_ci	 * PMI bit in the paca.
2078c2ecf20Sopenharmony_ci	 */
2088c2ecf20Sopenharmony_ci	if (get_paca()->irq_happened & PACA_IRQ_PMI)
2098c2ecf20Sopenharmony_ci		return true;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	return false;
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
2158c2ecf20Sopenharmony_ci/*
2168c2ecf20Sopenharmony_ci * To support disabling and enabling of irq with PMI, set of
2178c2ecf20Sopenharmony_ci * new powerpc_local_irq_pmu_save() and powerpc_local_irq_restore()
2188c2ecf20Sopenharmony_ci * functions are added. These macros are implemented using generic
2198c2ecf20Sopenharmony_ci * linux local_irq_* code from include/linux/irqflags.h.
2208c2ecf20Sopenharmony_ci */
2218c2ecf20Sopenharmony_ci#define raw_local_irq_pmu_save(flags)					\
2228c2ecf20Sopenharmony_ci	do {								\
2238c2ecf20Sopenharmony_ci		typecheck(unsigned long, flags);			\
2248c2ecf20Sopenharmony_ci		flags = irq_soft_mask_or_return(IRQS_DISABLED |	\
2258c2ecf20Sopenharmony_ci				IRQS_PMI_DISABLED);			\
2268c2ecf20Sopenharmony_ci	} while(0)
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci#define raw_local_irq_pmu_restore(flags)				\
2298c2ecf20Sopenharmony_ci	do {								\
2308c2ecf20Sopenharmony_ci		typecheck(unsigned long, flags);			\
2318c2ecf20Sopenharmony_ci		arch_local_irq_restore(flags);				\
2328c2ecf20Sopenharmony_ci	} while(0)
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci#ifdef CONFIG_TRACE_IRQFLAGS
2358c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_save(flags)			\
2368c2ecf20Sopenharmony_ci	 do {							\
2378c2ecf20Sopenharmony_ci		raw_local_irq_pmu_save(flags);			\
2388c2ecf20Sopenharmony_ci		if (!raw_irqs_disabled_flags(flags))		\
2398c2ecf20Sopenharmony_ci			trace_hardirqs_off();			\
2408c2ecf20Sopenharmony_ci	} while(0)
2418c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_restore(flags)			\
2428c2ecf20Sopenharmony_ci	do {							\
2438c2ecf20Sopenharmony_ci		if (!raw_irqs_disabled_flags(flags))		\
2448c2ecf20Sopenharmony_ci			trace_hardirqs_on();			\
2458c2ecf20Sopenharmony_ci		raw_local_irq_pmu_restore(flags);		\
2468c2ecf20Sopenharmony_ci	} while(0)
2478c2ecf20Sopenharmony_ci#else
2488c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_save(flags)			\
2498c2ecf20Sopenharmony_ci	do {							\
2508c2ecf20Sopenharmony_ci		raw_local_irq_pmu_save(flags);			\
2518c2ecf20Sopenharmony_ci	} while(0)
2528c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_restore(flags)			\
2538c2ecf20Sopenharmony_ci	do {							\
2548c2ecf20Sopenharmony_ci		raw_local_irq_pmu_restore(flags);		\
2558c2ecf20Sopenharmony_ci	} while (0)
2568c2ecf20Sopenharmony_ci#endif  /* CONFIG_TRACE_IRQFLAGS */
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S */
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3E
2618c2ecf20Sopenharmony_ci#define __hard_irq_enable()	wrtee(MSR_EE)
2628c2ecf20Sopenharmony_ci#define __hard_irq_disable()	wrtee(0)
2638c2ecf20Sopenharmony_ci#define __hard_EE_RI_disable()	wrtee(0)
2648c2ecf20Sopenharmony_ci#define __hard_RI_enable()	do { } while (0)
2658c2ecf20Sopenharmony_ci#else
2668c2ecf20Sopenharmony_ci#define __hard_irq_enable()	__mtmsrd(MSR_EE|MSR_RI, 1)
2678c2ecf20Sopenharmony_ci#define __hard_irq_disable()	__mtmsrd(MSR_RI, 1)
2688c2ecf20Sopenharmony_ci#define __hard_EE_RI_disable()	__mtmsrd(0, 1)
2698c2ecf20Sopenharmony_ci#define __hard_RI_enable()	__mtmsrd(MSR_RI, 1)
2708c2ecf20Sopenharmony_ci#endif
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#define hard_irq_disable()	do {					\
2738c2ecf20Sopenharmony_ci	unsigned long flags;						\
2748c2ecf20Sopenharmony_ci	__hard_irq_disable();						\
2758c2ecf20Sopenharmony_ci	flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED);		\
2768c2ecf20Sopenharmony_ci	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;			\
2778c2ecf20Sopenharmony_ci	if (!arch_irqs_disabled_flags(flags)) {				\
2788c2ecf20Sopenharmony_ci		asm ("stdx %%r1, 0, %1 ;"				\
2798c2ecf20Sopenharmony_ci		     : "=m" (local_paca->saved_r1)			\
2808c2ecf20Sopenharmony_ci		     : "b" (&local_paca->saved_r1));			\
2818c2ecf20Sopenharmony_ci		trace_hardirqs_off();					\
2828c2ecf20Sopenharmony_ci	}								\
2838c2ecf20Sopenharmony_ci} while(0)
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic inline bool __lazy_irq_pending(u8 irq_happened)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	return !!(irq_happened & ~PACA_IRQ_HARD_DIS);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci/*
2918c2ecf20Sopenharmony_ci * Check if a lazy IRQ is pending. Should be called with IRQs hard disabled.
2928c2ecf20Sopenharmony_ci */
2938c2ecf20Sopenharmony_cistatic inline bool lazy_irq_pending(void)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	return __lazy_irq_pending(get_paca()->irq_happened);
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci/*
2998c2ecf20Sopenharmony_ci * Check if a lazy IRQ is pending, with no debugging checks.
3008c2ecf20Sopenharmony_ci * Should be called with IRQs hard disabled.
3018c2ecf20Sopenharmony_ci * For use in RI disabled code or other constrained situations.
3028c2ecf20Sopenharmony_ci */
3038c2ecf20Sopenharmony_cistatic inline bool lazy_irq_pending_nocheck(void)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	return __lazy_irq_pending(local_paca->irq_happened);
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci/*
3098c2ecf20Sopenharmony_ci * This is called by asynchronous interrupts to conditionally
3108c2ecf20Sopenharmony_ci * re-enable hard interrupts after having cleared the source
3118c2ecf20Sopenharmony_ci * of the interrupt. They are kept disabled if there is a different
3128c2ecf20Sopenharmony_ci * soft-masked interrupt pending that requires hard masking.
3138c2ecf20Sopenharmony_ci */
3148c2ecf20Sopenharmony_cistatic inline void may_hard_irq_enable(void)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	if (!(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK)) {
3178c2ecf20Sopenharmony_ci		get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
3188c2ecf20Sopenharmony_ci		__hard_irq_enable();
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic inline bool arch_irq_disabled_regs(struct pt_regs *regs)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	return (regs->softe & IRQS_DISABLED);
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ciextern bool prep_irq_for_idle(void);
3288c2ecf20Sopenharmony_ciextern bool prep_irq_for_idle_irqsoff(void);
3298c2ecf20Sopenharmony_ciextern void irq_set_pending_from_srr1(unsigned long srr1);
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci#define fini_irq_for_idle_irqsoff() trace_hardirqs_off();
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ciextern void force_external_irq_replay(void);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cistatic inline void irq_soft_mask_regs_set_state(struct pt_regs *regs, unsigned long val)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	regs->softe = val;
3388c2ecf20Sopenharmony_ci}
3398c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_save_flags(void)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	return mfmsr();
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic inline void arch_local_irq_restore(unsigned long flags)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_BOOKE))
3498c2ecf20Sopenharmony_ci		wrtee(flags);
3508c2ecf20Sopenharmony_ci	else
3518c2ecf20Sopenharmony_ci		mtmsr(flags);
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_irq_save(void)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	unsigned long flags = arch_local_save_flags();
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_BOOKE))
3598c2ecf20Sopenharmony_ci		wrtee(0);
3608c2ecf20Sopenharmony_ci	else if (IS_ENABLED(CONFIG_PPC_8xx))
3618c2ecf20Sopenharmony_ci		wrtspr(SPRN_EID);
3628c2ecf20Sopenharmony_ci	else
3638c2ecf20Sopenharmony_ci		mtmsr(flags & ~MSR_EE);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	return flags;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic inline void arch_local_irq_disable(void)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_BOOKE))
3718c2ecf20Sopenharmony_ci		wrtee(0);
3728c2ecf20Sopenharmony_ci	else if (IS_ENABLED(CONFIG_PPC_8xx))
3738c2ecf20Sopenharmony_ci		wrtspr(SPRN_EID);
3748c2ecf20Sopenharmony_ci	else
3758c2ecf20Sopenharmony_ci		mtmsr(mfmsr() & ~MSR_EE);
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic inline void arch_local_irq_enable(void)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_BOOKE))
3818c2ecf20Sopenharmony_ci		wrtee(MSR_EE);
3828c2ecf20Sopenharmony_ci	else if (IS_ENABLED(CONFIG_PPC_8xx))
3838c2ecf20Sopenharmony_ci		wrtspr(SPRN_EIE);
3848c2ecf20Sopenharmony_ci	else
3858c2ecf20Sopenharmony_ci		mtmsr(mfmsr() | MSR_EE);
3868c2ecf20Sopenharmony_ci}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled_flags(unsigned long flags)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	return (flags & MSR_EE) == 0;
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled(void)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	return arch_irqs_disabled_flags(arch_local_save_flags());
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci#define hard_irq_disable()		arch_local_irq_disable()
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_cistatic inline bool arch_irq_disabled_regs(struct pt_regs *regs)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	return !(regs->msr & MSR_EE);
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic inline void may_hard_irq_enable(void) { }
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistatic inline void clear_pmi_irq_pending(void) { }
4088c2ecf20Sopenharmony_cistatic inline void set_pmi_irq_pending(void) { }
4098c2ecf20Sopenharmony_cistatic inline bool pmi_irq_pending(void) { return false; }
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic inline void irq_soft_mask_regs_set_state(struct pt_regs *regs, unsigned long val)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci#define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci#endif  /* __ASSEMBLY__ */
4198c2ecf20Sopenharmony_ci#endif	/* __KERNEL__ */
4208c2ecf20Sopenharmony_ci#endif	/* _ASM_POWERPC_HW_IRQ_H */
421