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
23 #include <asm/mach-goldfish/hardware.h>
24 #include <asm/io.h>
25 #include <asm/irq_cpu.h>
26 #include <asm/setup.h>
27 #include <asm/mach-goldfish/irq.h>
28
29 static void __iomem *goldfish_interrupt;
30
goldfish_mask_irq(struct irq_data * d)31 void goldfish_mask_irq(struct irq_data *d)
32 {
33 writel(d->irq-GOLDFISH_IRQ_BASE,
34 goldfish_interrupt + GOLDFISH_INTERRUPT_DISABLE);
35 }
36
goldfish_unmask_irq(struct irq_data * d)37 void goldfish_unmask_irq(struct irq_data *d)
38 {
39 writel(d->irq-GOLDFISH_IRQ_BASE,
40 goldfish_interrupt + GOLDFISH_INTERRUPT_ENABLE);
41 }
42
43 static struct irq_chip goldfish_irq_chip = {
44 .name = "goldfish",
45 .irq_mask = goldfish_mask_irq,
46 .irq_mask_ack = goldfish_mask_irq,
47 .irq_unmask = goldfish_unmask_irq,
48 };
49
goldfish_init_irq(void)50 void goldfish_init_irq(void)
51 {
52 unsigned int i;
53 goldfish_interrupt = IO_ADDRESS(GOLDFISH_INTERRUPT_BASE);
54
55 /*
56 * Disable all interrupt sources
57 */
58 writel(1, goldfish_interrupt + GOLDFISH_INTERRUPT_DISABLE_ALL);
59
60 for (i = GOLDFISH_IRQ_BASE; i < GOLDFISH_IRQ_BASE+32; i++) {
61 irq_set_chip(i, &goldfish_irq_chip);
62 irq_set_handler(i, handle_level_irq);
63 #if 0
64 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
65 #endif
66 }
67 }
68
goldfish_irq_dispatch(void)69 void goldfish_irq_dispatch(void)
70 {
71 uint32_t irq;
72 /*
73 * Disable all interrupt sources
74 */
75 irq = readl(goldfish_interrupt + GOLDFISH_INTERRUPT_NUMBER);
76 do_IRQ(GOLDFISH_IRQ_BASE+irq);
77 }
78
goldfish_fiq_dispatch(void)79 void goldfish_fiq_dispatch(void)
80 {
81 panic("goldfish_fiq_dispatch");
82 }
83
plat_irq_dispatch(void)84 asmlinkage void plat_irq_dispatch(void)
85 {
86 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
87
88 if (pending & CAUSEF_IP2)
89 goldfish_irq_dispatch();
90 else if (pending & CAUSEF_IP3)
91 goldfish_fiq_dispatch();
92 else if (pending & CAUSEF_IP7)
93 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
94 else
95 spurious_interrupt();
96 }
97
98 static struct irqaction cascade = {
99 .handler = no_action,
100 .flags = IRQF_NO_THREAD,
101 .name = "cascade",
102 };
103
mips_timer_dispatch(void)104 static void mips_timer_dispatch(void)
105 {
106 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IRQ_COMPARE);
107 }
108
arch_init_irq(void)109 void __init arch_init_irq(void)
110 {
111 mips_cpu_irq_init();
112 goldfish_init_irq();
113
114 if (cpu_has_vint) {
115 set_vi_handler(MIPS_CPU_IRQ_PIC, goldfish_irq_dispatch);
116 set_vi_handler(MIPS_CPU_IRQ_PIC, goldfish_fiq_dispatch);
117 }
118 setup_irq(MIPS_CPU_IRQ_BASE+MIPS_CPU_IRQ_PIC, &cascade);
119 setup_irq(MIPS_CPU_IRQ_BASE+MIPS_CPU_IRQ_FIQ, &cascade);
120
121 if (cpu_has_vint)
122 set_vi_handler(MIPS_CPU_IRQ_COMPARE, mips_timer_dispatch);
123 }
124