3 * Based on linux/arch/mips/kernel/irq_txx9.c,
4 * and RBTX49xx patch from CELF patch archive.
6 * Copyright 2001, 2003-2005 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
10 * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file "COPYING" in the main directory of this archive
17 * TX4939 defines 64 IRQs.
18 * Similer to irq_txx9.c but different register layouts.
20 #include <linux/init.h>
21 #include <linux/interrupt.h>
22 #include <linux/irq.h>
23 #include <linux/types.h>
24 #include <asm/irq_cpu.h>
25 #include <asm/txx9irq.h>
26 #include <asm/txx9/tx4939.h>
28 /* IRCER : Int. Control Enable */
29 #define TXx9_IRCER_ICE 0x00000001
31 /* IRCR : Int. Control */
32 #define TXx9_IRCR_LOW 0x00000000
33 #define TXx9_IRCR_HIGH 0x00000001
34 #define TXx9_IRCR_DOWN 0x00000002
35 #define TXx9_IRCR_UP 0x00000003
36 #define TXx9_IRCR_EDGE(cr) ((cr) & 0x00000002)
38 /* IRSCR : Int. Status Control */
39 #define TXx9_IRSCR_EIClrE 0x00000100
40 #define TXx9_IRSCR_EIClr_MASK 0x0000000f
42 /* IRCSR : Int. Current Status */
43 #define TXx9_IRCSR_IF 0x00010000
51 } tx4939irq
[TX4939_NUM_IR
] __read_mostly
;
53 static void tx4939_irq_unmask(struct irq_data
*d
)
55 unsigned int irq_nr
= d
->irq
- TXX9_IRQ_BASE
;
60 lvlp
= &tx4939_ircptr
->lvl
[(irq_nr
% 16) / 2].r
;
63 lvlp
= &tx4939_ircptr
->lvl
[8 + (irq_nr
% 16) / 2].r
;
65 ofs
= (irq_nr
& 16) + (irq_nr
& 1) * 8;
66 __raw_writel((__raw_readl(lvlp
) & ~(0xff << ofs
))
67 | (tx4939irq
[irq_nr
].level
<< ofs
),
71 static inline void tx4939_irq_mask(struct irq_data
*d
)
73 unsigned int irq_nr
= d
->irq
- TXX9_IRQ_BASE
;
78 lvlp
= &tx4939_ircptr
->lvl
[(irq_nr
% 16) / 2].r
;
81 lvlp
= &tx4939_ircptr
->lvl
[8 + (irq_nr
% 16) / 2].r
;
83 ofs
= (irq_nr
& 16) + (irq_nr
& 1) * 8;
84 __raw_writel((__raw_readl(lvlp
) & ~(0xff << ofs
))
85 | (irc_dlevel
<< ofs
),
90 static void tx4939_irq_mask_ack(struct irq_data
*d
)
92 unsigned int irq_nr
= d
->irq
- TXX9_IRQ_BASE
;
95 if (TXx9_IRCR_EDGE(tx4939irq
[irq_nr
].mode
)) {
97 /* clear edge detection */
98 __raw_writel((TXx9_IRSCR_EIClrE
| (irq_nr
& 0xf))
100 &tx4939_ircptr
->edc
.r
);
104 static int tx4939_irq_set_type(struct irq_data
*d
, unsigned int flow_type
)
106 unsigned int irq_nr
= d
->irq
- TXX9_IRQ_BASE
;
112 if (flow_type
& IRQF_TRIGGER_PROBE
)
114 switch (flow_type
& IRQF_TRIGGER_MASK
) {
115 case IRQF_TRIGGER_RISING
:
118 case IRQF_TRIGGER_FALLING
:
119 mode
= TXx9_IRCR_DOWN
;
121 case IRQF_TRIGGER_HIGH
:
122 mode
= TXx9_IRCR_HIGH
;
124 case IRQF_TRIGGER_LOW
:
125 mode
= TXx9_IRCR_LOW
;
132 crp
= &tx4939_ircptr
->dm
[(irq_nr
& 8) >> 3].r
;
135 crp
= &tx4939_ircptr
->dm2
[((irq_nr
& 8) >> 3)].r
;
137 ofs
= (((irq_nr
& 16) >> 1) | (irq_nr
& (8 - 1))) * 2;
138 cr
= __raw_readl(crp
);
140 cr
|= (mode
& 0x3) << ofs
;
141 __raw_writel(cr
, crp
);
142 tx4939irq
[irq_nr
].mode
= mode
;
146 static struct irq_chip tx4939_irq_chip
= {
148 .irq_ack
= tx4939_irq_mask_ack
,
149 .irq_mask
= tx4939_irq_mask
,
150 .irq_mask_ack
= tx4939_irq_mask_ack
,
151 .irq_unmask
= tx4939_irq_unmask
,
152 .irq_set_type
= tx4939_irq_set_type
,
155 static int tx4939_irq_set_pri(int irc_irq
, int new_pri
)
159 if ((unsigned int)irc_irq
>= TX4939_NUM_IR
)
161 old_pri
= tx4939irq
[irc_irq
].level
;
162 tx4939irq
[irc_irq
].level
= new_pri
;
166 void __init
tx4939_irq_init(void)
171 /* disable interrupt control */
172 __raw_writel(0, &tx4939_ircptr
->den
.r
);
173 __raw_writel(0, &tx4939_ircptr
->maskint
.r
);
174 __raw_writel(0, &tx4939_ircptr
->maskext
.r
);
175 /* irq_base + 0 is not used */
176 for (i
= 1; i
< TX4939_NUM_IR
; i
++) {
177 tx4939irq
[i
].level
= 4; /* middle level */
178 tx4939irq
[i
].mode
= TXx9_IRCR_LOW
;
179 irq_set_chip_and_handler(TXX9_IRQ_BASE
+ i
, &tx4939_irq_chip
,
183 /* mask all IRC interrupts */
184 __raw_writel(0, &tx4939_ircptr
->msk
.r
);
185 for (i
= 0; i
< 16; i
++)
186 __raw_writel(0, &tx4939_ircptr
->lvl
[i
].r
);
187 /* setup IRC interrupt mode (Low Active) */
188 for (i
= 0; i
< 2; i
++)
189 __raw_writel(0, &tx4939_ircptr
->dm
[i
].r
);
190 for (i
= 0; i
< 2; i
++)
191 __raw_writel(0, &tx4939_ircptr
->dm2
[i
].r
);
192 /* enable interrupt control */
193 __raw_writel(TXx9_IRCER_ICE
, &tx4939_ircptr
->den
.r
);
194 __raw_writel(irc_elevel
, &tx4939_ircptr
->msk
.r
);
196 irq_set_chained_handler(MIPS_CPU_IRQ_BASE
+ TX4939_IRC_INT
,
199 /* raise priority for errors, timers, sio */
200 tx4939_irq_set_pri(TX4939_IR_WTOERR
, 7);
201 tx4939_irq_set_pri(TX4939_IR_PCIERR
, 7);
202 tx4939_irq_set_pri(TX4939_IR_PCIPME
, 7);
203 for (i
= 0; i
< TX4939_NUM_IR_TMR
; i
++)
204 tx4939_irq_set_pri(TX4939_IR_TMR(i
), 6);
205 for (i
= 0; i
< TX4939_NUM_IR_SIO
; i
++)
206 tx4939_irq_set_pri(TX4939_IR_SIO(i
), 5);
211 u32 csr
= __raw_readl(&tx4939_ircptr
->cs
.r
);
213 if (likely(!(csr
& TXx9_IRCSR_IF
)))
214 return TXX9_IRQ_BASE
+ (csr
& (TX4939_NUM_IR
- 1));