hw_irq.h 5.6 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
L
Linus Torvalds 已提交
2 3 4
/*
 * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
 */
K
Kumar Gala 已提交
5 6 7
#ifndef _ASM_POWERPC_HW_IRQ_H
#define _ASM_POWERPC_HW_IRQ_H

L
Linus Torvalds 已提交
8 9 10
#ifdef __KERNEL__

#include <linux/errno.h>
11
#include <linux/compiler.h>
K
Kumar Gala 已提交
12 13
#include <asm/ptrace.h>
#include <asm/processor.h>
L
Linus Torvalds 已提交
14

15 16 17 18 19 20 21 22 23 24 25 26 27 28
#ifdef CONFIG_PPC64

/*
 * PACA flags in paca->irq_happened.
 *
 * This bits are set when interrupts occur while soft-disabled
 * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS
 * is set whenever we manually hard disable.
 */
#define PACA_IRQ_HARD_DIS	0x01
#define PACA_IRQ_DBELL		0x02
#define PACA_IRQ_EE		0x04
#define PACA_IRQ_DEC		0x08 /* Or FIT */
#define PACA_IRQ_EE_EDGE	0x10 /* BookE only */
29
#define PACA_IRQ_HMI		0x20
30

31 32 33 34 35 36
/*
 * flags for paca->soft_enabled
 */
#define IRQS_ENABLED	1
#define IRQS_DISABLED	0

37 38 39 40
#endif /* CONFIG_PPC64 */

#ifndef __ASSEMBLY__

41
extern void replay_system_reset(void);
42 43
extern void __replay_interrupt(unsigned int vector);

44
extern void timer_interrupt(struct pt_regs *);
45
extern void performance_monitor_exception(struct pt_regs *regs);
46 47
extern void WatchdogException(struct pt_regs *regs);
extern void unknown_exception(struct pt_regs *regs);
L
Linus Torvalds 已提交
48

49 50 51
#ifdef CONFIG_PPC64
#include <asm/paca.h>

52 53 54 55 56 57 58 59 60 61 62 63
static inline notrace unsigned long soft_enabled_return(void)
{
	unsigned long flags;

	asm volatile(
		"lbz %0,%1(13)"
		: "=r" (flags)
		: "i" (offsetof(struct paca_struct, soft_enabled)));

	return flags;
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
/*
 * The "memory" clobber acts as both a compiler barrier
 * for the critical section and as a clobber because
 * we changed paca->soft_enabled
 */
static inline notrace void soft_enabled_set(unsigned long enable)
{
	asm volatile(
		"stb %0,%1(13)"
		:
		: "r" (enable),
		  "i" (offsetof(struct paca_struct, soft_enabled))
		: "memory");
}

D
David Howells 已提交
79
static inline unsigned long arch_local_save_flags(void)
80
{
81
	return soft_enabled_return();
82 83
}

84
static inline void arch_local_irq_disable(void)
85
{
86
	soft_enabled_set(IRQS_DISABLED);
87
}
L
Linus Torvalds 已提交
88

D
David Howells 已提交
89
extern void arch_local_irq_restore(unsigned long);
L
Linus Torvalds 已提交
90

D
David Howells 已提交
91 92
static inline void arch_local_irq_enable(void)
{
93
	arch_local_irq_restore(IRQS_ENABLED);
D
David Howells 已提交
94 95 96 97
}

static inline unsigned long arch_local_irq_save(void)
{
98 99 100 101 102 103 104 105 106 107
	unsigned long flags;

	asm volatile(
		"lbz %0,%1(13); stb %2,%1(13)"
		: "=&r" (flags)
		: "i" (offsetof(struct paca_struct, soft_enabled)),
		  "r" (IRQS_DISABLED)
		: "memory");

	return flags;
D
David Howells 已提交
108 109 110 111
}

static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
112
	return flags == IRQS_DISABLED;
D
David Howells 已提交
113
}
L
Linus Torvalds 已提交
114

D
David Howells 已提交
115 116 117 118
static inline bool arch_irqs_disabled(void)
{
	return arch_irqs_disabled_flags(arch_local_save_flags());
}
L
Linus Torvalds 已提交
119

120
#ifdef CONFIG_PPC_BOOK3E
121 122
#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory")
#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory")
123
#else
124 125
#define __hard_irq_enable()	__mtmsrd(local_paca->kernel_msr | MSR_EE, 1)
#define __hard_irq_disable()	__mtmsrd(local_paca->kernel_msr, 1)
126
#endif
127

128
#define hard_irq_disable()	do {			\
129
	u8 _was_enabled;				\
130
	__hard_irq_disable();				\
131
	_was_enabled = local_paca->soft_enabled;	\
132
	local_paca->soft_enabled = IRQS_DISABLED;\
133
	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;	\
134
	if (_was_enabled == IRQS_ENABLED)	\
135
		trace_hardirqs_off();			\
136
} while(0)
137

