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