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 <yyuasa@mvista.com or source@mvista.com> 6 * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 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. <yyuasa@mvista.com> or <source@mvista.com> 25 * - New creation, NEC VR4122 and VR4131 are supported. 26 * - Added support for NEC VR4111 and VR4121. 27 * 28 * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 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_data.cputype == CPU_VR4111 || 161 current_cpu_data.cputype == CPU_VR4121) { 162 spin_lock_irqsave(&desc->lock, flags); 163 icu1_set(MPIUINTREG, mask); 164 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_data.cputype == CPU_VR4111 || 176 current_cpu_data.cputype == CPU_VR4121) { 177 spin_lock_irqsave(&desc->lock, flags); 178 icu1_clear(MPIUINTREG, mask); 179 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_data.cputype == CPU_VR4111 || 191 current_cpu_data.cputype == CPU_VR4121) { 192 spin_lock_irqsave(&desc->lock, flags); 193 icu1_set(MAIUINTREG, mask); 194 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_data.cputype == CPU_VR4111 || 206 current_cpu_data.cputype == CPU_VR4121) { 207 spin_lock_irqsave(&desc->lock, flags); 208 icu1_clear(MAIUINTREG, mask); 209 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_data.cputype == CPU_VR4111 || 221 current_cpu_data.cputype == CPU_VR4121) { 222 spin_lock_irqsave(&desc->lock, flags); 223 icu1_set(MKIUINTREG, mask); 224 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_data.cputype == CPU_VR4111 || 236 current_cpu_data.cputype == CPU_VR4121) { 237 spin_lock_irqsave(&desc->lock, flags); 238 icu1_clear(MKIUINTREG, mask); 239 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 spin_lock_irqsave(&desc->lock, flags); 251 icu1_set(MMACINTREG, mask); 252 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 spin_lock_irqsave(&desc->lock, flags); 263 icu1_clear(MMACINTREG, mask); 264 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 spin_lock_irqsave(&desc->lock, flags); 275 icu1_set(MDSIUINTREG, mask); 276 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 spin_lock_irqsave(&desc->lock, flags); 287 icu1_clear(MDSIUINTREG, mask); 288 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 spin_lock_irqsave(&desc->lock, flags); 299 icu2_set(MFIRINTREG, mask); 300 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 spin_lock_irqsave(&desc->lock, flags); 311 icu2_clear(MFIRINTREG, mask); 312 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_data.cputype == CPU_VR4122 || 323 current_cpu_data.cputype == CPU_VR4131 || 324 current_cpu_data.cputype == CPU_VR4133) { 325 spin_lock_irqsave(&desc->lock, flags); 326 icu2_write(MPCIINTREG, PCIINT0); 327 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_data.cputype == CPU_VR4122 || 339 current_cpu_data.cputype == CPU_VR4131 || 340 current_cpu_data.cputype == CPU_VR4133) { 341 spin_lock_irqsave(&desc->lock, flags); 342 icu2_write(MPCIINTREG, 0); 343 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_data.cputype == CPU_VR4122 || 355 current_cpu_data.cputype == CPU_VR4131 || 356 current_cpu_data.cputype == CPU_VR4133) { 357 spin_lock_irqsave(&desc->lock, flags); 358 icu2_write(MSCUINTREG, SCUINT0); 359 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_data.cputype == CPU_VR4122 || 371 current_cpu_data.cputype == CPU_VR4131 || 372 current_cpu_data.cputype == CPU_VR4133) { 373 spin_lock_irqsave(&desc->lock, flags); 374 icu2_write(MSCUINTREG, 0); 375 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_data.cputype == CPU_VR4122 || 387 current_cpu_data.cputype == CPU_VR4131 || 388 current_cpu_data.cputype == CPU_VR4133) { 389 spin_lock_irqsave(&desc->lock, flags); 390 icu2_set(MCSIINTREG, mask); 391 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_data.cputype == CPU_VR4122 || 403 current_cpu_data.cputype == CPU_VR4131 || 404 current_cpu_data.cputype == CPU_VR4133) { 405 spin_lock_irqsave(&desc->lock, flags); 406 icu2_clear(MCSIINTREG, mask); 407 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_data.cputype == CPU_VR4122 || 419 current_cpu_data.cputype == CPU_VR4131 || 420 current_cpu_data.cputype == CPU_VR4133) { 421 spin_lock_irqsave(&desc->lock, flags); 422 icu2_write(MBCUINTREG, BCUINTR); 423 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_data.cputype == CPU_VR4122 || 435 current_cpu_data.cputype == CPU_VR4131 || 436 current_cpu_data.cputype == CPU_VR4133) { 437 spin_lock_irqsave(&desc->lock, flags); 438 icu2_write(MBCUINTREG, 0); 439 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 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 return -EINVAL; 529 } 530 531 sysint1_assign[pin] = assign; 532 icu1_write(INTASSIGN0, intassign0); 533 icu1_write(INTASSIGN1, intassign1); 534 535 spin_unlock_irq(&desc->lock); 536 537 return 0; 538} 539 540static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) 541{ 542 struct irq_desc *desc = irq_desc + irq; 543 uint16_t intassign2, intassign3; 544 unsigned int pin; 545 546 pin = SYSINT2_IRQ_TO_PIN(irq); 547 548 spin_lock_irq(&desc->lock); 549 550 intassign2 = icu1_read(INTASSIGN2); 551 intassign3 = icu1_read(INTASSIGN3); 552 553 switch (pin) { 554 case 0: 555 intassign2 &= ~INTASSIGN_MASK; 556 intassign2 |= (uint16_t)assign; 557 break; 558 case 1: 559 intassign2 &= ~(INTASSIGN_MASK << 3); 560 intassign2 |= (uint16_t)assign << 3; 561 break; 562 case 3: 563 intassign2 &= ~(INTASSIGN_MASK << 6); 564 intassign2 |= (uint16_t)assign << 6; 565 break; 566 case 4: 567 intassign2 &= ~(INTASSIGN_MASK << 9); 568 intassign2 |= (uint16_t)assign << 9; 569 break; 570 case 5: 571 intassign2 &= ~(INTASSIGN_MASK << 12); 572 intassign2 |= (uint16_t)assign << 12; 573 break; 574 case 6: 575 intassign3 &= ~INTASSIGN_MASK; 576 intassign3 |= (uint16_t)assign; 577 break; 578 case 7: 579 intassign3 &= ~(INTASSIGN_MASK << 3); 580 intassign3 |= (uint16_t)assign << 3; 581 break; 582 case 8: 583 intassign3 &= ~(INTASSIGN_MASK << 6); 584 intassign3 |= (uint16_t)assign << 6; 585 break; 586 case 9: 587 intassign3 &= ~(INTASSIGN_MASK << 9); 588 intassign3 |= (uint16_t)assign << 9; 589 break; 590 case 10: 591 intassign3 &= ~(INTASSIGN_MASK << 12); 592 intassign3 |= (uint16_t)assign << 12; 593 break; 594 default: 595 return -EINVAL; 596 } 597 598 sysint2_assign[pin] = assign; 599 icu1_write(INTASSIGN2, intassign2); 600 icu1_write(INTASSIGN3, intassign3); 601 602 spin_unlock_irq(&desc->lock); 603 604 return 0; 605} 606 607int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) 608{ 609 int retval = -EINVAL; 610 611 if (current_cpu_data.cputype != CPU_VR4133) 612 return -EINVAL; 613 614 if (intassign > INTASSIGN_MAX) 615 return -EINVAL; 616 617 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST) 618 retval = set_sysint1_assign(irq, intassign); 619 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST) 620 retval = set_sysint2_assign(irq, intassign); 621 622 return retval; 623} 624 625EXPORT_SYMBOL(vr41xx_set_intassign); 626 627static int icu_get_irq(unsigned int irq) 628{ 629 uint16_t pend1, pend2; 630 uint16_t mask1, mask2; 631 int i; 632 633 pend1 = icu1_read(SYSINT1REG); 634 mask1 = icu1_read(MSYSINT1REG); 635 636 pend2 = icu2_read(SYSINT2REG); 637 mask2 = icu2_read(MSYSINT2REG); 638 639 mask1 &= pend1; 640 mask2 &= pend2; 641 642 if (mask1) { 643 for (i = 0; i < 16; i++) { 644 if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i))) 645 return SYSINT1_IRQ(i); 646 } 647 } 648 649 if (mask2) { 650 for (i = 0; i < 16; i++) { 651 if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i))) 652 return SYSINT2_IRQ(i); 653 } 654 } 655 656 printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); 657 658 atomic_inc(&irq_err_count); 659 660 return -1; 661} 662 663static int __init vr41xx_icu_init(void) 664{ 665 unsigned long icu1_start, icu2_start; 666 int i; 667 668 switch (current_cpu_data.cputype) { 669 case CPU_VR4111: 670 case CPU_VR4121: 671 icu1_start = ICU1_TYPE1_BASE; 672 icu2_start = ICU2_TYPE1_BASE; 673 break; 674 case CPU_VR4122: 675 case CPU_VR4131: 676 case CPU_VR4133: 677 icu1_start = ICU1_TYPE2_BASE; 678 icu2_start = ICU2_TYPE2_BASE; 679 break; 680 default: 681 printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n"); 682 return -ENODEV; 683 } 684 685 if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL) 686 return -EBUSY; 687 688 if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) { 689 release_mem_region(icu1_start, ICU1_SIZE); 690 return -EBUSY; 691 } 692 693 icu1_base = ioremap(icu1_start, ICU1_SIZE); 694 if (icu1_base == NULL) { 695 release_mem_region(icu1_start, ICU1_SIZE); 696 release_mem_region(icu2_start, ICU2_SIZE); 697 return -ENOMEM; 698 } 699 700 icu2_base = ioremap(icu2_start, ICU2_SIZE); 701 if (icu2_base == NULL) { 702 iounmap(icu1_base); 703 release_mem_region(icu1_start, ICU1_SIZE); 704 release_mem_region(icu2_start, ICU2_SIZE); 705 return -ENOMEM; 706 } 707 708 icu1_write(MSYSINT1REG, 0); 709 icu1_write(MGIUINTLREG, 0xffff); 710 711 icu2_write(MSYSINT2REG, 0); 712 icu2_write(MGIUINTHREG, 0xffff); 713 714 for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) 715 set_irq_chip_and_handler(i, &sysint1_irq_type, 716 handle_level_irq); 717 718 for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) 719 set_irq_chip_and_handler(i, &sysint2_irq_type, 720 handle_level_irq); 721 722 cascade_irq(INT0_IRQ, icu_get_irq); 723 cascade_irq(INT1_IRQ, icu_get_irq); 724 cascade_irq(INT2_IRQ, icu_get_irq); 725 cascade_irq(INT3_IRQ, icu_get_irq); 726 cascade_irq(INT4_IRQ, icu_get_irq); 727 728 return 0; 729} 730 731core_initcall(vr41xx_icu_init); 732