Path: blob/master/arch/mn10300/include/asm/irqflags.h
15126 views
/* MN10300 IRQ flag handling1*2* Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public Licence7* as published by the Free Software Foundation; either version8* 2 of the Licence, or (at your option) any later version.9*/1011#ifndef _ASM_IRQFLAGS_H12#define _ASM_IRQFLAGS_H1314#include <asm/cpu-regs.h>15#ifndef __ASSEMBLY__16#include <linux/smp.h>17#endif1819/*20* interrupt control21* - "disabled": run in IM1/222* - level 0 - kernel debugger23* - level 1 - virtual serial DMA (if present)24* - level 5 - normal interrupt priority25* - level 6 - timer interrupt26* - "enabled": run in IM727*/28#define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)2930#ifndef __ASSEMBLY__3132static inline unsigned long arch_local_save_flags(void)33{34unsigned long flags;3536asm volatile("mov epsw,%0" : "=d"(flags));37return flags;38}3940static inline void arch_local_irq_disable(void)41{42asm volatile(43" and %0,epsw \n"44" or %1,epsw \n"45" nop \n"46" nop \n"47" nop \n"48:49: "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)50: "memory");51}5253static inline unsigned long arch_local_irq_save(void)54{55unsigned long flags;5657flags = arch_local_save_flags();58arch_local_irq_disable();59return flags;60}6162/*63* we make sure arch_irq_enable() doesn't cause priority inversion64*/65extern unsigned long __mn10300_irq_enabled_epsw[];6667static inline void arch_local_irq_enable(void)68{69unsigned long tmp;70int cpu = raw_smp_processor_id();7172asm volatile(73" mov epsw,%0 \n"74" and %1,%0 \n"75" or %2,%0 \n"76" mov %0,epsw \n"77: "=&d"(tmp)78: "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])79: "memory", "cc");80}8182static inline void arch_local_irq_restore(unsigned long flags)83{84asm volatile(85" mov %0,epsw \n"86" nop \n"87" nop \n"88" nop \n"89:90: "d"(flags)91: "memory", "cc");92}9394static inline bool arch_irqs_disabled_flags(unsigned long flags)95{96return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);97}9899static inline bool arch_irqs_disabled(void)100{101return arch_irqs_disabled_flags(arch_local_save_flags());102}103104/*105* Hook to save power by halting the CPU106* - called from the idle loop107* - must reenable interrupts (which takes three instruction cycles to complete)108*/109static inline void arch_safe_halt(void)110{111#ifdef CONFIG_SMP112arch_local_irq_enable();113#else114asm volatile(115" or %0,epsw \n"116" nop \n"117" nop \n"118" bset %2,(%1) \n"119:120: "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)121: "cc");122#endif123}124125#define __sleep_cpu() \126do { \127asm volatile( \128" bset %1,(%0)\n" \129"1: btst %1,(%0)\n" \130" bne 1b\n" \131: \132: "i"(&CPUM), "i"(CPUM_SLEEP) \133: "cc" \134); \135} while (0)136137static inline void arch_local_cli(void)138{139asm volatile(140" and %0,epsw \n"141" nop \n"142" nop \n"143" nop \n"144:145: "i"(~EPSW_IE)146: "memory"147);148}149150static inline unsigned long arch_local_cli_save(void)151{152unsigned long flags = arch_local_save_flags();153arch_local_cli();154return flags;155}156157static inline void arch_local_sti(void)158{159asm volatile(160" or %0,epsw \n"161:162: "i"(EPSW_IE)163: "memory");164}165166static inline void arch_local_change_intr_mask_level(unsigned long level)167{168asm volatile(169" and %0,epsw \n"170" or %1,epsw \n"171:172: "i"(~EPSW_IM), "i"(EPSW_IE | level)173: "cc", "memory");174}175176#else /* !__ASSEMBLY__ */177178#define LOCAL_SAVE_FLAGS(reg) \179mov epsw,reg180181#define LOCAL_IRQ_DISABLE \182and ~EPSW_IM,epsw; \183or EPSW_IE|MN10300_CLI_LEVEL,epsw; \184nop; \185nop; \186nop187188#define LOCAL_IRQ_ENABLE \189or EPSW_IE|EPSW_IM_7,epsw190191#define LOCAL_IRQ_RESTORE(reg) \192mov reg,epsw193194#define LOCAL_CLI_SAVE(reg) \195mov epsw,reg; \196and ~EPSW_IE,epsw; \197nop; \198nop; \199nop200201#define LOCAL_CLI \202and ~EPSW_IE,epsw; \203nop; \204nop; \205nop206207#define LOCAL_STI \208or EPSW_IE,epsw209210#define LOCAL_CHANGE_INTR_MASK_LEVEL(level) \211and ~EPSW_IM,epsw; \212or EPSW_IE|(level),epsw213214#endif /* __ASSEMBLY__ */215#endif /* _ASM_IRQFLAGS_H */216217218