Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
icu.c
Go to the documentation of this file.
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 
156 {
157  struct irq_desc *desc = irq_to_desc(PIU_IRQ);
158  unsigned long flags;
159 
160  if (current_cpu_type() == CPU_VR4111 ||
162  raw_spin_lock_irqsave(&desc->lock, flags);
163  icu1_set(MPIUINTREG, mask);
164  raw_spin_unlock_irqrestore(&desc->lock, flags);
165  }
166 }
167 
169 
171 {
172  struct irq_desc *desc = irq_to_desc(PIU_IRQ);
173  unsigned long flags;
174 
175  if (current_cpu_type() == CPU_VR4111 ||
177  raw_spin_lock_irqsave(&desc->lock, flags);
178  icu1_clear(MPIUINTREG, mask);
179  raw_spin_unlock_irqrestore(&desc->lock, flags);
180  }
181 }
182 
184 
186 {
187  struct irq_desc *desc = irq_to_desc(AIU_IRQ);
188  unsigned long flags;
189 
190  if (current_cpu_type() == CPU_VR4111 ||
192  raw_spin_lock_irqsave(&desc->lock, flags);
193  icu1_set(MAIUINTREG, mask);
194  raw_spin_unlock_irqrestore(&desc->lock, flags);
195  }
196 }
197 
199 
201 {
202  struct irq_desc *desc = irq_to_desc(AIU_IRQ);
203  unsigned long flags;
204 
205  if (current_cpu_type() == CPU_VR4111 ||
207  raw_spin_lock_irqsave(&desc->lock, flags);
208  icu1_clear(MAIUINTREG, mask);
209  raw_spin_unlock_irqrestore(&desc->lock, flags);
210  }
211 }
212 
214 
216 {
217  struct irq_desc *desc = irq_to_desc(KIU_IRQ);
218  unsigned long flags;
219 
220  if (current_cpu_type() == CPU_VR4111 ||
222  raw_spin_lock_irqsave(&desc->lock, flags);
223  icu1_set(MKIUINTREG, mask);
224  raw_spin_unlock_irqrestore(&desc->lock, flags);
225  }
226 }
227 
229 
231 {
232  struct irq_desc *desc = irq_to_desc(KIU_IRQ);
233  unsigned long flags;
234 
235  if (current_cpu_type() == CPU_VR4111 ||
237  raw_spin_lock_irqsave(&desc->lock, flags);
238  icu1_clear(MKIUINTREG, mask);
239  raw_spin_unlock_irqrestore(&desc->lock, flags);
240  }
241 }
242 
244 
246 {
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 
256 
258 {
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 
268 
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 
280 
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 
292 
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 
304 
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 
316 
318 {
319  struct irq_desc *desc = irq_to_desc(PCI_IRQ);
320  unsigned long flags;
321 
322  if (current_cpu_type() == CPU_VR4122 ||
325  raw_spin_lock_irqsave(&desc->lock, flags);
327  raw_spin_unlock_irqrestore(&desc->lock, flags);
328  }
329 }
330 
332 
334 {
335  struct irq_desc *desc = irq_to_desc(PCI_IRQ);
336  unsigned long flags;
337 
338  if (current_cpu_type() == CPU_VR4122 ||
341  raw_spin_lock_irqsave(&desc->lock, flags);
343  raw_spin_unlock_irqrestore(&desc->lock, flags);
344  }
345 }
346 
348 
350 {
351  struct irq_desc *desc = irq_to_desc(SCU_IRQ);
352  unsigned long flags;
353 
354  if (current_cpu_type() == CPU_VR4122 ||
357  raw_spin_lock_irqsave(&desc->lock, flags);
359  raw_spin_unlock_irqrestore(&desc->lock, flags);
360  }
361 }
362 
364 
366 {
367  struct irq_desc *desc = irq_to_desc(SCU_IRQ);
368  unsigned long flags;
369 
370  if (current_cpu_type() == CPU_VR4122 ||
373  raw_spin_lock_irqsave(&desc->lock, flags);
375  raw_spin_unlock_irqrestore(&desc->lock, flags);
376  }
377 }
378 
380 
382 {
383  struct irq_desc *desc = irq_to_desc(CSI_IRQ);
384  unsigned long flags;
385 
386  if (current_cpu_type() == CPU_VR4122 ||
389  raw_spin_lock_irqsave(&desc->lock, flags);
390  icu2_set(MCSIINTREG, mask);
391  raw_spin_unlock_irqrestore(&desc->lock, flags);
392  }
393 }
394 
396 
398 {
399  struct irq_desc *desc = irq_to_desc(CSI_IRQ);
400  unsigned long flags;
401 
402  if (current_cpu_type() == CPU_VR4122 ||
405  raw_spin_lock_irqsave(&desc->lock, flags);
406  icu2_clear(MCSIINTREG, mask);
407  raw_spin_unlock_irqrestore(&desc->lock, flags);
408  }
409 }
410 
412 
414 {
415  struct irq_desc *desc = irq_to_desc(BCU_IRQ);
416  unsigned long flags;
417 
418  if (current_cpu_type() == CPU_VR4122 ||
421  raw_spin_lock_irqsave(&desc->lock, flags);
423  raw_spin_unlock_irqrestore(&desc->lock, flags);
424  }
425 }
426 
428 
430 {
431  struct irq_desc *desc = irq_to_desc(BCU_IRQ);
432  unsigned long flags;
433 
434  if (current_cpu_type() == CPU_VR4122 ||
437  raw_spin_lock_irqsave(&desc->lock, flags);
439  raw_spin_unlock_irqrestore(&desc->lock, flags);
440  }
441 }
442 
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 
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 
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 
707  icu1_write(MGIUINTLREG, 0xffff);
708 
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,
715 
716  for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
717  irq_set_chip_and_handler(i, &sysint2_irq_type,
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);