1/* 2 * icu.c, Interrupt Control Unit routines for the NEC VR4100 series. 3 * 4 * Copyright (C) 2001-2002 MontaVista Software Inc. 5 * Author: Yoichi Yuasa <source@mvista.com> 6 * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22/* 23 * Changes: 24 * MontaVista Software Inc. <source@mvista.com> 25 * - New creation, NEC VR4122 and VR4131 are supported. 26 * - Added support for NEC VR4111 and VR4121. 27 * 28 * Yoichi Yuasa <yuasa@linux-mips.org> 29 * - Coped with INTASSIGN of NEC VR4133. 30 */ 31#include <linux/errno.h> 32#include <linux/init.h> 33#include <linux/ioport.h> 34#include <linux/irq.h> 35#include <linux/module.h> 36#include <linux/smp.h> 37#include <linux/types.h> 38 39#include <asm/cpu.h> 40#include <asm/io.h> 41#include <asm/vr41xx/irq.h> 42#include <asm/vr41xx/vr41xx.h> 43 44static void __iomem *icu1_base; 45static void __iomem *icu2_base; 46 47static unsigned char sysint1_assign[16] = { 48 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 49static unsigned char sysint2_assign[16] = { 50 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 51 52#define ICU1_TYPE1_BASE 0x0b000080UL 53#define ICU2_TYPE1_BASE 0x0b000200UL 54 55#define ICU1_TYPE2_BASE 0x0f000080UL 56#define ICU2_TYPE2_BASE 0x0f0000a0UL 57 58#define ICU1_SIZE 0x20 59#define ICU2_SIZE 0x1c 60 61#define SYSINT1REG 0x00 62#define PIUINTREG 0x02 63#define INTASSIGN0 0x04 64#define INTASSIGN1 0x06 65#define GIUINTLREG 0x08 66#define DSIUINTREG 0x0a 67#define MSYSINT1REG 0x0c 68#define MPIUINTREG 0x0e 69#define MAIUINTREG 0x10 70#define MKIUINTREG 0x12 71#define MMACINTREG 0x12 72#define MGIUINTLREG 0x14 73#define MDSIUINTREG 0x16 74#define NMIREG 0x18 75#define SOFTREG 0x1a 76#define INTASSIGN2 0x1c 77#define INTASSIGN3 0x1e 78 79#define SYSINT2REG 0x00 80#define GIUINTHREG 0x02 81#define FIRINTREG 0x04 82#define MSYSINT2REG 0x06 83#define MGIUINTHREG 0x08 84#define MFIRINTREG 0x0a 85#define PCIINTREG 0x0c 86 #define PCIINT0 0x0001 87#define SCUINTREG 0x0e 88 #define SCUINT0 0x0001 89#define CSIINTREG 0x10 90#define MPCIINTREG 0x12 91#define MSCUINTREG 0x14 92#define MCSIINTREG 0x16 93#define BCUINTREG 0x18 94 #define BCUINTR 0x0001 95#define MBCUINTREG 0x1a 96 97#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */ 98#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */ 99 100#define INT_TO_IRQ(x) ((x) + 2) /* Int0-4 -> IRQ2-6 */ 101 102#define icu1_read(offset) readw(icu1_base + (offset)) 103#define icu1_write(offset, value) writew((value), icu1_base + (offset)) 104 105#define icu2_read(offset) readw(icu2_base + (offset)) 106#define icu2_write(offset, value) writew((value), icu2_base + (offset)) 107 108#define INTASSIGN_MAX 4 109#define INTASSIGN_MASK 0x0007 110 111static inline uint16_t icu1_set(uint8_t offset, uint16_t set) 112{ 113 uint16_t data; 114 115 data = icu1_read(offset); 116 data |= set; 117 icu1_write(offset, data); 118 119 return data; 120} 121 122static inline uint16_t icu1_clear(uint8_t offset, uint16_t clear) 123{ 124 uint16_t data; 125 126 data = icu1_read(offset); 127 data &= ~clear; 128 icu1_write(offset, data); 129 130 return data; 131} 132 133static inline uint16_t icu2_set(uint8_t offset, uint16_t set) 134{ 135 uint16_t data; 136 137 data = icu2_read(offset); 138 data |= set; 139 icu2_write(offset, data); 140 141 return data; 142} 143 144static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear) 145{ 146 uint16_t data; 147 148 data = icu2_read(offset); 149 data &= ~clear; 150 icu2_write(offset, data); 151 152 return data; 153} 154 155void vr41xx_enable_piuint(uint16_t mask) 156{ 157 struct irq_desc *desc = irq_to_desc(PIU_IRQ); 158 unsigned long flags; 159 160 if (current_cpu_type() == CPU_VR4111 || 161 current_cpu_type() == CPU_VR4121) { 162 raw_spin_lock_irqsave(&desc->lock, flags); 163 icu1_set(MPIUINTREG, mask); 164 raw_spin_unlock_irqrestore(&desc->lock, flags); 165 } 166} 167 168EXPORT_SYMBOL(vr41xx_enable_piuint); 169 170void vr41xx_disable_piuint(uint16_t mask) 171{ 172 struct irq_desc *desc = irq_to_desc(PIU_IRQ); 173 unsigned long flags; 174 175 if (current_cpu_type() == CPU_VR4111 || 176 current_cpu_type() == CPU_VR4121) { 177 raw_spin_lock_irqsave(&desc->lock, flags); 178 icu1_clear(MPIUINTREG, mask); 179 raw_spin_unlock_irqrestore(&desc->lock, flags); 180 } 181} 182 183EXPORT_SYMBOL(vr41xx_disable_piuint); 184 185void vr41xx_enable_aiuint(uint16_t mask) 186{ 187 struct irq_desc *desc = irq_to_desc(AIU_IRQ); 188 unsigned long flags; 189 190 if (current_cpu_type() == CPU_VR4111 || 191 current_cpu_type() == CPU_VR4121) { 192 raw_spin_lock_irqsave(&desc->lock, flags); 193 icu1_set(MAIUINTREG, mask); 194 raw_spin_unlock_irqrestore(&desc->lock, flags); 195 } 196} 197 198EXPORT_SYMBOL(vr41xx_enable_aiuint); 199 200void vr41xx_disable_aiuint(uint16_t mask) 201{ 202 struct irq_desc *desc = irq_to_desc(AIU_IRQ); 203 unsigned long flags; 204 205 if (current_cpu_type() == CPU_VR4111 || 206 current_cpu_type() == CPU_VR4121) { 207 raw_spin_lock_irqsave(&desc->lock, flags); 208 icu1_clear(MAIUINTREG, mask); 209 raw_spin_unlock_irqrestore(&desc->lock, flags); 210 } 211} 212 213EXPORT_SYMBOL(vr41xx_disable_aiuint); 214 215void vr41xx_enable_kiuint(uint16_t mask) 216{ 217 struct irq_desc *desc = irq_to_desc(KIU_IRQ); 218 unsigned long flags; 219 220 if (current_cpu_type() == CPU_VR4111 || 221 current_cpu_type() == CPU_VR4121) { 222 raw_spin_lock_irqsave(&desc->lock, flags); 223 icu1_set(MKIUINTREG, mask); 224 raw_spin_unlock_irqrestore(&desc->lock, flags); 225 } 226} 227 228EXPORT_SYMBOL(vr41xx_enable_kiuint); 229 230void vr41xx_disable_kiuint(uint16_t mask) 231{ 232 struct irq_desc *desc = irq_to_desc(KIU_IRQ); 233 unsigned long flags; 234 235 if (current_cpu_type() == CPU_VR4111 || 236 current_cpu_type() == CPU_VR4121) { 237 raw_spin_lock_irqsave(&desc->lock, flags); 238 icu1_clear(MKIUINTREG, mask); 239 raw_spin_unlock_irqrestore(&desc->lock, flags); 240 } 241} 242 243EXPORT_SYMBOL(vr41xx_disable_kiuint); 244 245void vr41xx_enable_macint(uint16_t mask) 246{ 247 struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); 248 unsigned long flags; 249 250 raw_spin_lock_irqsave(&desc->lock, flags); 251 icu1_set(MMACINTREG, mask); 252 raw_spin_unlock_irqrestore(&desc->lock, flags); 253} 254 255EXPORT_SYMBOL(vr41xx_enable_macint); 256 257void vr41xx_disable_macint(uint16_t mask) 258{ 259 struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); 260 unsigned long flags; 261 262 raw_spin_lock_irqsave(&desc->lock, flags); 263 icu1_clear(MMACINTREG, mask); 264 raw_spin_unlock_irqrestore(&desc->lock, flags); 265} 266 267EXPORT_SYMBOL(vr41xx_disable_macint); 268 269void vr41xx_enable_dsiuint(uint16_t mask) 270{ 271 struct irq_desc *desc = irq_to_desc(DSIU_IRQ); 272 unsigned long flags; 273 274 raw_spin_lock_irqsave(&desc->lock, flags); 275 icu1_set(MDSIUINTREG, mask); 276 raw_spin_unlock_irqrestore(&desc->lock, flags); 277} 278 279EXPORT_SYMBOL(vr41xx_enable_dsiuint); 280 281void vr41xx_disable_dsiuint(uint16_t mask) 282{ 283 struct irq_desc *desc = irq_to_desc(DSIU_IRQ); 284 unsigned long flags; 285 286 raw_spin_lock_irqsave(&desc->lock, flags); 287 icu1_clear(MDSIUINTREG, mask); 288 raw_spin_unlock_irqrestore(&desc->lock, flags); 289} 290 291EXPORT_SYMBOL(vr41xx_disable_dsiuint); 292 293void vr41xx_enable_firint(uint16_t mask) 294{ 295 struct irq_desc *desc = irq_to_desc(FIR_IRQ); 296 unsigned long flags; 297 298 raw_spin_lock_irqsave(&desc->lock, flags); 299 icu2_set(MFIRINTREG, mask); 300 raw_spin_unlock_irqrestore(&desc->lock, flags); 301} 302 303EXPORT_SYMBOL(vr41xx_enable_firint); 304 305void vr41xx_disable_firint(uint16_t mask) 306{ 307 struct irq_desc *desc = irq_to_desc(FIR_IRQ); 308 unsigned long flags; 309 310 raw_spin_lock_irqsave(&desc->lock, flags); 311 icu2_clear(MFIRINTREG, mask); 312 raw_spin_unlock_irqrestore(&desc->lock, flags); 313} 314 315EXPORT_SYMBOL(vr41xx_disable_firint); 316 317void vr41xx_enable_pciint(void) 318{ 319 struct irq_desc *desc = irq_to_desc(PCI_IRQ); 320 unsigned long flags; 321 322 if (current_cpu_type() == CPU_VR4122 || 323 current_cpu_type() == CPU_VR4131 || 324 current_cpu_type() == CPU_VR4133) { 325 raw_spin_lock_irqsave(&desc->lock, flags); 326 icu2_write(MPCIINTREG, PCIINT0); 327 raw_spin_unlock_irqrestore(&desc->lock, flags); 328 } 329} 330 331EXPORT_SYMBOL(vr41xx_enable_pciint); 332 333void vr41xx_disable_pciint(void) 334{ 335 struct irq_desc *desc = irq_to_desc(PCI_IRQ); 336 unsigned long flags; 337 338 if (current_cpu_type() == CPU_VR4122 || 339 current_cpu_type() == CPU_VR4131 || 340 current_cpu_type() == CPU_VR4133) { 341 raw_spin_lock_irqsave(&desc->lock, flags); 342 icu2_write(MPCIINTREG, 0); 343 raw_spin_unlock_irqrestore(&desc->lock, flags); 344 } 345} 346 347EXPORT_SYMBOL(vr41xx_disable_pciint); 348 349void vr41xx_enable_scuint(void) 350{ 351 struct irq_desc *desc = irq_to_desc(SCU_IRQ); 352 unsigned long flags; 353 354 if (current_cpu_type() == CPU_VR4122 || 355 current_cpu_type() == CPU_VR4131 || 356 current_cpu_type() == CPU_VR4133) { 357 raw_spin_lock_irqsave(&desc->lock, flags); 358 icu2_write(MSCUINTREG, SCUINT0); 359 raw_spin_unlock_irqrestore(&desc->lock, flags); 360 } 361} 362 363EXPORT_SYMBOL(vr41xx_enable_scuint); 364 365void vr41xx_disable_scuint(void) 366{ 367 struct irq_desc *desc = irq_to_desc(SCU_IRQ); 368 unsigned long flags; 369 370 if (current_cpu_type() == CPU_VR4122 || 371 current_cpu_type() == CPU_VR4131 || 372 current_cpu_type() == CPU_VR4133) { 373 raw_spin_lock_irqsave(&desc->lock, flags); 374 icu2_write(MSCUINTREG, 0); 375 raw_spin_unlock_irqrestore(&desc->lock, flags); 376 } 377} 378 379EXPORT_SYMBOL(vr41xx_disable_scuint); 380 381void vr41xx_enable_csiint(uint16_t mask) 382{ 383 struct irq_desc *desc = irq_to_desc(CSI_IRQ); 384 unsigned long flags; 385 386 if (current_cpu_type() == CPU_VR4122 || 387 current_cpu_type() == CPU_VR4131 || 388 current_cpu_type() == CPU_VR4133) { 389 raw_spin_lock_irqsave(&desc->lock, flags); 390 icu2_set(MCSIINTREG, mask); 391 raw_spin_unlock_irqrestore(&desc->lock, flags); 392 } 393} 394 395EXPORT_SYMBOL(vr41xx_enable_csiint); 396 397void vr41xx_disable_csiint(uint16_t mask) 398{ 399 struct irq_desc *desc = irq_to_desc(CSI_IRQ); 400 unsigned long flags; 401 402 if (current_cpu_type() == CPU_VR4122 || 403 current_cpu_type() == CPU_VR4131 || 404 current_cpu_type() == CPU_VR4133) { 405 raw_spin_lock_irqsave(&desc->lock, flags); 406 icu2_clear(MCSIINTREG, mask); 407 raw_spin_unlock_irqrestore(&desc->lock, flags); 408 } 409} 410 411EXPORT_SYMBOL(vr41xx_disable_csiint); 412 413void vr41xx_enable_bcuint(void) 414{ 415 struct irq_desc *desc = irq_to_desc(BCU_IRQ); 416 unsigned long flags; 417 418 if (current_cpu_type() == CPU_VR4122 || 419 current_cpu_type() == CPU_VR4131 || 420 current_cpu_type() == CPU_VR4133) { 421 raw_spin_lock_irqsave(&desc->lock, flags); 422 icu2_write(MBCUINTREG, BCUINTR); 423 raw_spin_unlock_irqrestore(&desc->lock, flags); 424 } 425} 426 427EXPORT_SYMBOL(vr41xx_enable_bcuint); 428 429void vr41xx_disable_bcuint(void) 430{ 431 struct irq_desc *desc = irq_to_desc(BCU_IRQ); 432 unsigned long flags; 433 434 if (current_cpu_type() == CPU_VR4122 || 435 current_cpu_type() == CPU_VR4131 || 436 current_cpu_type() == CPU_VR4133) { 437 raw_spin_lock_irqsave(&desc->lock, flags); 438 icu2_write(MBCUINTREG, 0); 439 raw_spin_unlock_irqrestore(&desc->lock, flags); 440 } 441} 442 443EXPORT_SYMBOL(vr41xx_disable_bcuint); 444 445static void disable_sysint1_irq(struct irq_data *d) 446{ 447 icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); 448} 449 450static void enable_sysint1_irq(struct irq_data *d) 451{ 452 icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); 453} 454 455static struct irq_chip sysint1_irq_type = { 456 .name = "SYSINT1", 457 .irq_mask = disable_sysint1_irq, 458 .irq_unmask = enable_sysint1_irq, 459}; 460 461static void disable_sysint2_irq(struct irq_data *d) 462{ 463 icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); 464} 465 466static void enable_sysint2_irq(struct irq_data *d) 467{ 468 icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); 469} 470 471static struct irq_chip sysint2_irq_type = { 472 .name = "SYSINT2", 473 .irq_mask = disable_sysint2_irq, 474 .irq_unmask = enable_sysint2_irq, 475}; 476 477static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) 478{ 479 struct irq_desc *desc = irq_to_desc(irq); 480 uint16_t intassign0, intassign1; 481 unsigned int pin; 482 483 pin = SYSINT1_IRQ_TO_PIN(irq); 484 485 raw_spin_lock_irq(&desc->lock); 486 487 intassign0 = icu1_read(INTASSIGN0); 488 intassign1 = icu1_read(INTASSIGN1); 489 490 switch (pin) { 491 case 0: 492 intassign0 &= ~INTASSIGN_MASK; 493 intassign0 |= (uint16_t)assign; 494 break; 495 case 1: 496 intassign0 &= ~(INTASSIGN_MASK << 3); 497 intassign0 |= (uint16_t)assign << 3; 498 break; 499 case 2: 500 intassign0 &= ~(INTASSIGN_MASK << 6); 501 intassign0 |= (uint16_t)assign << 6; 502 break; 503 case 3: 504 intassign0 &= ~(INTASSIGN_MASK << 9); 505 intassign0 |= (uint16_t)assign << 9; 506 break; 507 case 8: 508 intassign0 &= ~(INTASSIGN_MASK << 12); 509 intassign0 |= (uint16_t)assign << 12; 510 break; 511 case 9: 512 intassign1 &= ~INTASSIGN_MASK; 513 intassign1 |= (uint16_t)assign; 514 break; 515 case 11: 516 intassign1 &= ~(INTASSIGN_MASK << 6); 517 intassign1 |= (uint16_t)assign << 6; 518 break; 519 case 12: 520 intassign1 &= ~(INTASSIGN_MASK << 9); 521 intassign1 |= (uint16_t)assign << 9; 522 break; 523 default: 524 raw_spin_unlock_irq(&desc->lock); 525 return -EINVAL; 526 } 527 528 sysint1_assign[pin] = assign; 529 icu1_write(INTASSIGN0, intassign0); 530 icu1_write(INTASSIGN1, intassign1); 531 532 raw_spin_unlock_irq(&desc->lock); 533 534 return 0; 535} 536 537static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) 538{ 539 struct irq_desc *desc = irq_to_desc(irq); 540 uint16_t intassign2, intassign3; 541 unsigned int pin; 542 543 pin = SYSINT2_IRQ_TO_PIN(irq); 544 545 raw_spin_lock_irq(&desc->lock); 546 547 intassign2 = icu1_read(INTASSIGN2); 548 intassign3 = icu1_read(INTASSIGN3); 549 550 switch (pin) { 551 case 0: 552 intassign2 &= ~INTASSIGN_MASK; 553 intassign2 |= (uint16_t)assign; 554 break; 555 case 1: 556 intassign2 &= ~(INTASSIGN_MASK << 3); 557 intassign2 |= (uint16_t)assign << 3; 558 break; 559 case 3: 560 intassign2 &= ~(INTASSIGN_MASK << 6); 561 intassign2 |= (uint16_t)assign << 6; 562 break; 563 case 4: 564 intassign2 &= ~(INTASSIGN_MASK << 9); 565 intassign2 |= (uint16_t)assign << 9; 566 break; 567 case 5: 568 intassign2 &= ~(INTASSIGN_MASK << 12); 569 intassign2 |= (uint16_t)assign << 12; 570 break; 571 case 6: 572 intassign3 &= ~INTASSIGN_MASK; 573 intassign3 |= (uint16_t)assign; 574 break; 575 case 7: 576 intassign3 &= ~(INTASSIGN_MASK << 3); 577 intassign3 |= (uint16_t)assign << 3; 578 break; 579 case 8: 580 intassign3 &= ~(INTASSIGN_MASK << 6); 581 intassign3 |= (uint16_t)assign << 6; 582 break; 583 case 9: 584 intassign3 &= ~(INTASSIGN_MASK << 9); 585 intassign3 |= (uint16_t)assign << 9; 586 break; 587 case 10: 588 intassign3 &= ~(INTASSIGN_MASK << 12); 589 intassign3 |= (uint16_t)assign << 12; 590 break; 591 default: 592 raw_spin_unlock_irq(&desc->lock); 593 return -EINVAL; 594 } 595 596 sysint2_assign[pin] = assign; 597 icu1_write(INTASSIGN2, intassign2); 598 icu1_write(INTASSIGN3, intassign3); 599 600 raw_spin_unlock_irq(&desc->lock); 601 602 return 0; 603} 604 605int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) 606{ 607 int retval = -EINVAL; 608 609 if (current_cpu_type() != CPU_VR4133) 610 return -EINVAL; 611 612 if (intassign > INTASSIGN_MAX) 613 return -EINVAL; 614 615 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST) 616 retval = set_sysint1_assign(irq, intassign); 617 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST) 618 retval = set_sysint2_assign(irq, intassign); 619 620 return retval; 621} 622 623EXPORT_SYMBOL(vr41xx_set_intassign); 624 625static int icu_get_irq(unsigned int irq) 626{ 627 uint16_t pend1, pend2; 628 uint16_t mask1, mask2; 629 int i; 630 631 pend1 = icu1_read(SYSINT1REG); 632 mask1 = icu1_read(MSYSINT1REG); 633 634 pend2 = icu2_read(SYSINT2REG); 635 mask2 = icu2_read(MSYSINT2REG); 636 637 mask1 &= pend1; 638 mask2 &= pend2; 639 640 if (mask1) { 641 for (i = 0; i < 16; i++) { 642 if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i))) 643 return SYSINT1_IRQ(i); 644 } 645 } 646 647 if (mask2) { 648 for (i = 0; i < 16; i++) { 649 if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i))) 650 return SYSINT2_IRQ(i); 651 } 652 } 653 654 printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); 655 656 atomic_inc(&irq_err_count); 657 658 return -1; 659} 660 661static int __init vr41xx_icu_init(void) 662{ 663 unsigned long icu1_start, icu2_start; 664 int i; 665 666 switch (current_cpu_type()) { 667 case CPU_VR4111: 668 case CPU_VR4121: 669 icu1_start = ICU1_TYPE1_BASE; 670 icu2_start = ICU2_TYPE1_BASE; 671 break; 672 case CPU_VR4122: 673 case CPU_VR4131: 674 case CPU_VR4133: 675 icu1_start = ICU1_TYPE2_BASE; 676 icu2_start = ICU2_TYPE2_BASE; 677 break; 678 default: 679 printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n"); 680 return -ENODEV; 681 } 682 683 if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL) 684 return -EBUSY; 685 686 if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) { 687 release_mem_region(icu1_start, ICU1_SIZE); 688 return -EBUSY; 689 } 690 691 icu1_base = ioremap(icu1_start, ICU1_SIZE); 692 if (icu1_base == NULL) { 693 release_mem_region(icu1_start, ICU1_SIZE); 694 release_mem_region(icu2_start, ICU2_SIZE); 695 return -ENOMEM; 696 } 697 698 icu2_base = ioremap(icu2_start, ICU2_SIZE); 699 if (icu2_base == NULL) { 700 iounmap(icu1_base); 701 release_mem_region(icu1_start, ICU1_SIZE); 702 release_mem_region(icu2_start, ICU2_SIZE); 703 return -ENOMEM; 704 } 705 706 icu1_write(MSYSINT1REG, 0); 707 icu1_write(MGIUINTLREG, 0xffff); 708 709 icu2_write(MSYSINT2REG, 0); 710 icu2_write(MGIUINTHREG, 0xffff); 711 712 for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) 713 irq_set_chip_and_handler(i, &sysint1_irq_type, 714 handle_level_irq); 715 716 for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) 717 irq_set_chip_and_handler(i, &sysint2_irq_type, 718 handle_level_irq); 719 720 cascade_irq(INT0_IRQ, icu_get_irq); 721 cascade_irq(INT1_IRQ, icu_get_irq); 722 cascade_irq(INT2_IRQ, icu_get_irq); 723 cascade_irq(INT3_IRQ, icu_get_irq); 724 cascade_irq(INT4_IRQ, icu_get_irq); 725 726 return 0; 727} 728 729core_initcall(vr41xx_icu_init); 730