linux/arch/blackfin/include/asm/irqflags.h
<<
>>
Prefs
   1/*
   2 * interface to Blackfin CEC
   3 *
   4 * Copyright 2009 Analog Devices Inc.
   5 * Licensed under the GPL-2 or later.
   6 */
   7
   8#ifndef __ASM_BFIN_IRQFLAGS_H__
   9#define __ASM_BFIN_IRQFLAGS_H__
  10
  11#include <mach/blackfin.h>
  12
  13#ifdef CONFIG_SMP
  14# include <asm/pda.h>
  15# include <asm/processor.h>
  16# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
  17#else
  18extern unsigned long bfin_irq_flags;
  19#endif
  20
  21static inline notrace void bfin_sti(unsigned long flags)
  22{
  23        asm volatile("sti %0;" : : "d" (flags));
  24}
  25
  26static inline notrace unsigned long bfin_cli(void)
  27{
  28        unsigned long flags;
  29        asm volatile("cli %0;" : "=d" (flags));
  30        return flags;
  31}
  32
  33#ifdef CONFIG_DEBUG_HWERR
  34# define bfin_no_irqs 0x3f
  35#else
  36# define bfin_no_irqs 0x1f
  37#endif
  38
  39/*****************************************************************************/
  40/*
  41 * Hard, untraced CPU interrupt flag manipulation and access.
  42 */
  43static inline notrace void __hard_local_irq_disable(void)
  44{
  45        bfin_cli();
  46}
  47
  48static inline notrace void __hard_local_irq_enable(void)
  49{
  50        bfin_sti(bfin_irq_flags);
  51}
  52
  53static inline notrace unsigned long hard_local_save_flags(void)
  54{
  55        return bfin_read_IMASK();
  56}
  57
  58static inline notrace unsigned long __hard_local_irq_save(void)
  59{
  60        unsigned long flags;
  61        flags = bfin_cli();
  62#ifdef CONFIG_DEBUG_HWERR
  63        bfin_sti(0x3f);
  64#endif
  65        return flags;
  66}
  67
  68static inline notrace int hard_irqs_disabled_flags(unsigned long flags)
  69{
  70#ifdef CONFIG_BF60x
  71        return (flags & IMASK_IVG11) == 0;
  72#else
  73        return (flags & ~0x3f) == 0;
  74#endif
  75}
  76
  77static inline notrace int hard_irqs_disabled(void)
  78{
  79        unsigned long flags = hard_local_save_flags();
  80        return hard_irqs_disabled_flags(flags);
  81}
  82
  83static inline notrace void __hard_local_irq_restore(unsigned long flags)
  84{
  85        if (!hard_irqs_disabled_flags(flags))
  86                __hard_local_irq_enable();
  87}
  88
  89/*****************************************************************************/
  90/*
  91 * Interrupt pipe handling.
  92 */
  93#ifdef CONFIG_IPIPE
  94
  95#include <linux/compiler.h>
  96#include <linux/ipipe_trace.h>
  97/*
  98 * Way too many inter-deps between low-level headers in this port, so
  99 * we redeclare the required bits we cannot pick from
 100 * <asm/ipipe_base.h> to prevent circular dependencies.
 101 */
 102void __ipipe_stall_root(void);
 103void __ipipe_unstall_root(void);
 104unsigned long __ipipe_test_root(void);
 105unsigned long __ipipe_test_and_stall_root(void);
 106void __ipipe_restore_root(unsigned long flags);
 107
 108#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
 109struct ipipe_domain;
 110extern struct ipipe_domain ipipe_root;
 111void ipipe_check_context(struct ipipe_domain *ipd);
 112#define __check_irqop_context(ipd)  ipipe_check_context(&ipipe_root)
 113#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */
 114#define __check_irqop_context(ipd)  do { } while (0)
 115#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */
 116
 117/*
 118 * Interrupt pipe interface to linux/irqflags.h.
 119 */
 120static inline notrace void arch_local_irq_disable(void)
 121{
 122        __check_irqop_context();
 123        __ipipe_stall_root();
 124        barrier();
 125}
 126
 127static inline notrace void arch_local_irq_enable(void)
 128{
 129        barrier();
 130        __check_irqop_context();
 131        __ipipe_unstall_root();
 132}
 133
 134static inline notrace unsigned long arch_local_save_flags(void)
 135{
 136        return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
 137}
 138
 139static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
 140{
 141        return flags == bfin_no_irqs;
 142}
 143
 144static inline notrace unsigned long arch_local_irq_save(void)
 145{
 146        unsigned long flags;
 147
 148        __check_irqop_context();
 149        flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
 150        barrier();
 151
 152        return flags;
 153}
 154
 155static inline notrace void arch_local_irq_restore(unsigned long flags)
 156{
 157        __check_irqop_context();
 158        __ipipe_restore_root(flags == bfin_no_irqs);
 159}
 160
 161static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
 162{
 163        /*
 164         * Merge virtual and real interrupt mask bits into a single
 165         * 32bit word.
 166         */
 167        return (real & ~(1 << 31)) | ((virt != 0) << 31);
 168}
 169
 170static inline notrace int arch_demangle_irq_bits(unsigned long *x)
 171{
 172        int virt = (*x & (1 << 31)) != 0;
 173        *x &= ~(1L << 31);
 174        return virt;
 175}
 176
 177/*
 178 * Interface to various arch routines that may be traced.
 179 */
 180#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
 181static inline notrace void hard_local_irq_disable(void)
 182{
 183        if (!hard_irqs_disabled()) {
 184                __hard_local_irq_disable();
 185                ipipe_trace_begin(0x80000000);
 186        }
 187}
 188
 189static inline notrace void hard_local_irq_enable(void)
 190{
 191        if (hard_irqs_disabled()) {
 192                ipipe_trace_end(0x80000000);
 193                __hard_local_irq_enable();
 194        }
 195}
 196
 197static inline notrace unsigned long hard_local_irq_save(void)
 198{
 199        unsigned long flags = hard_local_save_flags();
 200        if (!hard_irqs_disabled_flags(flags)) {
 201                __hard_local_irq_disable();
 202                ipipe_trace_begin(0x80000001);
 203        }
 204        return flags;
 205}
 206
 207static inline notrace void hard_local_irq_restore(unsigned long flags)
 208{
 209        if (!hard_irqs_disabled_flags(flags)) {
 210                ipipe_trace_end(0x80000001);
 211                __hard_local_irq_enable();
 212        }
 213}
 214
 215#else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 216# define hard_local_irq_disable()       __hard_local_irq_disable()
 217# define hard_local_irq_enable()        __hard_local_irq_enable()
 218# define hard_local_irq_save()          __hard_local_irq_save()
 219# define hard_local_irq_restore(flags)  __hard_local_irq_restore(flags)
 220#endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 221
 222#define hard_local_irq_save_cond()              hard_local_irq_save()
 223#define hard_local_irq_restore_cond(flags)      hard_local_irq_restore(flags)
 224
 225#else /* !CONFIG_IPIPE */
 226
 227/*
 228 * Direct interface to linux/irqflags.h.
 229 */
 230#define arch_local_save_flags()         hard_local_save_flags()
 231#define arch_local_irq_save()           __hard_local_irq_save()
 232#define arch_local_irq_restore(flags)   __hard_local_irq_restore(flags)
 233#define arch_local_irq_enable()         __hard_local_irq_enable()
 234#define arch_local_irq_disable()        __hard_local_irq_disable()
 235#define arch_irqs_disabled_flags(flags) hard_irqs_disabled_flags(flags)
 236#define arch_irqs_disabled()            hard_irqs_disabled()
 237
 238/*
 239 * Interface to various arch routines that may be traced.
 240 */
 241#define hard_local_irq_save()           __hard_local_irq_save()
 242#define hard_local_irq_restore(flags)   __hard_local_irq_restore(flags)
 243#define hard_local_irq_enable()         __hard_local_irq_enable()
 244#define hard_local_irq_disable()        __hard_local_irq_disable()
 245#define hard_local_irq_save_cond()              hard_local_save_flags()
 246#define hard_local_irq_restore_cond(flags)      do { (void)(flags); } while (0)
 247
 248#endif /* !CONFIG_IPIPE */
 249
 250#ifdef CONFIG_SMP
 251#define hard_local_irq_save_smp()               hard_local_irq_save()
 252#define hard_local_irq_restore_smp(flags)       hard_local_irq_restore(flags)
 253#else
 254#define hard_local_irq_save_smp()               hard_local_save_flags()
 255#define hard_local_irq_restore_smp(flags)       do { (void)(flags); } while (0)
 256#endif
 257
 258/*
 259 * Remap the arch-neutral IRQ state manipulation macros to the
 260 * blackfin-specific hard_local_irq_* API.
 261 */
 262#define local_irq_save_hw(flags)                        \
 263        do {                                            \
 264                (flags) = hard_local_irq_save();        \
 265        } while (0)
 266#define local_irq_restore_hw(flags)             \
 267        do {                                    \
 268                hard_local_irq_restore(flags);  \
 269        } while (0)
 270#define local_irq_disable_hw()                  \
 271        do {                                    \
 272                hard_local_irq_disable();       \
 273        } while (0)
 274#define local_irq_enable_hw()                   \
 275        do {                                    \
 276                hard_local_irq_enable();        \
 277        } while (0)
 278#define local_irq_save_hw_notrace(flags)                \
 279        do {                                            \
 280                (flags) = __hard_local_irq_save();      \
 281        } while (0)
 282#define local_irq_restore_hw_notrace(flags)             \
 283        do {                                            \
 284                __hard_local_irq_restore(flags);        \
 285        } while (0)
 286
 287#define irqs_disabled_hw()      hard_irqs_disabled()
 288
 289#endif
 290