linux/arch/powerpc/include/asm/hw_irq.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
   4 */
   5#ifndef _ASM_POWERPC_HW_IRQ_H
   6#define _ASM_POWERPC_HW_IRQ_H
   7
   8#ifdef __KERNEL__
   9
  10#include <linux/errno.h>
  11#include <linux/compiler.h>
  12#include <asm/ptrace.h>
  13#include <asm/processor.h>
  14
  15#ifdef CONFIG_PPC64
  16
  17/*
  18 * PACA flags in paca->irq_happened.
  19 *
  20 * This bits are set when interrupts occur while soft-disabled
  21 * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS
  22 * is set whenever we manually hard disable.
  23 */
  24#define PACA_IRQ_HARD_DIS       0x01
  25#define PACA_IRQ_DBELL          0x02
  26#define PACA_IRQ_EE             0x04
  27#define PACA_IRQ_DEC            0x08 /* Or FIT */
  28#define PACA_IRQ_EE_EDGE        0x10 /* BookE only */
  29#define PACA_IRQ_HMI            0x20
  30
  31#endif /* CONFIG_PPC64 */
  32
  33#ifndef __ASSEMBLY__
  34
  35extern void __replay_interrupt(unsigned int vector);
  36
  37extern void timer_interrupt(struct pt_regs *);
  38extern void performance_monitor_exception(struct pt_regs *regs);
  39extern void WatchdogException(struct pt_regs *regs);
  40extern void unknown_exception(struct pt_regs *regs);
  41
  42#ifdef CONFIG_PPC64
  43#include <asm/paca.h>
  44
  45static inline unsigned long arch_local_save_flags(void)
  46{
  47        unsigned long flags;
  48
  49        asm volatile(
  50                "lbz %0,%1(13)"
  51                : "=r" (flags)
  52                : "i" (offsetof(struct paca_struct, soft_enabled)));
  53
  54        return flags;
  55}
  56
  57static inline unsigned long arch_local_irq_disable(void)
  58{
  59        unsigned long flags, zero;
  60
  61        asm volatile(
  62                "li %1,0; lbz %0,%2(13); stb %1,%2(13)"
  63                : "=r" (flags), "=&r" (zero)
  64                : "i" (offsetof(struct paca_struct, soft_enabled))
  65                : "memory");
  66
  67        return flags;
  68}
  69
  70extern void arch_local_irq_restore(unsigned long);
  71
  72static inline void arch_local_irq_enable(void)
  73{
  74        arch_local_irq_restore(1);
  75}
  76
  77static inline unsigned long arch_local_irq_save(void)
  78{
  79        return arch_local_irq_disable();
  80}
  81
  82static inline bool arch_irqs_disabled_flags(unsigned long flags)
  83{
  84        return flags == 0;
  85}
  86
  87static inline bool arch_irqs_disabled(void)
  88{
  89        return arch_irqs_disabled_flags(arch_local_save_flags());
  90}
  91
  92#ifdef CONFIG_PPC_BOOK3E
  93#define __hard_irq_enable()     asm volatile("wrteei 1" : : : "memory")
  94#define __hard_irq_disable()    asm volatile("wrteei 0" : : : "memory")
  95#else
  96#define __hard_irq_enable()     __mtmsrd(local_paca->kernel_msr | MSR_EE, 1)
  97#define __hard_irq_disable()    __mtmsrd(local_paca->kernel_msr, 1)
  98#endif
  99
 100#define hard_irq_disable()      do {                    \
 101        u8 _was_enabled;                                \
 102        __hard_irq_disable();                           \
 103        _was_enabled = local_paca->soft_enabled;        \
 104        local_paca->soft_enabled = 0;                   \
 105        local_paca->irq_happened |= PACA_IRQ_HARD_DIS;  \
 106        if (_was_enabled)                               \
 107                trace_hardirqs_off();                   \
 108} while(0)
 109
 110static inline bool lazy_irq_pending(void)
 111{
 112        return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS);
 113}
 114
 115/*
 116 * This is called by asynchronous interrupts to conditionally
 117 * re-enable hard interrupts when soft-disabled after having
 118 * cleared the source of the interrupt
 119 */
 120static inline void may_hard_irq_enable(void)
 121{
 122        get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
 123        if (!(get_paca()->irq_happened & PACA_IRQ_EE))
 124                __hard_irq_enable();
 125}
 126
 127static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
 128{
 129        return !regs->softe;
 130}
 131
 132extern bool prep_irq_for_idle(void);
 133extern bool prep_irq_for_idle_irqsoff(void);
 134extern void irq_set_pending_from_srr1(unsigned long srr1);
 135
 136#define fini_irq_for_idle_irqsoff() trace_hardirqs_off();
 137
 138extern void force_external_irq_replay(void);
 139
 140#else /* CONFIG_PPC64 */
 141
 142#define SET_MSR_EE(x)   mtmsr(x)
 143
 144static inline unsigned long arch_local_save_flags(void)
 145{
 146        return mfmsr();
 147}
 148
 149static inline void arch_local_irq_restore(unsigned long flags)
 150{
 151#if defined(CONFIG_BOOKE)
 152        asm volatile("wrtee %0" : : "r" (flags) : "memory");
 153#else
 154        mtmsr(flags);
 155#endif
 156}
 157
 158static inline unsigned long arch_local_irq_save(void)
 159{
 160        unsigned long flags = arch_local_save_flags();
 161#ifdef CONFIG_BOOKE
 162        asm volatile("wrteei 0" : : : "memory");
 163#elif defined(CONFIG_PPC_8xx)
 164        wrtspr(SPRN_EID);
 165#else
 166        SET_MSR_EE(flags & ~MSR_EE);
 167#endif
 168        return flags;
 169}
 170
 171static inline void arch_local_irq_disable(void)
 172{
 173#ifdef CONFIG_BOOKE
 174        asm volatile("wrteei 0" : : : "memory");
 175#elif defined(CONFIG_PPC_8xx)
 176        wrtspr(SPRN_EID);
 177#else
 178        arch_local_irq_save();
 179#endif
 180}
 181
 182static inline void arch_local_irq_enable(void)
 183{
 184#ifdef CONFIG_BOOKE
 185        asm volatile("wrteei 1" : : : "memory");
 186#elif defined(CONFIG_PPC_8xx)
 187        wrtspr(SPRN_EIE);
 188#else
 189        unsigned long msr = mfmsr();
 190        SET_MSR_EE(msr | MSR_EE);
 191#endif
 192}
 193
 194static inline bool arch_irqs_disabled_flags(unsigned long flags)
 195{
 196        return (flags & MSR_EE) == 0;
 197}
 198
 199static inline bool arch_irqs_disabled(void)
 200{
 201        return arch_irqs_disabled_flags(arch_local_save_flags());
 202}
 203
 204#define hard_irq_disable()              arch_local_irq_disable()
 205
 206static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
 207{
 208        return !(regs->msr & MSR_EE);
 209}
 210
 211static inline void may_hard_irq_enable(void) { }
 212
 213#endif /* CONFIG_PPC64 */
 214
 215#define ARCH_IRQ_INIT_FLAGS     IRQ_NOREQUEST
 216
 217/*
 218 * interrupt-retrigger: should we handle this via lost interrupts and IPIs
 219 * or should we not care like we do now ? --BenH.
 220 */
 221struct irq_chip;
 222
 223#endif  /* __ASSEMBLY__ */
 224#endif  /* __KERNEL__ */
 225#endif  /* _ASM_POWERPC_HW_IRQ_H */
 226