Blackfin arch:  merge adeos blackfin part to arch/blackfin/

[Mike Frysinger <vapier.adi@gmail.com>:
 - handle bf531/bf532/bf534/bf536 variants in ipipe.h
 - cleanup IPIPE logic for bfin_set_irq_handler()
 - cleanup ipipe asm code a bit and add missing ENDPROC()
 - simplify IPIPE code in trap_c
 - unify some of the IPIPE code and fix style
 - simplify DO_IRQ_L1 handling with ipipe code
 - revert IRQ_SW_INT# addition from ipipe merge
 - remove duplicate get_{c,s}clk() prototypes
]

Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>

diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
index 98cf7c3..699781c 100644
--- a/arch/blackfin/configs/BF518F-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -204,14 +204,14 @@
 CONFIG_IRQ_PORTH_INTA=11
 CONFIG_IRQ_MAC_TX=11
 CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTA=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 667af6b..6dfcd27 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -199,14 +199,14 @@
 CONFIG_IRQ_PORTH_INTA=11
 CONFIG_IRQ_MAC_TX=11
 CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTA=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 70b50d0..2947dcb 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -188,14 +188,14 @@
 CONFIG_IRQ_PORTH_INTA=11
 CONFIG_IRQ_MAC_TX=11
 CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=8
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTA=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index ed84c62..4aa6687 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -148,14 +148,14 @@
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_MAC_RX=11
 CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=8
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
index f1d2b36..baf33e6 100644
--- a/arch/blackfin/configs/BF538-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -163,9 +163,9 @@
 CONFIG_IRQ_UART0_TX=10
 CONFIG_IRQ_UART1_RX=10
 CONFIG_IRQ_UART1_TX=10
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
 CONFIG_IRQ_WATCH=13
 CONFIG_IRQ_PORTF_INTA=12
 CONFIG_IRQ_PORTF_INTB=12
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index 0043da5..7195385 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -190,14 +190,14 @@
 CONFIG_IRQ_PORTH_INTA=11
 CONFIG_IRQ_MAC_TX=11
 CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTA=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
index 1b50d38..cbf4803 100644
--- a/arch/blackfin/configs/CM-BF537E_defconfig
+++ b/arch/blackfin/configs/CM-BF537E_defconfig
@@ -157,14 +157,14 @@
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_MAC_RX=11
 CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
index 2ca768d..f2ac0cc 100644
--- a/arch/blackfin/configs/CM-BF537U_defconfig
+++ b/arch/blackfin/configs/CM-BF537U_defconfig
@@ -157,14 +157,14 @@
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_MAC_RX=11
 CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index 648edd9..834fb8c 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -153,14 +153,14 @@
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_MAC_RX=11
 CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
index ffa2396..010f0aa7 100644
--- a/arch/blackfin/configs/SRV1_defconfig
+++ b/arch/blackfin/configs/SRV1_defconfig
@@ -172,14 +172,14 @@
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_MAC_RX=11
 CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
diff --git a/arch/blackfin/configs/TCM-BF537_defconfig b/arch/blackfin/configs/TCM-BF537_defconfig
index 6431192..0ba4aa8 100644
--- a/arch/blackfin/configs/TCM-BF537_defconfig
+++ b/arch/blackfin/configs/TCM-BF537_defconfig
@@ -144,14 +144,14 @@
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_MAC_RX=11
 CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
 CONFIG_IRQ_PORTG_INTB=12
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index d76275e..94b2a9b 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -92,18 +92,18 @@
 {
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter += i;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline void atomic_sub(int i, atomic_t *v)
 {
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter -= i;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 }
 
@@ -112,10 +112,10 @@
 	int __temp = 0;
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter += i;
 	__temp = v->counter;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 
 	return __temp;
@@ -126,10 +126,10 @@
 	int __temp = 0;
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter -= i;
 	__temp = v->counter;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return __temp;
 }
@@ -138,36 +138,36 @@
 {
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter++;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline void atomic_dec(volatile atomic_t *v)
 {
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter--;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter &= ~mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
 	long flags;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	v->counter |= mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Atomic operations are already serializing */
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h
index 9964e17..21b036e 100644
--- a/arch/blackfin/include/asm/bitops.h
+++ b/arch/blackfin/include/asm/bitops.h
@@ -90,9 +90,9 @@
 	unsigned long flags;
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	*a |= mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline void clear_bit(int nr, volatile unsigned long *addr)
@@ -102,9 +102,9 @@
 	unsigned long flags;
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	*a &= ~mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline void change_bit(int nr, volatile unsigned long *addr)
@@ -114,9 +114,9 @@
 
 	ADDR += nr >> 5;
 	mask = 1 << (nr & 31);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	*ADDR ^= mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
@@ -127,10 +127,10 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	retval = (mask & *a) != 0;
 	*a |= mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return retval;
 }
@@ -143,10 +143,10 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	retval = (mask & *a) != 0;
 	*a &= ~mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return retval;
 }
@@ -159,10 +159,10 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	retval = (mask & *a) != 0;
 	*a ^= mask;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 	return retval;
 }
 
diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h
index d94e4f5..b30a296 100644
--- a/arch/blackfin/include/asm/entry.h
+++ b/arch/blackfin/include/asm/entry.h
@@ -27,6 +27,14 @@
 #define SAVE_ALL_SYS		save_context_no_interrupts
 /* This is used for all normal interrupts.  It saves a minimum of registers
    to the stack, loads the IRQ number, and jumps to common code.  */
+#ifdef CONFIG_IPIPE
+# define LOAD_IPIPE_IPEND \
+	P0.l = lo(IPEND); \
+	P0.h = hi(IPEND); \
+	R1 = [P0];
+#else
+# define LOAD_IPIPE_IPEND
+#endif
 #define INTERRUPT_ENTRY(N)						\
     [--sp] = SYSCFG;							\
 									\
@@ -34,6 +42,7 @@
     [--sp] = R0;	/*orig_r0*/					\
     [--sp] = (R7:0,P5:0);						\
     R0 = (N);								\
