linux/arch/frv/include/asm/irqflags.h
<<
>>
Prefs
   1/* FR-V interrupt handling
   2 *
   3 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public Licence
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the Licence, or (at your option) any later version.
  10 */
  11
  12#ifndef _ASM_IRQFLAGS_H
  13#define _ASM_IRQFLAGS_H
  14
  15/*
  16 * interrupt flag manipulation
  17 * - use virtual interrupt management since touching the PSR is slow
  18 *   - ICC2.Z: T if interrupts virtually disabled
  19 *   - ICC2.C: F if interrupts really disabled
  20 * - if Z==1 upon interrupt:
  21 *   - C is set to 0
  22 *   - interrupts are really disabled
  23 *   - entry.S returns immediately
  24 * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
  25 *   - if taken, the trap:
  26 *     - sets ICC2.C
  27 *     - enables interrupts
  28 */
  29static inline void arch_local_irq_disable(void)
  30{
  31        /* set Z flag, but don't change the C flag */
  32        asm volatile("  andcc   gr0,gr0,gr0,icc2        \n"
  33                     :
  34                     :
  35                     : "memory", "icc2"
  36                     );
  37}
  38
  39static inline void arch_local_irq_enable(void)
  40{
  41        /* clear Z flag and then test the C flag */
  42        asm volatile("  oricc   gr0,#1,gr0,icc2         \n"
  43                     "  tihi    icc2,gr0,#2             \n"
  44                     :
  45                     :
  46                     : "memory", "icc2"
  47                     );
  48}
  49
  50static inline unsigned long arch_local_save_flags(void)
  51{
  52        unsigned long flags;
  53
  54        asm volatile("movsg ccr,%0"
  55                     : "=r"(flags)
  56                     :
  57                     : "memory");
  58
  59        /* shift ICC2.Z to bit 0 */
  60        flags >>= 26;
  61
  62        /* make flags 1 if interrupts disabled, 0 otherwise */
  63        return flags & 1UL;
  64
  65}
  66
  67static inline unsigned long arch_local_irq_save(void)
  68{
  69        unsigned long flags = arch_local_save_flags();
  70        arch_local_irq_disable();
  71        return flags;
  72}
  73
  74static inline void arch_local_irq_restore(unsigned long flags)
  75{
  76        /* load the Z flag by turning 1 if disabled into 0 if disabled
  77         * and thus setting the Z flag but not the C flag */
  78        asm volatile("  xoricc  %0,#1,gr0,icc2          \n"
  79                     /* then trap if Z=0 and C=0 */
  80                     "  tihi    icc2,gr0,#2             \n"
  81                     :
  82                     : "r"(flags)
  83                     : "memory", "icc2"
  84                     );
  85
  86}
  87
  88static inline bool arch_irqs_disabled_flags(unsigned long flags)
  89{
  90        return flags;
  91}
  92
  93static inline bool arch_irqs_disabled(void)
  94{
  95        return arch_irqs_disabled_flags(arch_local_save_flags());
  96}
  97
  98/*
  99 * real interrupt flag manipulation
 100 */
 101#define __arch_local_irq_disable()                      \
 102do {                                                    \
 103        unsigned long psr;                              \
 104        asm volatile("  movsg   psr,%0          \n"     \
 105                     "  andi    %0,%2,%0        \n"     \
 106                     "  ori     %0,%1,%0        \n"     \
 107                     "  movgs   %0,psr          \n"     \
 108                     : "=r"(psr)                        \
 109                     : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
 110                     : "memory");                       \
 111} while (0)
 112
 113#define __arch_local_irq_enable()                       \
 114do {                                                    \
 115        unsigned long psr;                              \
 116        asm volatile("  movsg   psr,%0          \n"     \
 117                     "  andi    %0,%1,%0        \n"     \
 118                     "  movgs   %0,psr          \n"     \
 119                     : "=r"(psr)                        \
 120                     : "i" (~PSR_PIL)                   \
 121                     : "memory");                       \
 122} while (0)
 123
 124#define __arch_local_save_flags(flags)          \
 125do {                                            \
 126        typecheck(unsigned long, flags);        \
 127        asm("movsg psr,%0"                      \
 128            : "=r"(flags)                       \
 129            :                                   \
 130            : "memory");                        \
 131} while (0)
 132
 133#define __arch_local_irq_save(flags)                    \
 134do {                                                    \
 135        unsigned long npsr;                             \
 136        typecheck(unsigned long, flags);                \
 137        asm volatile("  movsg   psr,%0          \n"     \
 138                     "  andi    %0,%3,%1        \n"     \
 139                     "  ori     %1,%2,%1        \n"     \
 140                     "  movgs   %1,psr          \n"     \
 141                     : "=r"(flags), "=r"(npsr)          \
 142                     : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
 143                     : "memory");                       \
 144} while (0)
 145
 146#define __arch_local_irq_restore(flags)                 \
 147do {                                                    \
 148        typecheck(unsigned long, flags);                \
 149        asm volatile("  movgs   %0,psr          \n"     \
 150                     :                                  \
 151                     : "r" (flags)                      \
 152                     : "memory");                       \
 153} while (0)
 154
 155#define __arch_irqs_disabled()                  \
 156        ((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
 157
 158#endif /* _ASM_IRQFLAGS_H */
 159