1 /* arch/mips/mach-goldfish/goldfish-platform.c
2 **
3 ** Copyright (C) 2007 Google, Inc.
4 **
5 ** This software is licensed under the terms of the GNU General Public
6 ** License version 2, as published by the Free Software Foundation, and
7 ** may be copied, distributed, and modified under those terms.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ** GNU General Public License for more details.
13 **
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/irq.h>
20 #include <linux/platform_device.h>
21 #include <linux/delay.h>
22 #include <linux/mtd/mtd.h>
23 #include <linux/mtd/nand.h>
24 #include <linux/mtd/partitions.h>
25 #include <linux/input.h>
26
27 #include <mach/hardware.h>
28 #include <asm/io.h>
29 #include <asm/irq_cpu.h>
30 #include <asm/mach-goldfish/irq.h>
31
32 static void __iomem *goldfish_interrupt;
33
goldfish_mask_irq(unsigned int irq)34 void goldfish_mask_irq(unsigned int irq)
35 {
36 writel(irq-GOLDFISH_IRQ_BASE,
37 goldfish_interrupt + GOLDFISH_INTERRUPT_DISABLE);
38 }
39
goldfish_unmask_irq(unsigned int irq)40 void goldfish_unmask_irq(unsigned int irq)
41 {
42 writel(irq-GOLDFISH_IRQ_BASE,
43 goldfish_interrupt + GOLDFISH_INTERRUPT_ENABLE);
44 }
45
46 static struct irq_chip goldfish_irq_chip = {
47 .name = "goldfish",
48 .mask = goldfish_mask_irq,
49 .mask_ack = goldfish_mask_irq,
50 .unmask = goldfish_unmask_irq,
51 };
52
goldfish_init_irq(void)53 void goldfish_init_irq(void)
54 {
55 unsigned int i;
56 goldfish_interrupt = IO_ADDRESS(GOLDFISH_INTERRUPT_BASE);
57
58 /*
59 * Disable all interrupt sources
60 */
61 writel(1, goldfish_interrupt + GOLDFISH_INTERRUPT_DISABLE_ALL);
62
63 for (i = GOLDFISH_IRQ_BASE; i < GOLDFISH_IRQ_BASE+32; i++) {
64 set_irq_chip(i, &goldfish_irq_chip);
65 set_irq_handler(i, handle_level_irq);
66 #if 0
67 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
68 #endif
69 }
70 }
71
goldfish_irq_dispatch(void)72 void goldfish_irq_dispatch(void)
73 {
74 uint32_t irq;
75 /*
76 * Disable all interrupt sources
77 */
78 irq = readl(goldfish_interrupt + GOLDFISH_INTERRUPT_NUMBER);
79 do_IRQ(GOLDFISH_IRQ_BASE+irq);
80 }
81
goldfish_fiq_dispatch(void)82 void goldfish_fiq_dispatch(void)
83 {
84 panic("goldfish_fiq_dispatch");
85 }
86
plat_irq_dispatch(void)87 asmlinkage void plat_irq_dispatch(void)
88 {
89 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
90
91 if (pending & CAUSEF_IP2)
92 goldfish_irq_dispatch();
93 else if (pending & CAUSEF_IP3)
94 goldfish_fiq_dispatch();
95 else if (pending & CAUSEF_IP7)
96 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
97 else
98 spurious_interrupt();
99 }
100
101 static struct irqaction cascade = {
102 .handler = no_action,
103 .mask = CPU_MASK_NONE,
104 .name = "cascade",
105 };
106
mips_timer_dispatch(void)107 static void mips_timer_dispatch(void)
108 {
109 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IRQ_COMPARE);
110 }
111
arch_init_irq(void)112 void __init arch_init_irq(void)
113 {
114 mips_cpu_irq_init();
115 goldfish_init_irq();
116
117 if (cpu_has_vint) {
118 set_vi_handler(MIPS_CPU_IRQ_PIC, goldfish_irq_dispatch);
119 set_vi_handler(MIPS_CPU_IRQ_PIC, goldfish_fiq_dispatch);
120 }
121 setup_irq(MIPS_CPU_IRQ_BASE+MIPS_CPU_IRQ_PIC, &cascade);
122 setup_irq(MIPS_CPU_IRQ_BASE+MIPS_CPU_IRQ_FIQ, &cascade);
123
124 if (cpu_has_vint)
125 set_vi_handler(MIPS_CPU_IRQ_COMPARE, mips_timer_dispatch);
126 }
127