Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.39 645 lines 21 kB view raw
1/* 2 * Copyright 2001, 2007-2008 MontaVista Software Inc. 3 * Author: MontaVista Software, Inc. <source@mvista.com> 4 * 5 * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * 23 * You should have received a copy of the GNU General Public License along 24 * with this program; if not, write to the Free Software Foundation, Inc., 25 * 675 Mass Ave, Cambridge, MA 02139, USA. 26 */ 27 28#include <linux/bitops.h> 29#include <linux/init.h> 30#include <linux/interrupt.h> 31#include <linux/irq.h> 32#include <linux/slab.h> 33#include <linux/sysdev.h> 34 35#include <asm/irq_cpu.h> 36#include <asm/mipsregs.h> 37#include <asm/mach-au1x00/au1000.h> 38#ifdef CONFIG_MIPS_PB1000 39#include <asm/mach-pb1x00/pb1000.h> 40#endif 41 42static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); 43 44/* NOTE on interrupt priorities: The original writers of this code said: 45 * 46 * Because of the tight timing of SETUP token to reply transactions, 47 * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT) 48 * needs the highest priority. 49 */ 50 51/* per-processor fixed function irqs */ 52struct au1xxx_irqmap { 53 int im_irq; 54 int im_type; 55 int im_request; /* set 1 to get higher priority */ 56}; 57 58struct au1xxx_irqmap au1000_irqmap[] __initdata = { 59 { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 60 { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 61 { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 62 { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 63 { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 64 { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 65 { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, 66 { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, 67 { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, 68 { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, 69 { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, 70 { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, 71 { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, 72 { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, 73 { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, 74 { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 75 { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 76 { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, 77 { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 78 { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 79 { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 80 { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, 81 { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 82 { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 83 { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, 84 { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, 85 { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, 86 { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 87 { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 88 { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 89 { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, 90 { -1, }, 91}; 92 93struct au1xxx_irqmap au1500_irqmap[] __initdata = { 94 { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 95 { AU1500_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 }, 96 { AU1500_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 }, 97 { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 98 { AU1500_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 }, 99 { AU1500_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 }, 100 { AU1500_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, 101 { AU1500_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, 102 { AU1500_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, 103 { AU1500_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, 104 { AU1500_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, 105 { AU1500_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, 106 { AU1500_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, 107 { AU1500_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, 108 { AU1500_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, 109 { AU1500_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 110 { AU1500_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 111 { AU1500_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, 112 { AU1500_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 113 { AU1500_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 114 { AU1500_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 115 { AU1500_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, 116 { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, 117 { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, 118 { AU1500_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, 119 { AU1500_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 120 { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 121 { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 122 { AU1500_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, 123 { -1, }, 124}; 125 126struct au1xxx_irqmap au1100_irqmap[] __initdata = { 127 { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 128 { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 129 { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 130 { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 131 { AU1100_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 132 { AU1100_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 133 { AU1100_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, 134 { AU1100_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, 135 { AU1100_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, 136 { AU1100_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, 137 { AU1100_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, 138 { AU1100_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, 139 { AU1100_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, 140 { AU1100_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, 141 { AU1100_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, 142 { AU1100_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 143 { AU1100_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 144 { AU1100_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, 145 { AU1100_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 146 { AU1100_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 147 { AU1100_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 148 { AU1100_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, 149 { AU1100_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 150 { AU1100_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 151 { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, 152 { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, 153 { AU1100_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, 154 { AU1100_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 155 { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 156 { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 157 { AU1100_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, 158 { -1, }, 159}; 160 161struct au1xxx_irqmap au1550_irqmap[] __initdata = { 162 { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 163 { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 }, 164 { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 }, 165 { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 166 { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 167 { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 }, 168 { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 }, 169 { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, 170 { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 171 { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 172 { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 173 { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 174 { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 175 { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 176 { AU1550_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, 177 { AU1550_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 178 { AU1550_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 179 { AU1550_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, 180 { AU1550_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 181 { AU1550_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 182 { AU1550_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 183 { AU1550_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, 184 { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 }, 185 { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, 186 { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, 187 { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, 188 { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 189 { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 190 { -1, }, 191}; 192 193struct au1xxx_irqmap au1200_irqmap[] __initdata = { 194 { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 195 { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 0 }, 196 { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 197 { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 198 { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 199 { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 200 { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 201 { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 202 { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 203 { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 204 { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 205 { AU1200_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, 206 { AU1200_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 207 { AU1200_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 208 { AU1200_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, 209 { AU1200_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, 210 { AU1200_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, 211 { AU1200_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, 212 { AU1200_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, 213 { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 }, 214 { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 215 { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 216 { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 217 { -1, }, 218}; 219 220 221static void au1x_ic0_unmask(struct irq_data *d) 222{ 223 unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; 224 au_writel(1 << bit, IC0_MASKSET); 225 au_writel(1 << bit, IC0_WAKESET); 226 au_sync(); 227} 228 229static void au1x_ic1_unmask(struct irq_data *d) 230{ 231 unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; 232 au_writel(1 << bit, IC1_MASKSET); 233 au_writel(1 << bit, IC1_WAKESET); 234 235/* very hacky. does the pb1000 cpld auto-disable this int? 236 * nowhere in the current kernel sources is it disabled. --mlau 237 */ 238#if defined(CONFIG_MIPS_PB1000) 239 if (d->irq == AU1000_GPIO15_INT) 240 au_writel(0x4000, PB1000_MDR); /* enable int */ 241#endif 242 au_sync(); 243} 244 245static void au1x_ic0_mask(struct irq_data *d) 246{ 247 unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; 248 au_writel(1 << bit, IC0_MASKCLR); 249 au_writel(1 << bit, IC0_WAKECLR); 250 au_sync(); 251} 252 253static void au1x_ic1_mask(struct irq_data *d) 254{ 255 unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; 256 au_writel(1 << bit, IC1_MASKCLR); 257 au_writel(1 << bit, IC1_WAKECLR); 258 au_sync(); 259} 260 261static void au1x_ic0_ack(struct irq_data *d) 262{ 263 unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; 264 265 /* 266 * This may assume that we don't get interrupts from 267 * both edges at once, or if we do, that we don't care. 268 */ 269 au_writel(1 << bit, IC0_FALLINGCLR); 270 au_writel(1 << bit, IC0_RISINGCLR); 271 au_sync(); 272} 273 274static void au1x_ic1_ack(struct irq_data *d) 275{ 276 unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; 277 278 /* 279 * This may assume that we don't get interrupts from 280 * both edges at once, or if we do, that we don't care. 281 */ 282 au_writel(1 << bit, IC1_FALLINGCLR); 283 au_writel(1 << bit, IC1_RISINGCLR); 284 au_sync(); 285} 286 287static void au1x_ic0_maskack(struct irq_data *d) 288{ 289 unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; 290 291 au_writel(1 << bit, IC0_WAKECLR); 292 au_writel(1 << bit, IC0_MASKCLR); 293 au_writel(1 << bit, IC0_RISINGCLR); 294 au_writel(1 << bit, IC0_FALLINGCLR); 295 au_sync(); 296} 297 298static void au1x_ic1_maskack(struct irq_data *d) 299{ 300 unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; 301 302 au_writel(1 << bit, IC1_WAKECLR); 303 au_writel(1 << bit, IC1_MASKCLR); 304 au_writel(1 << bit, IC1_RISINGCLR); 305 au_writel(1 << bit, IC1_FALLINGCLR); 306 au_sync(); 307} 308 309static int au1x_ic1_setwake(struct irq_data *d, unsigned int on) 310{ 311 int bit = d->irq - AU1000_INTC1_INT_BASE; 312 unsigned long wakemsk, flags; 313 314 /* only GPIO 0-7 can act as wakeup source. Fortunately these 315 * are wired up identically on all supported variants. 316 */ 317 if ((bit < 0) || (bit > 7)) 318 return -EINVAL; 319 320 local_irq_save(flags); 321 wakemsk = au_readl(SYS_WAKEMSK); 322 if (on) 323 wakemsk |= 1 << bit; 324 else 325 wakemsk &= ~(1 << bit); 326 au_writel(wakemsk, SYS_WAKEMSK); 327 au_sync(); 328 local_irq_restore(flags); 329 330 return 0; 331} 332 333/* 334 * irq_chips for both ICs; this way the mask handlers can be 335 * as short as possible. 336 */ 337static struct irq_chip au1x_ic0_chip = { 338 .name = "Alchemy-IC0", 339 .irq_ack = au1x_ic0_ack, 340 .irq_mask = au1x_ic0_mask, 341 .irq_mask_ack = au1x_ic0_maskack, 342 .irq_unmask = au1x_ic0_unmask, 343 .irq_set_type = au1x_ic_settype, 344}; 345 346static struct irq_chip au1x_ic1_chip = { 347 .name = "Alchemy-IC1", 348 .irq_ack = au1x_ic1_ack, 349 .irq_mask = au1x_ic1_mask, 350 .irq_mask_ack = au1x_ic1_maskack, 351 .irq_unmask = au1x_ic1_unmask, 352 .irq_set_type = au1x_ic_settype, 353 .irq_set_wake = au1x_ic1_setwake, 354}; 355 356static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) 357{ 358 struct irq_chip *chip; 359 unsigned long icr[6]; 360 unsigned int bit, ic, irq = d->irq; 361 irq_flow_handler_t handler = NULL; 362 unsigned char *name = NULL; 363 int ret; 364 365 if (irq >= AU1000_INTC1_INT_BASE) { 366 bit = irq - AU1000_INTC1_INT_BASE; 367 chip = &au1x_ic1_chip; 368 ic = 1; 369 } else { 370 bit = irq - AU1000_INTC0_INT_BASE; 371 chip = &au1x_ic0_chip; 372 ic = 0; 373 } 374 375 if (bit > 31) 376 return -EINVAL; 377 378 icr[0] = ic ? IC1_CFG0SET : IC0_CFG0SET; 379 icr[1] = ic ? IC1_CFG1SET : IC0_CFG1SET; 380 icr[2] = ic ? IC1_CFG2SET : IC0_CFG2SET; 381 icr[3] = ic ? IC1_CFG0CLR : IC0_CFG0CLR; 382 icr[4] = ic ? IC1_CFG1CLR : IC0_CFG1CLR; 383 icr[5] = ic ? IC1_CFG2CLR : IC0_CFG2CLR; 384 385 ret = 0; 386 387 switch (flow_type) { /* cfgregs 2:1:0 */ 388 case IRQ_TYPE_EDGE_RISING: /* 0:0:1 */ 389 au_writel(1 << bit, icr[5]); 390 au_writel(1 << bit, icr[4]); 391 au_writel(1 << bit, icr[0]); 392 handler = handle_edge_irq; 393 name = "riseedge"; 394 break; 395 case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */ 396 au_writel(1 << bit, icr[5]); 397 au_writel(1 << bit, icr[1]); 398 au_writel(1 << bit, icr[3]); 399 handler = handle_edge_irq; 400 name = "falledge"; 401 break; 402 case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */ 403 au_writel(1 << bit, icr[5]); 404 au_writel(1 << bit, icr[1]); 405 au_writel(1 << bit, icr[0]); 406 handler = handle_edge_irq; 407 name = "bothedge"; 408 break; 409 case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */ 410 au_writel(1 << bit, icr[2]); 411 au_writel(1 << bit, icr[4]); 412 au_writel(1 << bit, icr[0]); 413 handler = handle_level_irq; 414 name = "hilevel"; 415 break; 416 case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */ 417 au_writel(1 << bit, icr[2]); 418 au_writel(1 << bit, icr[1]); 419 au_writel(1 << bit, icr[3]); 420 handler = handle_level_irq; 421 name = "lowlevel"; 422 break; 423 case IRQ_TYPE_NONE: /* 0:0:0 */ 424 au_writel(1 << bit, icr[5]); 425 au_writel(1 << bit, icr[4]); 426 au_writel(1 << bit, icr[3]); 427 break; 428 default: 429 ret = -EINVAL; 430 } 431 __irq_set_chip_handler_name_locked(d->irq, chip, handler, name); 432 433 au_sync(); 434 435 return ret; 436} 437 438asmlinkage void plat_irq_dispatch(void) 439{ 440 unsigned int pending = read_c0_status() & read_c0_cause(); 441 unsigned long s, off; 442 443 if (pending & CAUSEF_IP7) { 444 off = MIPS_CPU_IRQ_BASE + 7; 445 goto handle; 446 } else if (pending & CAUSEF_IP2) { 447 s = IC0_REQ0INT; 448 off = AU1000_INTC0_INT_BASE; 449 } else if (pending & CAUSEF_IP3) { 450 s = IC0_REQ1INT; 451 off = AU1000_INTC0_INT_BASE; 452 } else if (pending & CAUSEF_IP4) { 453 s = IC1_REQ0INT; 454 off = AU1000_INTC1_INT_BASE; 455 } else if (pending & CAUSEF_IP5) { 456 s = IC1_REQ1INT; 457 off = AU1000_INTC1_INT_BASE; 458 } else 459 goto spurious; 460 461 s = au_readl(s); 462 if (unlikely(!s)) { 463spurious: 464 spurious_interrupt(); 465 return; 466 } 467 off += __ffs(s); 468handle: 469 do_IRQ(off); 470} 471 472static void __init au1000_init_irq(struct au1xxx_irqmap *map) 473{ 474 unsigned int bit, irq_nr; 475 int i; 476 477 /* 478 * Initialize interrupt controllers to a safe state. 479 */ 480 au_writel(0xffffffff, IC0_CFG0CLR); 481 au_writel(0xffffffff, IC0_CFG1CLR); 482 au_writel(0xffffffff, IC0_CFG2CLR); 483 au_writel(0xffffffff, IC0_MASKCLR); 484 au_writel(0xffffffff, IC0_ASSIGNCLR); 485 au_writel(0xffffffff, IC0_WAKECLR); 486 au_writel(0xffffffff, IC0_SRCSET); 487 au_writel(0xffffffff, IC0_FALLINGCLR); 488 au_writel(0xffffffff, IC0_RISINGCLR); 489 au_writel(0x00000000, IC0_TESTBIT); 490 491 au_writel(0xffffffff, IC1_CFG0CLR); 492 au_writel(0xffffffff, IC1_CFG1CLR); 493 au_writel(0xffffffff, IC1_CFG2CLR); 494 au_writel(0xffffffff, IC1_MASKCLR); 495 au_writel(0xffffffff, IC1_ASSIGNCLR); 496 au_writel(0xffffffff, IC1_WAKECLR); 497 au_writel(0xffffffff, IC1_SRCSET); 498 au_writel(0xffffffff, IC1_FALLINGCLR); 499 au_writel(0xffffffff, IC1_RISINGCLR); 500 au_writel(0x00000000, IC1_TESTBIT); 501 502 mips_cpu_irq_init(); 503 504 /* register all 64 possible IC0+IC1 irq sources as type "none". 505 * Use set_irq_type() to set edge/level behaviour at runtime. 506 */ 507 for (i = AU1000_INTC0_INT_BASE; 508 (i < AU1000_INTC0_INT_BASE + 32); i++) 509 au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); 510 511 for (i = AU1000_INTC1_INT_BASE; 512 (i < AU1000_INTC1_INT_BASE + 32); i++) 513 au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); 514 515 /* 516 * Initialize IC0, which is fixed per processor. 517 */ 518 while (map->im_irq != -1) { 519 irq_nr = map->im_irq; 520 521 if (irq_nr >= AU1000_INTC1_INT_BASE) { 522 bit = irq_nr - AU1000_INTC1_INT_BASE; 523 if (map->im_request) 524 au_writel(1 << bit, IC1_ASSIGNSET); 525 } else { 526 bit = irq_nr - AU1000_INTC0_INT_BASE; 527 if (map->im_request) 528 au_writel(1 << bit, IC0_ASSIGNSET); 529 } 530 531 au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type); 532 ++map; 533 } 534 535 set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3); 536} 537 538void __init arch_init_irq(void) 539{ 540 switch (alchemy_get_cputype()) { 541 case ALCHEMY_CPU_AU1000: 542 au1000_init_irq(au1000_irqmap); 543 break; 544 case ALCHEMY_CPU_AU1500: 545 au1000_init_irq(au1500_irqmap); 546 break; 547 case ALCHEMY_CPU_AU1100: 548 au1000_init_irq(au1100_irqmap); 549 break; 550 case ALCHEMY_CPU_AU1550: 551 au1000_init_irq(au1550_irqmap); 552 break; 553 case ALCHEMY_CPU_AU1200: 554 au1000_init_irq(au1200_irqmap); 555 break; 556 } 557} 558 559struct alchemy_ic_sysdev { 560 struct sys_device sysdev; 561 void __iomem *base; 562 unsigned long pmdata[7]; 563}; 564 565static int alchemy_ic_suspend(struct sys_device *dev, pm_message_t state) 566{ 567 struct alchemy_ic_sysdev *icdev = 568 container_of(dev, struct alchemy_ic_sysdev, sysdev); 569 570 icdev->pmdata[0] = __raw_readl(icdev->base + IC_CFG0RD); 571 icdev->pmdata[1] = __raw_readl(icdev->base + IC_CFG1RD); 572 icdev->pmdata[2] = __raw_readl(icdev->base + IC_CFG2RD); 573 icdev->pmdata[3] = __raw_readl(icdev->base + IC_SRCRD); 574 icdev->pmdata[4] = __raw_readl(icdev->base + IC_ASSIGNRD); 575 icdev->pmdata[5] = __raw_readl(icdev->base + IC_WAKERD); 576 icdev->pmdata[6] = __raw_readl(icdev->base + IC_MASKRD); 577 578 return 0; 579} 580 581static int alchemy_ic_resume(struct sys_device *dev) 582{ 583 struct alchemy_ic_sysdev *icdev = 584 container_of(dev, struct alchemy_ic_sysdev, sysdev); 585 586 __raw_writel(0xffffffff, icdev->base + IC_MASKCLR); 587 __raw_writel(0xffffffff, icdev->base + IC_CFG0CLR); 588 __raw_writel(0xffffffff, icdev->base + IC_CFG1CLR); 589 __raw_writel(0xffffffff, icdev->base + IC_CFG2CLR); 590 __raw_writel(0xffffffff, icdev->base + IC_SRCCLR); 591 __raw_writel(0xffffffff, icdev->base + IC_ASSIGNCLR); 592 __raw_writel(0xffffffff, icdev->base + IC_WAKECLR); 593 __raw_writel(0xffffffff, icdev->base + IC_RISINGCLR); 594 __raw_writel(0xffffffff, icdev->base + IC_FALLINGCLR); 595 __raw_writel(0x00000000, icdev->base + IC_TESTBIT); 596 wmb(); 597 __raw_writel(icdev->pmdata[0], icdev->base + IC_CFG0SET); 598 __raw_writel(icdev->pmdata[1], icdev->base + IC_CFG1SET); 599 __raw_writel(icdev->pmdata[2], icdev->base + IC_CFG2SET); 600 __raw_writel(icdev->pmdata[3], icdev->base + IC_SRCSET); 601 __raw_writel(icdev->pmdata[4], icdev->base + IC_ASSIGNSET); 602 __raw_writel(icdev->pmdata[5], icdev->base + IC_WAKESET); 603 wmb(); 604 605 __raw_writel(icdev->pmdata[6], icdev->base + IC_MASKSET); 606 wmb(); 607 608 return 0; 609} 610 611static struct sysdev_class alchemy_ic_sysdev_class = { 612 .name = "ic", 613 .suspend = alchemy_ic_suspend, 614 .resume = alchemy_ic_resume, 615}; 616 617static int __init alchemy_ic_sysdev_init(void) 618{ 619 struct alchemy_ic_sysdev *icdev; 620 unsigned long icbase[2] = { IC0_PHYS_ADDR, IC1_PHYS_ADDR }; 621 int err, i; 622 623 err = sysdev_class_register(&alchemy_ic_sysdev_class); 624 if (err) 625 return err; 626 627 for (i = 0; i < 2; i++) { 628 icdev = kzalloc(sizeof(struct alchemy_ic_sysdev), GFP_KERNEL); 629 if (!icdev) 630 return -ENOMEM; 631 632 icdev->base = ioremap(icbase[i], 0x1000); 633 634 icdev->sysdev.id = i; 635 icdev->sysdev.cls = &alchemy_ic_sysdev_class; 636 err = sysdev_register(&icdev->sysdev); 637 if (err) { 638 kfree(icdev); 639 return err; 640 } 641 } 642 643 return 0; 644} 645device_initcall(alchemy_ic_sysdev_init);