Commit | Line | Data |
---|---|---|
b27311e1 AN |
1 | /* |
2 | * Toshiba RBTX4939 interrupt routines | |
3 | * Based on linux/arch/mips/txx9/rbtx4938/irq.c, | |
4 | * and RBTX49xx patch from CELF patch archive. | |
5 | * | |
6 | * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation | |
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | |
8 | * terms of the GNU General Public License version 2. This program is | |
9 | * licensed "as is" without any warranty of any kind, whether express | |
10 | * or implied. | |
11 | */ | |
12 | #include <linux/init.h> | |
13 | #include <linux/interrupt.h> | |
ca4d3e67 | 14 | #include <linux/irq.h> |
b27311e1 AN |
15 | #include <asm/mipsregs.h> |
16 | #include <asm/txx9/rbtx4939.h> | |
17 | ||
18 | /* | |
19 | * RBTX4939 IOC controller definition | |
20 | */ | |
21 | ||
d7ae7c71 | 22 | static void rbtx4939_ioc_irq_unmask(struct irq_data *d) |
b27311e1 | 23 | { |
d7ae7c71 | 24 | int ioc_nr = d->irq - RBTX4939_IRQ_IOC; |
b27311e1 AN |
25 | |
26 | writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr); | |
27 | } | |
28 | ||
d7ae7c71 | 29 | static void rbtx4939_ioc_irq_mask(struct irq_data *d) |
b27311e1 | 30 | { |
d7ae7c71 | 31 | int ioc_nr = d->irq - RBTX4939_IRQ_IOC; |
b27311e1 AN |
32 | |
33 | writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr); | |
34 | mmiowb(); | |
35 | } | |
36 | ||
37 | static struct irq_chip rbtx4939_ioc_irq_chip = { | |
38 | .name = "IOC", | |
d7ae7c71 TG |
39 | .irq_mask = rbtx4939_ioc_irq_mask, |
40 | .irq_unmask = rbtx4939_ioc_irq_unmask, | |
b27311e1 AN |
41 | }; |
42 | ||
43 | ||
44 | static inline int rbtx4939_ioc_irqroute(void) | |
45 | { | |
46 | unsigned char istat = readb(rbtx4939_ifac2_addr); | |
47 | ||
48 | if (unlikely(istat == 0)) | |
49 | return -1; | |
50 | return RBTX4939_IRQ_IOC + __fls8(istat); | |
51 | } | |
52 | ||
53 | static int rbtx4939_irq_dispatch(int pending) | |
54 | { | |
55 | int irq; | |
56 | ||
57 | if (pending & CAUSEF_IP7) | |
58 | return MIPS_CPU_IRQ_BASE + 7; | |
59 | irq = tx4939_irq(); | |
60 | if (likely(irq >= 0)) { | |
61 | /* redirect IOC interrupts */ | |
62 | switch (irq) { | |
63 | case RBTX4939_IRQ_IOCINT: | |
64 | irq = rbtx4939_ioc_irqroute(); | |
65 | break; | |
66 | } | |
67 | } else if (pending & CAUSEF_IP0) | |
68 | irq = MIPS_CPU_IRQ_BASE + 0; | |
69 | else if (pending & CAUSEF_IP1) | |
70 | irq = MIPS_CPU_IRQ_BASE + 1; | |
71 | else | |
72 | irq = -1; | |
73 | return irq; | |
74 | } | |
75 | ||
76 | void __init rbtx4939_irq_setup(void) | |
77 | { | |
78 | int i; | |
79 | ||
80 | /* mask all IOC interrupts */ | |
81 | writeb(0, rbtx4939_ien_addr); | |
82 | ||
83 | /* clear SoftInt interrupts */ | |
84 | writeb(0, rbtx4939_softint_addr); | |
85 | ||
86 | txx9_irq_dispatch = rbtx4939_irq_dispatch; | |
87 | ||
88 | tx4939_irq_init(); | |
89 | for (i = RBTX4939_IRQ_IOC; | |
90 | i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++) | |
91 | set_irq_chip_and_handler(i, &rbtx4939_ioc_irq_chip, | |
92 | handle_level_irq); | |
93 | ||
94 | set_irq_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq); | |
95 | } |