Blame view

arch/mips/ath79/irq.c 5.1 KB
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  /*
   *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
   *
   *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
   *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
   *
   *  Parts of this file are based on Atheros' 2.6.15 BSP
   *
   *  This program is free software; you can redistribute it and/or modify it
   *  under the terms of the GNU General Public License version 2 as published
   *  by the Free Software Foundation.
   */
  
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  
  #include <asm/irq_cpu.h>
  #include <asm/mipsregs.h>
  
  #include <asm/mach-ath79/ath79.h>
  #include <asm/mach-ath79/ar71xx_regs.h>
  #include "common.h"
  
  static unsigned int ath79_ip2_flush_reg;
  static unsigned int ath79_ip3_flush_reg;
  
  static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
  {
  	void __iomem *base = ath79_reset_base;
  	u32 pending;
  
  	pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
  		  __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  
  	if (pending & MISC_INT_UART)
  		generic_handle_irq(ATH79_MISC_IRQ_UART);
  
  	else if (pending & MISC_INT_DMA)
  		generic_handle_irq(ATH79_MISC_IRQ_DMA);
  
  	else if (pending & MISC_INT_PERFC)
  		generic_handle_irq(ATH79_MISC_IRQ_PERFC);
  
  	else if (pending & MISC_INT_TIMER)
  		generic_handle_irq(ATH79_MISC_IRQ_TIMER);
d2b4ac1e5   Gabor Juhos   MIPS: ath79: Hand...
48
49
50
51
52
53
54
55
  	else if (pending & MISC_INT_TIMER2)
  		generic_handle_irq(ATH79_MISC_IRQ_TIMER2);
  
  	else if (pending & MISC_INT_TIMER3)
  		generic_handle_irq(ATH79_MISC_IRQ_TIMER3);
  
  	else if (pending & MISC_INT_TIMER4)
  		generic_handle_irq(ATH79_MISC_IRQ_TIMER4);
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
56
57
58
59
60
61
62
63
64
65
66
  	else if (pending & MISC_INT_OHCI)
  		generic_handle_irq(ATH79_MISC_IRQ_OHCI);
  
  	else if (pending & MISC_INT_ERROR)
  		generic_handle_irq(ATH79_MISC_IRQ_ERROR);
  
  	else if (pending & MISC_INT_GPIO)
  		generic_handle_irq(ATH79_MISC_IRQ_GPIO);
  
  	else if (pending & MISC_INT_WDOG)
  		generic_handle_irq(ATH79_MISC_IRQ_WDOG);
d2b4ac1e5   Gabor Juhos   MIPS: ath79: Hand...
67
68
  	else if (pending & MISC_INT_ETHSW)
  		generic_handle_irq(ATH79_MISC_IRQ_ETHSW);
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
69
70
71
  	else
  		spurious_interrupt();
  }
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
72
  static void ar71xx_misc_irq_unmask(struct irq_data *d)
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
73
  {
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
74
  	unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
75
76
  	void __iomem *base = ath79_reset_base;
  	u32 t;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
77
78
79
80
81
82
  	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  
  	/* flush write */
  	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  }
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
83
  static void ar71xx_misc_irq_mask(struct irq_data *d)
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
84
  {
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
85
  	unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
86
87
  	void __iomem *base = ath79_reset_base;
  	u32 t;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
88
89
90
91
92
93
  	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  
  	/* flush write */
  	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  }
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
94
  static void ar724x_misc_irq_ack(struct irq_data *d)
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
95
  {
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
96
  	unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
97
98
  	void __iomem *base = ath79_reset_base;
  	u32 t;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
99
100
101
102
103
104
105
106
107
  	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
  	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
  
  	/* flush write */
  	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
  }
  
  static struct irq_chip ath79_misc_irq_chip = {
  	.name		= "MISC",
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
108
109
  	.irq_unmask	= ar71xx_misc_irq_unmask,
  	.irq_mask	= ar71xx_misc_irq_mask,
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
110
111
112
113
114
115
116
117
118
119
120
  };
  
  static void __init ath79_misc_irq_init(void)
  {
  	void __iomem *base = ath79_reset_base;
  	int i;
  
  	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
  	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
  
  	if (soc_is_ar71xx() || soc_is_ar913x())
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
121
  		ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
54eed4c77   Gabor Juhos   MIPS: ath79: Add ...
122
  	else if (soc_is_ar724x() || soc_is_ar933x())
3fb8818bd   Thomas Gleixner   MIPS: ath79: Conv...
123
  		ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
124
125
126
127
128
  	else
  		BUG();
  
  	for (i = ATH79_MISC_IRQ_BASE;
  	     i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
e4ec7989b   Thomas Gleixner   MIPS: Convert the...
129
  		irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
130
131
  					 handle_level_irq);
  	}
e4ec7989b   Thomas Gleixner   MIPS: Convert the...
132
  	irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  }
  
  asmlinkage void plat_irq_dispatch(void)
  {
  	unsigned long pending;
  
  	pending = read_c0_status() & read_c0_cause() & ST0_IM;
  
  	if (pending & STATUSF_IP7)
  		do_IRQ(ATH79_CPU_IRQ_TIMER);
  
  	else if (pending & STATUSF_IP2) {
  		ath79_ddr_wb_flush(ath79_ip2_flush_reg);
  		do_IRQ(ATH79_CPU_IRQ_IP2);
  	}
  
  	else if (pending & STATUSF_IP4)
  		do_IRQ(ATH79_CPU_IRQ_GE0);
  
  	else if (pending & STATUSF_IP5)
  		do_IRQ(ATH79_CPU_IRQ_GE1);
  
  	else if (pending & STATUSF_IP3) {
  		ath79_ddr_wb_flush(ath79_ip3_flush_reg);
  		do_IRQ(ATH79_CPU_IRQ_USB);
  	}
  
  	else if (pending & STATUSF_IP6)
  		do_IRQ(ATH79_CPU_IRQ_MISC);
  
  	else
  		spurious_interrupt();
  }
  
  void __init arch_init_irq(void)
  {
  	if (soc_is_ar71xx()) {
  		ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI;
  		ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB;
  	} else if (soc_is_ar724x()) {
  		ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE;
  		ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB;
  	} else if (soc_is_ar913x()) {
  		ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC;
  		ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB;
54eed4c77   Gabor Juhos   MIPS: ath79: Add ...
178
179
180
  	} else if (soc_is_ar933x()) {
  		ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC;
  		ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB;
d4a67d9dc   Gabor Juhos   MIPS: Add initial...
181
182
183
184
185
186
187
  	} else
  		BUG();
  
  	cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
  	mips_cpu_irq_init();
  	ath79_misc_irq_init();
  }