+    LOAD_IPIPE_IPEND							\
     jump __common_int_entry;
 
 /* For timer interrupts, we need to save IPEND, since the user_mode
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
new file mode 100644
index 0000000..76f53d8
--- /dev/null
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -0,0 +1,278 @@
+/*   -*- linux-c -*-
+ *   include/asm-blackfin/ipipe.h
+ *
+ *   Copyright (C) 2002-2007 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ASM_BLACKFIN_IPIPE_H
+#define __ASM_BLACKFIN_IPIPE_H
+
+#ifdef CONFIG_IPIPE
+
+#include <linux/cpumask.h>
+#include <linux/list.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+#include <linux/ipipe_percpu.h>
+#include <asm/ptrace.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/atomic.h>
+#include <asm/traps.h>
+
+#define IPIPE_ARCH_STRING     "1.8-00"
+#define IPIPE_MAJOR_NUMBER    1
+#define IPIPE_MINOR_NUMBER    8
+#define IPIPE_PATCH_NUMBER    0
+
+#ifdef CONFIG_SMP
+#error "I-pipe/blackfin: SMP not implemented"
+#else /* !CONFIG_SMP */
+#define ipipe_processor_id()	0
+#endif	/* CONFIG_SMP */
+
+#define prepare_arch_switch(next)		\
+do {						\
+	ipipe_schedule_notify(current, next);	\
+	local_irq_disable_hw();			\
+} while (0)
+
+#define task_hijacked(p)						\
+	({								\
+		int __x__ = ipipe_current_domain != ipipe_root_domain;	\
+		/* We would need to clear the SYNC flag for the root domain */ \
+		/* over the current processor in SMP mode. */		\
+		local_irq_enable_hw(); __x__;				\
+	})
+
+struct ipipe_domain;
+
+struct ipipe_sysinfo {
+
+	int ncpus;		/* Number of CPUs on board */
+	u64 cpufreq;		/* CPU frequency (in Hz) */
+
+	/* Arch-dependent block */
+
+	struct {
+		unsigned tmirq;	/* Timer tick IRQ */
+		u64 tmfreq;	/* Timer frequency */
+	} archdep;
+};
+
+#define ipipe_read_tsc(t)					\
+	({							\
+	unsigned long __cy2;					\
+	__asm__ __volatile__ ("1: %0 = CYCLES2\n"		\
+				"%1 = CYCLES\n"			\
+				"%2 = CYCLES2\n"		\
+				"CC = %2 == %0\n"		\
+				"if ! CC jump 1b\n"		\
+				: "=r" (((unsigned long *)&t)[1]),	\
+				  "=r" (((unsigned long *)&t)[0]),	\
+				  "=r" (__cy2)				\
+				: /*no input*/ : "CC");			\
+	t;								\
+	})
+
+#define ipipe_cpu_freq()	__ipipe_core_clock
+#define ipipe_tsc2ns(_t)	(((unsigned long)(_t)) * __ipipe_freq_scale)
+#define ipipe_tsc2us(_t)	(ipipe_tsc2ns(_t) / 1000 + 1)
+
+/* Private interface -- Internal use only */
+
+#define __ipipe_check_platform()	do { } while (0)
+
+#define __ipipe_init_platform()		do { } while (0)
+
+extern atomic_t __ipipe_irq_lvdepth[IVG15 + 1];
+
+extern unsigned long __ipipe_irq_lvmask;
+
+extern struct ipipe_domain ipipe_root;
+
+/* enable/disable_irqdesc _must_ be used in pairs. */
+
+void __ipipe_enable_irqdesc(struct ipipe_domain *ipd,
+			    unsigned irq);
+
+void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
+			     unsigned irq);
+
+#define __ipipe_enable_irq(irq)		(irq_desc[irq].chip->unmask(irq))
+
+#define __ipipe_disable_irq(irq)	(irq_desc[irq].chip->mask(irq))
+
+#define __ipipe_lock_root()					\
+	set_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)
+
+#define __ipipe_unlock_root()					\
+	clear_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)
+
+void __ipipe_enable_pipeline(void);
+
+#define __ipipe_hook_critical_ipi(ipd) do { } while (0)
+
+#define __ipipe_sync_pipeline(syncmask)					\
+	do {								\
+		struct ipipe_domain *ipd = ipipe_current_domain;	\
+		if (likely(ipd != ipipe_root_domain || !test_bit(IPIPE_ROOTLOCK_FLAG, &ipd->flags))) \
+			__ipipe_sync_stage(syncmask);			\
+	} while (0)
+
+void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
+
+int __ipipe_get_irq_priority(unsigned irq);
+
+int __ipipe_get_irqthread_priority(unsigned irq);
+
+void __ipipe_stall_root_raw(void);
+
+void __ipipe_unstall_root_raw(void);
+
+void __ipipe_serial_debug(const char *fmt, ...);
+
+DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
+
+extern unsigned long __ipipe_core_clock;
+
+extern unsigned long __ipipe_freq_scale;
+
+extern unsigned long __ipipe_irq_tail_hook;
+
+static inline unsigned long __ipipe_ffnz(unsigned long ul)
+{
+	return ffs(ul) - 1;
+}
+
+#define __ipipe_run_irqtail()  /* Must be a macro */			\
+	do {								\
+		asmlinkage void __ipipe_call_irqtail(void);		\
+		unsigned long __pending;				\
+		CSYNC();					\
+		__pending = bfin_read_IPEND();				\
+		if (__pending & 0x8000) {				\
+			__pending &= ~0x8010;				\
+			if (__pending && (__pending & (__pending - 1)) == 0) \
+				__ipipe_call_irqtail();			\
+		}							\
+	} while (0)
+
+#define __ipipe_run_isr(ipd, irq)					\
+	do {								\
+		if (ipd == ipipe_root_domain) {				\
+			/*						\
+			 * Note: the I-pipe implements a threaded interrupt model on \
+			 * this arch for Linux external IRQs. The interrupt handler we \
+			 * call here only wakes up the associated IRQ thread. \
+			 */						\
+			if (ipipe_virtual_irq_p(irq)) {			\
+				/* No irqtail here; virtual interrupts have no effect \
+				   on IPEND so there is no need for processing \
+				   deferral. */				\
+				local_irq_enable_nohead(ipd);		\
+				ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
+				local_irq_disable_nohead(ipd);		\
+			} else						\
+				/*					\
+				 * No need to run the irqtail here either; \
+				 * we can't be preempted by hw IRQs, so	\
+				 * non-Linux IRQs cannot stack over the short \
+				 * thread wakeup code. Which in turn means \
+				 * that no irqtail condition could be pending \
+				 * for domains above Linux in the pipeline. \
+				 */					\
+				ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
+		} else {						\
+			__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
+			local_irq_enable_nohead(ipd);			\
+			ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
+			/* Attempt to exit the outer interrupt level before \
+			 * starting the deferred IRQ processing. */	\
+			local_irq_disable_nohead(ipd);			\
+			__ipipe_run_irqtail();				\
+			__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
+		}							\
+	} while (0)
+
+#define __ipipe_syscall_watched_p(p, sc)	\
+	(((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls)
+
+void ipipe_init_irq_threads(void);
+
+int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
+
+#define IS_SYSIRQ(irq)		((irq) > IRQ_CORETMR && (irq) <= SYS_IRQS)
+#define IS_GPIOIRQ(irq)		((irq) >= GPIO_IRQ_BASE && (irq) < NR_IRQS)
+
+#define IRQ_SYSTMR		IRQ_TIMER0
+#define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
+
+#if defined(CONFIG_BF531) || defined(CONFIG_BF532) || defined(CONFIG_BF533)
+#define PRIO_GPIODEMUX(irq)	CONFIG_PFA
+#elif defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
+#define PRIO_GPIODEMUX(irq)	CONFIG_IRQ_PROG_INTA
+#elif defined(CONFIG_BF52x)
+#define PRIO_GPIODEMUX(irq)	((irq) == IRQ_PORTF_INTA ? CONFIG_IRQ_PORTF_INTA : \
+				 (irq) == IRQ_PORTG_INTA ? CONFIG_IRQ_PORTG_INTA : \
+				 (irq) == IRQ_PORTH_INTA ? CONFIG_IRQ_PORTH_INTA : \
+				 -1)
+#elif defined(CONFIG_BF561)
+#define PRIO_GPIODEMUX(irq)	((irq) == IRQ_PROG0_INTA ? CONFIG_IRQ_PROG0_INTA : \
+				 (irq) == IRQ_PROG1_INTA ? CONFIG_IRQ_PROG1_INTA : \
+				 (irq) == IRQ_PROG2_INTA ? CONFIG_IRQ_PROG2_INTA : \
+				 -1)
+#define bfin_write_TIMER_DISABLE(val)	bfin_write_TMRS8_DISABLE(val)
+#define bfin_write_TIMER_ENABLE(val)	bfin_write_TMRS8_ENABLE(val)
+#define bfin_write_TIMER_STATUS(val)	bfin_write_TMRS8_STATUS(val)
+#define bfin_read_TIMER_STATUS()	bfin_read_TMRS8_STATUS()
+#elif defined(CONFIG_BF54x)
+#define PRIO_GPIODEMUX(irq)	((irq) == IRQ_PINT0 ? CONFIG_IRQ_PINT0 : \
+				 (irq) == IRQ_PINT1 ? CONFIG_IRQ_PINT1 : \
+				 (irq) == IRQ_PINT2 ? CONFIG_IRQ_PINT2 : \
+				 (irq) == IRQ_PINT3 ? CONFIG_IRQ_PINT3 : \
+				 -1)
+#define bfin_write_TIMER_DISABLE(val)	bfin_write_TIMER_DISABLE0(val)
+#define bfin_write_TIMER_ENABLE(val)	bfin_write_TIMER_ENABLE0(val)
+#define bfin_write_TIMER_STATUS(val)	bfin_write_TIMER_STATUS0(val)
+#define bfin_read_TIMER_STATUS(val)	bfin_read_TIMER_STATUS0(val)
+#else
+# error "no PRIO_GPIODEMUX() for this part"
+#endif
+
+#define __ipipe_root_tick_p(regs)	((regs->ipend & 0x10) != 0)
+
+#else /* !CONFIG_IPIPE */
+
+#define task_hijacked(p)		0
+#define ipipe_trap_notify(t, r)  	0
+
+#define __ipipe_stall_root_raw()	do { } while (0)
+#define __ipipe_unstall_root_raw()	do { } while (0)
+
+#define ipipe_init_irq_threads()		do { } while (0)
+#define ipipe_start_irq_thread(irq, desc)	0
+
+#define IRQ_SYSTMR		IRQ_CORETMR
+#define IRQ_PRIOTMR		IRQ_CORETMR
+
+#define __ipipe_root_tick_p(regs)	1
+
+#endif /* !CONFIG_IPIPE */
+
+#endif	/* !__ASM_BLACKFIN_IPIPE_H */
diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h
new file mode 100644
index 0000000..cb1025a
--- /dev/null
+++ b/arch/blackfin/include/asm/ipipe_base.h
@@ -0,0 +1,80 @@
+/*   -*- linux-c -*-
+ *   include/asm-blackfin/_baseipipe.h
+ *
+ *   Copyright (C) 2007 Philippe Gerum.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ASM_BLACKFIN_IPIPE_BASE_H
+#define __ASM_BLACKFIN_IPIPE_BASE_H
+
+#ifdef CONFIG_IPIPE
+
+#define IPIPE_NR_XIRQS		NR_IRQS
+#define IPIPE_IRQ_ISHIFT	5	/* 2^5 for 32bits arch. */
+
+/* Blackfin-specific, global domain flags */
+#define IPIPE_ROOTLOCK_FLAG	1	/* Lock pipeline for root */
+
+ /* Blackfin traps -- i.e. exception vector numbers */
+#define IPIPE_NR_FAULTS		52 /* We leave a gap after VEC_ILL_RES. */
+/* Pseudo-vectors used for kernel events */
+#define IPIPE_FIRST_EVENT	IPIPE_NR_FAULTS
+#define IPIPE_EVENT_SYSCALL	(IPIPE_FIRST_EVENT)
+#define IPIPE_EVENT_SCHEDULE	(IPIPE_FIRST_EVENT + 1)
+#define IPIPE_EVENT_SIGWAKE	(IPIPE_FIRST_EVENT + 2)
+#define IPIPE_EVENT_SETSCHED	(IPIPE_FIRST_EVENT + 3)
+#define IPIPE_EVENT_INIT	(IPIPE_FIRST_EVENT + 4)
+#define IPIPE_EVENT_EXIT	(IPIPE_FIRST_EVENT + 5)
+#define IPIPE_EVENT_CLEANUP	(IPIPE_FIRST_EVENT + 6)
+#define IPIPE_LAST_EVENT	IPIPE_EVENT_CLEANUP
+#define IPIPE_NR_EVENTS		(IPIPE_LAST_EVENT + 1)
+
+#define IPIPE_TIMER_IRQ		IRQ_CORETMR
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+
+extern int test_bit(int nr, const void *addr);
+
+
+extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
+
+static inline void __ipipe_stall_root(void)
+{
+	volatile unsigned long *p = &__ipipe_root_status;
+	set_bit(0, p);
+}
+
+static inline unsigned long __ipipe_test_and_stall_root(void)
+{
+	volatile unsigned long *p = &__ipipe_root_status;
+	return test_and_set_bit(0, p);
+}
+
+static inline unsigned long __ipipe_test_root(void)
+{
+	const unsigned long *p = &__ipipe_root_status;
+	return test_bit(0, p);
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* CONFIG_IPIPE */
+
+#endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */
diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h
index 21e25f7..3d97790 100644
--- a/arch/blackfin/include/asm/irq.h
+++ b/arch/blackfin/include/asm/irq.h
@@ -22,11 +22,176 @@
 #include <asm/pda.h>
 #include <asm/processor.h>
 
-static __inline__ int irq_canonicalize(int irq)
+#ifdef CONFIG_SMP
+/* Forward decl needed due to cdef inter dependencies */
+static inline uint32_t __pure bfin_dspid(void);
+# define blackfin_core_id() (bfin_dspid() & 0xff)
+# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
+#else
+extern unsigned long bfin_irq_flags;
+#endif
+
+#ifdef CONFIG_IPIPE
+
+#include <linux/ipipe_trace.h>
+
+void __ipipe_unstall_root(void);
+
+void __ipipe_restore_root(unsigned long flags);
+
+#ifdef CONFIG_DEBUG_HWERR
+# define __all_masked_irq_flags 0x3f
+# define __save_and_cli_hw(x) \
+	__asm__ __volatile__( \
+		"cli %0;" \
+		"sti %1;" \
+		: "=&d"(x) \
+		: "d" (0x3F) \
+	)
+#else
+# define __all_masked_irq_flags 0x1f
+# define __save_and_cli_hw(x) \
+	__asm__ __volatile__( \
+		"cli %0;" \
+		: "=&d"(x) \
+	)
+#endif
+
+#define irqs_enabled_from_flags_hw(x)	((x) != __all_masked_irq_flags)
+#define raw_irqs_disabled_flags(flags)	(!irqs_enabled_from_flags_hw(flags))
+#define local_test_iflag_hw(x)		irqs_enabled_from_flags_hw(x)
+
+#define local_save_flags(x)						\
+	do {								\
+		(x) = __ipipe_test_root() ? \
+			__all_masked_irq_flags : bfin_irq_flags; \
+	} while (0)
+
+#define local_irq_save(x)				\
+	do {						\
+		(x) = __ipipe_test_and_stall_root();	\
+	} while (0)
+
+#define local_irq_restore(x)	__ipipe_restore_root(x)
+#define local_irq_disable()	__ipipe_stall_root()
+#define local_irq_enable()	__ipipe_unstall_root()
+#define irqs_disabled()		__ipipe_test_root()
+
+#define local_save_flags_hw(x) \
+	__asm__ __volatile__( \
+		"cli %0;" \
+		"sti %0;" \
+		: "=d"(x) \
+	)
+
+#define	irqs_disabled_hw()				\
+	({						\
+		unsigned long flags;			\
+		local_save_flags_hw(flags);		\
+		!irqs_enabled_from_flags_hw(flags);	\
+	})
+
+static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
 {
-	return irq;
+	/* Merge virtual and real interrupt mask bits into a single
+	   32bit word. */
+	return (real & ~(1 << 31)) | ((virt != 0) << 31);
 }
 
+static inline int raw_demangle_irq_bits(unsigned long *x)
+{
+	int virt = (*x & (1 << 31)) != 0;
+	*x &= ~(1L << 31);
+	return virt;
+}
+
+#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
+
+#define local_irq_disable_hw()						\
+	do {								\
+		int _tmp_dummy;						\
+		if (!irqs_disabled_hw())				\
+			ipipe_trace_begin(0x80000000);			\
+		__asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : );	\
+	} while (0)
+
+#define local_irq_enable_hw()						\
+	do {								\
+		if (irqs_disabled_hw())					\
+			ipipe_trace_end(0x80000000);			\
+		__asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags));	\
+	} while (0)
+
+#define local_irq_save_hw(x)				\
+	do {						\
+		__save_and_cli_hw(x);			\
+		if (local_test_iflag_hw(x))		\
+			ipipe_trace_begin(0x80000001);	\
+	} while (0)
+
+#define local_irq_restore_hw(x)				\
+	do {						\
+		if (local_test_iflag_hw(x)) {		\
+			ipipe_trace_end(0x80000001);	\
+			local_irq_enable_hw_notrace();	\
+		}					\
+	} while (0)
+
+#define local_irq_disable_hw_notrace()					\
+	do {								\
+		int _tmp_dummy;						\
+		__asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : );	\
+	} while (0)
+
+#define local_irq_enable_hw_notrace() \
+	__asm__ __volatile__( \
+		"sti %0;" \
+		: \
+		: "d"(bfin_irq_flags) \
+	)
+
+#define local_irq_save_hw_notrace(x) __save_and_cli_hw(x)
+
+#define local_irq_restore_hw_notrace(x)			\
+	do {						\
+		if (local_test_iflag_hw(x))		\
+			local_irq_enable_hw_notrace();	\
+	} while (0)
+
+#else /* CONFIG_IPIPE_TRACE_IRQSOFF */
+
+#define local_irq_enable_hw() \
+	__asm__ __volatile__( \
+		"sti %0;" \
+		: \
+		: "d"(bfin_irq_flags) \
+	)
+
+#define local_irq_disable_hw()			\
+	do {					\
+		int _tmp_dummy;			\
+		__asm__ __volatile__ (		\
+			"cli %0;"		\
+			: "=d" (_tmp_dummy));	\
+	} while (0)
+
+#define local_irq_restore_hw(x) \
+	do { \
+		if (irqs_enabled_from_flags_hw(x)) \
+			local_irq_enable_hw(); \
+	} while (0)
+
+#define local_irq_save_hw(x)		__save_and_cli_hw(x)
+
+#define local_irq_disable_hw_notrace()	local_irq_disable_hw()
+#define local_irq_enable_hw_notrace()	local_irq_enable_hw()
+#define local_irq_save_hw_notrace(x)	local_irq_save_hw(x)
+#define local_irq_restore_hw_notrace(x)	local_irq_restore_hw(x)
+
+#endif  /* CONFIG_IPIPE_TRACE_IRQSOFF */
+
+#else /* !CONFIG_IPIPE */
+
 /*
  * Interrupt configuring macros.
  */
