select GENERIC_LIB_MULDI3
        select GENERIC_LIB_UCMPDI2
        select GENERIC_TIME_VSYSCALL
-       select HANDLE_DOMAIN_IRQ
        select HAVE_ARCH_TRACEHOOK
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_EXIT_THREAD
 
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
+#include <linux/hardirq.h>
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip.h>
 #include <nds32_intrinsic.h>
 
+#include <asm/irq_regs.h>
+
 unsigned long wake_mask;
 
 static void ativic32_ack_irq(struct irq_data *data)
                - NDS32_VECTOR_offINTERRUPT;
 }
 
-asmlinkage void asm_do_IRQ(struct pt_regs *regs)
+static void ativic32_handle_irq(struct pt_regs *regs)
 {
        irq_hw_number_t hwirq = get_intr_src();
-       handle_domain_irq(root_domain, hwirq, regs);
+       generic_handle_domain_irq(root_domain, hwirq);
+}
+
+/*
+ * TODO: convert nds32 to GENERIC_IRQ_MULTI_HANDLER so that this entry logic
+ * can live in arch code.
+ */
+asmlinkage void asm_do_IRQ(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs;
+
+       irq_enter();
+       old_regs = set_irq_regs(regs);
+       ativic32_handle_irq(regs);
+       set_irq_regs(old_regs);
+       irq_exit();
 }
 
 int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)