PageRenderTime 76ms CodeModel.GetById 10ms app.highlight 62ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/mips/vr41xx/common/icu.c

http://github.com/mirrors/linux
C | 716 lines | 564 code | 135 blank | 17 comment | 81 complexity | 49a2e8d44569e993172d4cb70fa58a66 MD5 | raw file
  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);