@@ -39,21 +204,6 @@
 		); \
 	} while (0)
 
-#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
-# define NOP_PAD_ANOMALY_05000244 "nop; nop;"
-#else
-# define NOP_PAD_ANOMALY_05000244
-#endif
-
-#ifdef CONFIG_SMP
-/* Forward decl needed due to cdef inter dependencies */
-static inline uint32_t __pure bfin_dspid(void);
-# define blackfin_core_id() (bfin_dspid() & 0xff)
-# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
-#else
-extern unsigned long bfin_irq_flags;
-#endif
-
 #define local_irq_enable() \
 	__asm__ __volatile__( \
 		"sti %0;" \
@@ -61,16 +211,6 @@
 		: "d" (bfin_irq_flags) \
 	)
 
-#define idle_with_irq_disabled() \
-	__asm__ __volatile__( \
-		NOP_PAD_ANOMALY_05000244 \
-		".align 8;" \
-		"sti %0;" \
-		"idle;" \
-		: \
-		: "d" (bfin_irq_flags) \
-	)
-
 #ifdef CONFIG_DEBUG_HWERR
 # define __save_and_cli(x) \
 	__asm__ __volatile__( \
@@ -116,4 +256,33 @@
 	!irqs_enabled_from_flags(flags);	\
 })
 
+#define local_irq_save_hw(x)		local_irq_save(x)
+#define local_irq_restore_hw(x)		local_irq_restore(x)
+#define local_irq_enable_hw()		local_irq_enable()
+#define local_irq_disable_hw()		local_irq_disable()
+#define irqs_disabled_hw()		irqs_disabled()
+
+#endif /* !CONFIG_IPIPE */
+
+#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
+# define NOP_PAD_ANOMALY_05000244 "nop; nop;"
+#else
+# define NOP_PAD_ANOMALY_05000244
+#endif
+
+#define idle_with_irq_disabled() \
+	__asm__ __volatile__( \
+		NOP_PAD_ANOMALY_05000244 \
+		".align 8;" \
+		"sti %0;" \
+		"idle;" \
+		: \
+		: "d" (bfin_irq_flags) \
+	)
+
+static inline int irq_canonicalize(int irq)
+{
+	return irq;
+}
+
 #endif				/* _BFIN_IRQ_H_ */
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
index 812e6e6..a4c8254 100644
--- a/arch/blackfin/include/asm/system.h
+++ b/arch/blackfin/include/asm/system.h
@@ -141,7 +141,7 @@
 	unsigned long tmp = 0;
 	unsigned long flags = 0;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	switch (size) {
 	case 1:
@@ -163,7 +163,7 @@
 			 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
 		break;
 	}
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 	return tmp;
 }
 
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index f0902c1..38a2333 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -15,6 +15,8 @@
     obj-y += time.o
 endif
 
+obj-$(CONFIG_IPIPE)                  += ipipe.o
+obj-$(CONFIG_IPIPE_TRACE_MCOUNT)     += mcount.o
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
 obj-$(CONFIG_CPLB_INFO)              += cplbinfo.o
 obj-$(CONFIG_MODULES)                += module.o
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 2c72b15..4c14331 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -422,13 +422,13 @@
 void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
 	unsigned long flags; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	if (arg) \
 		gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
 	else \
 		gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
 	AWA_DUMMY_READ(name); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
 
@@ -444,13 +444,13 @@
 void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
 	unsigned long flags; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	if (arg) \
 		gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
 	else \
 		gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
 	AWA_DUMMY_READ(name); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
 #else
@@ -473,10 +473,10 @@
 void set_gpio_toggle(unsigned gpio)
 {
 	unsigned long flags;
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
 	AWA_DUMMY_READ(toggle);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 #else
 void set_gpio_toggle(unsigned gpio)
@@ -494,10 +494,10 @@
 void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
 { \
 	unsigned long flags; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	gpio_bankb[gpio_bank(gpio)]->name = arg; \
 	AWA_DUMMY_READ(name); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 } \
 EXPORT_SYMBOL(set_gpiop_ ## name);
 #else
@@ -525,10 +525,10 @@
 { \
 	unsigned long flags; \
 	unsigned short ret; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
 	AWA_DUMMY_READ(name); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 	return ret; \
 } \
 EXPORT_SYMBOL(get_gpio_ ## name);
@@ -558,10 +558,10 @@
 { \
 	unsigned long flags; \
 	unsigned short ret; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	ret = (gpio_bankb[gpio_bank(gpio)]->name); \
 	AWA_DUMMY_READ(name); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 	return ret; \
 } \
 EXPORT_SYMBOL(get_gpiop_ ## name);
@@ -611,10 +611,10 @@
 	if ((check_gpio(gpio) < 0) || !type)
 		return -EINVAL;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
 	wakeup_flags_map[gpio] = type;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return 0;
 }
@@ -627,11 +627,11 @@
 	if (check_gpio(gpio) < 0)
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 EXPORT_SYMBOL(gpio_pm_wakeup_free);
 
@@ -882,7 +882,7 @@
 	if (!(per & P_DEFINED))
 		return -ENODEV;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	/* If a pin can be muxed as either GPIO or peripheral, make
 	 * sure it is not already a GPIO pin when we request it.
@@ -893,7 +893,7 @@
 		printk(KERN_ERR
 		       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
 		       __func__, ident, get_label(ident));
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return -EBUSY;
 	}
 
@@ -923,7 +923,7 @@
 			printk(KERN_ERR
 			       "%s: Peripheral %d function %d is already reserved by %s !\n",
 			       __func__, ident, P_FUNCT2MUX(per), get_label(ident));
-			local_irq_restore(flags);
+			local_irq_restore_hw(flags);
 			return -EBUSY;
 		}
 	}
@@ -938,7 +938,7 @@
 #endif
 	port_setup(ident, PERIPHERAL_USAGE);
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 	set_label(ident, label);
 
 	return 0;
@@ -980,10 +980,10 @@
 	if (check_gpio(ident) < 0)
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return;
 	}
 
@@ -994,7 +994,7 @@
 
 	set_label(ident, "free");
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 EXPORT_SYMBOL(peripheral_free);
 
@@ -1028,7 +1028,7 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	/*
 	 * Allow that the identical GPIO can
@@ -1037,7 +1037,7 @@
 	 */
 
 	if (cmp_label(gpio, label) == 0) {
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return 0;
 	}
 
@@ -1045,7 +1045,7 @@
 		dump_stack();
 		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
 		       gpio, get_label(gpio));
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return -EBUSY;
 	}
 	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
@@ -1053,7 +1053,7 @@
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return -EBUSY;
 	}
 	if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))
@@ -1063,7 +1063,7 @@
 	reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
 	set_label(gpio, label);
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	port_setup(gpio, GPIO_USAGE);
 
@@ -1078,12 +1078,12 @@
 	if (check_gpio(gpio) < 0)
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
 		dump_stack();
 		gpio_error(gpio);
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return;
 	}
 
@@ -1091,7 +1091,7 @@
 
 	set_label(gpio, "free");
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 EXPORT_SYMBOL(bfin_gpio_free);
 
@@ -1102,14 +1102,14 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
 		dump_stack();
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n",
 		       gpio);
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return -EBUSY;
 	}
 	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
@@ -1117,7 +1117,7 @@
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return -EBUSY;
 	}
 	if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))
@@ -1128,7 +1128,7 @@
 	reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio);
 	set_label(gpio, label);
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	port_setup(gpio, GPIO_USAGE);
 
@@ -1142,12 +1142,12 @@
 	if (check_gpio(gpio) < 0)
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
 		dump_stack();
 		gpio_error(gpio);
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		return;
 	}
 
@@ -1155,7 +1155,7 @@
 
 	set_label(gpio, "free");
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 
@@ -1169,10 +1169,10 @@
 		return -EINVAL;
 	}
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
 	gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return 0;
 }
@@ -1187,11 +1187,11 @@
 		return -EINVAL;
 	}
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
 	gpio_set_value(gpio, value);
 	gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return 0;
 }
@@ -1218,10 +1218,10 @@
 
 	port_setup(gpio, GPIO_USAGE);
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
 	gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #else
@@ -1232,11 +1232,11 @@
 	int ret;
 
 	if (unlikely(get_gpio_edge(gpio))) {
-		local_irq_save(flags);
+		local_irq_save_hw(flags);
 		set_gpio_edge(gpio, 0);
 		ret = get_gpio_data(gpio);
 		set_gpio_edge(gpio, 1);
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 
 		return ret;
 	} else
@@ -1254,11 +1254,11 @@
 		return -EINVAL;
 	}
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
 	gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
 	AWA_DUMMY_READ(inen);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return 0;
 }
@@ -1273,7 +1273,7 @@
 		return -EINVAL;
 	}
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
 
 	if (value)
@@ -1283,7 +1283,7 @@
 
 	gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
 	AWA_DUMMY_READ(dir);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return 0;
 }
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index 5ef5d1a..87463ce 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -332,7 +332,7 @@
 
 	nr_cplb_flush[cpu]++;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	disable_icplb();
 	for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
 		icplb_tbl[cpu][i].data = 0;
@@ -346,7 +346,7 @@
 		bfin_write32(DCPLB_DATA0 + i * 4, 0);
 	}
 	enable_dcplb();
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 }
 
@@ -362,7 +362,7 @@
 		return;
 	}
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	current_rwx_mask[cpu] = masks;
 
 	d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
@@ -382,5 +382,5 @@
 		addr += PAGE_SIZE;
 	}
 	enable_dcplb();
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index c0c3fe8..a9cfba9 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -42,6 +42,10 @@
 #endif
 
 ENTRY(_ret_from_fork)
