2 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
3 * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
10 #include <linux/init.h>
11 #include <linux/kernel_stat.h>
12 #include <linux/signal.h>
13 #include <linux/sched.h>
14 #include <linux/interrupt.h>
15 #include <linux/slab.h>
16 #include <linux/random.h>
18 #include <linux/irq.h>
19 #include <asm/mipsregs.h>
20 #include <asm/irq_cpu.h>
24 /* interrupt controller */
25 #define IRQ_STATUS_REG 0x00 /* Read */
26 #define IRQ_ENABLE_REG 0x08 /* Read/Write */
27 #define IRQ_DISABLE_REG 0x0C /* Write */
29 #define IRQ_MASK 0xffff
31 static inline void intc_write_reg(u32 val
, unsigned int reg
)
33 void __iomem
*base
= (void __iomem
*)KSEG1ADDR(ADM8668_INTC_BASE
);
35 __raw_writel(val
, base
+ reg
);
38 static inline u32
intc_read_reg(unsigned int reg
)
40 void __iomem
*base
= (void __iomem
*)KSEG1ADDR(ADM8668_INTC_BASE
);
42 return __raw_readl(base
+ reg
);
45 static void adm8668_irq_cascade(void)
50 intsrc
= intc_read_reg(IRQ_STATUS_REG
) & IRQ_MASK
;
52 irq
= fls(intsrc
) - 1;
61 void plat_irq_dispatch(void)
65 pending
= read_c0_cause() & read_c0_status() & ST0_IM
;
67 /* timer interrupt, that we renumbered */
68 if (pending
& STATUSF_IP7
)
69 do_IRQ(MIPS_CPU_IRQ_BASE
+ 7);
70 else if (pending
& STATUSF_IP2
)
71 adm8668_irq_cascade();
79 static void enable_adm8668_irq(struct irq_data
*d
)
81 intc_write_reg((1 << d
->irq
), IRQ_ENABLE_REG
);
85 static void ack_adm8668_irq(struct irq_data
*d
)
87 intc_write_reg((1 << d
->irq
), IRQ_DISABLE_REG
);
94 static struct irq_chip adm8668_irq_type
= {
96 .irq_ack
= ack_adm8668_irq
,
97 .irq_mask
= ack_adm8668_irq
,
98 .irq_unmask
= enable_adm8668_irq
104 static void __init
init_adm8668_irqs(void)
108 /* disable all interrupts for the moment */
109 intc_write_reg(IRQ_MASK
, IRQ_DISABLE_REG
);
111 for (i
= 0; i
<= ADM8668_IRQ_MAX
; i
++)
112 irq_set_chip_and_handler(i
, &adm8668_irq_type
,
115 /* hw0 is where our interrupts are uh.. interrupted at. */
116 set_c0_status(IE_IRQ0
);
122 void __init
arch_init_irq(void)