diff options
Diffstat (limited to 'arch/mips/alchemy/common/irq.c')
-rw-r--r-- | arch/mips/alchemy/common/irq.c | 875 |
1 files changed, 613 insertions, 262 deletions
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c index 8b60ba0675e2..94fbcd19eb9c 100644 --- a/arch/mips/alchemy/common/irq.c +++ b/arch/mips/alchemy/common/irq.c | |||
@@ -25,19 +25,15 @@ | |||
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/bitops.h> | 28 | #include <linux/export.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/irq.h> | ||
32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
33 | #include <linux/syscore_ops.h> | 32 | #include <linux/syscore_ops.h> |
34 | 33 | ||
35 | #include <asm/irq_cpu.h> | 34 | #include <asm/irq_cpu.h> |
36 | #include <asm/mipsregs.h> | ||
37 | #include <asm/mach-au1x00/au1000.h> | 35 | #include <asm/mach-au1x00/au1000.h> |
38 | #ifdef CONFIG_MIPS_PB1000 | 36 | #include <asm/mach-au1x00/gpio-au1300.h> |
39 | #include <asm/mach-pb1x00/pb1000.h> | ||
40 | #endif | ||
41 | 37 | ||
42 | /* Interrupt Controller register offsets */ | 38 | /* Interrupt Controller register offsets */ |
43 | #define IC_CFG0RD 0x40 | 39 | #define IC_CFG0RD 0x40 |
@@ -69,7 +65,17 @@ | |||
69 | #define IC_FALLINGCLR 0x7C | 65 | #define IC_FALLINGCLR 0x7C |
70 | #define IC_TESTBIT 0x80 | 66 | #define IC_TESTBIT 0x80 |
71 | 67 | ||
72 | static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); | 68 | /* per-processor fixed function irqs */ |
69 | struct alchemy_irqmap { | ||
70 | int irq; /* linux IRQ number */ | ||
71 | int type; /* IRQ_TYPE_ */ | ||
72 | int prio; /* irq priority, 0 highest, 3 lowest */ | ||
73 | int internal; /* GPIC: internal source (no ext. pin)? */ | ||
74 | }; | ||
75 | |||
76 | static int au1x_ic_settype(struct irq_data *d, unsigned int type); | ||
77 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type); | ||
78 | |||
73 | 79 | ||
74 | /* NOTE on interrupt priorities: The original writers of this code said: | 80 | /* NOTE on interrupt priorities: The original writers of this code said: |
75 | * | 81 | * |
@@ -77,176 +83,207 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); | |||
77 | * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT) | 83 | * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT) |
78 | * needs the highest priority. | 84 | * needs the highest priority. |
79 | */ | 85 | */ |
80 | 86 | struct alchemy_irqmap au1000_irqmap[] __initdata = { | |
81 | /* per-processor fixed function irqs */ | 87 | { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
82 | struct au1xxx_irqmap { | 88 | { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
83 | int im_irq; | 89 | { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
84 | int im_type; | 90 | { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
85 | int im_request; /* set 1 to get higher priority */ | 91 | { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
92 | { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
93 | { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
94 | { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
95 | { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
96 | { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
97 | { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
98 | { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
99 | { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
100 | { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
101 | { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
102 | { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
103 | { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
104 | { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
105 | { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
106 | { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
107 | { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
108 | { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, | ||
109 | { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
110 | { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
111 | { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, | ||
112 | { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
113 | { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, | ||
114 | { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
115 | { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
116 | { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
117 | { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
118 | { -1, }, | ||
86 | }; | 119 | }; |
87 | 120 | ||
88 | struct au1xxx_irqmap au1000_irqmap[] __initdata = { | 121 | struct alchemy_irqmap au1500_irqmap[] __initdata = { |
89 | { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 122 | { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
90 | { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 123 | { AU1500_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
91 | { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 124 | { AU1500_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
92 | { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 125 | { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
93 | { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 126 | { AU1500_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
94 | { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 127 | { AU1500_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
95 | { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, | 128 | { AU1500_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
96 | { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, | 129 | { AU1500_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
97 | { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, | 130 | { AU1500_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
98 | { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, | 131 | { AU1500_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
99 | { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, | 132 | { AU1500_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
100 | { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, | 133 | { AU1500_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
101 | { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, | 134 | { AU1500_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
102 | { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, | 135 | { AU1500_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
103 | { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 136 | { AU1500_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
104 | { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 137 | { AU1500_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
105 | { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 138 | { AU1500_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
106 | { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 139 | { AU1500_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
107 | { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 140 | { AU1500_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
108 | { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 141 | { AU1500_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
109 | { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 142 | { AU1500_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
110 | { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 143 | { AU1500_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
111 | { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 144 | { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
112 | { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 145 | { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
113 | { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | 146 | { AU1500_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
114 | { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 147 | { AU1500_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
115 | { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 148 | { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
116 | { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 149 | { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
117 | { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 150 | { AU1500_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
118 | { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
119 | { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, | ||
120 | { -1, }, | 151 | { -1, }, |
121 | }; | 152 | }; |
122 | 153 | ||
123 | struct au1xxx_irqmap au1500_irqmap[] __initdata = { | 154 | struct alchemy_irqmap au1100_irqmap[] __initdata = { |
124 | { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 155 | { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
125 | { AU1500_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 }, | 156 | { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
126 | { AU1500_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 }, | 157 | { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
127 | { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 158 | { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
128 | { AU1500_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 }, | 159 | { AU1100_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
129 | { AU1500_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 }, | 160 | { AU1100_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
130 | { AU1500_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, | 161 | { AU1100_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
131 | { AU1500_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, | 162 | { AU1100_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
132 | { AU1500_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, | 163 | { AU1100_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
133 | { AU1500_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, | 164 | { AU1100_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
134 | { AU1500_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, | 165 | { AU1100_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
135 | { AU1500_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, | 166 | { AU1100_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
136 | { AU1500_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, | 167 | { AU1100_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
137 | { AU1500_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, | 168 | { AU1100_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
138 | { AU1500_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 169 | { AU1100_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
139 | { AU1500_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 170 | { AU1100_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
140 | { AU1500_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 171 | { AU1100_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
141 | { AU1500_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 172 | { AU1100_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
142 | { AU1500_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 173 | { AU1100_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
143 | { AU1500_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 174 | { AU1100_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
144 | { AU1500_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 175 | { AU1100_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
145 | { AU1500_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 176 | { AU1100_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
146 | { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | 177 | { AU1100_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
147 | { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 178 | { AU1100_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
148 | { AU1500_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 179 | { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
149 | { AU1500_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 180 | { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
150 | { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 181 | { AU1100_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
151 | { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 182 | { AU1100_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
152 | { AU1500_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 183 | { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
184 | { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, | ||
185 | { AU1100_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, | ||
153 | { -1, }, | 186 | { -1, }, |
154 | }; | 187 | }; |
155 | 188 | ||
156 | struct au1xxx_irqmap au1100_irqmap[] __initdata = { | 189 | struct alchemy_irqmap au1550_irqmap[] __initdata = { |
157 | { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 190 | { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
158 | { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 191 | { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
159 | { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 192 | { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
160 | { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 193 | { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
161 | { AU1100_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 194 | { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
162 | { AU1100_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 195 | { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
163 | { AU1100_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, | 196 | { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
164 | { AU1100_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, | 197 | { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
165 | { AU1100_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, | 198 | { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
166 | { AU1100_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, | 199 | { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
167 | { AU1100_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, | 200 | { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
168 | { AU1100_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, | 201 | { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
169 | { AU1100_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, | 202 | { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
170 | { AU1100_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, | 203 | { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
171 | { AU1100_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 204 | { AU1550_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
172 | { AU1100_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 205 | { AU1550_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
173 | { AU1100_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 206 | { AU1550_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
174 | { AU1100_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 207 | { AU1550_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
175 | { AU1100_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 208 | { AU1550_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
176 | { AU1100_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 209 | { AU1550_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
177 | { AU1100_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 210 | { AU1550_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
178 | { AU1100_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 211 | { AU1550_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
179 | { AU1100_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 212 | { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
180 | { AU1100_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 213 | { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
181 | { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | 214 | { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
182 | { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 215 | { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
183 | { AU1100_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 216 | { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
184 | { AU1100_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 217 | { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
185 | { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
186 | { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
187 | { AU1100_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, | ||
188 | { -1, }, | 218 | { -1, }, |
189 | }; | 219 | }; |
190 | 220 | ||
191 | struct au1xxx_irqmap au1550_irqmap[] __initdata = { | 221 | struct alchemy_irqmap au1200_irqmap[] __initdata = { |
192 | { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 222 | { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
193 | { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 }, | 223 | { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
194 | { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 }, | 224 | { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
195 | { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 225 | { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
196 | { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 226 | { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
197 | { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 }, | 227 | { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
198 | { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 }, | 228 | { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
199 | { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 229 | { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
200 | { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 230 | { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
201 | { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 231 | { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
202 | { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 232 | { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
203 | { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 233 | { AU1200_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
204 | { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 234 | { AU1200_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
205 | { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 235 | { AU1200_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
206 | { AU1550_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 236 | { AU1200_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
207 | { AU1550_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 237 | { AU1200_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
208 | { AU1550_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 238 | { AU1200_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
209 | { AU1550_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 239 | { AU1200_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
210 | { AU1550_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 240 | { AU1200_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
211 | { AU1550_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 241 | { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
212 | { AU1550_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 242 | { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
213 | { AU1550_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 243 | { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
214 | { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 244 | { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
215 | { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | ||
216 | { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | ||
217 | { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | ||
218 | { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
219 | { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
220 | { -1, }, | 245 | { -1, }, |
221 | }; | 246 | }; |
222 | 247 | ||
223 | struct au1xxx_irqmap au1200_irqmap[] __initdata = { | 248 | static struct alchemy_irqmap au1300_irqmap[] __initdata = { |
224 | { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 249 | /* multifunction: gpio pin or device */ |
225 | { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 250 | { AU1300_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
226 | { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 251 | { AU1300_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
227 | { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 252 | { AU1300_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
228 | { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 253 | { AU1300_SD1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
229 | { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 254 | { AU1300_SD2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
230 | { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 255 | { AU1300_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
231 | { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 256 | { AU1300_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
232 | { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 257 | { AU1300_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
233 | { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 258 | { AU1300_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
234 | { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 259 | { AU1300_NAND_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
235 | { AU1200_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 260 | /* au1300 internal */ |
236 | { AU1200_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 261 | { AU1300_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
237 | { AU1200_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 262 | { AU1300_MMU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
238 | { AU1200_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 263 | { AU1300_MPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
239 | { AU1200_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 264 | { AU1300_GPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
240 | { AU1200_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 265 | { AU1300_UDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
241 | { AU1200_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 266 | { AU1300_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
242 | { AU1200_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 267 | { AU1300_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
243 | { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 268 | { AU1300_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
244 | { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 269 | { AU1300_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
245 | { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 270 | { AU1300_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
246 | { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 271 | { AU1300_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
247 | { -1, }, | 272 | { AU1300_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
273 | { AU1300_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 1, }, | ||
274 | { AU1300_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
275 | { AU1300_SD0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
276 | { AU1300_USB_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
277 | { AU1300_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
278 | { AU1300_BSA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
279 | { AU1300_MPE_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
280 | { AU1300_ITE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
281 | { AU1300_AES_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
282 | { AU1300_CIM_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
283 | { -1, }, /* terminator */ | ||
248 | }; | 284 | }; |
249 | 285 | ||
286 | /******************************************************************************/ | ||
250 | 287 | ||
251 | static void au1x_ic0_unmask(struct irq_data *d) | 288 | static void au1x_ic0_unmask(struct irq_data *d) |
252 | { | 289 | { |
@@ -265,14 +302,6 @@ static void au1x_ic1_unmask(struct irq_data *d) | |||
265 | 302 | ||
266 | __raw_writel(1 << bit, base + IC_MASKSET); | 303 | __raw_writel(1 << bit, base + IC_MASKSET); |
267 | __raw_writel(1 << bit, base + IC_WAKESET); | 304 | __raw_writel(1 << bit, base + IC_WAKESET); |
268 | |||
269 | /* very hacky. does the pb1000 cpld auto-disable this int? | ||
270 | * nowhere in the current kernel sources is it disabled. --mlau | ||
271 | */ | ||
272 | #if defined(CONFIG_MIPS_PB1000) | ||
273 | if (d->irq == AU1000_GPIO15_INT) | ||
274 | __raw_writel(0x4000, (void __iomem *)PB1000_MDR); /* enable int */ | ||
275 | #endif | ||
276 | wmb(); | 305 | wmb(); |
277 | } | 306 | } |
278 | 307 | ||
@@ -470,40 +499,219 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) | |||
470 | return ret; | 499 | return ret; |
471 | } | 500 | } |
472 | 501 | ||
473 | asmlinkage void plat_irq_dispatch(void) | 502 | /******************************************************************************/ |
503 | |||
504 | /* | ||
505 | * au1300_gpic_chgcfg - change PIN configuration. | ||
506 | * @gpio: pin to change (0-based GPIO number from datasheet). | ||
507 | * @clr: clear all bits set in 'clr'. | ||
508 | * @set: set these bits. | ||
509 | * | ||
510 | * modifies a pins' configuration register, bits set in @clr will | ||
511 | * be cleared in the register, bits in @set will be set. | ||
512 | */ | ||
513 | static inline void au1300_gpic_chgcfg(unsigned int gpio, | ||
514 | unsigned long clr, | ||
515 | unsigned long set) | ||
516 | { | ||
517 | void __iomem *r = AU1300_GPIC_ADDR; | ||
518 | unsigned long l; | ||
519 | |||
520 | r += gpio * 4; /* offset into pin config array */ | ||
521 | l = __raw_readl(r + AU1300_GPIC_PINCFG); | ||
522 | l &= ~clr; | ||
523 | l |= set; | ||
524 | __raw_writel(l, r + AU1300_GPIC_PINCFG); | ||
525 | wmb(); | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * au1300_pinfunc_to_gpio - assign a pin as GPIO input (GPIO ctrl). | ||
530 | * @pin: pin (0-based GPIO number from datasheet). | ||
531 | * | ||
532 | * Assigns a GPIO pin to the GPIO controller, so its level can either | ||
533 | * be read or set through the generic GPIO functions. | ||
534 | * If you need a GPOUT, use au1300_gpio_set_value(pin, 0/1). | ||
535 | * REVISIT: is this function really necessary? | ||
536 | */ | ||
537 | void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio) | ||
538 | { | ||
539 | au1300_gpio_direction_input(gpio + AU1300_GPIO_BASE); | ||
540 | } | ||
541 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_gpio); | ||
542 | |||
543 | /* | ||
544 | * au1300_pinfunc_to_dev - assign a pin to the device function. | ||
545 | * @pin: pin (0-based GPIO number from datasheet). | ||
546 | * | ||
547 | * Assigns a GPIO pin to its associated device function; the pin will be | ||
548 | * driven by the device and not through GPIO functions. | ||
549 | */ | ||
550 | void au1300_pinfunc_to_dev(enum au1300_multifunc_pins gpio) | ||
551 | { | ||
552 | void __iomem *r = AU1300_GPIC_ADDR; | ||
553 | unsigned long bit; | ||
554 | |||
555 | r += GPIC_GPIO_BANKOFF(gpio); | ||
556 | bit = GPIC_GPIO_TO_BIT(gpio); | ||
557 | __raw_writel(bit, r + AU1300_GPIC_DEVSEL); | ||
558 | wmb(); | ||
559 | } | ||
560 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_dev); | ||
561 | |||
562 | /* | ||
563 | * au1300_set_irq_priority - set internal priority of IRQ. | ||
564 | * @irq: irq to set priority (linux irq number). | ||
565 | * @p: priority (0 = highest, 3 = lowest). | ||
566 | */ | ||
567 | void au1300_set_irq_priority(unsigned int irq, int p) | ||
474 | { | 568 | { |
475 | unsigned int pending = read_c0_status() & read_c0_cause(); | 569 | irq -= ALCHEMY_GPIC_INT_BASE; |
476 | unsigned long s, off; | 570 | au1300_gpic_chgcfg(irq, GPIC_CFG_IL_MASK, GPIC_CFG_IL_SET(p)); |
477 | 571 | } | |
478 | if (pending & CAUSEF_IP7) { | 572 | EXPORT_SYMBOL_GPL(au1300_set_irq_priority); |
479 | off = MIPS_CPU_IRQ_BASE + 7; | 573 | |
480 | goto handle; | 574 | /* |
481 | } else if (pending & CAUSEF_IP2) { | 575 | * au1300_set_dbdma_gpio - assign a gpio to one of the DBDMA triggers. |
482 | s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ0INT; | 576 | * @dchan: dbdma trigger select (0, 1). |
483 | off = AU1000_INTC0_INT_BASE; | 577 | * @gpio: pin to assign as trigger. |
484 | } else if (pending & CAUSEF_IP3) { | 578 | * |
485 | s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ1INT; | 579 | * DBDMA controller has 2 external trigger sources; this function |
486 | off = AU1000_INTC0_INT_BASE; | 580 | * assigns a GPIO to the selected trigger. |
487 | } else if (pending & CAUSEF_IP4) { | 581 | */ |
488 | s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ0INT; | 582 | void au1300_set_dbdma_gpio(int dchan, unsigned int gpio) |
489 | off = AU1000_INTC1_INT_BASE; | 583 | { |
490 | } else if (pending & CAUSEF_IP5) { | 584 | unsigned long r; |
491 | s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ1INT; | 585 | |
492 | off = AU1000_INTC1_INT_BASE; | 586 | if ((dchan >= 0) && (dchan <= 1)) { |
493 | } else | 587 | r = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); |
494 | goto spurious; | 588 | r &= ~(0xff << (8 * dchan)); |
495 | 589 | r |= (gpio & 0x7f) << (8 * dchan); | |
496 | s = __raw_readl((void __iomem *)s); | 590 | __raw_writel(r, AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); |
497 | if (unlikely(!s)) { | 591 | wmb(); |
498 | spurious: | ||
499 | spurious_interrupt(); | ||
500 | return; | ||
501 | } | 592 | } |
502 | off += __ffs(s); | ||
503 | handle: | ||
504 | do_IRQ(off); | ||
505 | } | 593 | } |
506 | 594 | ||
595 | static inline void gpic_pin_set_idlewake(unsigned int gpio, int allow) | ||
596 | { | ||
597 | au1300_gpic_chgcfg(gpio, GPIC_CFG_IDLEWAKE, | ||
598 | allow ? GPIC_CFG_IDLEWAKE : 0); | ||
599 | } | ||
600 | |||
601 | static void au1300_gpic_mask(struct irq_data *d) | ||
602 | { | ||
603 | void __iomem *r = AU1300_GPIC_ADDR; | ||
604 | unsigned long bit, irq = d->irq; | ||
605 | |||
606 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
607 | r += GPIC_GPIO_BANKOFF(irq); | ||
608 | bit = GPIC_GPIO_TO_BIT(irq); | ||
609 | __raw_writel(bit, r + AU1300_GPIC_IDIS); | ||
610 | wmb(); | ||
611 | |||
612 | gpic_pin_set_idlewake(irq, 0); | ||
613 | } | ||
614 | |||
615 | static void au1300_gpic_unmask(struct irq_data *d) | ||
616 | { | ||
617 | void __iomem *r = AU1300_GPIC_ADDR; | ||
618 | unsigned long bit, irq = d->irq; | ||
619 | |||
620 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
621 | |||
622 | gpic_pin_set_idlewake(irq, 1); | ||
623 | |||
624 | r += GPIC_GPIO_BANKOFF(irq); | ||
625 | bit = GPIC_GPIO_TO_BIT(irq); | ||
626 | __raw_writel(bit, r + AU1300_GPIC_IEN); | ||
627 | wmb(); | ||
628 | } | ||
629 | |||
630 | static void au1300_gpic_maskack(struct irq_data *d) | ||
631 | { | ||
632 | void __iomem *r = AU1300_GPIC_ADDR; | ||
633 | unsigned long bit, irq = d->irq; | ||
634 | |||
635 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
636 | r += GPIC_GPIO_BANKOFF(irq); | ||
637 | bit = GPIC_GPIO_TO_BIT(irq); | ||
638 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ | ||
639 | __raw_writel(bit, r + AU1300_GPIC_IDIS); /* mask */ | ||
640 | wmb(); | ||
641 | |||
642 | gpic_pin_set_idlewake(irq, 0); | ||
643 | } | ||
644 | |||
645 | static void au1300_gpic_ack(struct irq_data *d) | ||
646 | { | ||
647 | void __iomem *r = AU1300_GPIC_ADDR; | ||
648 | unsigned long bit, irq = d->irq; | ||
649 | |||
650 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
651 | r += GPIC_GPIO_BANKOFF(irq); | ||
652 | bit = GPIC_GPIO_TO_BIT(irq); | ||
653 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ | ||
654 | wmb(); | ||
655 | } | ||
656 | |||
657 | static struct irq_chip au1300_gpic = { | ||
658 | .name = "GPIOINT", | ||
659 | .irq_ack = au1300_gpic_ack, | ||
660 | .irq_mask = au1300_gpic_mask, | ||
661 | .irq_mask_ack = au1300_gpic_maskack, | ||
662 | .irq_unmask = au1300_gpic_unmask, | ||
663 | .irq_set_type = au1300_gpic_settype, | ||
664 | }; | ||
665 | |||
666 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type) | ||
667 | { | ||
668 | unsigned long s; | ||
669 | unsigned char *name = NULL; | ||
670 | irq_flow_handler_t hdl = NULL; | ||
671 | |||
672 | switch (type) { | ||
673 | case IRQ_TYPE_LEVEL_HIGH: | ||
674 | s = GPIC_CFG_IC_LEVEL_HIGH; | ||
675 | name = "high"; | ||
676 | hdl = handle_level_irq; | ||
677 | break; | ||
678 | case IRQ_TYPE_LEVEL_LOW: | ||
679 | s = GPIC_CFG_IC_LEVEL_LOW; | ||
680 | name = "low"; | ||
681 | hdl = handle_level_irq; | ||
682 | break; | ||
683 | case IRQ_TYPE_EDGE_RISING: | ||
684 | s = GPIC_CFG_IC_EDGE_RISE; | ||
685 | name = "posedge"; | ||
686 | hdl = handle_edge_irq; | ||
687 | break; | ||
688 | case IRQ_TYPE_EDGE_FALLING: | ||
689 | s = GPIC_CFG_IC_EDGE_FALL; | ||
690 | name = "negedge"; | ||
691 | hdl = handle_edge_irq; | ||
692 | break; | ||
693 | case IRQ_TYPE_EDGE_BOTH: | ||
694 | s = GPIC_CFG_IC_EDGE_BOTH; | ||
695 | name = "bothedge"; | ||
696 | hdl = handle_edge_irq; | ||
697 | break; | ||
698 | case IRQ_TYPE_NONE: | ||
699 | s = GPIC_CFG_IC_OFF; | ||
700 | name = "disabled"; | ||
701 | hdl = handle_level_irq; | ||
702 | break; | ||
703 | default: | ||
704 | return -EINVAL; | ||
705 | } | ||
706 | |||
707 | __irq_set_chip_handler_name_locked(d->irq, &au1300_gpic, hdl, name); | ||
708 | |||
709 | au1300_gpic_chgcfg(d->irq - ALCHEMY_GPIC_INT_BASE, GPIC_CFG_IC_MASK, s); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | /******************************************************************************/ | ||
507 | 715 | ||
508 | static inline void ic_init(void __iomem *base) | 716 | static inline void ic_init(void __iomem *base) |
509 | { | 717 | { |
@@ -521,13 +729,159 @@ static inline void ic_init(void __iomem *base) | |||
521 | wmb(); | 729 | wmb(); |
522 | } | 730 | } |
523 | 731 | ||
524 | static void __init au1000_init_irq(struct au1xxx_irqmap *map) | 732 | static unsigned long alchemy_gpic_pmdata[ALCHEMY_GPIC_INT_NUM + 6]; |
733 | |||
734 | static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d) | ||
735 | { | ||
736 | d[0] = __raw_readl(base + IC_CFG0RD); | ||
737 | d[1] = __raw_readl(base + IC_CFG1RD); | ||
738 | d[2] = __raw_readl(base + IC_CFG2RD); | ||
739 | d[3] = __raw_readl(base + IC_SRCRD); | ||
740 | d[4] = __raw_readl(base + IC_ASSIGNRD); | ||
741 | d[5] = __raw_readl(base + IC_WAKERD); | ||
742 | d[6] = __raw_readl(base + IC_MASKRD); | ||
743 | ic_init(base); /* shut it up too while at it */ | ||
744 | } | ||
745 | |||
746 | static inline void alchemy_ic_resume_one(void __iomem *base, unsigned long *d) | ||
747 | { | ||
748 | ic_init(base); | ||
749 | |||
750 | __raw_writel(d[0], base + IC_CFG0SET); | ||
751 | __raw_writel(d[1], base + IC_CFG1SET); | ||
752 | __raw_writel(d[2], base + IC_CFG2SET); | ||
753 | __raw_writel(d[3], base + IC_SRCSET); | ||
754 | __raw_writel(d[4], base + IC_ASSIGNSET); | ||
755 | __raw_writel(d[5], base + IC_WAKESET); | ||
756 | wmb(); | ||
757 | |||
758 | __raw_writel(d[6], base + IC_MASKSET); | ||
759 | wmb(); | ||
760 | } | ||
761 | |||
762 | static int alchemy_ic_suspend(void) | ||
763 | { | ||
764 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), | ||
765 | alchemy_gpic_pmdata); | ||
766 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), | ||
767 | &alchemy_gpic_pmdata[7]); | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static void alchemy_ic_resume(void) | ||
772 | { | ||
773 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), | ||
774 | &alchemy_gpic_pmdata[7]); | ||
775 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), | ||
776 | alchemy_gpic_pmdata); | ||
777 | } | ||
778 | |||
779 | static int alchemy_gpic_suspend(void) | ||
780 | { | ||
781 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
782 | int i; | ||
783 | |||
784 | /* save 4 interrupt mask status registers */ | ||
785 | alchemy_gpic_pmdata[0] = __raw_readl(base + AU1300_GPIC_IEN + 0x0); | ||
786 | alchemy_gpic_pmdata[1] = __raw_readl(base + AU1300_GPIC_IEN + 0x4); | ||
787 | alchemy_gpic_pmdata[2] = __raw_readl(base + AU1300_GPIC_IEN + 0x8); | ||
788 | alchemy_gpic_pmdata[3] = __raw_readl(base + AU1300_GPIC_IEN + 0xc); | ||
789 | |||
790 | /* save misc register(s) */ | ||
791 | alchemy_gpic_pmdata[4] = __raw_readl(base + AU1300_GPIC_DMASEL); | ||
792 | |||
793 | /* molto silenzioso */ | ||
794 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); | ||
795 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); | ||
796 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); | ||
797 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); | ||
798 | wmb(); | ||
799 | |||
800 | /* save pin/int-type configuration */ | ||
801 | base += AU1300_GPIC_PINCFG; | ||
802 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) | ||
803 | alchemy_gpic_pmdata[i + 5] = __raw_readl(base + (i << 2)); | ||
804 | |||
805 | wmb(); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static void alchemy_gpic_resume(void) | ||
811 | { | ||
812 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
813 | int i; | ||
814 | |||
815 | /* disable all first */ | ||
816 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); | ||
817 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); | ||
818 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); | ||
819 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); | ||
820 | wmb(); | ||
821 | |||
822 | /* restore pin/int-type configurations */ | ||
823 | base += AU1300_GPIC_PINCFG; | ||
824 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) | ||
825 | __raw_writel(alchemy_gpic_pmdata[i + 5], base + (i << 2)); | ||
826 | wmb(); | ||
827 | |||
828 | /* restore misc register(s) */ | ||
829 | base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
830 | __raw_writel(alchemy_gpic_pmdata[4], base + AU1300_GPIC_DMASEL); | ||
831 | wmb(); | ||
832 | |||
833 | /* finally restore masks */ | ||
834 | __raw_writel(alchemy_gpic_pmdata[0], base + AU1300_GPIC_IEN + 0x0); | ||
835 | __raw_writel(alchemy_gpic_pmdata[1], base + AU1300_GPIC_IEN + 0x4); | ||
836 | __raw_writel(alchemy_gpic_pmdata[2], base + AU1300_GPIC_IEN + 0x8); | ||
837 | __raw_writel(alchemy_gpic_pmdata[3], base + AU1300_GPIC_IEN + 0xc); | ||
838 | wmb(); | ||
839 | } | ||
840 | |||
841 | static struct syscore_ops alchemy_ic_pmops = { | ||
842 | .suspend = alchemy_ic_suspend, | ||
843 | .resume = alchemy_ic_resume, | ||
844 | }; | ||
845 | |||
846 | static struct syscore_ops alchemy_gpic_pmops = { | ||
847 | .suspend = alchemy_gpic_suspend, | ||
848 | .resume = alchemy_gpic_resume, | ||
849 | }; | ||
850 | |||
851 | /******************************************************************************/ | ||
852 | |||
853 | /* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */ | ||
854 | #define DISP(name, base, addr) \ | ||
855 | static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d) \ | ||
856 | { \ | ||
857 | unsigned long r = __raw_readl((void __iomem *)KSEG1ADDR(addr)); \ | ||
858 | if (likely(r)) \ | ||
859 | generic_handle_irq(base + __ffs(r)); \ | ||
860 | else \ | ||
861 | spurious_interrupt(); \ | ||
862 | } | ||
863 | |||
864 | DISP(ic0r0, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ0INT) | ||
865 | DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT) | ||
866 | DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT) | ||
867 | DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT) | ||
868 | |||
869 | static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d) | ||
870 | { | ||
871 | int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC); | ||
872 | generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i); | ||
873 | } | ||
874 | |||
875 | /******************************************************************************/ | ||
876 | |||
877 | static void __init au1000_init_irq(struct alchemy_irqmap *map) | ||
525 | { | 878 | { |
526 | unsigned int bit, irq_nr; | 879 | unsigned int bit, irq_nr; |
527 | void __iomem *base; | 880 | void __iomem *base; |
528 | 881 | ||
529 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR)); | 882 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR)); |
530 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR)); | 883 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR)); |
884 | register_syscore_ops(&alchemy_ic_pmops); | ||
531 | mips_cpu_irq_init(); | 885 | mips_cpu_irq_init(); |
532 | 886 | ||
533 | /* register all 64 possible IC0+IC1 irq sources as type "none". | 887 | /* register all 64 possible IC0+IC1 irq sources as type "none". |
@@ -544,8 +898,8 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
544 | /* | 898 | /* |
545 | * Initialize IC0, which is fixed per processor. | 899 | * Initialize IC0, which is fixed per processor. |
546 | */ | 900 | */ |
547 | while (map->im_irq != -1) { | 901 | while (map->irq != -1) { |
548 | irq_nr = map->im_irq; | 902 | irq_nr = map->irq; |
549 | 903 | ||
550 | if (irq_nr >= AU1000_INTC1_INT_BASE) { | 904 | if (irq_nr >= AU1000_INTC1_INT_BASE) { |
551 | bit = irq_nr - AU1000_INTC1_INT_BASE; | 905 | bit = irq_nr - AU1000_INTC1_INT_BASE; |
@@ -554,16 +908,61 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
554 | bit = irq_nr - AU1000_INTC0_INT_BASE; | 908 | bit = irq_nr - AU1000_INTC0_INT_BASE; |
555 | base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); | 909 | base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
556 | } | 910 | } |
557 | if (map->im_request) | 911 | if (map->prio == 0) |
558 | __raw_writel(1 << bit, base + IC_ASSIGNSET); | 912 | __raw_writel(1 << bit, base + IC_ASSIGNSET); |
559 | 913 | ||
560 | au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type); | 914 | au1x_ic_settype(irq_get_irq_data(irq_nr), map->type); |
561 | ++map; | 915 | ++map; |
562 | } | 916 | } |
563 | 917 | ||
564 | set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3); | 918 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, au1000_ic0r0_dispatch); |
919 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, au1000_ic0r1_dispatch); | ||
920 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, au1000_ic1r0_dispatch); | ||
921 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, au1000_ic1r1_dispatch); | ||
922 | } | ||
923 | |||
924 | static void __init alchemy_gpic_init_irq(const struct alchemy_irqmap *dints) | ||
925 | { | ||
926 | int i; | ||
927 | void __iomem *bank_base; | ||
928 | |||
929 | register_syscore_ops(&alchemy_gpic_pmops); | ||
930 | mips_cpu_irq_init(); | ||
931 | |||
932 | /* disable & ack all possible interrupt sources */ | ||
933 | for (i = 0; i < 4; i++) { | ||
934 | bank_base = AU1300_GPIC_ADDR + (i * 4); | ||
935 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IDIS); | ||
936 | wmb(); | ||
937 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IPEND); | ||
938 | wmb(); | ||
939 | } | ||
940 | |||
941 | /* register an irq_chip for them, with 2nd highest priority */ | ||
942 | for (i = ALCHEMY_GPIC_INT_BASE; i <= ALCHEMY_GPIC_INT_LAST; i++) { | ||
943 | au1300_set_irq_priority(i, 1); | ||
944 | au1300_gpic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); | ||
945 | } | ||
946 | |||
947 | /* setup known on-chip sources */ | ||
948 | while ((i = dints->irq) != -1) { | ||
949 | au1300_gpic_settype(irq_get_irq_data(i), dints->type); | ||
950 | au1300_set_irq_priority(i, dints->prio); | ||
951 | |||
952 | if (dints->internal) | ||
953 | au1300_pinfunc_to_dev(i - ALCHEMY_GPIC_INT_BASE); | ||
954 | |||
955 | dints++; | ||
956 | } | ||
957 | |||
958 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, alchemy_gpic_dispatch); | ||
959 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, alchemy_gpic_dispatch); | ||
960 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, alchemy_gpic_dispatch); | ||
961 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, alchemy_gpic_dispatch); | ||
565 | } | 962 | } |
566 | 963 | ||
964 | /******************************************************************************/ | ||
965 | |||
567 | void __init arch_init_irq(void) | 966 | void __init arch_init_irq(void) |
568 | { | 967 | { |
569 | switch (alchemy_get_cputype()) { | 968 | switch (alchemy_get_cputype()) { |
@@ -582,65 +981,17 @@ void __init arch_init_irq(void) | |||
582 | case ALCHEMY_CPU_AU1200: | 981 | case ALCHEMY_CPU_AU1200: |
583 | au1000_init_irq(au1200_irqmap); | 982 | au1000_init_irq(au1200_irqmap); |
584 | break; | 983 | break; |
984 | case ALCHEMY_CPU_AU1300: | ||
985 | alchemy_gpic_init_irq(au1300_irqmap); | ||
986 | break; | ||
987 | default: | ||
988 | pr_err("unknown Alchemy IRQ core\n"); | ||
989 | break; | ||
585 | } | 990 | } |
586 | } | 991 | } |
587 | 992 | ||
588 | 993 | asmlinkage void plat_irq_dispatch(void) | |
589 | static unsigned long alchemy_ic_pmdata[7 * 2]; | ||
590 | |||
591 | static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d) | ||
592 | { | ||
593 | d[0] = __raw_readl(base + IC_CFG0RD); | ||
594 | d[1] = __raw_readl(base + IC_CFG1RD); | ||
595 | d[2] = __raw_readl(base + IC_CFG2RD); | ||
596 | d[3] = __raw_readl(base + IC_SRCRD); | ||
597 | d[4] = __raw_readl(base + IC_ASSIGNRD); | ||
598 | d[5] = __raw_readl(base + IC_WAKERD); | ||
599 | d[6] = __raw_readl(base + IC_MASKRD); | ||
600 | ic_init(base); /* shut it up too while at it */ | ||
601 | } | ||
602 | |||
603 | static inline void alchemy_ic_resume_one(void __iomem *base, unsigned long *d) | ||
604 | { | ||
605 | ic_init(base); | ||
606 | |||
607 | __raw_writel(d[0], base + IC_CFG0SET); | ||
608 | __raw_writel(d[1], base + IC_CFG1SET); | ||
609 | __raw_writel(d[2], base + IC_CFG2SET); | ||
610 | __raw_writel(d[3], base + IC_SRCSET); | ||
611 | __raw_writel(d[4], base + IC_ASSIGNSET); | ||
612 | __raw_writel(d[5], base + IC_WAKESET); | ||
613 | wmb(); | ||
614 | |||
615 | __raw_writel(d[6], base + IC_MASKSET); | ||
616 | wmb(); | ||
617 | } | ||
618 | |||
619 | static int alchemy_ic_suspend(void) | ||
620 | { | ||
621 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), | ||
622 | alchemy_ic_pmdata); | ||
623 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), | ||
624 | &alchemy_ic_pmdata[7]); | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static void alchemy_ic_resume(void) | ||
629 | { | ||
630 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), | ||
631 | &alchemy_ic_pmdata[7]); | ||
632 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), | ||
633 | alchemy_ic_pmdata); | ||
634 | } | ||
635 | |||
636 | static struct syscore_ops alchemy_ic_syscore_ops = { | ||
637 | .suspend = alchemy_ic_suspend, | ||
638 | .resume = alchemy_ic_resume, | ||
639 | }; | ||
640 | |||
641 | static int __init alchemy_ic_pm_init(void) | ||
642 | { | 994 | { |
643 | register_syscore_ops(&alchemy_ic_syscore_ops); | 995 | unsigned long r = (read_c0_status() & read_c0_cause()) >> 8; |
644 | return 0; | 996 | do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff)); |
645 | } | 997 | } |
646 | device_initcall(alchemy_ic_pm_init); | ||