+#ifdef CONFIG_IPIPE
+	[--sp] = reti; 		/* IRQs on. */
+	SP += 4;
+#endif /* CONFIG_IPIPE */
 	SP += -12;
 	call _schedule_tail;
 	SP += 12;
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
new file mode 100644
index 0000000..339be5a
--- /dev/null
+++ b/arch/blackfin/kernel/ipipe.c
@@ -0,0 +1,428 @@
+/* -*- linux-c -*-
+ * linux/arch/blackfin/kernel/ipipe.c
+ *
+ * Copyright (C) 2005-2007 Philippe Gerum.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Architecture-dependent I-pipe support for the Blackfin.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kthread.h>
+#include <asm/unistd.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+
+static int create_irq_threads;
+
+DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
+
+static DEFINE_PER_CPU(unsigned long, pending_irqthread_mask);
+
+static DEFINE_PER_CPU(int [IVG13 + 1], pending_irq_count);
+
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
+
+static void __ipipe_no_irqtail(void);
+
+unsigned long __ipipe_irq_tail_hook = (unsigned long)&__ipipe_no_irqtail;
+EXPORT_SYMBOL(__ipipe_irq_tail_hook);
+
+unsigned long __ipipe_core_clock;
+EXPORT_SYMBOL(__ipipe_core_clock);
+
+unsigned long __ipipe_freq_scale;
+EXPORT_SYMBOL(__ipipe_freq_scale);
+
+atomic_t __ipipe_irq_lvdepth[IVG15 + 1];
+
+unsigned long __ipipe_irq_lvmask = __all_masked_irq_flags;
+EXPORT_SYMBOL(__ipipe_irq_lvmask);
+
+static void __ipipe_ack_irq(unsigned irq, struct irq_desc *desc)
+{
+	desc->ipipe_ack(irq, desc);
+}
+
+/*
+ * __ipipe_enable_pipeline() -- We are running on the boot CPU, hw
+ * interrupts are off, and secondary CPUs are still lost in space.
+ */
+void __ipipe_enable_pipeline(void)
+{
+	unsigned irq;
+
+	__ipipe_core_clock = get_cclk(); /* Fetch this once. */
+	__ipipe_freq_scale = 1000000000UL / __ipipe_core_clock;
+
+	for (irq = 0; irq < NR_IRQS; ++irq)
+		ipipe_virtualize_irq(ipipe_root_domain,
+				     irq,
+				     (ipipe_irq_handler_t)&asm_do_IRQ,
+				     NULL,
+				     &__ipipe_ack_irq,
+				     IPIPE_HANDLE_MASK | IPIPE_PASS_MASK);
+}
+
+/*
+ * __ipipe_handle_irq() -- IPIPE's generic IRQ handler. An optimistic
+ * interrupt protection log is maintained here for each domain. Hw
+ * interrupts are masked on entry.
+ */
+void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
+{
+	struct ipipe_domain *this_domain, *next_domain;
+	struct list_head *head, *pos;
+	int m_ack, s = -1;
+
+	/*
+	 * Software-triggered IRQs do not need any ack.  The contents
+	 * of the register frame should only be used when processing
+	 * the timer interrupt, but not for handling any other
+	 * interrupt.
+	 */
+	m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
+
+	this_domain = ipipe_current_domain;
+
+	if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
+		head = &this_domain->p_link;
+	else {
+		head = __ipipe_pipeline.next;
+		next_domain = list_entry(head, struct ipipe_domain, p_link);
+		if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
+			if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
+				next_domain->irqs[irq].acknowledge(irq, irq_desc + irq);
+			if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags))
+				s = __test_and_set_bit(IPIPE_STALL_FLAG,
+						       &ipipe_root_cpudom_var(status));
+			__ipipe_dispatch_wired(next_domain, irq);
+				goto finalize;
+			return;
+		}
+	}
+
+	/* Ack the interrupt. */
+
+	pos = head;
+
+	while (pos != &__ipipe_pipeline) {
+		next_domain = list_entry(pos, struct ipipe_domain, p_link);
+		/*
+		 * For each domain handling the incoming IRQ, mark it
+		 * as pending in its log.
+		 */
+		if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) {
+			/*
+			 * Domains that handle this IRQ are polled for
+			 * acknowledging it by decreasing priority
+			 * order. The interrupt must be made pending
+			 * _first_ in the domain's status flags before
+			 * the PIC is unlocked.
+			 */
+			__ipipe_set_irq_pending(next_domain, irq);
+
+			if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
+				next_domain->irqs[irq].acknowledge(irq, irq_desc + irq);
+				m_ack = 1;
+			}
+		}
+
+		/*
+		 * If the domain does not want the IRQ to be passed
+		 * down the interrupt pipe, exit the loop now.
+		 */
+		if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
+			break;
+
+		pos = next_domain->p_link.next;
+	}
+
+	/*
+	 * Now walk the pipeline, yielding control to the highest
+	 * priority domain that has pending interrupt(s) or
+	 * immediately to the current domain if the interrupt has been
+	 * marked as 'sticky'. This search does not go beyond the
+	 * current domain in the pipeline. We also enforce the
+	 * additional root stage lock (blackfin-specific). */
+
+	if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags))
+		s = __test_and_set_bit(IPIPE_STALL_FLAG,
+				       &ipipe_root_cpudom_var(status));
+finalize:
+
+	__ipipe_walk_pipeline(head);
+
+	if (!s)
+		__clear_bit(IPIPE_STALL_FLAG,
+			    &ipipe_root_cpudom_var(status));
+}
+
+int __ipipe_check_root(void)
+{
+	return ipipe_root_domain_p;
+}
+
+void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
+{
+	struct irq_desc *desc = irq_desc + irq;
+	int prio = desc->ic_prio;
+
+	desc->depth = 0;
+	if (ipd != &ipipe_root &&
+	    atomic_inc_return(&__ipipe_irq_lvdepth[prio]) == 1)
+		__set_bit(prio, &__ipipe_irq_lvmask);
+}
+EXPORT_SYMBOL(__ipipe_enable_irqdesc);
+
+void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
+{
+	struct irq_desc *desc = irq_desc + irq;
+	int prio = desc->ic_prio;
+
+	if (ipd != &ipipe_root &&
+	    atomic_dec_and_test(&__ipipe_irq_lvdepth[prio]))
+		__clear_bit(prio, &__ipipe_irq_lvmask);
+}
+EXPORT_SYMBOL(__ipipe_disable_irqdesc);
+
+void __ipipe_stall_root_raw(void)
+{
+	/*
+	 * This code is called by the ins{bwl} routines (see
+	 * arch/blackfin/lib/ins.S), which are heavily used by the
+	 * network stack. It masks all interrupts but those handled by
+	 * non-root domains, so that we keep decent network transfer
+	 * rates for Linux without inducing pathological jitter for
+	 * the real-time domain.
+	 */
+	__asm__ __volatile__ ("sti %0;" : : "d"(__ipipe_irq_lvmask));
+
+	__set_bit(IPIPE_STALL_FLAG,
+		  &ipipe_root_cpudom_var(status));
+}
+
+void __ipipe_unstall_root_raw(void)
+{
+	__clear_bit(IPIPE_STALL_FLAG,
+		    &ipipe_root_cpudom_var(status));
+
+	__asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags));
+}
+
+int __ipipe_syscall_root(struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	/* We need to run the IRQ tail hook whenever we don't
+	 * propagate a syscall to higher domains, because we know that
+	 * important operations might be pending there (e.g. Xenomai
+	 * deferred rescheduling). */
+
+	if (!__ipipe_syscall_watched_p(current, regs->orig_p0)) {
+		void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
+		hook();
+		return 0;
+	}
+
+	/*
+	 * This routine either returns:
+	 * 0 -- if the syscall is to be passed to Linux;
+	 * 1 -- if the syscall should not be passed to Linux, and no
+	 * tail work should be performed;
+	 * -1 -- if the syscall should not be passed to Linux but the
+	 * tail work has to be performed (for handling signals etc).
+	 */
+
+	if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) &&
+	    __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) {
+		if (ipipe_root_domain_p && !in_atomic()) {
+			/*
+			 * Sync pending VIRQs before _TIF_NEED_RESCHED
+			 * is tested.
+			 */
+			local_irq_save_hw(flags);
+			if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0)
+				__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
+			local_irq_restore_hw(flags);
+			return -1;
+		}
+		return 1;
+	}
+
+	return 0;
+}
+
+unsigned long ipipe_critical_enter(void (*syncfn) (void))
+{
+	unsigned long flags;
+
+	local_irq_save_hw(flags);
+
+	return flags;
+}
+
+void ipipe_critical_exit(unsigned long flags)
+{
+	local_irq_restore_hw(flags);
+}
+
+static void __ipipe_no_irqtail(void)
+{
+}
+
+int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
+{
+	info->ncpus = num_online_cpus();
+	info->cpufreq = ipipe_cpu_freq();
+	info->archdep.tmirq = IPIPE_TIMER_IRQ;
+	info->archdep.tmfreq = info->cpufreq;
+
+	return 0;
+}
+
+/*
+ * ipipe_trigger_irq() -- Push the interrupt at front of the pipeline
+ * just like if it has been actually received from a hw source. Also
+ * works for virtual interrupts.
+ */
+int ipipe_trigger_irq(unsigned irq)
+{
+	unsigned long flags;
+
+	if (irq >= IPIPE_NR_IRQS ||
+	    (ipipe_virtual_irq_p(irq)
+	     && !test_bit(irq - IPIPE_VIRQ_BASE, &__ipipe_virtual_irq_map)))
+		return -EINVAL;
+
+	local_irq_save_hw(flags);
+
+	__ipipe_handle_irq(irq, NULL);
+
+	local_irq_restore_hw(flags);
+
+	return 1;
+}
+
+/* Move Linux IRQ to threads. */
+
+static int do_irqd(void *__desc)
+{
+	struct irq_desc *desc = __desc;
+	unsigned irq = desc - irq_desc;
+	int thrprio = desc->thr_prio;
+	int thrmask = 1 << thrprio;
+	int cpu = smp_processor_id();
+	cpumask_t cpumask;
+
+	sigfillset(&current->blocked);
+	current->flags |= PF_NOFREEZE;
+	cpumask = cpumask_of_cpu(cpu);
+	set_cpus_allowed(current, cpumask);
+	ipipe_setscheduler_root(current, SCHED_FIFO, 50 + thrprio);
+
+	while (!kthread_should_stop()) {
+		local_irq_disable();
+		if (!(desc->status & IRQ_SCHEDULED)) {
+			set_current_state(TASK_INTERRUPTIBLE);
+resched:
+			local_irq_enable();
+			schedule();
+			local_irq_disable();
+		}
+		__set_current_state(TASK_RUNNING);
+		/*
+		 * If higher priority interrupt servers are ready to
+		 * run, reschedule immediately. We need this for the
+		 * GPIO demux IRQ handler to unmask the interrupt line
+		 * _last_, after all GPIO IRQs have run.
+		 */
+		if (per_cpu(pending_irqthread_mask, cpu) & ~(thrmask|(thrmask-1)))
+			goto resched;
+		if (--per_cpu(pending_irq_count[thrprio], cpu) == 0)
+			per_cpu(pending_irqthread_mask, cpu) &= ~thrmask;
+		desc->status &= ~IRQ_SCHEDULED;
+		desc->thr_handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs));
+		local_irq_enable();
+	}
+	__set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+static void kick_irqd(unsigned irq, void *cookie)
+{
+	struct irq_desc *desc = irq_desc + irq;
+	int thrprio = desc->thr_prio;
+	int thrmask = 1 << thrprio;
+	int cpu = smp_processor_id();
+
+	if (!(desc->status & IRQ_SCHEDULED)) {
+		desc->status |= IRQ_SCHEDULED;
+		per_cpu(pending_irqthread_mask, cpu) |= thrmask;
+		++per_cpu(pending_irq_count[thrprio], cpu);
+		wake_up_process(desc->thread);
+	}
+}
+
+int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc)
+{
+	if (desc->thread || !create_irq_threads)
+		return 0;
+
+	desc->thread = kthread_create(do_irqd, desc, "IRQ %d", irq);
+	if (desc->thread == NULL) {
+		printk(KERN_ERR "irqd: could not create IRQ thread %d!\n", irq);
+		return -ENOMEM;
+	}
+
+	wake_up_process(desc->thread);
+
+	desc->thr_handler = ipipe_root_domain->irqs[irq].handler;
+	ipipe_root_domain->irqs[irq].handler = &kick_irqd;
+
+	return 0;
+}
+
+void __init ipipe_init_irq_threads(void)
+{
+	unsigned irq;
+	struct irq_desc *desc;
+
+	create_irq_threads = 1;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		desc = irq_desc + irq;
+		if (desc->action != NULL ||
+			(desc->status & IRQ_NOREQUEST) != 0)
+			ipipe_start_irq_thread(irq, desc);
+	}
+}
+
+EXPORT_SYMBOL(show_stack);
+
+#ifdef CONFIG_IPIPE_TRACE_MCOUNT
+void notrace _mcount(void);
+EXPORT_SYMBOL(_mcount);
+#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index 1624e11..ab8209c 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -108,8 +108,9 @@
 {
 	struct pt_regs *old_regs;
 	struct irq_desc *desc = irq_desc + irq;
+#ifndef CONFIG_IPIPE
 	unsigned short pending, other_ints;
-
+#endif
 	old_regs = set_irq_regs(regs);
 
 	/*
@@ -137,6 +138,7 @@
 #endif
 	generic_handle_irq(irq);
 
+#ifndef CONFIG_IPIPE	/* Useless and bugous over the I-pipe: IRQs are threaded. */
 	/* If we're the only interrupt running (ignoring IRQ15 which is for
 	   syscalls), lower our priority to IRQ14 so that softirqs run at
 	   that level.  If there's another, lower-level interrupt, irq_exit
@@ -146,6 +148,7 @@
 	other_ints = pending & (pending - 1);
 	if (other_ints == 0)
 		lower_to_irq14();
+#endif /* !CONFIG_IPIPE */
 	irq_exit();
 
 	set_irq_regs(old_regs);
diff --git a/arch/blackfin/kernel/mcount.S b/arch/blackfin/kernel/mcount.S
new file mode 100644
index 0000000..edcfb38
--- /dev/null
+++ b/arch/blackfin/kernel/mcount.S
@@ -0,0 +1,70 @@
+/*
+ * linux/arch/blackfin/mcount.S
+ *
+ * Copyright (C) 2006 Analog Devices Inc.
+ *
+ * 2007/04/12 Save index, length, modify and base registers. --rpm
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+.text
+
+.align 4 	/* just in case */
+
+ENTRY(__mcount)
+	[--sp] = i0;
+	[--sp] = i1;
+	[--sp] = i2;
+	[--sp] = i3;
+	[--sp] = l0;
+	[--sp] = l1;
+	[--sp] = l2;
+	[--sp] = l3;
+	[--sp] = m0;
+	[--sp] = m1;
+	[--sp] = m2;
+	[--sp] = m3;
+	[--sp] = b0;
+	[--sp] = b1;
+	[--sp] = b2;
+	[--sp] = b3;
+	[--sp] = ( r7:0, p5:0 );
+	[--sp] = ASTAT;
+
+	p1.L = _ipipe_trace_enable;
+	p1.H = _ipipe_trace_enable;
+	r7 = [p1];
+	CC = r7 == 0;
+	if CC jump out;
+	link 0x10;
+	r0 = 0x0;
+	[sp + 0xc] = r0; /* v */
+	r0 = 0x0;	/* type: IPIPE_TRACE_FN */
+	r1 = rets;
+	p0 = [fp];	/* p0: Prior FP */
+	r2 = [p0 + 4];	/* r2: Prior RETS */
+	call ___ipipe_trace;
+	unlink;
+out:
+	ASTAT = [sp++];
+	( r7:0, p5:0 ) = [sp++];
+	b3 = [sp++];
+	b2 = [sp++];
+	b1 = [sp++];
+	b0 = [sp++];
+	m3 = [sp++];
+	m2 = [sp++];
+	m1 = [sp++];
+	m0 = [sp++];
+	l3 = [sp++];
+	l2 = [sp++];
+	l1 = [sp++];
+	l0 = [sp++];
+	i3 = [sp++];
+	i2 = [sp++];
+	i1 = [sp++];
+	i0 = [sp++];
+	rts;
+ENDPROC(__mcount)
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 1ec0faa..33e2e89 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -82,11 +82,14 @@
  */
 static void default_idle(void)
 {
-	local_irq_disable();
+#ifdef CONFIG_IPIPE
+	ipipe_suspend_domain();
+#endif
+	local_irq_disable_hw();
 	if (!need_resched())
 		idle_with_irq_disabled();
 
-	local_irq_enable();
+	local_irq_enable_hw();
 }
 
 /*
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index ec4dfa3..172b4c58 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -31,7 +31,7 @@
 #endif
 };
 
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
 void __init setup_system_timer0(void)
 {
 	/* Power down the core timer, just to play safe. */
@@ -74,7 +74,7 @@
 static void __init
 time_sched_init(irqreturn_t(*timer_routine) (int, void *))
 {
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
 	setup_system_timer0();
 	bfin_timer_irq.handler = timer_routine;
 	setup_irq(IRQ_TIMER0, &bfin_timer_irq);
@@ -94,7 +94,7 @@
 	unsigned long offset;
 	unsigned long clocks_per_jiffy;
 
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
 	clocks_per_jiffy = bfin_read_TIMER0_PERIOD();
 	offset = bfin_read_TIMER0_COUNTER() / \
 		(((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
@@ -133,7 +133,8 @@
 	static long last_rtc_update;
 
 	write_seqlock(&xtime_lock);
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
+/* FIXME: Here TIMIL0 is not set when IPIPE enabled, why? */
 	if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
 #endif
 		do_timer(1);
@@ -155,13 +156,17 @@
 				/* Do it again in 60s. */
 				last_rtc_update = xtime.tv_sec - 600;
 		}
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
 		set_gptimer_status(0, TIMER_STATUS_TIMIL0);
 	}
 #endif
 	write_sequnlock(&xtime_lock);
 
+#ifdef CONFIG_IPIPE
+	update_root_process_times(get_irq_regs());
+#else
 	update_process_times(user_mode(get_irq_regs()));
+#endif
 	profile_tick(CPU_PROFILING);
 
 	return IRQ_HANDLED;
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 950cc82..956aefb 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -577,10 +577,15 @@
 		}
 	}
 
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_addr = (void __user *)fp->pc;
-	force_sig_info(sig, &info, current);
+#ifdef CONFIG_IPIPE
+	if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp))
+#endif
+	{
+		info.si_signo = sig;
+		info.si_errno = 0;
+		info.si_addr = (void __user *)fp->pc;
+		force_sig_info(sig, &info, current);
+	}
 
 	trace_buffer_restore(j);
 	return;
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
index d60554d..1b84b21 100644
--- a/arch/blackfin/lib/ins.S
+++ b/arch/blackfin/lib/ins.S
@@ -56,7 +56,16 @@
 ENTRY(_insl)
 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
 	P0 = R0;	/* P0 = port */
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	cli R3;
+#endif
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
 	SSYNC;
