• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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