Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/vr41xx/common/icu.c
10820 views
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 <[email protected]>
6
* Copyright (C) 2003-2006 Yoichi Yuasa <[email protected]>
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. <[email protected]>
25
* - New creation, NEC VR4122 and VR4131 are supported.
26
* - Added support for NEC VR4111 and VR4121.
27
*
28
* Yoichi Yuasa <[email protected]>
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
44
static void __iomem *icu1_base;
45
static void __iomem *icu2_base;
46
47
static unsigned char sysint1_assign[16] = {
48
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
49
static 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
111
static 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
122
static 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
133
static 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
144
static 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
155
void 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
168
EXPORT_SYMBOL(vr41xx_enable_piuint);
169
170
void 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
183
EXPORT_SYMBOL(vr41xx_disable_piuint);
184
185
void 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
198
EXPORT_SYMBOL(vr41xx_enable_aiuint);
199
200
void 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
213
EXPORT_SYMBOL(vr41xx_disable_aiuint);
214
215
void 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
228
EXPORT_SYMBOL(vr41xx_enable_kiuint);
229
230
void 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
243
EXPORT_SYMBOL(vr41xx_disable_kiuint);
244
245
void 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
255
EXPORT_SYMBOL(vr41xx_enable_macint);
256
257
void 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
267
EXPORT_SYMBOL(vr41xx_disable_macint);
268
269
void 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
279
EXPORT_SYMBOL(vr41xx_enable_dsiuint);
280
281
void 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
291
EXPORT_SYMBOL(vr41xx_disable_dsiuint);
292
293
void 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
303
EXPORT_SYMBOL(vr41xx_enable_firint);
304
305
void 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
315
EXPORT_SYMBOL(vr41xx_disable_firint);
316
317
void 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
331
EXPORT_SYMBOL(vr41xx_enable_pciint);
332
333
void 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
347
EXPORT_SYMBOL(vr41xx_disable_pciint);
348
349
void 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
363
EXPORT_SYMBOL(vr41xx_enable_scuint);
364
365
void 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
379
EXPORT_SYMBOL(vr41xx_disable_scuint);
380
381
void 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
395
EXPORT_SYMBOL(vr41xx_enable_csiint);
396
397
void 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
411
EXPORT_SYMBOL(vr41xx_disable_csiint);
412
413
void 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
427
EXPORT_SYMBOL(vr41xx_enable_bcuint);
428
429
void 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
443
EXPORT_SYMBOL(vr41xx_disable_bcuint);
444
445
static void disable_sysint1_irq(struct irq_data *d)
446
{
447
icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
448
}
449
450
static void enable_sysint1_irq(struct irq_data *d)
451
{
452
icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
453
}
454
455
static struct irq_chip sysint1_irq_type = {
456
.name = "SYSINT1",
457
.irq_mask = disable_sysint1_irq,
458
.irq_unmask = enable_sysint1_irq,
459
};
460
461
static void disable_sysint2_irq(struct irq_data *d)
462
{
463
icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq));
464
}
465
466
static void enable_sysint2_irq(struct irq_data *d)
467
{
468
icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq));
469
}
470
471
static struct irq_chip sysint2_irq_type = {
472
.name = "SYSINT2",
473
.irq_mask = disable_sysint2_irq,
474
.irq_unmask = enable_sysint2_irq,
475
};
476
477
static 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
537
static 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
605
int 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
623
EXPORT_SYMBOL(vr41xx_set_intassign);
624
625
static 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
661
static 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
729
core_initcall(vr41xx_icu_init);
730
731