@@ -65,7 +74,14 @@
 		[P1++] = R0;
 		NOP;
 .Llong_loop_e: 	NOP;
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	sti R3;
+#endif
 	RTS;
 #else
 	P0 = R0;	/* P0 = port */
@@ -74,13 +90,28 @@
 	SSYNC;
 	LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
 .Llong_loop_s:
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	CLI R3;
+#endif
 	NOP; NOP; NOP;
 	R0 = [P0];
 	[P1++] = R0;
 .Llong_loop_e:
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	STI R3;
-
+#endif
 	RTS;
 #endif
 ENDPROC(_insl)
@@ -88,7 +119,16 @@
 ENTRY(_insw)
 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
 	P0 = R0;	/* P0 = port */
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	cli R3;
+#endif
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
 	SSYNC;
@@ -97,7 +137,14 @@
 		W[P1++] = R0;
 		NOP;
 .Lword_loop_e: 	NOP;
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	sti R3;
+#endif
 	RTS;
 #else
 	P0 = R0;	/* P0 = port */
@@ -106,12 +153,28 @@
 	SSYNC;
 	LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
 .Lword_loop_s:
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	CLI R3;
+#endif
 	NOP; NOP; NOP;
 	R0 = W[P0];
 	W[P1++] = R0;
 .Lword_loop_e:
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	STI R3;
+#endif
 	RTS;
 
 #endif
@@ -120,7 +183,16 @@
 ENTRY(_insw_8)
 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
 	P0 = R0;	/* P0 = port */
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	cli R3;
+#endif
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
 	SSYNC;
@@ -131,7 +203,14 @@
 		B[P1++] = R0;
 		NOP;
 .Lword8_loop_e: NOP;
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	sti R3;
+#endif
 	RTS;
 #else
 	P0 = R0;	/* P0 = port */
@@ -140,7 +219,16 @@
 	SSYNC;
 	LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
 .Lword8_loop_s:
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	CLI R3;
+#endif
 	NOP; NOP; NOP;
 	R0 = W[P0];
 	B[P1++] = R0;
@@ -148,8 +236,14 @@
 	B[P1++] = R0;
 	NOP;
 .Lword8_loop_e:
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	STI R3;
-
+#endif
 	RTS;
 #endif
 ENDPROC(_insw_8)
@@ -157,7 +251,16 @@
 ENTRY(_insb)
 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
 	P0 = R0;	/* P0 = port */
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	cli R3;
+#endif
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
 	SSYNC;
@@ -166,7 +269,14 @@
 		B[P1++] = R0;
 		NOP;
 .Lbyte_loop_e:  NOP;
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	sti R3;
+#endif
 	RTS;
 #else
 	P0 = R0;        /* P0 = port */
@@ -175,13 +285,28 @@
 	SSYNC;
 	LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
 .Lbyte_loop_s:
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	CLI R3;
+#endif
 	NOP; NOP; NOP;
 	R0 = B[P0];
 	B[P1++] = R0;
 .Lbyte_loop_e:
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	STI R3;
-
+#endif
 	RTS;
 #endif
 ENDPROC(_insb)
@@ -189,7 +314,16 @@
 ENTRY(_insl_16)
 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
 	P0 = R0;	/* P0 = port */
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	cli R3;
+#endif
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
 	SSYNC;
@@ -200,7 +334,14 @@
 		  W[P1++] = R0;
 		  NOP;
 .Llong16_loop_e:  NOP;
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	sti R3;
+#endif
 	RTS;
 #else
 	P0 = R0;	/* P0 = port */
@@ -209,14 +350,30 @@
 	SSYNC;
 	LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
 .Llong16_loop_s:
+#ifdef CONFIG_IPIPE
+	[--sp] = rets
+	[--sp] = (P5:0);
+	sp += -12
+	call ___ipipe_stall_root_raw
+	sp += 12
+	(P5:0) = [sp++];
+#else
 	CLI R3;
+#endif
 	NOP; NOP; NOP;
 	R0 = [P0];
 	W[P1++] = R0;
 	R0 = R0 >> 16;
 	W[P1++] = R0;
 .Llong16_loop_e:
+#ifdef CONFIG_IPIPE
+	sp += -12
+	call ___ipipe_unstall_root_raw
+	sp += 12
+	rets = [sp++]
+#else
 	STI R3;
+#endif
 	RTS;
 #endif
 ENDPROC(_insl_16)
diff --git a/arch/blackfin/mach-bf518/Kconfig b/arch/blackfin/mach-bf518/Kconfig
index 00f2d37..f397ede 100644
--- a/arch/blackfin/mach-bf518/Kconfig
+++ b/arch/blackfin/mach-bf518/Kconfig
@@ -154,29 +154,29 @@
 config IRQ_PORTH_INTB
 	int "IRQ_PORTH_INTB"
 	default 11
-config IRQ_TMR0
-	int "IRQ_TMR0"
+config IRQ_TIMER0
+	int "IRQ_TIMER0"
+	default 8
+config IRQ_TIMER1
+	int "IRQ_TIMER1"
 	default 12
-config IRQ_TMR1
-	int "IRQ_TMR1"
+config IRQ_TIMER2
+	int "IRQ_TIMER2"
 	default 12
-config IRQ_TMR2
-	int "IRQ_TMR2"
+config IRQ_TIMER3
+	int "IRQ_TIMER3"
 	default 12
-config IRQ_TMR3
-	int "IRQ_TMR3"
+config IRQ_TIMER4
+	int "IRQ_TIMER4"
 	default 12
-config IRQ_TMR4
-	int "IRQ_TMR4"
+config IRQ_TIMER5
+	int "IRQ_TIMER5"
 	default 12
-config IRQ_TMR5
-	int "IRQ_TMR5"
+config IRQ_TIMER6
+	int "IRQ_TIMER6"
 	default 12
-config IRQ_TMR6
-	int "IRQ_TMR6"
-	default 12
-config IRQ_TMR7
-	int "IRQ_TMR7"
+config IRQ_TIMER7
+	int "IRQ_TIMER7"
 	default 12
 config IRQ_PORTG_INTA
 	int "IRQ_PORTG_INTA"
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
index 9fbcd22..ee3d473 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
@@ -1163,7 +1163,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -1177,7 +1177,7 @@
 
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -1188,7 +1188,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -1202,7 +1202,7 @@
 
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/irq.h b/arch/blackfin/mach-bf518/include/mach/irq.h
index e5062f1..3ff0f09 100644
--- a/arch/blackfin/mach-bf518/include/mach/irq.h
+++ b/arch/blackfin/mach-bf518/include/mach/irq.h
@@ -98,14 +98,14 @@
 #define IRQ_PORTH_INTA   	BFIN_IRQ(29)	/* Port H Interrupt A */
 #define IRQ_MAC_TX		BFIN_IRQ(30)	/* DMA2 Channel (MAC TX) */
 #define IRQ_PORTH_INTB		BFIN_IRQ(31)	/* Port H Interrupt B */
-#define IRQ_TMR0		BFIN_IRQ(32)	/* Timer 0 */
-#define IRQ_TMR1		BFIN_IRQ(33)	/* Timer 1 */
-#define IRQ_TMR2		BFIN_IRQ(34)	/* Timer 2 */
-#define IRQ_TMR3		BFIN_IRQ(35)	/* Timer 3 */
-#define IRQ_TMR4		BFIN_IRQ(36)	/* Timer 4 */
-#define IRQ_TMR5		BFIN_IRQ(37)	/* Timer 5 */
-#define IRQ_TMR6		BFIN_IRQ(38)	/* Timer 6 */
-#define IRQ_TMR7		BFIN_IRQ(39)	/* Timer 7 */
+#define IRQ_TIMER0		BFIN_IRQ(32)	/* Timer 0 */
+#define IRQ_TIMER1		BFIN_IRQ(33)	/* Timer 1 */
+#define IRQ_TIMER2		BFIN_IRQ(34)	/* Timer 2 */
+#define IRQ_TIMER3		BFIN_IRQ(35)	/* Timer 3 */
+#define IRQ_TIMER4		BFIN_IRQ(36)	/* Timer 4 */
+#define IRQ_TIMER5		BFIN_IRQ(37)	/* Timer 5 */
+#define IRQ_TIMER6		BFIN_IRQ(38)	/* Timer 6 */
+#define IRQ_TIMER7		BFIN_IRQ(39)	/* Timer 7 */
 #define IRQ_PORTG_INTA		BFIN_IRQ(40)	/* Port G Interrupt A */
 #define IRQ_PORTG_INTB		BFIN_IRQ(41)	/* Port G Interrupt B */
 #define IRQ_MEM_DMA0		BFIN_IRQ(42)	/* MDMA Stream 0 */
@@ -230,14 +230,14 @@
 #define IRQ_PORTH_INTB_POS	28
 
 /* IAR4 BIT FIELDS */
-#define IRQ_TMR0_POS		0
-#define IRQ_TMR1_POS		4
-#define IRQ_TMR2_POS		8
-#define IRQ_TMR3_POS		12
-#define IRQ_TMR4_POS		16
-#define IRQ_TMR5_POS		20
-#define IRQ_TMR6_POS		24
-#define IRQ_TMR7_POS		28
+#define IRQ_TIMER0_POS		0
+#define IRQ_TIMER1_POS		4
+#define IRQ_TIMER2_POS		8
+#define IRQ_TIMER3_POS		12
+#define IRQ_TIMER4_POS		16
+#define IRQ_TIMER5_POS		20
+#define IRQ_TIMER6_POS		24
+#define IRQ_TIMER7_POS		28
 
 /* IAR5 BIT FIELDS */
 #define IRQ_PORTG_INTA_POS	0
