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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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(unsigned int irq) 446{ 447 icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); 448} 449 450static void enable_sysint1_irq(unsigned int irq) 451{ 452 icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); 453} 454 455static struct irq_chip sysint1_irq_type = { 456 .name = "SYSINT1", 457 .ack = disable_sysint1_irq, 458 .mask = disable_sysint1_irq, 459 .mask_ack = disable_sysint1_irq, 460 .unmask = enable_sysint1_irq, 461}; 462 463static void disable_sysint2_irq(unsigned int irq) 464{ 465 icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); 466} 467 468static void enable_sysint2_irq(unsigned int irq) 469{ 470 icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); 471} 472 473static struct irq_chip sysint2_irq_type = { 474 .name = "SYSINT2", 475 .ack = disable_sysint2_irq, 476 .mask = disable_sysint2_irq, 477 .mask_ack = disable_sysint2_irq, 478 .unmask = enable_sysint2_irq, 479}; 480 481static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) 482{ 483 struct irq_desc *desc = irq_desc + irq; 484 uint16_t intassign0, intassign1; 485 unsigned int pin; 486 487 pin = SYSINT1_IRQ_TO_PIN(irq); 488 489 raw_spin_lock_irq(&desc->lock); 490 491 intassign0 = icu1_read(INTASSIGN0); 492 intassign1 = icu1_read(INTASSIGN1); 493 494 switch (pin) { 495 case 0: 496 intassign0 &= ~INTASSIGN_MASK; 497 intassign0 |= (uint16_t)assign; 498 break; 499 case 1: 500 intassign0 &= ~(INTASSIGN_MASK << 3); 501 intassign0 |= (uint16_t)assign << 3; 502 break; 503 case 2: 504 intassign0 &= ~(INTASSIGN_MASK << 6); 505 intassign0 |= (uint16_t)assign << 6; 506 break; 507 case 3: 508 intassign0 &= ~(INTASSIGN_MASK << 9); 509 intassign0 |= (uint16_t)assign << 9; 510 break; 511 case 8: 512 intassign0 &= ~(INTASSIGN_MASK << 12); 513 intassign0 |= (uint16_t)assign << 12; 514 break; 515 case 9: 516 intassign1 &= ~INTASSIGN_MASK; 517 intassign1 |= (uint16_t)assign; 518 break; 519 case 11: 520 intassign1 &= ~(INTASSIGN_MASK << 6); 521 intassign1 |= (uint16_t)assign << 6; 522 break; 523 case 12: 524 intassign1 &= ~(INTASSIGN_MASK << 9); 525 intassign1 |= (uint16_t)assign << 9; 526 break; 527 default: 528 raw_spin_unlock_irq(&desc->lock); 529 return -EINVAL; 530 } 531 532 sysint1_assign[pin] = assign; 533 icu1_write(INTASSIGN0, intassign0); 534 icu1_write(INTASSIGN1, intassign1); 535 536 raw_spin_unlock_irq(&desc->lock); 537 538 return 0; 539} 540 541static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) 542{ 543 struct irq_desc *desc = irq_desc + irq; 544 uint16_t intassign2, intassign3; 545 unsigned int pin; 546 547 pin = SYSINT2_IRQ_TO_PIN(irq); 548 549 raw_spin_lock_irq(&desc->lock); 550 551 intassign2 = icu1_read(INTASSIGN2); 552 intassign3 = icu1_read(INTASSIGN3); 553 554 switch (pin) { 555 case 0: 556 intassign2 &= ~INTASSIGN_MASK; 557 intassign2 |= (uint16_t)assign; 558 break; 559 case 1: 560 intassign2 &= ~(INTASSIGN_MASK << 3); 561 intassign2 |= (uint16_t)assign << 3; 562 break; 563 case 3: 564 intassign2 &= ~(INTASSIGN_MASK << 6); 565 intassign2 |= (uint16_t)assign << 6; 566 break; 567 case 4: 568 intassign2 &= ~(INTASSIGN_MASK << 9); 569 intassign2 |= (uint16_t)assign << 9; 570 break; 571 case 5: 572 intassign2 &= ~(INTASSIGN_MASK << 12); 573 intassign2 |= (uint16_t)assign << 12; 574 break; 575 case 6: 576 intassign3 &= ~INTASSIGN_MASK; 577 intassign3 |= (uint16_t)assign; 578 break; 579 case 7: 580 intassign3 &= ~(INTASSIGN_MASK << 3); 581 intassign3 |= (uint16_t)assign << 3; 582 break; 583 case 8: 584 intassign3 &= ~(INTASSIGN_MASK << 6); 585 intassign3 |= (uint16_t)assign << 6; 586 break; 587 case 9: 588 intassign3 &= ~(INTASSIGN_MASK << 9); 589 intassign3 |= (uint16_t)assign << 9; 590 break; 591 case 10: 592 intassign3 &= ~(INTASSIGN_MASK << 12); 593 intassign3 |= (uint16_t)assign << 12; 594 break; 595 default: 596 raw_spin_unlock_irq(&desc->lock); 597 return -EINVAL; 598 } 599 600 sysint2_assign[pin] = assign; 601 icu1_write(INTASSIGN2, intassign2); 602 icu1_write(INTASSIGN3, intassign3); 603 604 raw_spin_unlock_irq(&desc->lock); 605 606 return 0; 607} 608 609int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) 610{ 611 int retval = -EINVAL; 612 613 if (current_cpu_type() != CPU_VR4133) 614 return -EINVAL; 615 616 if (intassign > INTASSIGN_MAX) 617 return -EINVAL; 618 619 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST) 620 retval = set_sysint1_assign(irq, intassign); 621 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST) 622 retval = set_sysint2_assign(irq, intassign); 623 624 return retval; 625} 626 627EXPORT_SYMBOL(vr41xx_set_intassign); 628 629static int icu_get_irq(unsigned int irq) 630{ 631 uint16_t pend1, pend2; 632 uint16_t mask1, mask2; 633 int i; 634 635 pend1 = icu1_read(SYSINT1REG); 636 mask1 = icu1_read(MSYSINT1REG); 637 638 pend2 = icu2_read(SYSINT2REG); 639 mask2 = icu2_read(MSYSINT2REG); 640 641 mask1 &= pend1; 642 mask2 &= pend2; 643 644 if (mask1) { 645 for (i = 0; i < 16; i++) { 646 if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i))) 647 return SYSINT1_IRQ(i); 648 } 649 } 650 651 if (mask2) { 652 for (i = 0; i < 16; i++) { 653 if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i))) 654 return SYSINT2_IRQ(i); 655 } 656 } 657 658 printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); 659 660 atomic_inc(&irq_err_count); 661 662 return -1; 663} 664 665static int __init vr41xx_icu_init(void) 666{ 667 unsigned long icu1_start, icu2_start; 668 int i; 669 670 switch (current_cpu_type()) { 671 case CPU_VR4111: 672 case CPU_VR4121: 673 icu1_start = ICU1_TYPE1_BASE; 674 icu2_start = ICU2_TYPE1_BASE; 675 break; 676 case CPU_VR4122: 677 case CPU_VR4131: 678 case CPU_VR4133: 679 icu1_start = ICU1_TYPE2_BASE; 680 icu2_start = ICU2_TYPE2_BASE; 681 break; 682 default: 683 printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n"); 684 return -ENODEV; 685 } 686 687 if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL) 688 return -EBUSY; 689 690 if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) { 691 release_mem_region(icu1_start, ICU1_SIZE); 692 return -EBUSY; 693 } 694 695 icu1_base = ioremap(icu1_start, ICU1_SIZE); 696 if (icu1_base == NULL) { 697 release_mem_region(icu1_start, ICU1_SIZE); 698 release_mem_region(icu2_start, ICU2_SIZE); 699 return -ENOMEM; 700 } 701 702 icu2_base = ioremap(icu2_start, ICU2_SIZE); 703 if (icu2_base == NULL) { 704 iounmap(icu1_base); 705 release_mem_region(icu1_start, ICU1_SIZE); 706 release_mem_region(icu2_start, ICU2_SIZE); 707 return -ENOMEM; 708 } 709 710 icu1_write(MSYSINT1REG, 0); 711 icu1_write(MGIUINTLREG, 0xffff); 712 713 icu2_write(MSYSINT2REG, 0); 714 icu2_write(MGIUINTHREG, 0xffff); 715 716 for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) 717 set_irq_chip_and_handler(i, &sysint1_irq_type, 718 handle_level_irq); 719 720 for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) 721 set_irq_chip_and_handler(i, &sysint2_irq_type, 722 handle_level_irq); 723 724 cascade_irq(INT0_IRQ, icu_get_irq); 725 cascade_irq(INT1_IRQ, icu_get_irq); 726 cascade_irq(INT2_IRQ, icu_get_irq); 727 cascade_irq(INT3_IRQ, icu_get_irq); 728 cascade_irq(INT4_IRQ, icu_get_irq); 729 730 return 0; 731} 732 733core_initcall(vr41xx_icu_init); 734