linux/arch/mn10300/include/asm/irqflags.h
<<
>>
Prefs
   1/* MN10300 IRQ flag 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#include <asm/cpu-regs.h>
  16#ifndef __ASSEMBLY__
  17#include <linux/smp.h>
  18#endif
  19
  20/*
  21 * interrupt control
  22 * - "disabled": run in IM1/2
  23 *   - level 0 - kernel debugger
  24 *   - level 1 - virtual serial DMA (if present)
  25 *   - level 5 - normal interrupt priority
  26 *   - level 6 - timer interrupt
  27 * - "enabled":  run in IM7
  28 */
  29#define MN10300_CLI_LEVEL       (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
  30
  31#ifndef __ASSEMBLY__
  32
  33static inline unsigned long arch_local_save_flags(void)
  34{
  35        unsigned long flags;
  36
  37        asm volatile("mov epsw,%0" : "=d"(flags));
  38        return flags;
  39}
  40
  41static inline void arch_local_irq_disable(void)
  42{
  43        asm volatile(
  44                "       and %0,epsw     \n"
  45                "       or %1,epsw      \n"
  46                "       nop             \n"
  47                "       nop             \n"
  48                "       nop             \n"
  49                :
  50                : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
  51                : "memory");
  52}
  53
  54static inline unsigned long arch_local_irq_save(void)
  55{
  56        unsigned long flags;
  57
  58        flags = arch_local_save_flags();
  59        arch_local_irq_disable();
  60        return flags;
  61}
  62
  63/*
  64 * we make sure arch_irq_enable() doesn't cause priority inversion
  65 */
  66extern unsigned long __mn10300_irq_enabled_epsw[];
  67
  68static inline void arch_local_irq_enable(void)
  69{
  70        unsigned long tmp;
  71        int cpu = raw_smp_processor_id();
  72
  73        asm volatile(
  74                "       mov     epsw,%0         \n"
  75                "       and     %1,%0           \n"
  76                "       or      %2,%0           \n"
  77                "       mov     %0,epsw         \n"
  78                : "=&d"(tmp)
  79                : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
  80                : "memory", "cc");
  81}
  82
  83static inline void arch_local_irq_restore(unsigned long flags)
  84{
  85        asm volatile(
  86                "       mov %0,epsw     \n"
  87                "       nop             \n"
  88                "       nop             \n"
  89                "       nop             \n"
  90                :
  91                : "d"(flags)
  92                : "memory", "cc");
  93}
  94
  95static inline bool arch_irqs_disabled_flags(unsigned long flags)
  96{
  97        return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
  98}
  99
 100static inline bool arch_irqs_disabled(void)
 101{
 102        return arch_irqs_disabled_flags(arch_local_save_flags());
 103}
 104
 105/*
 106 * Hook to save power by halting the CPU
 107 * - called from the idle loop
 108 * - must reenable interrupts (which takes three instruction cycles to complete)
 109 */
 110static inline void arch_safe_halt(void)
 111{
 112#ifdef CONFIG_SMP
 113        arch_local_irq_enable();
 114#else
 115        asm volatile(
 116                "       or      %0,epsw \n"
 117                "       nop             \n"
 118                "       nop             \n"
 119                "       bset    %2,(%1) \n"
 120                :
 121                : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
 122                : "cc");
 123#endif
 124}
 125
 126#define __sleep_cpu()                           \
 127do {                                            \
 128        asm volatile(                           \
 129                "       bset    %1,(%0)\n"      \
 130                "1:     btst    %1,(%0)\n"      \
 131                "       bne     1b\n"           \
 132                :                               \
 133                : "i"(&CPUM), "i"(CPUM_SLEEP)   \
 134                : "cc"                          \
 135                );                              \
 136} while (0)
 137
 138static inline void arch_local_cli(void)
 139{
 140        asm volatile(
 141                "       and     %0,epsw         \n"
 142                "       nop                     \n"
 143                "       nop                     \n"
 144                "       nop                     \n"
 145                :
 146                : "i"(~EPSW_IE)
 147                : "memory"
 148                );
 149}
 150
 151static inline unsigned long arch_local_cli_save(void)
 152{
 153        unsigned long flags = arch_local_save_flags();
 154        arch_local_cli();
 155        return flags;
 156}
 157
 158static inline void arch_local_sti(void)
 159{
 160        asm volatile(
 161                "       or      %0,epsw         \n"
 162                :
 163                : "i"(EPSW_IE)
 164                : "memory");
 165}
 166
 167static inline void arch_local_change_intr_mask_level(unsigned long level)
 168{
 169        asm volatile(
 170                "       and     %0,epsw         \n"
 171                "       or      %1,epsw         \n"
 172                :
 173                : "i"(~EPSW_IM), "i"(EPSW_IE | level)
 174                : "cc", "memory");
 175}
 176
 177#else /* !__ASSEMBLY__ */
 178
 179#define LOCAL_SAVE_FLAGS(reg)                   \
 180        mov     epsw,reg
 181
 182#define LOCAL_IRQ_DISABLE                               \
 183        and     ~EPSW_IM,epsw;                          \
 184        or      EPSW_IE|MN10300_CLI_LEVEL,epsw;         \
 185        nop;                                            \
 186        nop;                                            \
 187        nop
 188
 189#define LOCAL_IRQ_ENABLE                \
 190        or      EPSW_IE|EPSW_IM_7,epsw
 191
 192#define LOCAL_IRQ_RESTORE(reg)  \
 193        mov     reg,epsw
 194
 195#define LOCAL_CLI_SAVE(reg)     \
 196        mov     epsw,reg;       \
 197        and     ~EPSW_IE,epsw;  \
 198        nop;                    \
 199        nop;                    \
 200        nop
 201
 202#define LOCAL_CLI               \
 203        and     ~EPSW_IE,epsw;  \
 204        nop;                    \
 205        nop;                    \
 206        nop
 207
 208#define LOCAL_STI               \
 209        or      EPSW_IE,epsw
 210
 211#define LOCAL_CHANGE_INTR_MASK_LEVEL(level)     \
 212        and     ~EPSW_IM,epsw;                  \
 213        or      EPSW_IE|(level),epsw
 214
 215#endif /* __ASSEMBLY__ */
 216#endif /* _ASM_IRQFLAGS_H */
 217