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