diff --git a/arch/blackfin/mach-bf518/ints-priority.c b/arch/blackfin/mach-bf518/ints-priority.c
index c490c79..3151fd5 100644
--- a/arch/blackfin/mach-bf518/ints-priority.c
+++ b/arch/blackfin/mach-bf518/ints-priority.c
@@ -70,14 +70,14 @@
 			((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
 			((CONFIG_IRQ_PORTH_INTB - 7) << IRQ_PORTH_INTB_POS));
 
-	bfin_write_SIC_IAR4(((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
-			((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
-			((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
-			((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
-			((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS) |
-			((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
-			((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
-			((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS));
+	bfin_write_SIC_IAR4(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+			((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+			((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+			((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+			((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+			((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+			((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+			((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS));
 
 	bfin_write_SIC_IAR5(((CONFIG_IRQ_PORTG_INTA - 7) << IRQ_PORTG_INTA_POS) |
 			((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig
index 3cde4be..8438ec6 100644
--- a/arch/blackfin/mach-bf527/Kconfig
+++ b/arch/blackfin/mach-bf527/Kconfig
@@ -168,29 +168,29 @@
 config IRQ_PORTH_INTB
 	int "IRQ_PORTH_INTB"
 	default 11
-config IRQ_TMR0
-	int "IRQ_TMR0"
+config IRQ_TIMER0
+	int "IRQ_TIMER0"
+	default 8
+config IRQ_TIMER1
+	int "IRQ_TIMER1"
 	default 12
-config IRQ_TMR1
-	int "IRQ_TMR1"
+config IRQ_TIMER2
+	int "IRQ_TIMER2"
 	default 12
-config IRQ_TMR2
-	int "IRQ_TMR2"
+config IRQ_TIMER3
+	int "IRQ_TIMER3"
 	default 12
-config IRQ_TMR3
-	int "IRQ_TMR3"
+config IRQ_TIMER4
+	int "IRQ_TIMER4"
 	default 12
-config IRQ_TMR4
-	int "IRQ_TMR4"
+config IRQ_TIMER5
+	int "IRQ_TIMER5"
 	default 12
-config IRQ_TMR5
-	int "IRQ_TMR5"
+config IRQ_TIMER6
+	int "IRQ_TIMER6"
 	default 12
-config IRQ_TMR6
-	int "IRQ_TMR6"
-	default 12
-config IRQ_TMR7
-	int "IRQ_TMR7"
+config IRQ_TIMER7
+	int "IRQ_TIMER7"
 	default 12
 config IRQ_PORTG_INTA
 	int "IRQ_PORTG_INTA"
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
index 8a374c3..1fe76d8 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
@@ -1163,7 +1163,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -1177,7 +1177,7 @@
 
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -1188,7 +1188,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -1202,7 +1202,7 @@
 
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/irq.h b/arch/blackfin/mach-bf527/include/mach/irq.h
index 4e2b3f2..8ea660d 100644
--- a/arch/blackfin/mach-bf527/include/mach/irq.h
+++ b/arch/blackfin/mach-bf527/include/mach/irq.h
@@ -96,14 +96,14 @@
 #define IRQ_MAC_TX		BFIN_IRQ(30)	/* DMA2 Channel (MAC TX/NAND) */
 #define IRQ_NFC			BFIN_IRQ(30)	/* DMA2 Channel (MAC TX/NAND) */
 #define IRQ_PORTH_INTB		BFIN_IRQ(31)	/* Port H Interrupt B */
-#define IRQ_TMR0		BFIN_IRQ(32)	/* Timer 0 */
-#define IRQ_TMR1		BFIN_IRQ(33)	/* Timer 1 */
-#define IRQ_TMR2		BFIN_IRQ(34)	/* Timer 2 */
-#define IRQ_TMR3		BFIN_IRQ(35)	/* Timer 3 */
-#define IRQ_TMR4		BFIN_IRQ(36)	/* Timer 4 */
-#define IRQ_TMR5		BFIN_IRQ(37)	/* Timer 5 */
-#define IRQ_TMR6		BFIN_IRQ(38)	/* Timer 6 */
-#define IRQ_TMR7		BFIN_IRQ(39)	/* Timer 7 */
+#define IRQ_TIMER0		BFIN_IRQ(32)	/* Timer 0 */
+#define IRQ_TIMER1		BFIN_IRQ(33)	/* Timer 1 */
+#define IRQ_TIMER2		BFIN_IRQ(34)	/* Timer 2 */
+#define IRQ_TIMER3		BFIN_IRQ(35)	/* Timer 3 */
+#define IRQ_TIMER4		BFIN_IRQ(36)	/* Timer 4 */
+#define IRQ_TIMER5		BFIN_IRQ(37)	/* Timer 5 */
+#define IRQ_TIMER6		BFIN_IRQ(38)	/* Timer 6 */
+#define IRQ_TIMER7		BFIN_IRQ(39)	/* Timer 7 */
 #define IRQ_PORTG_INTA		BFIN_IRQ(40)	/* Port G Interrupt A */
 #define IRQ_PORTG_INTB		BFIN_IRQ(41)	/* Port G Interrupt B */
 #define IRQ_MEM_DMA0		BFIN_IRQ(42)	/* MDMA Stream 0 */
@@ -227,14 +227,14 @@
 #define IRQ_PORTH_INTB_POS	28
 
 /* IAR4 BIT FIELDS */
-#define IRQ_TMR0_POS		0
-#define IRQ_TMR1_POS		4
-#define IRQ_TMR2_POS		8
-#define IRQ_TMR3_POS		12
-#define IRQ_TMR4_POS		16
-#define IRQ_TMR5_POS		20
-#define IRQ_TMR6_POS		24
-#define IRQ_TMR7_POS		28
+#define IRQ_TIMER0_POS		0
+#define IRQ_TIMER1_POS		4
+#define IRQ_TIMER2_POS		8
+#define IRQ_TIMER3_POS		12
+#define IRQ_TIMER4_POS		16
+#define IRQ_TIMER5_POS		20
+#define IRQ_TIMER6_POS		24
+#define IRQ_TIMER7_POS		28
 
 /* IAR5 BIT FIELDS */
 #define IRQ_PORTG_INTA_POS	0
diff --git a/arch/blackfin/mach-bf527/ints-priority.c b/arch/blackfin/mach-bf527/ints-priority.c
index 8a23674..f8c8acd 100644
--- a/arch/blackfin/mach-bf527/ints-priority.c
+++ b/arch/blackfin/mach-bf527/ints-priority.c
@@ -69,14 +69,14 @@
 			((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
 			((CONFIG_IRQ_PORTH_INTB - 7) << IRQ_PORTH_INTB_POS));
 
-	bfin_write_SIC_IAR4(((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
-			((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
-			((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
-			((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
-			((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS) |
-			((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
-			((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
-			((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS));
+	bfin_write_SIC_IAR4(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+			((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+			((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+			((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+			((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+			((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+			((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+			((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS));
 
 	bfin_write_SIC_IAR5(((CONFIG_IRQ_PORTG_INTA - 7) << IRQ_PORTG_INTA_POS) |
 			((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
diff --git a/arch/blackfin/mach-bf533/Kconfig b/arch/blackfin/mach-bf533/Kconfig
index 76beb75..14427de 100644
--- a/arch/blackfin/mach-bf533/Kconfig
+++ b/arch/blackfin/mach-bf533/Kconfig
@@ -59,7 +59,7 @@
 	default 10
 config TIMER0
 	int "TIMER0"
-	default 11
+	default 8
 config TIMER1
 	int "TIMER1"
 	default 11
diff --git a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
index d7b08f6..bbc3c83 100644
--- a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
@@ -684,10 +684,10 @@
 static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
 { \
 	unsigned long flags; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	bfin_write16(FIO_FLAG_##name, val); \
 	bfin_read_CHIPID(); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 }
 BFIN_WRITE_FIO_FLAG(D)
 BFIN_WRITE_FIO_FLAG(C)
@@ -699,10 +699,10 @@
 { \
 	unsigned long flags; \
 	u16 ret; \
-	local_irq_save(flags); \
+	local_irq_save_hw(flags); \
 	ret = bfin_read16(FIO_FLAG_##name); \
 	bfin_read_CHIPID(); \
-	local_irq_restore(flags); \
+	local_irq_restore_hw(flags); \
 	return ret; \
 }
 BFIN_READ_FIO_FLAG(D)
@@ -729,7 +729,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr = bfin_read32(SIC_IWR);
 	/* Only allow PPL Wakeup) */
@@ -740,7 +740,7 @@
 	asm("IDLE;");
 
 	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -751,7 +751,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr = bfin_read32(SIC_IWR);
 	/* Only allow PPL Wakeup) */
@@ -762,7 +762,7 @@
 	asm("IDLE;");
 
 	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif				/* _CDEF_BF532_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/irq.h b/arch/blackfin/mach-bf533/include/mach/irq.h
index e7dd315..db1e346 100644
--- a/arch/blackfin/mach-bf533/include/mach/irq.h
+++ b/arch/blackfin/mach-bf533/include/mach/irq.h
@@ -100,9 +100,9 @@
 #define	IRQ_SPI			20	/*DMA5 Interrupt (SPI) */
 #define	IRQ_UART0_RX		21	/*DMA6 Interrupt (UART RX) */
 #define	IRQ_UART0_TX		22	/*DMA7 Interrupt (UART TX) */
-#define	IRQ_TMR0		23	/*Timer 0 */
-#define	IRQ_TMR1		24	/*Timer 1 */
-#define	IRQ_TMR2		25	/*Timer 2 */
+#define	IRQ_TIMER0		23	/*Timer 0 */
+#define	IRQ_TIMER1		24	/*Timer 1 */
+#define	IRQ_TIMER2		25	/*Timer 2 */
 #define	IRQ_PROG_INTA		26	/*Programmable Flags A (8) */
 #define	IRQ_PROG_INTB		27	/*Programmable Flags B (8) */
 #define	IRQ_MEM_DMA0		28	/*DMA8/9 Interrupt (Memory DMA Stream 0) */
diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig
index 8255374..bbc08fd 100644
--- a/arch/blackfin/mach-bf537/Kconfig
+++ b/arch/blackfin/mach-bf537/Kconfig
@@ -64,29 +64,29 @@
 config IRQ_MAC_TX
 	int "IRQ_MAC_TX"
 	default 11
-config IRQ_TMR0
-	int "IRQ_TMR0"
+config IRQ_TIMER0
+	int "IRQ_TIMER0"
+	default 8
+config IRQ_TIMER1
+	int "IRQ_TIMER1"
 	default 12
-config IRQ_TMR1
-	int "IRQ_TMR1"
+config IRQ_TIMER2
+	int "IRQ_TIMER2"
 	default 12
-config IRQ_TMR2
-	int "IRQ_TMR2"
+config IRQ_TIMER3
+	int "IRQ_TIMER3"
 	default 12
-config IRQ_TMR3
-	int "IRQ_TMR3"
+config IRQ_TIMER4
+	int "IRQ_TIMER4"
 	default 12
-config IRQ_TMR4
-	int "IRQ_TMR4"
+config IRQ_TIMER5
+	int "IRQ_TIMER5"
 	default 12
-config IRQ_TMR5
-	int "IRQ_TMR5"
+config IRQ_TIMER6
+	int "IRQ_TIMER6"
 	default 12
-config IRQ_TMR6
-	int "IRQ_TMR6"
-	default 12
-config IRQ_TMR7
-	int "IRQ_TMR7"
+config IRQ_TIMER7
+	int "IRQ_TIMER7"
 	default 12
 config IRQ_PROG_INTA
 	int "IRQ_PROG_INTA"
diff --git a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
index f341692..5f8b5f8 100644
--- a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
@@ -1783,7 +1783,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr = bfin_read32(SIC_IWR);
 	/* Only allow PPL Wakeup) */
@@ -1794,7 +1794,7 @@
 	asm("IDLE;");
 
 	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -1805,7 +1805,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr = bfin_read32(SIC_IWR);
 	/* Only allow PPL Wakeup) */
@@ -1816,7 +1816,7 @@
 	asm("IDLE;");
 
 	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif				/* _CDEF_BF534_H */
diff --git a/arch/blackfin/mach-bf537/include/mach/irq.h b/arch/blackfin/mach-bf537/include/mach/irq.h
index 2e68a8a..b2a71d5 100644
--- a/arch/blackfin/mach-bf537/include/mach/irq.h
+++ b/arch/blackfin/mach-bf537/include/mach/irq.h
@@ -82,14 +82,14 @@
 #define IRQ_CAN_TX          23	/*CAN Transmit Interrupt */
 #define IRQ_MAC_RX          24	/*DMA1 (Ethernet RX) Interrupt */
 #define IRQ_MAC_TX          25	/*DMA2 (Ethernet TX) Interrupt */
-#define IRQ_TMR0            26	/*Timer 0 */
-#define IRQ_TMR1            27	/*Timer 1 */
-#define IRQ_TMR2            28	/*Timer 2 */
-#define IRQ_TMR3            29	/*Timer 3 */
-#define IRQ_TMR4            30	/*Timer 4 */
-#define IRQ_TMR5            31	/*Timer 5 */
-#define IRQ_TMR6            32	/*Timer 6 */
-#define IRQ_TMR7            33	/*Timer 7 */
+#define IRQ_TIMER0            26	/*Timer 0 */
+#define IRQ_TIMER1            27	/*Timer 1 */
+#define IRQ_TIMER2            28	/*Timer 2 */
+#define IRQ_TIMER3            29	/*Timer 3 */
+#define IRQ_TIMER4            30	/*Timer 4 */
+#define IRQ_TIMER5            31	/*Timer 5 */
+#define IRQ_TIMER6            32	/*Timer 6 */
+#define IRQ_TIMER7            33	/*Timer 7 */
 #define IRQ_PROG_INTA       34	/* PF Ports F&G (PF15:0) Interrupt A */
 #define IRQ_PORTG_INTB      35	/* PF Port G (PF15:0) Interrupt B */
 #define IRQ_MEM_DMA0        36	/*(Memory DMA Stream 0) */
@@ -195,16 +195,16 @@
 #define IRQ_CAN_TX_POS      0
 #define IRQ_MAC_RX_POS      4
 #define IRQ_MAC_TX_POS      8
-#define IRQ_TMR0_POS        12
-#define IRQ_TMR1_POS        16
-#define IRQ_TMR2_POS        20
-#define IRQ_TMR3_POS        24
-#define IRQ_TMR4_POS        28
+#define IRQ_TIMER0_POS        12
+#define IRQ_TIMER1_POS        16
+#define IRQ_TIMER2_POS        20
+#define IRQ_TIMER3_POS        24
+#define IRQ_TIMER4_POS        28
 
 /* IAR3 BIT FIELDS*/
-#define IRQ_TMR5_POS        0
-#define IRQ_TMR6_POS        4
-#define IRQ_TMR7_POS        8
+#define IRQ_TIMER5_POS        0
+#define IRQ_TIMER6_POS        4
+#define IRQ_TIMER7_POS        8
 #define IRQ_PROG_INTA_POS   12
 #define IRQ_PORTG_INTB_POS   16
 #define IRQ_MEM_DMA0_POS    20
diff --git a/arch/blackfin/mach-bf537/ints-priority.c b/arch/blackfin/mach-bf537/ints-priority.c
index b1300b3..51c4808 100644
--- a/arch/blackfin/mach-bf537/ints-priority.c
+++ b/arch/blackfin/mach-bf537/ints-priority.c
@@ -55,15 +55,15 @@
 	bfin_write_SIC_IAR2(((CONFIG_IRQ_CAN_TX - 7) << IRQ_CAN_TX_POS) |
 			    ((CONFIG_IRQ_MAC_RX - 7) << IRQ_MAC_RX_POS) |
 			    ((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
-			    ((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
-			    ((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
-			    ((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
-			    ((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
-			    ((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS));
+			    ((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+			    ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+			    ((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+			    ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+			    ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS));
 
-	bfin_write_SIC_IAR3(((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
-			    ((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
-			    ((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS) |
+	bfin_write_SIC_IAR3(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+			    ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+			    ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
 			    ((CONFIG_IRQ_PROG_INTA - 7) << IRQ_PROG_INTA_POS) |
 			    ((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
 			    ((CONFIG_IRQ_MEM_DMA0 - 7) << IRQ_MEM_DMA0_POS) |
diff --git a/arch/blackfin/mach-bf538/Kconfig b/arch/blackfin/mach-bf538/Kconfig
index a6f3307..f068c35 100644
--- a/arch/blackfin/mach-bf538/Kconfig
+++ b/arch/blackfin/mach-bf538/Kconfig
@@ -55,14 +55,14 @@
 config IRQ_UART0_TX
 	int "IRQ_UART0_TX"
 	default 10
-config IRQ_TMR0
-	int "IRQ_TMR0"
+config IRQ_TIMER0
+	int "IRQ_TIMER0"
+	default 8
+config IRQ_TIMER1
+	int "IRQ_TIMER1"
 	default 11
-config IRQ_TMR1
-	int "IRQ_TMR1"
-	default 11
-config IRQ_TMR2
-	int "IRQ_TMR2"
+config IRQ_TIMER2
+	int "IRQ_TIMER2"
 	default 11
 config IRQ_PORTF_INTA
 	int "IRQ_PORTF_INTA"
diff --git a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
index 7e469b8..241725b 100644
--- a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
+++ b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
@@ -2063,7 +2063,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -2077,7 +2077,7 @@
 
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -2088,7 +2088,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -2102,7 +2102,7 @@
 
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif
diff --git a/arch/blackfin/mach-bf538/include/mach/irq.h b/arch/blackfin/mach-bf538/include/mach/irq.h
index 60bdac4..fdc87fe 100644
--- a/arch/blackfin/mach-bf538/include/mach/irq.h
+++ b/arch/blackfin/mach-bf538/include/mach/irq.h
@@ -81,9 +81,9 @@
 #define IRQ_SPI0		BFIN_IRQ(13)	/* DMA 5 Channel (SPI0) */
 #define IRQ_UART0_RX		BFIN_IRQ(14)	/* DMA 6 Channel (UART0 RX) */
 #define IRQ_UART0_TX		BFIN_IRQ(15)	/* DMA 7 Channel (UART0 TX) */
-#define IRQ_TMR0		BFIN_IRQ(16)	/* Timer 0 */
-#define IRQ_TMR1		BFIN_IRQ(17)	/* Timer 1 */
-#define IRQ_TMR2		BFIN_IRQ(18)	/* Timer 2 */
+#define IRQ_TIMER0		BFIN_IRQ(16)	/* Timer 0 */
+#define IRQ_TIMER1		BFIN_IRQ(17)	/* Timer 1 */
+#define IRQ_TIMER2		BFIN_IRQ(18)	/* Timer 2 */
 #define IRQ_PORTF_INTA		BFIN_IRQ(19)	/* Port F Interrupt A */
 #define IRQ_PORTF_INTB		BFIN_IRQ(20)	/* Port F Interrupt B */
 #define IRQ_MEM0_DMA0		BFIN_IRQ(21)	/* MDMA0 Stream 0 */
@@ -168,9 +168,9 @@
 #define IRQ_UART0_TX_POS	28
 
 /* IAR2 BIT FIELDS */
-#define IRQ_TMR0_POS		0
-#define IRQ_TMR1_POS		4
-#define IRQ_TMR2_POS		8
+#define IRQ_TIMER0_POS		0
+#define IRQ_TIMER1_POS		4
+#define IRQ_TIMER2_POS		8
 #define IRQ_PORTF_INTA_POS	12
 #define IRQ_PORTF_INTB_POS	16
 #define IRQ_MEM0_DMA0_POS	20
diff --git a/arch/blackfin/mach-bf538/ints-priority.c b/arch/blackfin/mach-bf538/ints-priority.c
index f81f2ac..70d17e5 100644
--- a/arch/blackfin/mach-bf538/ints-priority.c
+++ b/arch/blackfin/mach-bf538/ints-priority.c
@@ -53,9 +53,9 @@
 			((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
 			((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
 
-	bfin_write_SIC_IAR2(((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
-			((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
-			((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
+	bfin_write_SIC_IAR2(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+			((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+			((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
 			((CONFIG_IRQ_PORTF_INTA - 7) << IRQ_PORTF_INTA_POS) |
 			((CONFIG_IRQ_PORTF_INTB - 7) << IRQ_PORTF_INTB_POS) |
 			((CONFIG_IRQ_MEM0_DMA0 - 7) << IRQ_MEM0_DMA0_POS) |
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
index 1bfcd8f..dcf6571 100644
--- a/arch/blackfin/mach-bf548/Kconfig
+++ b/arch/blackfin/mach-bf548/Kconfig
@@ -250,7 +250,7 @@
 	default 11
 config IRQ_TIMER0
 	int "IRQ_TIMER0"
-	default 11
+	default 8
 config IRQ_TIMER1
 	int "IRQ_TIMER1"
 	default 11
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
index 0a3b210..6e636c4 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
@@ -2702,7 +2702,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -2719,7 +2719,7 @@
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
 	bfin_write32(SIC_IWR2, iwr2);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -2730,7 +2730,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SIC_IWR0);
 	iwr1 = bfin_read32(SIC_IWR1);
@@ -2747,7 +2747,7 @@
 	bfin_write32(SIC_IWR0, iwr0);
 	bfin_write32(SIC_IWR1, iwr1);
 	bfin_write32(SIC_IWR2, iwr2);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif /* _CDEF_BF54X_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h
index ad380d1..60299a7 100644
--- a/arch/blackfin/mach-bf548/include/mach/irq.h
+++ b/arch/blackfin/mach-bf548/include/mach/irq.h
@@ -158,7 +158,7 @@
 #define IRQ_PINT2		BFIN_IRQ(94)	/* PINT2 Interrupt */
 #define IRQ_PINT3		BFIN_IRQ(95)	/* PINT3 Interrupt */
 
-#define SYS_IRQS        	IRQ_PINT3
+#define SYS_IRQS		IRQ_PINT3
 
 #define BFIN_PA_IRQ(x)		((x) + SYS_IRQS + 1)
 #define IRQ_PA0			BFIN_PA_IRQ(0)
diff --git a/arch/blackfin/mach-bf561/Kconfig b/arch/blackfin/mach-bf561/Kconfig
index 5d56438..638ec38 100644
--- a/arch/blackfin/mach-bf561/Kconfig
+++ b/arch/blackfin/mach-bf561/Kconfig
@@ -138,7 +138,7 @@
 	default 9
 config IRQ_TIMER0
 	int "TIMER 0  Interrupt"
-	default 10
+	default 8
 config IRQ_TIMER1
 	int "TIMER 1  Interrupt"
 	default 10
diff --git a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
index b16875d..95d609f 100644
--- a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
@@ -1537,7 +1537,7 @@
 	if (val == bfin_read_PLL_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SICA_IWR0);
 	iwr1 = bfin_read32(SICA_IWR1);
@@ -1551,7 +1551,7 @@
 
 	bfin_write32(SICA_IWR0, iwr0);
 	bfin_write32(SICA_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 /* Writing to VR_CTL initiates a PLL relock sequence. */
@@ -1562,7 +1562,7 @@
 	if (val == bfin_read_VR_CTL())
 		return;
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr0 = bfin_read32(SICA_IWR0);
 	iwr1 = bfin_read32(SICA_IWR1);
@@ -1576,7 +1576,7 @@
 
 	bfin_write32(SICA_IWR0, iwr0);
 	bfin_write32(SICA_IWR1, iwr1);
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 #endif				/* _CDEF_BF561_H */
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index 56f68d8..72e16605 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -104,7 +104,7 @@
 		 cclk_hz, target_freq, freqs.old);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 		plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
 		tscale = dpm_state_table[index].tscale;
 		bfin_write_PLL_DIV(plldiv);
@@ -115,7 +115,7 @@
 	cycles += 10; /* ~10 cycles we lose after get_cycles() */
 	__bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index);
 	__bfin_cycles_mod = index;
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 	/* TODO: just test case for cycles clock source, remove later */
 	pr_debug("cpufreq: done\n");
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 2604b53..c1bdd1e 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -129,8 +129,15 @@
 #endif
 	r1 =  sp;
 	SP += -12;
+#ifdef CONFIG_IPIPE
+	call ___ipipe_grab_irq
+	SP += 12;
+	cc = r0 == 0;
+	if cc jump .Lcommon_restore_context;
+#else /* CONFIG_IPIPE */
 	call _do_irq;
 	SP += 12;
+#endif /* CONFIG_IPIPE */
 	call _return_from_int;
 .Lcommon_restore_context:
 	RESTORE_CONTEXT
@@ -247,3 +254,56 @@
 	call _system_call;
 	jump .Lcommon_restore_context;
 ENDPROC(_evt_system_call)
+
+#ifdef CONFIG_IPIPE
+ENTRY(___ipipe_call_irqtail)
+	r0.l = 1f;
+	r0.h = 1f;
+	reti = r0;
+	rti;
+1:
+	[--sp] = rets;
+	[--sp] = ( r7:4, p5:3 );
+	p0.l = ___ipipe_irq_tail_hook;
+	p0.h = ___ipipe_irq_tail_hook;
+	p0 = [p0];
+	sp += -12;
+	call (p0);
+	sp += 12;
+	( r7:4, p5:3 ) = [sp++];
+	rets = [sp++];
+
+	[--sp] = reti;
+	reti = [sp++];          /* IRQs are off. */
+	r0.h = 3f;
+	r0.l = 3f;
+	p0.l = lo(EVT14);
+	p0.h = hi(EVT14);
+	[p0] = r0;
+	csync;
+	r0 = 0x401f;
+	sti r0;
+	raise 14;
+	[--sp] = reti;          /* IRQs on. */
+2:
+	jump 2b;                /* Likely paranoid. */
+3:
+	sp += 4;                /* Discard saved RETI */
+	r0.h = _evt14_softirq;
+	r0.l = _evt14_softirq;
+	p0.l = lo(EVT14);
+	p0.h = hi(EVT14);
+	[p0] = r0;
+	csync;
+	p0.l = _bfin_irq_flags;
+	p0.h = _bfin_irq_flags;
+	r0 = [p0];
+	sti r0;
+#if 0 /* FIXME: this actually raises scheduling latencies */
+	/* Reenable interrupts */
+	[--sp] = reti;
+	r0 = [sp++];
+#endif
+	rts;
+ENDPROC(___ipipe_call_irqtail)
+#endif /* CONFIG_IPIPE */
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 7c1db77..1bba603 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -34,6 +34,9 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
+#ifdef CONFIG_IPIPE
+#include <linux/ipipe.h>
+#endif
 #ifdef CONFIG_KGDB
 #include <linux/kgdb.h>
 #endif
@@ -135,8 +138,8 @@
 static void bfin_core_mask_irq(unsigned int irq)
 {
 	bfin_irq_flags &= ~(1 << irq);
-	if (!irqs_disabled())
-		local_irq_enable();
+	if (!irqs_disabled_hw())
+		local_irq_enable_hw();
 }
 
 static void bfin_core_unmask_irq(unsigned int irq)
@@ -151,8 +154,8 @@
 	 * local_irq_enable just does "STI bfin_irq_flags", so it's exactly
 	 * what we need.
 	 */
-	if (!irqs_disabled())
-		local_irq_enable();
+	if (!irqs_disabled_hw())
+		local_irq_enable_hw();
 	return;
 }
 
@@ -235,7 +238,7 @@
 	break;
 	}
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	if (state) {
 		bfin_sic_iwr[bank] |= (1 << bit);
@@ -246,7 +249,7 @@
 		vr_wakeup  &= ~wakeup;
 	}
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 
 	return 0;
 }
@@ -272,6 +275,19 @@
 #endif
 };
 
+static void bfin_handle_irq(unsigned irq)
+{
+#ifdef CONFIG_IPIPE
+	struct pt_regs regs;    /* Contents not used. */
+	ipipe_trace_irq_entry(irq);
+	__ipipe_handle_irq(irq, &regs);
+	ipipe_trace_irq_exit(irq);
+#else /* !CONFIG_IPIPE */
+	struct irq_desc *desc = irq_desc + irq;
+	desc->handle_irq(irq, desc);
+#endif  /* !CONFIG_IPIPE */
+}
+
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 static int error_int_mask;
 
@@ -325,10 +341,9 @@
 		irq = IRQ_UART1_ERROR;
 
 	if (irq) {
-		if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) {
-			struct irq_desc *desc = irq_desc + irq;
-			desc->handle_irq(irq, desc);
-		} else {
+		if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR)))
+			bfin_handle_irq(irq);
+		else {
 
 			switch (irq) {
 			case IRQ_PPI_ERROR:
@@ -374,10 +389,14 @@
 
 static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 {
+#ifdef CONFIG_IPIPE
+	_set_irq_handler(irq, handle_edge_irq);
+#else
 	struct irq_desc *desc = irq_desc + irq;
 	/* May not call generic set_irq_handler() due to spinlock
 	   recursion. */
 	desc->handle_irq = handle;
+#endif
 }
 
 static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
@@ -563,10 +582,8 @@
 			mask = get_gpiop_data(i) & get_gpiop_maska(i);
 
 			while (mask) {
-				if (mask & 1) {
-					desc = irq_desc + irq;
-					desc->handle_irq(irq, desc);
-				}
+				if (mask & 1)
+					bfin_handle_irq(irq);
 				irq++;
 				mask >>= 1;
 			}
@@ -576,10 +593,8 @@
 			mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio);
 
 			do {
-				if (mask & 1) {
-					desc = irq_desc + irq;
-					desc->handle_irq(irq, desc);
-				}
+				if (mask & 1)
+					bfin_handle_irq(irq);
 				irq++;
 				mask >>= 1;
 			} while (mask);
@@ -900,8 +915,7 @@
 	while (request) {
 		if (request & 1) {
 			irq = pint2irq_lut[pint_val] + SYS_IRQS;
-			desc = irq_desc + irq;
-			desc->handle_irq(irq, desc);
+			bfin_handle_irq(irq);
 		}
 		pint_val++;
 		request >>= 1;
@@ -1025,11 +1039,10 @@
 			break;
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 		case IRQ_GENERIC_ERROR:
-			set_irq_handler(irq, bfin_demux_error_irq);
-
+			set_irq_chained_handler(irq, bfin_demux_error_irq);
 			break;
 #endif
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
 		case IRQ_TIMER0:
 			set_irq_handler(irq, handle_percpu_irq);
 			break;
@@ -1041,7 +1054,17 @@
 			break;
 #endif
 		default:
+#ifdef CONFIG_IPIPE
+	/*
+	 * We want internal interrupt sources to be masked, because
+	 * ISRs may trigger interrupts recursively (e.g. DMA), but
+	 * interrupts are _not_ masked at CPU level. So let's handle
+	 * them as level interrupts.
+	 */
+			set_irq_handler(irq, handle_level_irq);
+#else /* !CONFIG_IPIPE */
 			set_irq_handler(irq, handle_simple_irq);
+#endif /* !CONFIG_IPIPE */
 			break;
 		}
 	}
@@ -1101,6 +1124,14 @@
 	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
 #endif
 
+#ifdef CONFIG_IPIPE
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		struct irq_desc *desc = irq_desc + irq;
+		desc->ic_prio = __ipipe_get_irq_priority(irq);
+		desc->thr_prio = __ipipe_get_irqthread_priority(irq);
+	}
+#endif /* CONFIG_IPIPE */
+
 	return 0;
 }
 
@@ -1156,3 +1187,161 @@
 	}
 	asm_do_IRQ(vec, fp);
 }
+
+#ifdef CONFIG_IPIPE
+
+int __ipipe_get_irq_priority(unsigned irq)
+{
+	int ient, prio;
+
+	if (irq <= IRQ_CORETMR)
+		return irq;
+
+	for (ient = 0; ient < NR_PERI_INTS; ient++) {
+		struct ivgx *ivg = ivg_table + ient;
+		if (ivg->irqno == irq) {
+			for (prio = 0; prio <= IVG13-IVG7; prio++) {
+				if (ivg7_13[prio].ifirst <= ivg &&
+				    ivg7_13[prio].istop > ivg)
+					return IVG7 + prio;
+			}
+		}
+	}
+
+	return IVG15;
+}
+
+int __ipipe_get_irqthread_priority(unsigned irq)
+{
+	int ient, prio;
+	int demux_irq;
+
+	/* The returned priority value is rescaled to [0..IVG13+1]
+	 * with 0 being the lowest effective priority level. */
+
+	if (irq <= IRQ_CORETMR)
+		return IVG13 - irq + 1;
+
+	/* GPIO IRQs are given the priority of the demux
+	 * interrupt. */
+	if (IS_GPIOIRQ(irq)) {
+#if defined(CONFIG_BF54x)
+		u32 bank = PINT_2_BANK(irq2pint_lut[irq - SYS_IRQS]);
+		demux_irq = (bank == 0 ? IRQ_PINT0 :
+				bank == 1 ? IRQ_PINT1 :
+				bank == 2 ? IRQ_PINT2 :
+				IRQ_PINT3);
+#elif defined(CONFIG_BF561)
+		demux_irq = (irq >= IRQ_PF32 ? IRQ_PROG2_INTA :
+				irq >= IRQ_PF16 ? IRQ_PROG1_INTA :
+				IRQ_PROG0_INTA);
+#elif defined(CONFIG_BF52x)
+		demux_irq = (irq >= IRQ_PH0 ? IRQ_PORTH_INTA :
+				irq >= IRQ_PG0 ? IRQ_PORTG_INTA :
+				IRQ_PORTF_INTA);
+#else
+		demux_irq = irq;
+#endif
+		return IVG13 - PRIO_GPIODEMUX(demux_irq) + 1;
+	}
+
+	/* The GPIO demux interrupt is given a lower priority
+	 * than the GPIO IRQs, so that its threaded handler
+	 * unmasks the interrupt line after the decoded IRQs
+	 * have been processed. */
+	prio = PRIO_GPIODEMUX(irq);
+	/* demux irq? */
+	if (prio != -1)
+		return IVG13 - prio;
+
+	for (ient = 0; ient < NR_PERI_INTS; ient++) {
+		struct ivgx *ivg = ivg_table + ient;
+		if (ivg->irqno == irq) {
+			for (prio = 0; prio <= IVG13-IVG7; prio++) {
+				if (ivg7_13[prio].ifirst <= ivg &&
+				    ivg7_13[prio].istop > ivg)
+					return IVG7 - prio;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */
+#ifdef CONFIG_DO_IRQ_L1
+__attribute__((l1_text))
+#endif
+asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
+{
+	struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
+	struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
+	int irq;
+
+	if (likely(vec == EVT_IVTMR_P)) {
+		irq = IRQ_CORETMR;
+		goto handle_irq;
+	}
+
+	SSYNC();
+
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+	{
+		unsigned long sic_status[3];
+
+		sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
+		sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
+#ifdef CONFIG_BF54x
+		sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
+#endif
+		for (;; ivg++) {
+			if (ivg >= ivg_stop) {
+				atomic_inc(&num_spurious);
+				return 0;
+			}
+			if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
+				break;
+		}
+	}
+#else
+	{
+		unsigned long sic_status;
+
+		sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
+
+		for (;; ivg++) {
+			if (ivg >= ivg_stop) {
+				atomic_inc(&num_spurious);
+				return 0;
+			} else if (sic_status & ivg->isrflag)
+				break;
+		}
+	}
+#endif
+
+	irq = ivg->irqno;
+
+	if (irq == IRQ_SYSTMR) {
+		bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */
+		/* This is basically what we need from the register frame. */
+		__raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend;
+		__raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc;
+		if (!ipipe_root_domain_p)
+			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
+		else
+			__raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10;
+	}
+
+handle_irq:
+
+	ipipe_trace_irq_entry(irq);
+	__ipipe_handle_irq(irq, regs);
+       ipipe_trace_irq_exit(irq);
+
+       if (ipipe_root_domain_p)
+		return !test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
+
+       return 0;
+}
+
+#endif /* CONFIG_IPIPE */
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 96600b8..d3d70fd 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -71,7 +71,7 @@
 	gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
 #endif
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 	bfin_pm_standby_setup();
 
 #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
@@ -105,7 +105,7 @@
 	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
 #endif
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 }
 
 int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -249,12 +249,12 @@
 	wakeup |= GPWE;
 #endif
 
-	local_irq_save(flags);
+	local_irq_save_hw(flags);
 
 	ret = blackfin_dma_suspend();
 
 	if (ret) {
-		local_irq_restore(flags);
+		local_irq_restore_hw(flags);
 		kfree(memptr);
 		return ret;
 	}
@@ -275,7 +275,7 @@
 	bfin_gpio_pm_hibernate_restore();
 	blackfin_dma_resume();
 
-	local_irq_restore(flags);
+	local_irq_restore_hw(flags);
 	kfree(memptr);
 
 	return 0;
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 66c47a7..77c9928 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -348,7 +348,7 @@
 
 static void __cpuinit setup_secondary(unsigned int cpu)
 {
-#ifndef CONFIG_TICK_SOURCE_SYSTMR0
+#if !(defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE))
 	struct irq_desc *timer_desc;
 #endif
 	unsigned long ilat;
@@ -369,7 +369,7 @@
 	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
 	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
 
-#ifdef CONFIG_TICK_SOURCE_SYSTMR0
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
 	/* Power down the core timer, just to play safe. */
 	bfin_write_TCNTL(0);