138 139 140 141 142
static inline bool lazy_irq_pending(void)
{
	return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS);
}

143 144 145 146 147 148 149 150 151 152 153
/*
 * This is called by asynchronous interrupts to conditionally
 * re-enable hard interrupts when soft-disabled after having
 * cleared the source of the interrupt
 */
static inline void may_hard_irq_enable(void)
{
	get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
	if (!(get_paca()->irq_happened & PACA_IRQ_EE))
		__hard_irq_enable();
}
154

155 156
static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
{
157
	return (regs->softe == IRQS_DISABLED);
158 159
}

160
extern bool prep_irq_for_idle(void);
161
extern bool prep_irq_for_idle_irqsoff(void);
162
extern void irq_set_pending_from_srr1(unsigned long srr1);
163 164

#define fini_irq_for_idle_irqsoff() trace_hardirqs_off();
165

166 167
extern void force_external_irq_replay(void);

D
David Howells 已提交
168
#else /* CONFIG_PPC64 */
L
Linus Torvalds 已提交
169

K
Kumar Gala 已提交
170
#define SET_MSR_EE(x)	mtmsr(x)
D
David Howells 已提交
171 172 173 174 175 176 177 178 179 180

static inline unsigned long arch_local_save_flags(void)
{
	return mfmsr();
}

static inline void arch_local_irq_restore(unsigned long flags)
{
#if defined(CONFIG_BOOKE)
	asm volatile("wrtee %0" : : "r" (flags) : "memory");
K
Kumar Gala 已提交
181
#else
D
David Howells 已提交
182
	mtmsr(flags);
K
Kumar Gala 已提交
183
#endif
D
David Howells 已提交
184
}
L
Linus Torvalds 已提交
185

D
David Howells 已提交
186
static inline unsigned long arch_local_irq_save(void)
L
Linus Torvalds 已提交
187
{
D
David Howells 已提交
188
	unsigned long flags = arch_local_save_flags();
K
Kumar Gala 已提交
189
#ifdef CONFIG_BOOKE
D
David Howells 已提交
190
	asm volatile("wrteei 0" : : : "memory");
191 192
#elif defined(CONFIG_PPC_8xx)
	wrtspr(SPRN_EID);
K
Kumar Gala 已提交
193
#else
D
David Howells 已提交
194
	SET_MSR_EE(flags & ~MSR_EE);
K
Kumar Gala 已提交
195
#endif
D
David Howells 已提交
196
	return flags;
L
Linus Torvalds 已提交
197 198
}

D
David Howells 已提交
199
static inline void arch_local_irq_disable(void)
L
Linus Torvalds 已提交
200
{
K
Kumar Gala 已提交
201
#ifdef CONFIG_BOOKE
D
David Howells 已提交
202
	asm volatile("wrteei 0" : : : "memory");
203 204
#elif defined(CONFIG_PPC_8xx)
	wrtspr(SPRN_EID);
K
Kumar Gala 已提交
205
#else
D
David Howells 已提交
206
	arch_local_irq_save();
K
Kumar Gala 已提交
207
#endif
L
Linus Torvalds 已提交
208 209
}

D
David Howells 已提交
210
static inline void arch_local_irq_enable(void)
L
Linus Torvalds 已提交
211
{
K
Kumar Gala 已提交
212
#ifdef CONFIG_BOOKE
D
David Howells 已提交
213
	asm volatile("wrteei 1" : : : "memory");
214 215
#elif defined(CONFIG_PPC_8xx)
	wrtspr(SPRN_EIE);
K
Kumar Gala 已提交
216
#else
D
David Howells 已提交
217 218
	unsigned long msr = mfmsr();
	SET_MSR_EE(msr | MSR_EE);
K
Kumar Gala 已提交
219
#endif
L
Linus Torvalds 已提交
220 221
}

D
David Howells 已提交
222
static inline bool arch_irqs_disabled_flags(unsigned long flags)
223 224 225 226
{
	return (flags & MSR_EE) == 0;
}

D
David Howells 已提交
227 228 229 230 231 232 233
static inline bool arch_irqs_disabled(void)
{
	return arch_irqs_disabled_flags(arch_local_save_flags());
}

#define hard_irq_disable()		arch_local_irq_disable()

234 235 236 237 238
static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
{
	return !(regs->msr & MSR_EE);
}

239 240
static inline void may_hard_irq_enable(void) { }

241
#endif /* CONFIG_PPC64 */
L
Linus Torvalds 已提交
242

243 244
#define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST

245 246 247
/*
 * interrupt-retrigger: should we handle this via lost interrupts and IPIs
 * or should we not care like we do now ? --BenH.
L
Linus Torvalds 已提交
248
 */
249
struct irq_chip;
K
Kumar Gala 已提交
250

251
#endif  /* __ASSEMBLY__ */
K
Kumar Gala 已提交
252 253
#endif	/* __KERNEL__ */
#endif	/* _ASM_POWERPC_HW_IRQ_H */