Blame view

arch/mips/kernel/irq-msc01.c 3.96 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
27f768192   Ralf Baechle   [MIPS] Cleanup un...
6
7
8
9
10
   *
   * Copyright (c) 2004 MIPS Inc
   * Author: chris@mips.com
   *
   * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
  #include <linux/interrupt.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
  #include <linux/sched.h>
  #include <linux/kernel_stat.h>
  #include <asm/io.h>
  #include <asm/irq.h>
  #include <asm/msc01_ic.h>
411ba7fcb   Atsushi Nemoto   [MIPS] Fix some s...
19
  #include <asm/traps.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
  
  static unsigned long _icctrl_msc;
  #define MSC01_IC_REG_BASE	_icctrl_msc
  
  #define MSCIC_WRITE(reg, data)	do { *(volatile u32 *)(reg) = data; } while (0)
  #define MSCIC_READ(reg, data)	do { data = *(volatile u32 *)(reg); } while (0)
  
  static unsigned int irq_base;
  
  /* mask off an interrupt */
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
30
  static inline void mask_msc_irq(struct irq_data *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  {
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
32
  	unsigned int irq = d->irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
38
39
  	if (irq < (irq_base + 32))
  		MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
  	else
  		MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32));
  }
  
  /* unmask an interrupt */
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
40
  static inline void unmask_msc_irq(struct irq_data *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  {
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
42
  	unsigned int irq = d->irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
48
49
  	if (irq < (irq_base + 32))
  		MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
  	else
  		MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32));
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
   * Masks and ACKs an IRQ
   */
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
52
  static void level_mask_and_ack_msc_irq(struct irq_data *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  {
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
54
55
56
  	unsigned int irq = d->irq;
  
  	mask_msc_irq(d);
e01402b11   Ralf Baechle   More AP / SP bits...
57
  	if (!cpu_has_veic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  		MSCIC_WRITE(MSC01_IC_EOI, 0);
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
59
  	/* This actually needs to be a call into platform code */
1146fe305   Ralf Baechle   [MIPS] SMTC: Make...
60
  	smtc_im_ack_irq(irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
65
  }
  
  /*
   * Masks and ACKs an IRQ
   */
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
66
  static void edge_mask_and_ack_msc_irq(struct irq_data *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  {
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
68
69
70
  	unsigned int irq = d->irq;
  
  	mask_msc_irq(d);
e01402b11   Ralf Baechle   More AP / SP bits...
71
  	if (!cpu_has_veic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
  		MSCIC_WRITE(MSC01_IC_EOI, 0);
  	else {
  		u32 r;
  		MSCIC_READ(MSC01_IC_SUP+irq*8, r);
  		MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
  		MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
  	}
1146fe305   Ralf Baechle   [MIPS] SMTC: Make...
79
  	smtc_im_ack_irq(irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
   * Interrupt handler for interrupts coming from SOC-it.
   */
937a80157   Ralf Baechle   [MIPS] Complete f...
85
  void ll_msc_irq(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
  {
   	unsigned int irq;
  
  	/* read the interrupt vector register */
  	MSCIC_READ(MSC01_IC_VEC, irq);
  	if (irq < 64)
937a80157   Ralf Baechle   [MIPS] Complete f...
92
  		do_IRQ(irq + irq_base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
  	else {
  		/* Ignore spurious interrupt */
  	}
  }
411ba7fcb   Atsushi Nemoto   [MIPS] Fix some s...
97
  static void msc_bind_eic_interrupt(int irq, int set)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
  {
  	MSCIC_WRITE(MSC01_IC_RAMW,
  		    (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
  }
411ba7fcb   Atsushi Nemoto   [MIPS] Fix some s...
102
  static struct irq_chip msc_levelirq_type = {
70d21cdee   Atsushi Nemoto   [MIPS] use name i...
103
  	.name = "SOC-it-Level",
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
104
105
106
107
108
  	.irq_ack = level_mask_and_ack_msc_irq,
  	.irq_mask = mask_msc_irq,
  	.irq_mask_ack = level_mask_and_ack_msc_irq,
  	.irq_unmask = unmask_msc_irq,
  	.irq_eoi = unmask_msc_irq,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  };
411ba7fcb   Atsushi Nemoto   [MIPS] Fix some s...
110
  static struct irq_chip msc_edgeirq_type = {
70d21cdee   Atsushi Nemoto   [MIPS] use name i...
111
  	.name = "SOC-it-Edge",
e15883da8   Thomas Gleixner   MIPS: MSC01: Conv...
112
113
114
115
116
  	.irq_ack = edge_mask_and_ack_msc_irq,
  	.irq_mask = mask_msc_irq,
  	.irq_mask_ack = edge_mask_and_ack_msc_irq,
  	.irq_unmask = unmask_msc_irq,
  	.irq_eoi = unmask_msc_irq,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  };
d725cf381   Chris Dearman   [MIPS] MT: Reenab...
118
  void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  {
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
120
  	_icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
127
128
129
130
131
  
  	/* Reset interrupt controller - initialises all registers to 0 */
  	MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
  
  	board_bind_eic_interrupt = &msc_bind_eic_interrupt;
  
  	for (; nirq >= 0; nirq--, imp++) {
  		int n = imp->im_irq;
  
  		switch (imp->im_type) {
  		case MSC01_IRQ_EDGE:
e4ec7989b   Thomas Gleixner   MIPS: Convert the...
132
133
134
135
  			irq_set_chip_and_handler_name(irqbase + n,
  						      &msc_edgeirq_type,
  						      handle_edge_irq,
  						      "edge");
e01402b11   Ralf Baechle   More AP / SP bits...
136
  			if (cpu_has_veic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
  				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
  			else
  				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
  			break;
  		case MSC01_IRQ_LEVEL:
e4ec7989b   Thomas Gleixner   MIPS: Convert the...
142
143
144
145
  			irq_set_chip_and_handler_name(irqbase + n,
  						      &msc_levelirq_type,
  						      handle_level_irq,
  						      "level");
e01402b11   Ralf Baechle   More AP / SP bits...
146
  			if (cpu_has_veic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
  				MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
  			else
  				MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
  		}
  	}
d725cf381   Chris Dearman   [MIPS] MT: Reenab...
152
  	irq_base = irqbase;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
  
  	MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT);	/* Enable interrupt generation */
  
  }