aboutsummaryrefslogtreecommitdiffstats
path: root/arch/frv
diff options
context:
space:
mode:
Diffstat (limited to 'arch/frv')
-rw-r--r--arch/frv/Kconfig12
-rw-r--r--arch/frv/kernel/Makefile5
-rw-r--r--arch/frv/kernel/irq-mb93091.c157
-rw-r--r--arch/frv/kernel/irq-mb93093.c115
-rw-r--r--arch/frv/kernel/irq-mb93493.c160
-rw-r--r--arch/frv/kernel/irq-routing.c291
-rw-r--r--arch/frv/kernel/irq.c741
-rw-r--r--arch/frv/kernel/setup.c1
-rw-r--r--arch/frv/kernel/time.c1
-rw-r--r--arch/frv/mb93090-mb00/pci-irq.c1
-rw-r--r--arch/frv/mm/init.c2
11 files changed, 394 insertions, 1092 deletions
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index a601a17cf568..f7b171b92ea2 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -27,7 +27,11 @@ config GENERIC_CALIBRATE_DELAY
27 27
28config GENERIC_HARDIRQS 28config GENERIC_HARDIRQS
29 bool 29 bool
30 default n 30 default y
31
32config GENERIC_HARDIRQS_NO__DO_IRQ
33 bool
34 default y
31 35
32config GENERIC_TIME 36config GENERIC_TIME
33 bool 37 bool
@@ -251,6 +255,12 @@ config MB93091_NO_MB
251endchoice 255endchoice
252endif 256endif
253 257
258config FUJITSU_MB93493
259 bool "MB93493 Multimedia chip"
260 help
261 Select this option if the MB93493 multimedia chip is going to be
262 used.
263
254choice 264choice
255 prompt "GP-Relative data support" 265 prompt "GP-Relative data support"
256 default GPREL_DATA_8 266 default GPREL_DATA_8
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index 5a827b349b5e..32db3499c461 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -10,15 +10,14 @@ extra-y:= head.o init_task.o vmlinux.lds
10obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \ 10obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
11 process.o traps.o ptrace.o signal.o dma.o \ 11 process.o traps.o ptrace.o signal.o dma.o \
12 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \ 12 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
13 debug-stub.o irq.o irq-routing.o sleep.o uaccess.o 13 debug-stub.o irq.o sleep.o uaccess.o
14 14
15obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o 15obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
16 16
17obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o 17obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o
18obj-$(CONFIG_MB93093_PDK) += irq-mb93093.o
19obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
20obj-$(CONFIG_PM) += pm.o cmode.o 18obj-$(CONFIG_PM) += pm.o cmode.o
21obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o 19obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
20obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
22obj-$(CONFIG_SYSCTL) += sysctl.o 21obj-$(CONFIG_SYSCTL) += sysctl.o
23obj-$(CONFIG_FUTEX) += futex.o 22obj-$(CONFIG_FUTEX) += futex.o
24obj-$(CONFIG_MODULES) += module.o 23obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c
index 1381abcd5cc9..369bc0a7443d 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -24,7 +24,6 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/irq.h> 25#include <asm/irq.h>
26#include <asm/irc-regs.h> 26#include <asm/irc-regs.h>
27#include <asm/irq-routing.h>
28 27
29#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) 28#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
30 29
@@ -33,83 +32,131 @@
33#define __get_IFR() ({ __reg16(0xffc0000c); }) 32#define __get_IFR() ({ __reg16(0xffc0000c); })
34#define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0) 33#define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)
35 34
36static void frv_fpga_doirq(struct irq_source *source);
37static void frv_fpga_control(struct irq_group *group, int irq, int on);
38 35
39/*****************************************************************************/
40/* 36/*
41 * FPGA IRQ multiplexor 37 * on-motherboard FPGA PIC operations
42 */ 38 */
43static struct irq_source frv_fpga[4] = { 39static void frv_fpga_mask(unsigned int irq)
44#define __FPGA(X, M) \ 40{
45 [X] = { \ 41 uint16_t imr = __get_IMR();
46 .muxname = "fpga."#X, \
47 .irqmask = M, \
48 .doirq = frv_fpga_doirq, \
49 }
50 42
51 __FPGA(0, 0x0028), 43 imr |= 1 << (irq - IRQ_BASE_FPGA);
52 __FPGA(1, 0x0050),
53 __FPGA(2, 0x1c00),
54 __FPGA(3, 0x6386),
55};
56 44
57static struct irq_group frv_fpga_irqs = { 45 __set_IMR(imr);
58 .first_irq = IRQ_BASE_FPGA, 46}
59 .control = frv_fpga_control,
60 .sources = {
61 [ 1] = &frv_fpga[3],
62 [ 2] = &frv_fpga[3],
63 [ 3] = &frv_fpga[0],
64 [ 4] = &frv_fpga[1],
65 [ 5] = &frv_fpga[0],
66 [ 6] = &frv_fpga[1],
67 [ 7] = &frv_fpga[3],
68 [ 8] = &frv_fpga[3],
69 [ 9] = &frv_fpga[3],
70 [10] = &frv_fpga[2],
71 [11] = &frv_fpga[2],
72 [12] = &frv_fpga[2],
73 [13] = &frv_fpga[3],
74 [14] = &frv_fpga[3],
75 },
76};
77 47
48static void frv_fpga_ack(unsigned int irq)
49{
50 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
51}
78 52
79static void frv_fpga_control(struct irq_group *group, int index, int on) 53static void frv_fpga_mask_ack(unsigned int irq)
80{ 54{
81 uint16_t imr = __get_IMR(); 55 uint16_t imr = __get_IMR();
82 56
83 if (on) 57 imr |= 1 << (irq - IRQ_BASE_FPGA);
84 imr &= ~(1 << index); 58 __set_IMR(imr);
85 else 59
86 imr |= 1 << index; 60 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
61}
62
63static void frv_fpga_unmask(unsigned int irq)
64{
65 uint16_t imr = __get_IMR();
66
67 imr &= ~(1 << (irq - IRQ_BASE_FPGA));
87 68
88 __set_IMR(imr); 69 __set_IMR(imr);
89} 70}
90 71
91static void frv_fpga_doirq(struct irq_source *source) 72static struct irq_chip frv_fpga_pic = {
73 .name = "mb93091",
74 .ack = frv_fpga_ack,
75 .mask = frv_fpga_mask,
76 .mask_ack = frv_fpga_mask_ack,
77 .unmask = frv_fpga_unmask,
78};
79
80/*
81 * FPGA PIC interrupt handler
82 */
83static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
92{ 84{
93 uint16_t mask, imr; 85 uint16_t imr, mask = (unsigned long) _mask;
94 86
95 imr = __get_IMR(); 87 imr = __get_IMR();
96 mask = source->irqmask & ~imr & __get_IFR(); 88 mask = mask & ~imr & __get_IFR();
97 if (mask) { 89
98 __set_IMR(imr | mask); 90 /* poll all the triggered IRQs */
99 __clr_IFR(mask); 91 while (mask) {
100 distribute_irqs(&frv_fpga_irqs, mask); 92 int irq;
101 __set_IMR(imr); 93
94 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
95 irq = 31 - irq;
96 mask &= ~(1 << irq);
97
98 generic_handle_irq(IRQ_BASE_FPGA + irq, regs);
102 } 99 }
100
101 return IRQ_HANDLED;
103} 102}
104 103
104/*
105 * define an interrupt action for each FPGA PIC output
106 * - use dev_id to indicate the FPGA PIC input to output mappings
107 */
108static struct irqaction fpga_irq[4] = {
109 [0] = {
110 .handler = fpga_interrupt,
111 .flags = IRQF_DISABLED | IRQF_SHARED,
112 .mask = CPU_MASK_NONE,
113 .name = "fpga.0",
114 .dev_id = (void *) 0x0028UL,
115 },
116 [1] = {
117 .handler = fpga_interrupt,
118 .flags = IRQF_DISABLED | IRQF_SHARED,
119 .mask = CPU_MASK_NONE,
120 .name = "fpga.1",
121 .dev_id = (void *) 0x0050UL,
122 },
123 [2] = {
124 .handler = fpga_interrupt,
125 .flags = IRQF_DISABLED | IRQF_SHARED,
126 .mask = CPU_MASK_NONE,
127 .name = "fpga.2",
128 .dev_id = (void *) 0x1c00UL,
129 },
130 [3] = {
131 .handler = fpga_interrupt,
132 .flags = IRQF_DISABLED | IRQF_SHARED,
133 .mask = CPU_MASK_NONE,
134 .name = "fpga.3",
135 .dev_id = (void *) 0x6386UL,
136 }
137};
138
139/*
140 * initialise the motherboard FPGA's PIC
141 */
105void __init fpga_init(void) 142void __init fpga_init(void)
106{ 143{
144 int irq;
145
146 /* all PIC inputs are all set to be low-level driven, apart from the
147 * NMI button (15) which is fixed at falling-edge
148 */
107 __set_IMR(0x7ffe); 149 __set_IMR(0x7ffe);
108 __clr_IFR(0x0000); 150 __clr_IFR(0x0000);
109 151
110 frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0); 152 for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
111 frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1); 153 set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
112 frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2); 154
113 frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3); 155 set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
114 frv_irq_set_group(&frv_fpga_irqs); 156
157 /* the FPGA drives the first four external IRQ inputs on the CPU PIC */
158 setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
159 setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]);
160 setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]);
161 setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]);
115} 162}
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index 48b2a6420888..a43a22158956 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -1,6 +1,6 @@
1/* irq-mb93093.c: MB93093 FPGA interrupt handling 1/* irq-mb93093.c: MB93093 FPGA interrupt handling
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/irq.h> 25#include <asm/irq.h>
26#include <asm/irc-regs.h> 26#include <asm/irc-regs.h>
27#include <asm/irq-routing.h>
28 27
29#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR))) 28#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
30 29
@@ -33,66 +32,102 @@
33#define __get_IFR() ({ __reg16(0x02); }) 32#define __get_IFR() ({ __reg16(0x02); })
34#define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0) 33#define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0)
35 34
36static void frv_fpga_doirq(struct irq_source *source);
37static void frv_fpga_control(struct irq_group *group, int irq, int on);
38
39/*****************************************************************************/
40/* 35/*
41 * FPGA IRQ multiplexor 36 * off-CPU FPGA PIC operations
42 */ 37 */
43static struct irq_source frv_fpga[4] = { 38static void frv_fpga_mask(unsigned int irq)
44#define __FPGA(X, M) \ 39{
45 [X] = { \ 40 uint16_t imr = __get_IMR();
46 .muxname = "fpga."#X, \
47 .irqmask = M, \
48 .doirq = frv_fpga_doirq, \
49 }
50 41
51 __FPGA(0, 0x0700), 42 imr |= 1 << (irq - IRQ_BASE_FPGA);
52}; 43 __set_IMR(imr);
44}
53 45
54static struct irq_group frv_fpga_irqs = { 46static void frv_fpga_ack(unsigned int irq)
55 .first_irq = IRQ_BASE_FPGA, 47{
56 .control = frv_fpga_control, 48 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
57 .sources = { 49}
58 [ 8] = &frv_fpga[0], 50
59 [ 9] = &frv_fpga[0], 51static void frv_fpga_mask_ack(unsigned int irq)
60 [10] = &frv_fpga[0], 52{
61 }, 53 uint16_t imr = __get_IMR();
62};
63 54
55 imr |= 1 << (irq - IRQ_BASE_FPGA);
56 __set_IMR(imr);
57
58 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
59}
64 60
65static void frv_fpga_control(struct irq_group *group, int index, int on) 61static void frv_fpga_unmask(unsigned int irq)
66{ 62{
67 uint16_t imr = __get_IMR(); 63 uint16_t imr = __get_IMR();
68 64
69 if (on) 65 imr &= ~(1 << (irq - IRQ_BASE_FPGA));
70 imr &= ~(1 << index);
71 else
72 imr |= 1 << index;
73 66
74 __set_IMR(imr); 67 __set_IMR(imr);
75} 68}
76 69
77static void frv_fpga_doirq(struct irq_source *source) 70static struct irq_chip frv_fpga_pic = {
71 .name = "mb93093",
72 .ack = frv_fpga_ack,
73 .mask = frv_fpga_mask,
74 .mask_ack = frv_fpga_mask_ack,
75 .unmask = frv_fpga_unmask,
76 .end = frv_fpga_end,
77};
78
79/*
80 * FPGA PIC interrupt handler
81 */
82static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
78{ 83{
79 uint16_t mask, imr; 84 uint16_t imr, mask = (unsigned long) _mask;
80 85
81 imr = __get_IMR(); 86 imr = __get_IMR();
82 mask = source->irqmask & ~imr & __get_IFR(); 87 mask = mask & ~imr & __get_IFR();
83 if (mask) { 88
84 __set_IMR(imr | mask); 89 /* poll all the triggered IRQs */
85 __clr_IFR(mask); 90 while (mask) {
86 distribute_irqs(&frv_fpga_irqs, mask); 91 int irq;
87 __set_IMR(imr); 92
93 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
94 irq = 31 - irq;
95 mask &= ~(1 << irq);
96
97 generic_irq_handle(IRQ_BASE_FPGA + irq, regs);
88 } 98 }
99
100 return IRQ_HANDLED;
89} 101}
90 102
103/*
104 * define an interrupt action for each FPGA PIC output
105 * - use dev_id to indicate the FPGA PIC input to output mappings
106 */
107static struct irqaction fpga_irq[1] = {
108 [0] = {
109 .handler = fpga_interrupt,
110 .flags = IRQF_DISABLED,
111 .mask = CPU_MASK_NONE,
112 .name = "fpga.0",
113 .dev_id = (void *) 0x0700UL,
114 }
115};
116
117/*
118 * initialise the motherboard FPGA's PIC
119 */
91void __init fpga_init(void) 120void __init fpga_init(void)
92{ 121{
122 int irq;
123
124 /* all PIC inputs are all set to be edge triggered */
93 __set_IMR(0x0700); 125 __set_IMR(0x0700);
94 __clr_IFR(0x0000); 126 __clr_IFR(0x0000);
95 127
96 frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2); 128 for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
97 frv_irq_set_group(&frv_fpga_irqs); 129 set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
130
131 /* the FPGA drives external IRQ input #2 on the CPU PIC */
132 setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
98} 133}
diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c
index 988d035640e1..39c0188a3498 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -1,6 +1,6 @@
1/* irq-mb93493.c: MB93493 companion chip interrupt handler 1/* irq-mb93493.c: MB93493 companion chip interrupt handler
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -24,84 +24,126 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/irq.h> 25#include <asm/irq.h>
26#include <asm/irc-regs.h> 26#include <asm/irc-regs.h>
27#include <asm/irq-routing.h>
28#include <asm/mb93493-irqs.h> 27#include <asm/mb93493-irqs.h>
28#include <asm/mb93493-regs.h>
29 29
30static void frv_mb93493_doirq(struct irq_source *source); 30#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493))
31
32#define IRQ_ROUTING \
33 (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \
34 IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \
35 IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \
36 IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \
37 IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \
38 IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \
39 IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \
40 IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \
41 IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \
42 IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN))
31 43
32/*****************************************************************************/
33/* 44/*
34 * MB93493 companion chip IRQ multiplexor 45 * daughter board PIC operations
46 * - there is no way to ACK interrupts in the MB93493 chip
35 */ 47 */
36static struct irq_source frv_mb93493[2] = { 48static void frv_mb93493_mask(unsigned int irq)
37 [0] = {
38 .muxname = "mb93493.0",
39 .muxdata = __region_CS3 + 0x3d0,
40 .doirq = frv_mb93493_doirq,
41 .irqmask = 0x0000,
42 },
43 [1] = {
44 .muxname = "mb93493.1",
45 .muxdata = __region_CS3 + 0x3d4,
46 .doirq = frv_mb93493_doirq,
47 .irqmask = 0x0000,
48 },
49};
50
51static void frv_mb93493_control(struct irq_group *group, int index, int on)
52{ 49{
53 struct irq_source *source;
54 uint32_t iqsr; 50 uint32_t iqsr;
51 volatile void *piqsr;
55 52
56 if ((frv_mb93493[0].irqmask & (1 << index))) 53 if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
57 source = &frv_mb93493[0]; 54 piqsr = __addr_MB93493_IQSR(1);
58 else 55 else
59 source = &frv_mb93493[1]; 56 piqsr = __addr_MB93493_IQSR(0);
57
58 iqsr = readl(piqsr);
59 iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
60 writel(iqsr, piqsr);
61}
60 62
61 iqsr = readl(source->muxdata); 63static void frv_mb93493_ack(unsigned int irq)
62 if (on) 64{
63 iqsr |= 1 << (index + 16); 65}
66
67static void frv_mb93493_unmask(unsigned int irq)
68{
69 uint32_t iqsr;
70 volatile void *piqsr;
71
72 if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
73 piqsr = __addr_MB93493_IQSR(1);
64 else 74 else
65 iqsr &= ~(1 << (index + 16)); 75 piqsr = __addr_MB93493_IQSR(0);
66 76
67 writel(iqsr, source->muxdata); 77 iqsr = readl(piqsr);
78 iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
79 writel(iqsr, piqsr);
68} 80}
69 81
70static struct irq_group frv_mb93493_irqs = { 82static struct irq_chip frv_mb93493_pic = {
71 .first_irq = IRQ_BASE_MB93493, 83 .name = "mb93093",
72 .control = frv_mb93493_control, 84 .ack = frv_mb93493_ack,
85 .mask = frv_mb93493_mask,
86 .mask_ack = frv_mb93493_mask,
87 .unmask = frv_mb93493_unmask,
73}; 88};
74 89
75static void frv_mb93493_doirq(struct irq_source *source) 90/*
91 * MB93493 PIC interrupt handler
92 */
93static irqreturn_t mb93493_interrupt(int irq, void *_piqsr, struct pt_regs *regs)
76{ 94{
77 uint32_t mask = readl(source->muxdata); 95 volatile void *piqsr = _piqsr;
78 mask = mask & (mask >> 16) & 0xffff; 96 uint32_t iqsr;
79 97
80 if (mask) 98 iqsr = readl(piqsr);
81 distribute_irqs(&frv_mb93493_irqs, mask); 99 iqsr = iqsr & (iqsr >> 16) & 0xffff;
82}
83 100
84static void __init mb93493_irq_route(int irq, int source) 101 /* poll all the triggered IRQs */
85{ 102 while (iqsr) {
86 frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493); 103 int irq;
87 frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source]; 104
105 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr));
106 irq = 31 - irq;
107 iqsr &= ~(1 << irq);
108
109 generic_handle_irq(IRQ_BASE_MB93493 + irq, regs);
110 }
111
112 return IRQ_HANDLED;
88} 113}
89 114
90void __init route_mb93493_irqs(void) 115/*
116 * define an interrupt action for each MB93493 PIC output
117 * - use dev_id to indicate the MB93493 PIC input to output mappings
118 */
119static struct irqaction mb93493_irq[2] = {
120 [0] = {
121 .handler = mb93493_interrupt,
122 .flags = IRQF_DISABLED | IRQF_SHARED,
123 .mask = CPU_MASK_NONE,
124 .name = "mb93493.0",
125 .dev_id = (void *) __addr_MB93493_IQSR(0),
126 },
127 [1] = {
128 .handler = mb93493_interrupt,
129 .flags = IRQF_DISABLED | IRQF_SHARED,
130 .mask = CPU_MASK_NONE,
131 .name = "mb93493.1",
132 .dev_id = (void *) __addr_MB93493_IQSR(1),
133 }
134};
135
136/*
137 * initialise the motherboard MB93493's PIC
138 */
139void __init mb93493_init(void)
91{ 140{
92 frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0); 141 int irq;
93 frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1); 142
94 143 for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
95 frv_irq_set_group(&frv_mb93493_irqs); 144 set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq);
96 145
97 mb93493_irq_route(IRQ_MB93493_VDC, IRQ_MB93493_VDC_ROUTE); 146 /* the MB93493 drives external IRQ inputs on the CPU PIC */
98 mb93493_irq_route(IRQ_MB93493_VCC, IRQ_MB93493_VCC_ROUTE); 147 setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
99 mb93493_irq_route(IRQ_MB93493_AUDIO_IN, IRQ_MB93493_AUDIO_IN_ROUTE); 148 setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]);
100 mb93493_irq_route(IRQ_MB93493_I2C_0, IRQ_MB93493_I2C_0_ROUTE);
101 mb93493_irq_route(IRQ_MB93493_I2C_1, IRQ_MB93493_I2C_1_ROUTE);
102 mb93493_irq_route(IRQ_MB93493_USB, IRQ_MB93493_USB_ROUTE);
103 mb93493_irq_route(IRQ_MB93493_LOCAL_BUS, IRQ_MB93493_LOCAL_BUS_ROUTE);
104 mb93493_irq_route(IRQ_MB93493_PCMCIA, IRQ_MB93493_PCMCIA_ROUTE);
105 mb93493_irq_route(IRQ_MB93493_GPIO, IRQ_MB93493_GPIO_ROUTE);
106 mb93493_irq_route(IRQ_MB93493_AUDIO_OUT, IRQ_MB93493_AUDIO_OUT_ROUTE);
107} 149}
diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c
deleted file mode 100644
index 53886adf47de..000000000000
--- a/arch/frv/kernel/irq-routing.c
+++ /dev/null
@@ -1,291 +0,0 @@
1/* irq-routing.c: IRQ routing
2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/sched.h>
13#include <linux/random.h>
14#include <linux/init.h>
15#include <linux/serial_reg.h>
16#include <asm/io.h>
17#include <asm/irq-routing.h>
18#include <asm/irc-regs.h>
19#include <asm/serial-regs.h>
20#include <asm/dma.h>
21
22struct irq_level frv_irq_levels[16] = {
23 [0 ... 15] = {
24 .lock = SPIN_LOCK_UNLOCKED,
25 }
26};
27
28struct irq_group *irq_groups[NR_IRQ_GROUPS];
29
30extern struct irq_group frv_cpu_irqs;
31
32void __init frv_irq_route(struct irq_source *source, int irqlevel)
33{
34 source->level = &frv_irq_levels[irqlevel];
35 source->next = frv_irq_levels[irqlevel].sources;
36 frv_irq_levels[irqlevel].sources = source;
37}
38
39void __init frv_irq_route_external(struct irq_source *source, int irq)
40{
41 int irqlevel = 0;
42
43 switch (irq) {
44 case IRQ_CPU_EXTERNAL0: irqlevel = IRQ_XIRQ0_LEVEL; break;
45 case IRQ_CPU_EXTERNAL1: irqlevel = IRQ_XIRQ1_LEVEL; break;
46 case IRQ_CPU_EXTERNAL2: irqlevel = IRQ_XIRQ2_LEVEL; break;
47 case IRQ_CPU_EXTERNAL3: irqlevel = IRQ_XIRQ3_LEVEL; break;
48 case IRQ_CPU_EXTERNAL4: irqlevel = IRQ_XIRQ4_LEVEL; break;
49 case IRQ_CPU_EXTERNAL5: irqlevel = IRQ_XIRQ5_LEVEL; break;
50 case IRQ_CPU_EXTERNAL6: irqlevel = IRQ_XIRQ6_LEVEL; break;
51 case IRQ_CPU_EXTERNAL7: irqlevel = IRQ_XIRQ7_LEVEL; break;
52 default: BUG();
53 }
54
55 source->level = &frv_irq_levels[irqlevel];
56 source->next = frv_irq_levels[irqlevel].sources;
57 frv_irq_levels[irqlevel].sources = source;
58}
59
60void __init frv_irq_set_group(struct irq_group *group)
61{
62 irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group;
63}
64
65void distribute_irqs(struct irq_group *group, unsigned long irqmask)
66{
67 struct irqaction *action;
68 int irq;
69
70 while (irqmask) {
71 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask));
72 if (irq < 0 || irq > 31)
73 asm volatile("break");
74 irq = 31 - irq;
75
76 irqmask &= ~(1 << irq);
77 action = group->actions[irq];
78
79 irq += group->first_irq;
80
81 if (action) {
82 int status = 0;
83
84// if (!(action->flags & IRQF_DISABLED))
85// local_irq_enable();
86
87 do {
88 status |= action->flags;
89 action->handler(irq, action->dev_id, __frame);
90 action = action->next;
91 } while (action);
92
93 if (status & IRQF_SAMPLE_RANDOM)
94 add_interrupt_randomness(irq);
95 local_irq_disable();
96 }
97 }
98}
99
100/*****************************************************************************/
101/*
102 * CPU UART interrupts
103 */
104static void frv_cpuuart_doirq(struct irq_source *source)
105{
106// uint8_t iir = readb(source->muxdata + UART_IIR * 8);
107// if ((iir & 0x0f) != UART_IIR_NO_INT)
108 distribute_irqs(&frv_cpu_irqs, source->irqmask);
109}
110
111struct irq_source frv_cpuuart[2] = {
112#define __CPUUART(X, A) \
113 [X] = { \
114 .muxname = "uart", \
115 .muxdata = (volatile void __iomem *)(unsigned long)A,\
116 .irqmask = 1 << IRQ_CPU_UART##X, \
117 .doirq = frv_cpuuart_doirq, \
118 }
119
120 __CPUUART(0, UART0_BASE),
121 __CPUUART(1, UART1_BASE),
122};
123
124/*****************************************************************************/
125/*
126 * CPU DMA interrupts
127 */
128static void frv_cpudma_doirq(struct irq_source *source)
129{
130 uint32_t cstr = readl(source->muxdata + DMAC_CSTRx);
131 if (cstr & DMAC_CSTRx_INT)
132 distribute_irqs(&frv_cpu_irqs, source->irqmask);
133}
134
135struct irq_source frv_cpudma[8] = {
136#define __CPUDMA(X, A) \
137 [X] = { \
138 .muxname = "dma", \
139 .muxdata = (volatile void __iomem *)(unsigned long)A,\
140 .irqmask = 1 << IRQ_CPU_DMA##X, \
141 .doirq = frv_cpudma_doirq, \
142 }
143
144 __CPUDMA(0, 0xfe000900),
145 __CPUDMA(1, 0xfe000980),
146 __CPUDMA(2, 0xfe000a00),
147 __CPUDMA(3, 0xfe000a80),
148 __CPUDMA(4, 0xfe001000),
149 __CPUDMA(5, 0xfe001080),
150 __CPUDMA(6, 0xfe001100),
151 __CPUDMA(7, 0xfe001180),
152};
153
154/*****************************************************************************/
155/*
156 * CPU timer interrupts - can't tell whether they've generated an interrupt or not
157 */
158static void frv_cputimer_doirq(struct irq_source *source)
159{
160 distribute_irqs(&frv_cpu_irqs, source->irqmask);
161}
162
163struct irq_source frv_cputimer[3] = {
164#define __CPUTIMER(X) \
165 [X] = { \
166 .muxname = "timer", \
167 .muxdata = NULL, \
168 .irqmask = 1 << IRQ_CPU_TIMER##X, \
169 .doirq = frv_cputimer_doirq, \
170 }
171
172 __CPUTIMER(0),
173 __CPUTIMER(1),
174 __CPUTIMER(2),
175};
176
177/*****************************************************************************/
178/*
179 * external CPU interrupts - can't tell directly whether they've generated an interrupt or not
180 */
181static void frv_cpuexternal_doirq(struct irq_source *source)
182{
183 distribute_irqs(&frv_cpu_irqs, source->irqmask);
184}
185
186struct irq_source frv_cpuexternal[8] = {
187#define __CPUEXTERNAL(X) \
188 [X] = { \
189 .muxname = "ext", \
190 .muxdata = NULL, \
191 .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \
192 .doirq = frv_cpuexternal_doirq, \
193 }
194
195 __CPUEXTERNAL(0),
196 __CPUEXTERNAL(1),
197 __CPUEXTERNAL(2),
198 __CPUEXTERNAL(3),
199 __CPUEXTERNAL(4),
200 __CPUEXTERNAL(5),
201 __CPUEXTERNAL(6),
202 __CPUEXTERNAL(7),
203};
204
205#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
206
207struct irq_group frv_cpu_irqs = {
208 .sources = {
209 [IRQ_CPU_UART0] = &frv_cpuuart[0],
210 [IRQ_CPU_UART1] = &frv_cpuuart[1],
211 [IRQ_CPU_TIMER0] = &frv_cputimer[0],
212 [IRQ_CPU_TIMER1] = &frv_cputimer[1],
213 [IRQ_CPU_TIMER2] = &frv_cputimer[2],
214 [IRQ_CPU_DMA0] = &frv_cpudma[0],
215 [IRQ_CPU_DMA1] = &frv_cpudma[1],
216 [IRQ_CPU_DMA2] = &frv_cpudma[2],
217 [IRQ_CPU_DMA3] = &frv_cpudma[3],
218 [IRQ_CPU_DMA4] = &frv_cpudma[4],
219 [IRQ_CPU_DMA5] = &frv_cpudma[5],
220 [IRQ_CPU_DMA6] = &frv_cpudma[6],
221 [IRQ_CPU_DMA7] = &frv_cpudma[7],
222 [IRQ_CPU_EXTERNAL0] = &frv_cpuexternal[0],
223 [IRQ_CPU_EXTERNAL1] = &frv_cpuexternal[1],
224 [IRQ_CPU_EXTERNAL2] = &frv_cpuexternal[2],
225 [IRQ_CPU_EXTERNAL3] = &frv_cpuexternal[3],
226 [IRQ_CPU_EXTERNAL4] = &frv_cpuexternal[4],
227 [IRQ_CPU_EXTERNAL5] = &frv_cpuexternal[5],
228 [IRQ_CPU_EXTERNAL6] = &frv_cpuexternal[6],
229 [IRQ_CPU_EXTERNAL7] = &frv_cpuexternal[7],
230 },
231};
232
233/*****************************************************************************/
234/*
235 * route the CPU's interrupt sources
236 */
237void __init route_cpu_irqs(void)
238{
239 frv_irq_set_group(&frv_cpu_irqs);
240
241 __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 IRQ detect levels */
242 __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */
243
244 /* route UART and error interrupts */
245 frv_irq_route(&frv_cpuuart[0], IRQ_UART0_LEVEL);
246 frv_irq_route(&frv_cpuuart[1], IRQ_UART1_LEVEL);
247
248 set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
249
250 /* route DMA channel interrupts */
251 frv_irq_route(&frv_cpudma[0], IRQ_DMA0_LEVEL);
252 frv_irq_route(&frv_cpudma[1], IRQ_DMA1_LEVEL);
253 frv_irq_route(&frv_cpudma[2], IRQ_DMA2_LEVEL);
254 frv_irq_route(&frv_cpudma[3], IRQ_DMA3_LEVEL);
255 frv_irq_route(&frv_cpudma[4], IRQ_DMA4_LEVEL);
256 frv_irq_route(&frv_cpudma[5], IRQ_DMA5_LEVEL);
257 frv_irq_route(&frv_cpudma[6], IRQ_DMA6_LEVEL);
258 frv_irq_route(&frv_cpudma[7], IRQ_DMA7_LEVEL);
259
260 set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL);
261 set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL);
262
263 /* route timer interrupts */
264 frv_irq_route(&frv_cputimer[0], IRQ_TIMER0_LEVEL);
265 frv_irq_route(&frv_cputimer[1], IRQ_TIMER1_LEVEL);
266 frv_irq_route(&frv_cputimer[2], IRQ_TIMER2_LEVEL);
267
268 set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
269
270 /* route external interrupts */
271 frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL);
272 frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL);
273 frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL);
274 frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL);
275 frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL);
276 frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL);
277 frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL);
278 frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL);
279
280 set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL);
281 set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL);
282
283#if defined(CONFIG_MB93091_VDK)
284 __set_TM1(0x55550000); /* XIRQ7-0 all active low */
285#elif defined(CONFIG_MB93093_PDK)
286 __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
287#else
288#error dont know external IRQ trigger levels for this setup
289#endif
290
291} /* end route_cpu_irqs() */
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 08967010be04..5ac041c7c0a4 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -1,6 +1,6 @@
1/* irq.c: FRV IRQ handling 1/* irq.c: FRV IRQ handling
2 * 2 *
3 * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -9,13 +9,6 @@
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12/*
13 * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
14 *
15 * IRQs are in fact implemented a bit like signal handlers for the kernel.
16 * Naturally it's not a 1:1 relation, but there are similarities.
17 */
18
19#include <linux/ptrace.h> 12#include <linux/ptrace.h>
20#include <linux/errno.h> 13#include <linux/errno.h>
21#include <linux/signal.h> 14#include <linux/signal.h>
@@ -43,19 +36,16 @@
43#include <asm/delay.h> 36#include <asm/delay.h>
44#include <asm/irq.h> 37#include <asm/irq.h>
45#include <asm/irc-regs.h> 38#include <asm/irc-regs.h>
46#include <asm/irq-routing.h>
47#include <asm/gdb-stub.h> 39#include <asm/gdb-stub.h>
48 40
49extern void __init fpga_init(void); 41#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
50extern void __init route_mb93493_irqs(void);
51
52static void register_irq_proc (unsigned int irq);
53 42
54/* 43extern void __init fpga_init(void);
55 * Special irq handlers. 44#ifdef CONFIG_FUJITSU_MB93493
56 */ 45extern void __init mb93493_init(void);
46#endif
57 47
58irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; } 48#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
59 49
60atomic_t irq_err_count; 50atomic_t irq_err_count;
61 51
@@ -64,215 +54,86 @@ atomic_t irq_err_count;
64 */ 54 */
65int show_interrupts(struct seq_file *p, void *v) 55int show_interrupts(struct seq_file *p, void *v)
66{ 56{
67 struct irqaction *action; 57 int i = *(loff_t *) v, cpu;
68 struct irq_group *group; 58 struct irqaction * action;
69 unsigned long flags; 59 unsigned long flags;
70 int level, grp, ix, i, j;
71
72 i = *(loff_t *) v;
73
74 switch (i) {
75 case 0:
76 seq_printf(p, " ");
77 for_each_online_cpu(j)
78 seq_printf(p, "CPU%d ",j);
79
80 seq_putc(p, '\n');
81 break;
82 60
83 case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP: 61 if (i == 0) {
84 local_irq_save(flags); 62 char cpuname[12];
85
86 grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP;
87 group = irq_groups[grp];
88 if (!group)
89 goto skip;
90
91 ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP;
92 action = group->actions[ix];
93 if (!action)
94 goto skip;
95
96 seq_printf(p, "%3d: ", i - 1);
97
98#ifndef CONFIG_SMP
99 seq_printf(p, "%10u ", kstat_irqs(i));
100#else
101 for_each_online_cpu(j)
102 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]);
103#endif
104
105 level = group->sources[ix]->level - frv_irq_levels;
106
107 seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level);
108 seq_printf(p, " %s", action->name);
109
110 for (action = action->next; action; action = action->next)
111 seq_printf(p, ", %s", action->name);
112 63
64 seq_printf(p, " ");
65 for_each_present_cpu(cpu) {
66 sprintf(cpuname, "CPU%d", cpu);
67 seq_printf(p, " %10s", cpuname);
68 }
113 seq_putc(p, '\n'); 69 seq_putc(p, '\n');
114skip: 70 }
115 local_irq_restore(flags);
116 break;
117 71
118 case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1: 72 if (i < NR_IRQS) {
119 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 73 spin_lock_irqsave(&irq_desc[i].lock, flags);
120 break; 74 action = irq_desc[i].action;
75 if (action) {
76 seq_printf(p, "%3d: ", i);
77 for_each_present_cpu(cpu)
78 seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
79 seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
80 seq_printf(p, " %s", action->name);
81 for (action = action->next;
82 action;
83 action = action->next)
84 seq_printf(p, ", %s", action->name);
85
86 seq_putc(p, '\n');
87 }
121 88
122 default: 89 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
123 break; 90 } else if (i == NR_IRQS) {
91 seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
124 } 92 }
125 93
126 return 0; 94 return 0;
127} 95}
128 96
129
130/* 97/*
131 * Generic enable/disable code: this just calls 98 * on-CPU PIC operations
132 * down into the PIC-specific version for the actual
133 * hardware disable after having gotten the irq
134 * controller lock.
135 */ 99 */
136 100static void frv_cpupic_ack(unsigned int irqlevel)
137/**
138 * disable_irq_nosync - disable an irq without waiting
139 * @irq: Interrupt to disable
140 *
141 * Disable the selected interrupt line. Disables and Enables are
142 * nested.
143 * Unlike disable_irq(), this function does not ensure existing
144 * instances of the IRQ handler have completed before returning.
145 *
146 * This function may be called from IRQ context.
147 */
148
149void disable_irq_nosync(unsigned int irq)
150{ 101{
151 struct irq_source *source; 102 __clr_RC(irqlevel);
152 struct irq_group *group; 103 __clr_IRL();
153 struct irq_level *level;
154 unsigned long flags;
155 int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
156
157 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
158 if (!group)
159 BUG();
160
161 source = group->sources[idx];
162 if (!source)
163 BUG();
164
165 level = source->level;
166
167 spin_lock_irqsave(&level->lock, flags);
168
169 if (group->control) {
170 if (!group->disable_cnt[idx]++)
171 group->control(group, idx, 0);
172 } else if (!level->disable_count++) {
173 __set_MASK(level - frv_irq_levels);
174 }
175
176 spin_unlock_irqrestore(&level->lock, flags);
177} 104}
178 105
179EXPORT_SYMBOL(disable_irq_nosync); 106static void frv_cpupic_mask(unsigned int irqlevel)
180
181/**
182 * disable_irq - disable an irq and wait for completion
183 * @irq: Interrupt to disable
184 *
185 * Disable the selected interrupt line. Enables and Disables are
186 * nested.
187 * This function waits for any pending IRQ handlers for this interrupt
188 * to complete before returning. If you use this function while
189 * holding a resource the IRQ handler may need you will deadlock.
190 *
191 * This function may be called - with care - from IRQ context.
192 */
193
194void disable_irq(unsigned int irq)
195{ 107{
196 disable_irq_nosync(irq); 108 __set_MASK(irqlevel);
197
198#ifdef CONFIG_SMP
199 if (!local_irq_count(smp_processor_id())) {
200 do {
201 barrier();
202 } while (irq_desc[irq].status & IRQ_INPROGRESS);
203 }
204#endif
205} 109}
206 110
207EXPORT_SYMBOL(disable_irq); 111static void frv_cpupic_mask_ack(unsigned int irqlevel)
208
209/**
210 * enable_irq - enable handling of an irq
211 * @irq: Interrupt to enable
212 *
213 * Undoes the effect of one call to disable_irq(). If this
214 * matches the last disable, processing of interrupts on this
215 * IRQ line is re-enabled.
216 *
217 * This function may be called from IRQ context.
218 */
219
220void enable_irq(unsigned int irq)
221{ 112{
222 struct irq_source *source; 113 __set_MASK(irqlevel);
223 struct irq_group *group; 114 __clr_RC(irqlevel);
224 struct irq_level *level; 115 __clr_IRL();
225 unsigned long flags; 116}
226 int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
227 int count;
228
229 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
230 if (!group)
231 BUG();
232
233 source = group->sources[idx];
234 if (!source)
235 BUG();
236
237 level = source->level;
238
239 spin_lock_irqsave(&level->lock, flags);
240
241 if (group->control)
242 count = group->disable_cnt[idx];
243 else
244 count = level->disable_count;
245
246 switch (count) {
247 case 1:
248 if (group->control) {
249 if (group->actions[idx])
250 group->control(group, idx, 1);
251 } else {
252 if (level->usage)
253 __clr_MASK(level - frv_irq_levels);
254 }
255 /* fall-through */
256
257 default:
258 count--;
259 break;
260
261 case 0:
262 printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0));
263 }
264 117
265 if (group->control) 118static void frv_cpupic_unmask(unsigned int irqlevel)
266 group->disable_cnt[idx] = count; 119{
267 else 120 __clr_MASK(irqlevel);
268 level->disable_count = count; 121}
269 122
270 spin_unlock_irqrestore(&level->lock, flags); 123static void frv_cpupic_end(unsigned int irqlevel)
124{
125 __clr_MASK(irqlevel);
271} 126}
272 127
273EXPORT_SYMBOL(enable_irq); 128static struct irq_chip frv_cpu_pic = {
129 .name = "cpu",
130 .ack = frv_cpupic_ack,
131 .mask = frv_cpupic_mask,
132 .mask_ack = frv_cpupic_mask_ack,
133 .unmask = frv_cpupic_unmask,
134 .end = frv_cpupic_end,
135};
274 136
275/*****************************************************************************/
276/* 137/*
277 * handles all normal device IRQ's 138 * handles all normal device IRQ's
278 * - registers are referred to by the __frame variable (GR28) 139 * - registers are referred to by the __frame variable (GR28)
@@ -281,463 +142,65 @@ EXPORT_SYMBOL(enable_irq);
281 */ 142 */
282asmlinkage void do_IRQ(void) 143asmlinkage void do_IRQ(void)
283{ 144{
284 struct irq_source *source;
285 int level, cpu;
286
287 irq_enter(); 145 irq_enter();
288 146 generic_handle_irq(__get_IRL(), __frame);
289 level = (__frame->tbr >> 4) & 0xf;
290 cpu = smp_processor_id();
291
292 if ((unsigned long) __frame - (unsigned long) (current + 1) < 512)
293 BUG();
294
295 __set_MASK(level);
296 __clr_RC(level);
297 __clr_IRL();
298
299 kstat_this_cpu.irqs[level]++;
300
301 for (source = frv_irq_levels[level].sources; source; source = source->next)
302 source->doirq(source);
303
304 __clr_MASK(level);
305
306 irq_exit(); 147 irq_exit();
148}
307 149
308} /* end do_IRQ() */
309
310/*****************************************************************************/
311/* 150/*
312 * handles all NMIs when not co-opted by the debugger 151 * handles all NMIs when not co-opted by the debugger
313 * - registers are referred to by the __frame variable (GR28) 152 * - registers are referred to by the __frame variable (GR28)
314 */ 153 */
315asmlinkage void do_NMI(void) 154asmlinkage void do_NMI(void)
316{ 155{
317} /* end do_NMI() */
318
319/*****************************************************************************/
320/**
321 * request_irq - allocate an interrupt line
322 * @irq: Interrupt line to allocate
323 * @handler: Function to be called when the IRQ occurs
324 * @irqflags: Interrupt type flags
325 * @devname: An ascii name for the claiming device
326 * @dev_id: A cookie passed back to the handler function
327 *
328 * This call allocates interrupt resources and enables the
329 * interrupt line and IRQ handling. From the point this
330 * call is made your handler function may be invoked. Since
331 * your handler function must clear any interrupt the board
332 * raises, you must take care both to initialise your hardware
333 * and to set up the interrupt handler in the right order.
334 *
335 * Dev_id must be globally unique. Normally the address of the
336 * device data structure is used as the cookie. Since the handler
337 * receives this value it makes sense to use it.
338 *
339 * If your interrupt is shared you must pass a non NULL dev_id
340 * as this is required when freeing the interrupt.
341 *
342 * Flags:
343 *
344 * IRQF_SHARED Interrupt is shared
345 *
346 * IRQF_DISABLED Disable local interrupts while processing
347 *
348 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
349 *
350 */
351
352int request_irq(unsigned int irq,
353 irqreturn_t (*handler)(int, void *, struct pt_regs *),
354 unsigned long irqflags,
355 const char * devname,
356 void *dev_id)
357{
358 int retval;
359 struct irqaction *action;
360
361#if 1
362 /*
363 * Sanity-check: shared interrupts should REALLY pass in
364 * a real dev-ID, otherwise we'll have trouble later trying
365 * to figure out which interrupt is which (messes up the
366 * interrupt freeing logic etc).
367 */
368 if (irqflags & IRQF_SHARED) {
369 if (!dev_id)
370 printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n",
371 devname, (&irq)[-1]);
372 }
373#endif
374
375 if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
376 return -EINVAL;
377 if (!handler)
378 return -EINVAL;
379
380 action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL);
381 if (!action)
382 return -ENOMEM;
383
384 action->handler = handler;
385 action->flags = irqflags;
386 action->mask = CPU_MASK_NONE;
387 action->name = devname;
388 action->next = NULL;
389 action->dev_id = dev_id;
390
391 retval = setup_irq(irq, action);
392 if (retval)
393 kfree(action);
394 return retval;
395}
396
397EXPORT_SYMBOL(request_irq);
398
399/**
400 * free_irq - free an interrupt
401 * @irq: Interrupt line to free
402 * @dev_id: Device identity to free
403 *
404 * Remove an interrupt handler. The handler is removed and if the
405 * interrupt line is no longer in use by any driver it is disabled.
406 * On a shared IRQ the caller must ensure the interrupt is disabled
407 * on the card it drives before calling this function. The function
408 * does not return until any executing interrupts for this IRQ
409 * have completed.
410 *
411 * This function may be called from interrupt context.
412 *
413 * Bugs: Attempting to free an irq in a handler for the same irq hangs
414 * the machine.
415 */
416
417void free_irq(unsigned int irq, void *dev_id)
418{
419 struct irq_source *source;
420 struct irq_group *group;
421 struct irq_level *level;
422 struct irqaction **p, **pp;
423 unsigned long flags;
424
425 if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
426 return;
427
428 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
429 if (!group)
430 BUG();
431
432 source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
433 if (!source)
434 BUG();
435
436 level = source->level;
437 p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
438
439 spin_lock_irqsave(&level->lock, flags);
440
441 for (pp = p; *pp; pp = &(*pp)->next) {
442 struct irqaction *action = *pp;
443
444 if (action->dev_id != dev_id)
445 continue;
446
447 /* found it - remove from the list of entries */
448 *pp = action->next;
449
450 level->usage--;
451
452 if (p == pp && group->control)
453 group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0);
454
455 if (level->usage == 0)
456 __set_MASK(level - frv_irq_levels);
457
458 spin_unlock_irqrestore(&level->lock,flags);
459
460#ifdef CONFIG_SMP
461 /* Wait to make sure it's not being used on another CPU */
462 while (desc->status & IRQ_INPROGRESS)
463 barrier();
464#endif
465 kfree(action);
466 return;
467 }
468}
469
470EXPORT_SYMBOL(free_irq);
471
472/*
473 * IRQ autodetection code..
474 *
475 * This depends on the fact that any interrupt that comes in on to an
476 * unassigned IRQ will cause GxICR_DETECT to be set
477 */
478
479static DECLARE_MUTEX(probe_sem);
480
481/**
482 * probe_irq_on - begin an interrupt autodetect
483 *
484 * Commence probing for an interrupt. The interrupts are scanned
485 * and a mask of potential interrupt lines is returned.
486 *
487 */
488
489unsigned long probe_irq_on(void)
490{
491 down(&probe_sem);
492 return 0;
493} 156}
494 157
495EXPORT_SYMBOL(probe_irq_on);
496
497/* 158/*
498 * Return a mask of triggered interrupts (this 159 * initialise the interrupt system
499 * can handle only legacy ISA interrupts).
500 */
501
502/**
503 * probe_irq_mask - scan a bitmap of interrupt lines
504 * @val: mask of interrupts to consider
505 *
506 * Scan the ISA bus interrupt lines and return a bitmap of
507 * active interrupts. The interrupt probe logic state is then
508 * returned to its previous value.
509 *
510 * Note: we need to scan all the irq's even though we will
511 * only return ISA irq numbers - just so that we reset them
512 * all to a known state.
513 */
514unsigned int probe_irq_mask(unsigned long xmask)
515{
516 up(&probe_sem);
517 return 0;
518}
519
520EXPORT_SYMBOL(probe_irq_mask);
521
522/*
523 * Return the one interrupt that triggered (this can
524 * handle any interrupt source).
525 */
526
527/**
528 * probe_irq_off - end an interrupt autodetect
529 * @xmask: mask of potential interrupts (unused)
530 *
531 * Scans the unused interrupt lines and returns the line which
532 * appears to have triggered the interrupt. If no interrupt was
533 * found then zero is returned. If more than one interrupt is
534 * found then minus the first candidate is returned to indicate
535 * their is doubt.
536 *
537 * The interrupt probe logic state is returned to its previous
538 * value.
539 *
540 * BUGS: When used in a module (which arguably shouldnt happen)
541 * nothing prevents two IRQ probe callers from overlapping. The
542 * results of this are non-optimal.
543 */ 160 */
544 161void __init init_IRQ(void)
545int probe_irq_off(unsigned long xmask)
546{
547 up(&probe_sem);
548 return -1;
549}
550
551EXPORT_SYMBOL(probe_irq_off);
552
553/* this was setup_x86_irq but it seems pretty generic */
554int setup_irq(unsigned int irq, struct irqaction *new)
555{
556 struct irq_source *source;
557 struct irq_group *group;
558 struct irq_level *level;
559 struct irqaction **p, **pp;
560 unsigned long flags;
561
562 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
563 if (!group)
564 BUG();
565
566 source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
567 if (!source)
568 BUG();
569
570 level = source->level;
571
572 p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
573
574 /*
575 * Some drivers like serial.c use request_irq() heavily,
576 * so we have to be careful not to interfere with a
577 * running system.
578 */
579 if (new->flags & IRQF_SAMPLE_RANDOM) {
580 /*
581 * This function might sleep, we want to call it first,
582 * outside of the atomic block.
583 * Yes, this might clear the entropy pool if the wrong
584 * driver is attempted to be loaded, without actually
585 * installing a new handler, but is this really a problem,
586 * only the sysadmin is able to do this.
587 */
588 rand_initialize_irq(irq);
589 }
590
591 /* must juggle the interrupt processing stuff with interrupts disabled */
592 spin_lock_irqsave(&level->lock, flags);
593
594 /* can't share interrupts unless all parties agree to */
595 if (level->usage != 0 && !(level->flags & new->flags & IRQF_SHARED)) {
596 spin_unlock_irqrestore(&level->lock,flags);
597 return -EBUSY;
598 }
599
600 /* add new interrupt at end of irq queue */
601 pp = p;
602 while (*pp)
603 pp = &(*pp)->next;
604
605 *pp = new;
606
607 level->usage++;
608 level->flags = new->flags;
609
610 /* turn the interrupts on */
611 if (level->usage == 1)
612 __clr_MASK(level - frv_irq_levels);
613
614 if (p == pp && group->control)
615 group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1);
616
617 spin_unlock_irqrestore(&level->lock, flags);
618 register_irq_proc(irq);
619 return 0;
620}
621
622static struct proc_dir_entry * root_irq_dir;
623static struct proc_dir_entry * irq_dir [NR_IRQS];
624
625#define HEX_DIGITS 8
626
627static unsigned int parse_hex_value (const char __user *buffer,
628 unsigned long count, unsigned long *ret)
629{
630 unsigned char hexnum [HEX_DIGITS];
631 unsigned long value;
632 int i;
633
634 if (!count)
635 return -EINVAL;
636 if (count > HEX_DIGITS)
637 count = HEX_DIGITS;
638 if (copy_from_user(hexnum, buffer, count))
639 return -EFAULT;
640
641 /*
642 * Parse the first 8 characters as a hex string, any non-hex char
643 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
644 */
645 value = 0;
646
647 for (i = 0; i < count; i++) {
648 unsigned int c = hexnum[i];
649
650 switch (c) {
651 case '0' ... '9': c -= '0'; break;
652 case 'a' ... 'f': c -= 'a'-10; break;
653 case 'A' ... 'F': c -= 'A'-10; break;
654 default:
655 goto out;
656 }
657 value = (value << 4) | c;
658 }
659out:
660 *ret = value;
661 return 0;
662}
663
664
665static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
666 int count, int *eof, void *data)
667{
668 unsigned long *mask = (unsigned long *) data;
669 if (count < HEX_DIGITS+1)
670 return -EINVAL;
671 return sprintf (page, "%08lx\n", *mask);
672}
673
674static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
675 unsigned long count, void *data)
676{
677 unsigned long *mask = (unsigned long *) data, full_count = count, err;
678 unsigned long new_value;
679
680 show_state();
681 err = parse_hex_value(buffer, count, &new_value);
682 if (err)
683 return err;
684
685 *mask = new_value;
686 return full_count;
687}
688
689#define MAX_NAMELEN 10
690
691static void register_irq_proc (unsigned int irq)
692{
693 char name [MAX_NAMELEN];
694
695 if (!root_irq_dir || irq_dir[irq])
696 return;
697
698 memset(name, 0, MAX_NAMELEN);
699 sprintf(name, "%d", irq);
700
701 /* create /proc/irq/1234 */
702 irq_dir[irq] = proc_mkdir(name, root_irq_dir);
703}
704
705unsigned long prof_cpu_mask = -1;
706
707void init_irq_proc (void)
708{ 162{
709 struct proc_dir_entry *entry; 163 int level;
710 int i;
711 164
712 /* create /proc/irq */ 165 for (level = 1; level <= 14; level++)
713 root_irq_dir = proc_mkdir("irq", NULL); 166 set_irq_chip_and_handler(level, &frv_cpu_pic,
167 handle_level_irq);
714 168
715 /* create /proc/irq/prof_cpu_mask */ 169 set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq);
716 entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
717 if (!entry)
718 return;
719 170
720 entry->nlink = 1; 171 /* set the trigger levels for internal interrupt sources
721 entry->data = (void *)&prof_cpu_mask; 172 * - timers all falling-edge
722 entry->read_proc = prof_cpu_mask_read_proc; 173 * - ERR0 is rising-edge
723 entry->write_proc = prof_cpu_mask_write_proc; 174 * - all others are high-level
724
725 /*
726 * Create entries for all existing IRQs.
727 */ 175 */
728 for (i = 0; i < NR_IRQS; i++) 176 __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */
729 register_irq_proc(i); 177 __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */
730} 178
179 /* route internal interrupts */
180 set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL,
181 IRQ_DMA0_LEVEL);
182 set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
183 set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL,
184 IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
185 set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL,
186 IRQ_DMA4_LEVEL);
187
188 /* route external interrupts */
189 set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL,
190 IRQ_XIRQ4_LEVEL);
191 set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL,
192 IRQ_XIRQ0_LEVEL);
193
194#if defined(CONFIG_MB93091_VDK)
195 __set_TM1(0x55550000); /* XIRQ7-0 all active low */
196#elif defined(CONFIG_MB93093_PDK)
197 __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
198#else
199#error dont know external IRQ trigger levels for this setup
200#endif
731 201
732/*****************************************************************************/
733/*
734 * initialise the interrupt system
735 */
736void __init init_IRQ(void)
737{
738 route_cpu_irqs();
739 fpga_init(); 202 fpga_init();
740#ifdef CONFIG_FUJITSU_MB93493 203#ifdef CONFIG_FUJITSU_MB93493
741 route_mb93493_irqs(); 204 mb93493_init();
742#endif 205#endif
743} /* end init_IRQ() */ 206}
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index af08ccd4ed6e..d96a57e5f030 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -43,7 +43,6 @@
43#include <asm/mb-regs.h> 43#include <asm/mb-regs.h>
44#include <asm/mb93493-regs.h> 44#include <asm/mb93493-regs.h>
45#include <asm/gdb-stub.h> 45#include <asm/gdb-stub.h>
46#include <asm/irq-routing.h>
47#include <asm/io.h> 46#include <asm/io.h>
48 47
49#ifdef CONFIG_BLK_DEV_INITRD 48#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 68a77fe3bb40..3d0284bccb94 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -26,7 +26,6 @@
26#include <asm/timer-regs.h> 26#include <asm/timer-regs.h>
27#include <asm/mb-regs.h> 27#include <asm/mb-regs.h>
28#include <asm/mb86943a.h> 28#include <asm/mb86943a.h>
29#include <asm/irq-routing.h>
30 29
31#include <linux/timex.h> 30#include <linux/timex.h>
32 31
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index 2278c80bd88c..ba587523c015 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -15,7 +15,6 @@
15 15
16#include <asm/io.h> 16#include <asm/io.h>
17#include <asm/smp.h> 17#include <asm/smp.h>
18#include <asm/irq-routing.h>
19 18
20#include "pci-frv.h" 19#include "pci-frv.h"
21 20
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index b5b4286f9dd4..3f3a0ed3539b 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -98,7 +98,7 @@ void show_mem(void)
98 */ 98 */
99void __init paging_init(void) 99void __init paging_init(void)
100{ 100{
101 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 101 unsigned long zones_size[MAX_NR_ZONES] = {0, };
102 102
103 /* allocate some pages for kernel housekeeping tasks */ 103 /* allocate some pages for kernel housekeeping tasks */
104 empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); 104 empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);