aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/vr41xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/vr41xx')
-rw-r--r--arch/mips/vr41xx/casio-e55/Makefile5
-rw-r--r--arch/mips/vr41xx/casio-e55/setup.c40
-rw-r--r--arch/mips/vr41xx/common/Makefile8
-rw-r--r--arch/mips/vr41xx/common/bcu.c222
-rw-r--r--arch/mips/vr41xx/common/cmu.c257
-rw-r--r--arch/mips/vr41xx/common/giu.c455
-rw-r--r--arch/mips/vr41xx/common/icu.c757
-rw-r--r--arch/mips/vr41xx/common/init.c85
-rw-r--r--arch/mips/vr41xx/common/int-handler.S114
-rw-r--r--arch/mips/vr41xx/common/pmu.c81
-rw-r--r--arch/mips/vr41xx/common/vrc4173.c581
-rw-r--r--arch/mips/vr41xx/ibm-workpad/Makefile5
-rw-r--r--arch/mips/vr41xx/ibm-workpad/setup.c40
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/Makefile8
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/init.c78
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/irq.c114
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c250
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/setup.c96
-rw-r--r--arch/mips/vr41xx/tanbac-tb0226/Makefile5
-rw-r--r--arch/mips/vr41xx/tanbac-tb0226/setup.c24
-rw-r--r--arch/mips/vr41xx/tanbac-tb0229/Makefile5
-rw-r--r--arch/mips/vr41xx/tanbac-tb0229/setup.c27
-rw-r--r--arch/mips/vr41xx/victor-mpc30x/Makefile5
-rw-r--r--arch/mips/vr41xx/victor-mpc30x/setup.c24
-rw-r--r--arch/mips/vr41xx/zao-capcella/Makefile5
-rw-r--r--arch/mips/vr41xx/zao-capcella/setup.c24
26 files changed, 3315 insertions, 0 deletions
diff --git a/arch/mips/vr41xx/casio-e55/Makefile b/arch/mips/vr41xx/casio-e55/Makefile
new file mode 100644
index 000000000000..d4c03cc8eb05
--- /dev/null
+++ b/arch/mips/vr41xx/casio-e55/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the CASIO CASSIOPEIA E-55/65 specific parts of the kernel
3#
4
5obj-y += setup.o
diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c
new file mode 100644
index 000000000000..aa8605ab76ff
--- /dev/null
+++ b/arch/mips/vr41xx/casio-e55/setup.c
@@ -0,0 +1,40 @@
1/*
2 * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
3 *
4 * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/init.h>
21#include <linux/ioport.h>
22
23#include <asm/io.h>
24#include <asm/vr41xx/e55.h>
25
26const char *get_system_type(void)
27{
28 return "CASIO CASSIOPEIA E-11/15/55/65";
29}
30
31static int __init casio_e55_setup(void)
32{
33 set_io_port_base(IO_PORT_BASE);
34 ioport_resource.start = IO_PORT_RESOURCE_START;
35 ioport_resource.end = IO_PORT_RESOURCE_END;
36
37 return 0;
38}
39
40arch_initcall(casio_e55_setup);
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
new file mode 100644
index 000000000000..92c11e9bbb3f
--- /dev/null
+++ b/arch/mips/vr41xx/common/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for common code of the NEC VR4100 series.
3#
4
5obj-y += bcu.o cmu.o giu.o icu.o init.o int-handler.o pmu.o
6obj-$(CONFIG_VRC4173) += vrc4173.o
7
8EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c
new file mode 100644
index 000000000000..cdfa4273a1c5
--- /dev/null
+++ b/arch/mips/vr41xx/common/bcu.c
@@ -0,0 +1,222 @@
1/*
2 * bcu.c, Bus Control Unit routines for the NEC VR4100 series.
3 *
4 * Copyright (C) 2002 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
6 * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
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. <yyuasa@mvista.com> or <source@mvista.com>
25 * - New creation, NEC VR4122 and VR4131 are supported.
26 * - Added support for NEC VR4111 and VR4121.
27 *
28 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
29 * - Added support for NEC VR4133.
30 */
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/smp.h>
34#include <linux/types.h>
35
36#include <asm/cpu.h>
37#include <asm/io.h>
38
39#define CLKSPEEDREG_TYPE1 (void __iomem *)KSEG1ADDR(0x0b000014)
40#define CLKSPEEDREG_TYPE2 (void __iomem *)KSEG1ADDR(0x0f000014)
41 #define CLKSP(x) ((x) & 0x001f)
42 #define CLKSP_VR4133(x) ((x) & 0x0007)
43
44 #define DIV2B 0x8000
45 #define DIV3B 0x4000
46 #define DIV4B 0x2000
47
48 #define DIVT(x) (((x) & 0xf000) >> 12)
49 #define DIVVT(x) (((x) & 0x0f00) >> 8)
50
51 #define TDIVMODE(x) (2 << (((x) & 0x1000) >> 12))
52 #define VTDIVMODE(x) (((x) & 0x0700) >> 8)
53
54static unsigned long vr41xx_vtclock;
55static unsigned long vr41xx_tclock;
56
57unsigned long vr41xx_get_vtclock_frequency(void)
58{
59 return vr41xx_vtclock;
60}
61
62EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency);
63
64unsigned long vr41xx_get_tclock_frequency(void)
65{
66 return vr41xx_tclock;
67}
68
69EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency);
70
71static inline uint16_t read_clkspeed(void)
72{
73 switch (current_cpu_data.cputype) {
74 case CPU_VR4111:
75 case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1);
76 case CPU_VR4122:
77 case CPU_VR4131:
78 case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2);
79 default:
80 printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
81 break;
82 }
83
84 return 0;
85}
86
87static inline unsigned long calculate_pclock(uint16_t clkspeed)
88{
89 unsigned long pclock = 0;
90
91 switch (current_cpu_data.cputype) {
92 case CPU_VR4111:
93 case CPU_VR4121:
94 pclock = 18432000 * 64;
95 pclock /= CLKSP(clkspeed);
96 break;
97 case CPU_VR4122:
98 pclock = 18432000 * 98;
99 pclock /= CLKSP(clkspeed);
100 break;
101 case CPU_VR4131:
102 pclock = 18432000 * 108;
103 pclock /= CLKSP(clkspeed);
104 break;
105 case CPU_VR4133:
106 switch (CLKSP_VR4133(clkspeed)) {
107 case 0:
108 pclock = 133000000;
109 break;
110 case 1:
111 pclock = 149000000;
112 break;
113 case 2:
114 pclock = 165900000;
115 break;
116 case 3:
117 pclock = 199100000;
118 break;
119 case 4:
120 pclock = 265900000;
121 break;
122 default:
123 printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n");
124 break;
125 }
126 break;
127 default:
128 printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
129 break;
130 }
131
132 printk(KERN_INFO "PClock: %ldHz\n", pclock);
133
134 return pclock;
135}
136
137static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock)
138{
139 unsigned long vtclock = 0;
140
141 switch (current_cpu_data.cputype) {
142 case CPU_VR4111:
143 /* The NEC VR4111 doesn't have the VTClock. */
144 break;
145 case CPU_VR4121:
146 vtclock = pclock;
147 /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */
148 if (DIVVT(clkspeed) == 9)
149 vtclock = pclock * 6;
150 /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */
151 else if (DIVVT(clkspeed) == 10)
152 vtclock = pclock * 4;
153 vtclock /= DIVVT(clkspeed);
154 printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
155 break;
156 case CPU_VR4122:
157 if(VTDIVMODE(clkspeed) == 7)
158 vtclock = pclock / 1;
159 else if(VTDIVMODE(clkspeed) == 1)
160 vtclock = pclock / 2;
161 else
162 vtclock = pclock / VTDIVMODE(clkspeed);
163 printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
164 break;
165 case CPU_VR4131:
166 case CPU_VR4133:
167 vtclock = pclock / VTDIVMODE(clkspeed);
168 printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
169 break;
170 default:
171 printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
172 break;
173 }
174
175 return vtclock;
176}
177
178static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock,
179 unsigned long vtclock)
180{
181 unsigned long tclock = 0;
182
183 switch (current_cpu_data.cputype) {
184 case CPU_VR4111:
185 if (!(clkspeed & DIV2B))
186 tclock = pclock / 2;
187 else if (!(clkspeed & DIV3B))
188 tclock = pclock / 3;
189 else if (!(clkspeed & DIV4B))
190 tclock = pclock / 4;
191 break;
192 case CPU_VR4121:
193 tclock = pclock / DIVT(clkspeed);
194 break;
195 case CPU_VR4122:
196 case CPU_VR4131:
197 case CPU_VR4133:
198 tclock = vtclock / TDIVMODE(clkspeed);
199 break;
200 default:
201 printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
202 break;
203 }
204
205 printk(KERN_INFO "TClock: %ldHz\n", tclock);
206
207 return tclock;
208}
209
210void vr41xx_calculate_clock_frequency(void)
211{
212 unsigned long pclock;
213 uint16_t clkspeed;
214
215 clkspeed = read_clkspeed();
216
217 pclock = calculate_pclock(clkspeed);
218 vr41xx_vtclock = calculate_vtclock(clkspeed, pclock);
219 vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock);
220}
221
222EXPORT_SYMBOL_GPL(vr41xx_calculate_clock_frequency);
diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c
new file mode 100644
index 000000000000..fcd3cb8cdd9d
--- /dev/null
+++ b/arch/mips/vr41xx/common/cmu.c
@@ -0,0 +1,257 @@
1/*
2 * cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
3 *
4 * Copyright (C) 2001-2002 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6 * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
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. <yyuasa@mvista.com> or <source@mvista.com>
25 * - New creation, NEC VR4122 and VR4131 are supported.
26 * - Added support for NEC VR4111 and VR4121.
27 *
28 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
29 * - Added support for NEC VR4133.
30 */
31#include <linux/init.h>
32#include <linux/ioport.h>
33#include <linux/module.h>
34#include <linux/smp.h>
35#include <linux/spinlock.h>
36#include <linux/types.h>
37
38#include <asm/cpu.h>
39#include <asm/io.h>
40#include <asm/vr41xx/vr41xx.h>
41
42#define CMU_TYPE1_BASE 0x0b000060UL
43#define CMU_TYPE1_SIZE 0x4
44
45#define CMU_TYPE2_BASE 0x0f000060UL
46#define CMU_TYPE2_SIZE 0x4
47
48#define CMU_TYPE3_BASE 0x0f000060UL
49#define CMU_TYPE3_SIZE 0x8
50
51#define CMUCLKMSK 0x0
52 #define MSKPIU 0x0001
53 #define MSKSIU 0x0002
54 #define MSKAIU 0x0004
55 #define MSKKIU 0x0008
56 #define MSKFIR 0x0010
57 #define MSKDSIU 0x0820
58 #define MSKCSI 0x0040
59 #define MSKPCIU 0x0080
60 #define MSKSSIU 0x0100
61 #define MSKSHSP 0x0200
62 #define MSKFFIR 0x0400
63 #define MSKSCSI 0x1000
64 #define MSKPPCIU 0x2000
65#define CMUCLKMSK2 0x4
66 #define MSKCEU 0x0001
67 #define MSKMAC0 0x0002
68 #define MSKMAC1 0x0004
69
70static void __iomem *cmu_base;
71static uint16_t cmuclkmsk, cmuclkmsk2;
72static spinlock_t cmu_lock;
73
74#define cmu_read(offset) readw(cmu_base + (offset))
75#define cmu_write(offset, value) writew((value), cmu_base + (offset))
76
77void vr41xx_supply_clock(vr41xx_clock_t clock)
78{
79 spin_lock_irq(&cmu_lock);
80
81 switch (clock) {
82 case PIU_CLOCK:
83 cmuclkmsk |= MSKPIU;
84 break;
85 case SIU_CLOCK:
86 cmuclkmsk |= MSKSIU | MSKSSIU;
87 break;
88 case AIU_CLOCK:
89 cmuclkmsk |= MSKAIU;
90 break;
91 case KIU_CLOCK:
92 cmuclkmsk |= MSKKIU;
93 break;
94 case FIR_CLOCK:
95 cmuclkmsk |= MSKFIR | MSKFFIR;
96 break;
97 case DSIU_CLOCK:
98 if (current_cpu_data.cputype == CPU_VR4111 ||
99 current_cpu_data.cputype == CPU_VR4121)
100 cmuclkmsk |= MSKDSIU;
101 else
102 cmuclkmsk |= MSKSIU | MSKDSIU;
103 break;
104 case CSI_CLOCK:
105 cmuclkmsk |= MSKCSI | MSKSCSI;
106 break;
107 case PCIU_CLOCK:
108 cmuclkmsk |= MSKPCIU;
109 break;
110 case HSP_CLOCK:
111 cmuclkmsk |= MSKSHSP;
112 break;
113 case PCI_CLOCK:
114 cmuclkmsk |= MSKPPCIU;
115 break;
116 case CEU_CLOCK:
117 cmuclkmsk2 |= MSKCEU;
118 break;
119 case ETHER0_CLOCK:
120 cmuclkmsk2 |= MSKMAC0;
121 break;
122 case ETHER1_CLOCK:
123 cmuclkmsk2 |= MSKMAC1;
124 break;
125 default:
126 break;
127 }
128
129 if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
130 clock == ETHER1_CLOCK)
131 cmu_write(CMUCLKMSK2, cmuclkmsk2);
132 else
133 cmu_write(CMUCLKMSK, cmuclkmsk);
134
135 spin_unlock_irq(&cmu_lock);
136}
137
138EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
139
140void vr41xx_mask_clock(vr41xx_clock_t clock)
141{
142 spin_lock_irq(&cmu_lock);
143
144 switch (clock) {
145 case PIU_CLOCK:
146 cmuclkmsk &= ~MSKPIU;
147 break;
148 case SIU_CLOCK:
149 if (current_cpu_data.cputype == CPU_VR4111 ||
150 current_cpu_data.cputype == CPU_VR4121) {
151 cmuclkmsk &= ~(MSKSIU | MSKSSIU);
152 } else {
153 if (cmuclkmsk & MSKDSIU)
154 cmuclkmsk &= ~MSKSSIU;
155 else
156 cmuclkmsk &= ~(MSKSIU | MSKSSIU);
157 }
158 break;
159 case AIU_CLOCK:
160 cmuclkmsk &= ~MSKAIU;
161 break;
162 case KIU_CLOCK:
163 cmuclkmsk &= ~MSKKIU;
164 break;
165 case FIR_CLOCK:
166 cmuclkmsk &= ~(MSKFIR | MSKFFIR);
167 break;
168 case DSIU_CLOCK:
169 if (current_cpu_data.cputype == CPU_VR4111 ||
170 current_cpu_data.cputype == CPU_VR4121) {
171 cmuclkmsk &= ~MSKDSIU;
172 } else {
173 if (cmuclkmsk & MSKSSIU)
174 cmuclkmsk &= ~MSKDSIU;
175 else
176 cmuclkmsk &= ~(MSKSIU | MSKDSIU);
177 }
178 break;
179 case CSI_CLOCK:
180 cmuclkmsk &= ~(MSKCSI | MSKSCSI);
181 break;
182 case PCIU_CLOCK:
183 cmuclkmsk &= ~MSKPCIU;
184 break;
185 case HSP_CLOCK:
186 cmuclkmsk &= ~MSKSHSP;
187 break;
188 case PCI_CLOCK:
189 cmuclkmsk &= ~MSKPPCIU;
190 break;
191 case CEU_CLOCK:
192 cmuclkmsk2 &= ~MSKCEU;
193 break;
194 case ETHER0_CLOCK:
195 cmuclkmsk2 &= ~MSKMAC0;
196 break;
197 case ETHER1_CLOCK:
198 cmuclkmsk2 &= ~MSKMAC1;
199 break;
200 default:
201 break;
202 }
203
204 if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
205 clock == ETHER1_CLOCK)
206 cmu_write(CMUCLKMSK2, cmuclkmsk2);
207 else
208 cmu_write(CMUCLKMSK, cmuclkmsk);
209
210 spin_unlock_irq(&cmu_lock);
211}
212
213EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
214
215static int __init vr41xx_cmu_init(void)
216{
217 unsigned long start, size;
218
219 switch (current_cpu_data.cputype) {
220 case CPU_VR4111:
221 case CPU_VR4121:
222 start = CMU_TYPE1_BASE;
223 size = CMU_TYPE1_SIZE;
224 break;
225 case CPU_VR4122:
226 case CPU_VR4131:
227 start = CMU_TYPE2_BASE;
228 size = CMU_TYPE2_SIZE;
229 break;
230 case CPU_VR4133:
231 start = CMU_TYPE3_BASE;
232 size = CMU_TYPE3_SIZE;
233 break;
234 default:
235 panic("Unexpected CPU of NEC VR4100 series");
236 break;
237 }
238
239 if (request_mem_region(start, size, "CMU") == NULL)
240 return -EBUSY;
241
242 cmu_base = ioremap(start, size);
243 if (cmu_base == NULL) {
244 release_mem_region(start, size);
245 return -EBUSY;
246 }
247
248 cmuclkmsk = cmu_read(CMUCLKMSK);
249 if (current_cpu_data.cputype == CPU_VR4133)
250 cmuclkmsk2 = cmu_read(CMUCLKMSK2);
251
252 spin_lock_init(&cmu_lock);
253
254 return 0;
255}
256
257core_initcall(vr41xx_cmu_init);
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
new file mode 100644
index 000000000000..9c6b21a79e8f
--- /dev/null
+++ b/arch/mips/vr41xx/common/giu.c
@@ -0,0 +1,455 @@
1/*
2 * giu.c, General-purpose I/O Unit Interrupt routines for NEC VR4100 series.
3 *
4 * Copyright (C) 2002 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6 * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23/*
24 * Changes:
25 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
26 * - New creation, NEC VR4111, VR4121, VR4122 and VR4131 are supported.
27 *
28 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
29 * - Added support for NEC VR4133.
30 * - Removed board_irq_init.
31 */
32#include <linux/errno.h>
33#include <linux/init.h>
34#include <linux/irq.h>
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/smp.h>
38#include <linux/types.h>
39
40#include <asm/cpu.h>
41#include <asm/io.h>
42#include <asm/vr41xx/vr41xx.h>
43
44#define GIUIOSELL_TYPE1 KSEG1ADDR(0x0b000100)
45#define GIUIOSELL_TYPE2 KSEG1ADDR(0x0f000140)
46
47#define GIUIOSELL 0x00
48#define GIUIOSELH 0x02
49#define GIUINTSTATL 0x08
50#define GIUINTSTATH 0x0a
51#define GIUINTENL 0x0c
52#define GIUINTENH 0x0e
53#define GIUINTTYPL 0x10
54#define GIUINTTYPH 0x12
55#define GIUINTALSELL 0x14
56#define GIUINTALSELH 0x16
57#define GIUINTHTSELL 0x18
58#define GIUINTHTSELH 0x1a
59#define GIUFEDGEINHL 0x20
60#define GIUFEDGEINHH 0x22
61#define GIUREDGEINHL 0x24
62#define GIUREDGEINHH 0x26
63
64static uint32_t giu_base;
65
66static struct irqaction giu_cascade = {
67 .handler = no_action,
68 .mask = CPU_MASK_NONE,
69 .name = "cascade",
70};
71
72#define read_giuint(offset) readw(giu_base + (offset))
73#define write_giuint(val, offset) writew((val), giu_base + (offset))
74
75#define GIUINT_HIGH_OFFSET 16
76
77static inline uint16_t set_giuint(uint8_t offset, uint16_t set)
78{
79 uint16_t res;
80
81 res = read_giuint(offset);
82 res |= set;
83 write_giuint(res, offset);
84
85 return res;
86}
87
88static inline uint16_t clear_giuint(uint8_t offset, uint16_t clear)
89{
90 uint16_t res;
91
92 res = read_giuint(offset);
93 res &= ~clear;
94 write_giuint(res, offset);
95
96 return res;
97}
98
99static unsigned int startup_giuint_low_irq(unsigned int irq)
100{
101 unsigned int pin;
102
103 pin = GIU_IRQ_TO_PIN(irq);
104 write_giuint((uint16_t)1 << pin, GIUINTSTATL);
105 set_giuint(GIUINTENL, (uint16_t)1 << pin);
106
107 return 0;
108}
109
110static void shutdown_giuint_low_irq(unsigned int irq)
111{
112 clear_giuint(GIUINTENL, (uint16_t)1 << GIU_IRQ_TO_PIN(irq));
113}
114
115static void enable_giuint_low_irq(unsigned int irq)
116{
117 set_giuint(GIUINTENL, (uint16_t)1 << GIU_IRQ_TO_PIN(irq));
118}
119
120#define disable_giuint_low_irq shutdown_giuint_low_irq
121
122static void ack_giuint_low_irq(unsigned int irq)
123{
124 unsigned int pin;
125
126 pin = GIU_IRQ_TO_PIN(irq);
127 clear_giuint(GIUINTENL, (uint16_t)1 << pin);
128 write_giuint((uint16_t)1 << pin, GIUINTSTATL);
129}
130
131static void end_giuint_low_irq(unsigned int irq)
132{
133 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
134 set_giuint(GIUINTENL, (uint16_t)1 << GIU_IRQ_TO_PIN(irq));
135}
136
137static struct hw_interrupt_type giuint_low_irq_type = {
138 .typename = "GIUINTL",
139 .startup = startup_giuint_low_irq,
140 .shutdown = shutdown_giuint_low_irq,
141 .enable = enable_giuint_low_irq,
142 .disable = disable_giuint_low_irq,
143 .ack = ack_giuint_low_irq,
144 .end = end_giuint_low_irq,
145};
146
147static unsigned int startup_giuint_high_irq(unsigned int irq)
148{
149 unsigned int pin;
150
151 pin = GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET);
152 write_giuint((uint16_t)1 << pin, GIUINTSTATH);
153 set_giuint(GIUINTENH, (uint16_t)1 << pin);
154
155 return 0;
156}
157
158static void shutdown_giuint_high_irq(unsigned int irq)
159{
160 clear_giuint(GIUINTENH, (uint16_t)1 << GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET));
161}
162
163static void enable_giuint_high_irq(unsigned int irq)
164{
165 set_giuint(GIUINTENH, (uint16_t)1 << GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET));
166}
167
168#define disable_giuint_high_irq shutdown_giuint_high_irq
169
170static void ack_giuint_high_irq(unsigned int irq)
171{
172 unsigned int pin;
173
174 pin = GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET);
175 clear_giuint(GIUINTENH, (uint16_t)1 << pin);
176 write_giuint((uint16_t)1 << pin, GIUINTSTATH);
177}
178
179static void end_giuint_high_irq(unsigned int irq)
180{
181 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
182 set_giuint(GIUINTENH, (uint16_t)1 << GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET));
183}
184
185static struct hw_interrupt_type giuint_high_irq_type = {
186 .typename = "GIUINTH",
187 .startup = startup_giuint_high_irq,
188 .shutdown = shutdown_giuint_high_irq,
189 .enable = enable_giuint_high_irq,
190 .disable = disable_giuint_high_irq,
191 .ack = ack_giuint_high_irq,
192 .end = end_giuint_high_irq,
193};
194
195void __init init_vr41xx_giuint_irq(void)
196{
197 int i;
198
199 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
200 if (i < (GIU_IRQ_BASE + GIUINT_HIGH_OFFSET))
201 irq_desc[i].handler = &giuint_low_irq_type;
202 else
203 irq_desc[i].handler = &giuint_high_irq_type;
204 }
205
206 setup_irq(GIUINT_CASCADE_IRQ, &giu_cascade);
207}
208
209void vr41xx_set_irq_trigger(int pin, int trigger, int hold)
210{
211 uint16_t mask;
212
213 if (pin < GIUINT_HIGH_OFFSET) {
214 mask = (uint16_t)1 << pin;
215 if (trigger != TRIGGER_LEVEL) {
216 set_giuint(GIUINTTYPL, mask);
217 if (hold == SIGNAL_HOLD)
218 set_giuint(GIUINTHTSELL, mask);
219 else
220 clear_giuint(GIUINTHTSELL, mask);
221 if (current_cpu_data.cputype == CPU_VR4133) {
222 switch (trigger) {
223 case TRIGGER_EDGE_FALLING:
224 set_giuint(GIUFEDGEINHL, mask);
225 clear_giuint(GIUREDGEINHL, mask);
226 break;
227 case TRIGGER_EDGE_RISING:
228 clear_giuint(GIUFEDGEINHL, mask);
229 set_giuint(GIUREDGEINHL, mask);
230 break;
231 default:
232 set_giuint(GIUFEDGEINHL, mask);
233 set_giuint(GIUREDGEINHL, mask);
234 break;
235 }
236 }
237 } else {
238 clear_giuint(GIUINTTYPL, mask);
239 clear_giuint(GIUINTHTSELL, mask);
240 }
241 write_giuint(mask, GIUINTSTATL);
242 } else {
243 mask = (uint16_t)1 << (pin - GIUINT_HIGH_OFFSET);
244 if (trigger != TRIGGER_LEVEL) {
245 set_giuint(GIUINTTYPH, mask);
246 if (hold == SIGNAL_HOLD)
247 set_giuint(GIUINTHTSELH, mask);
248 else
249 clear_giuint(GIUINTHTSELH, mask);
250 if (current_cpu_data.cputype == CPU_VR4133) {
251 switch (trigger) {
252 case TRIGGER_EDGE_FALLING:
253 set_giuint(GIUFEDGEINHH, mask);
254 clear_giuint(GIUREDGEINHH, mask);
255 break;
256 case TRIGGER_EDGE_RISING:
257 clear_giuint(GIUFEDGEINHH, mask);
258 set_giuint(GIUREDGEINHH, mask);
259 break;
260 default:
261 set_giuint(GIUFEDGEINHH, mask);
262 set_giuint(GIUREDGEINHH, mask);
263 break;
264 }
265 }
266 } else {
267 clear_giuint(GIUINTTYPH, mask);
268 clear_giuint(GIUINTHTSELH, mask);
269 }
270 write_giuint(mask, GIUINTSTATH);
271 }
272}
273
274EXPORT_SYMBOL(vr41xx_set_irq_trigger);
275
276void vr41xx_set_irq_level(int pin, int level)
277{
278 uint16_t mask;
279
280 if (pin < GIUINT_HIGH_OFFSET) {
281 mask = (uint16_t)1 << pin;
282 if (level == LEVEL_HIGH)
283 set_giuint(GIUINTALSELL, mask);
284 else
285 clear_giuint(GIUINTALSELL, mask);
286 write_giuint(mask, GIUINTSTATL);
287 } else {
288 mask = (uint16_t)1 << (pin - GIUINT_HIGH_OFFSET);
289 if (level == LEVEL_HIGH)
290 set_giuint(GIUINTALSELH, mask);
291 else
292 clear_giuint(GIUINTALSELH, mask);
293 write_giuint(mask, GIUINTSTATH);
294 }
295}
296
297EXPORT_SYMBOL(vr41xx_set_irq_level);
298
299#define GIUINT_NR_IRQS 32
300
301enum {
302 GIUINT_NO_CASCADE,
303 GIUINT_CASCADE
304};
305
306struct vr41xx_giuint_cascade {
307 unsigned int flag;
308 int (*get_irq_number)(int irq);
309};
310
311static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS];
312
313static int no_irq_number(int irq)
314{
315 return -EINVAL;
316}
317
318int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq))
319{
320 unsigned int pin;
321 int retval;
322
323 if (irq < GIU_IRQ(0) || irq > GIU_IRQ(31))
324 return -EINVAL;
325
326 if(!get_irq_number)
327 return -EINVAL;
328
329 pin = GIU_IRQ_TO_PIN(irq);
330 giuint_cascade[pin].flag = GIUINT_CASCADE;
331 giuint_cascade[pin].get_irq_number = get_irq_number;
332
333 retval = setup_irq(irq, &giu_cascade);
334 if (retval != 0) {
335 giuint_cascade[pin].flag = GIUINT_NO_CASCADE;
336 giuint_cascade[pin].get_irq_number = no_irq_number;
337 }
338
339 return retval;
340}
341
342EXPORT_SYMBOL(vr41xx_cascade_irq);
343
344static inline int get_irq_pin_number(void)
345{
346 uint16_t pendl, pendh, maskl, maskh;
347 int i;
348
349 pendl = read_giuint(GIUINTSTATL);
350 pendh = read_giuint(GIUINTSTATH);
351 maskl = read_giuint(GIUINTENL);
352 maskh = read_giuint(GIUINTENH);
353
354 maskl &= pendl;
355 maskh &= pendh;
356
357 if (maskl) {
358 for (i = 0; i < 16; i++) {
359 if (maskl & ((uint16_t)1 << i))
360 return i;
361 }
362 } else if (maskh) {
363 for (i = 0; i < 16; i++) {
364 if (maskh & ((uint16_t)1 << i))
365 return i + GIUINT_HIGH_OFFSET;
366 }
367 }
368
369 printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
370 maskl, pendl, maskh, pendh);
371
372 atomic_inc(&irq_err_count);
373
374 return -1;
375}
376
377static inline void ack_giuint_irq(int pin)
378{
379 if (pin < GIUINT_HIGH_OFFSET) {
380 clear_giuint(GIUINTENL, (uint16_t)1 << pin);
381 write_giuint((uint16_t)1 << pin, GIUINTSTATL);
382 } else {
383 pin -= GIUINT_HIGH_OFFSET;
384 clear_giuint(GIUINTENH, (uint16_t)1 << pin);
385 write_giuint((uint16_t)1 << pin, GIUINTSTATH);
386 }
387}
388
389static inline void end_giuint_irq(int pin)
390{
391 if (pin < GIUINT_HIGH_OFFSET)
392 set_giuint(GIUINTENL, (uint16_t)1 << pin);
393 else
394 set_giuint(GIUINTENH, (uint16_t)1 << (pin - GIUINT_HIGH_OFFSET));
395}
396
397void giuint_irq_dispatch(struct pt_regs *regs)
398{
399 struct vr41xx_giuint_cascade *cascade;
400 unsigned int giuint_irq;
401 int pin;
402
403 pin = get_irq_pin_number();
404 if (pin < 0)
405 return;
406
407 disable_irq(GIUINT_CASCADE_IRQ);
408
409 cascade = &giuint_cascade[pin];
410 giuint_irq = GIU_IRQ(pin);
411 if (cascade->flag == GIUINT_CASCADE) {
412 int irq = cascade->get_irq_number(giuint_irq);
413 ack_giuint_irq(pin);
414 if (irq >= 0)
415 do_IRQ(irq, regs);
416 end_giuint_irq(pin);
417 } else {
418 do_IRQ(giuint_irq, regs);
419 }
420
421 enable_irq(GIUINT_CASCADE_IRQ);
422}
423
424static int __init vr41xx_giu_init(void)
425{
426 int i;
427
428 switch (current_cpu_data.cputype) {
429 case CPU_VR4111:
430 case CPU_VR4121:
431 giu_base = GIUIOSELL_TYPE1;
432 break;
433 case CPU_VR4122:
434 case CPU_VR4131:
435 case CPU_VR4133:
436 giu_base = GIUIOSELL_TYPE2;
437 break;
438 default:
439 printk(KERN_ERR "GIU: Unexpected CPU of NEC VR4100 series\n");
440 return -EINVAL;
441 }
442
443 for (i = 0; i < GIUINT_NR_IRQS; i++) {
444 if (i < GIUINT_HIGH_OFFSET)
445 clear_giuint(GIUINTENL, (uint16_t)1 << i);
446 else
447 clear_giuint(GIUINTENH, (uint16_t)1 << (i - GIUINT_HIGH_OFFSET));
448 giuint_cascade[i].flag = GIUINT_NO_CASCADE;
449 giuint_cascade[i].get_irq_number = no_irq_number;
450 }
451
452 return 0;
453}
454
455early_initcall(vr41xx_giu_init);
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
new file mode 100644
index 000000000000..c842661144cb
--- /dev/null
+++ b/arch/mips/vr41xx/common/icu.c
@@ -0,0 +1,757 @@
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 <yyuasa@mvista.com or source@mvista.com>
6 * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23/*
24 * Changes:
25 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
26 * - New creation, NEC VR4122 and VR4131 are supported.
27 * - Added support for NEC VR4111 and VR4121.
28 *
29 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
30 * - Coped with INTASSIGN of NEC VR4133.
31 */
32#include <linux/errno.h>
33#include <linux/init.h>
34#include <linux/interrupt.h>
35#include <linux/irq.h>
36#include <linux/module.h>
37#include <linux/smp.h>
38#include <linux/types.h>
39
40#include <asm/cpu.h>
41#include <asm/io.h>
42#include <asm/irq.h>
43#include <asm/irq_cpu.h>
44#include <asm/vr41xx/vr41xx.h>
45
46extern asmlinkage void vr41xx_handle_interrupt(void);
47
48extern void init_vr41xx_giuint_irq(void);
49extern void giuint_irq_dispatch(struct pt_regs *regs);
50
51static uint32_t icu1_base;
52static uint32_t icu2_base;
53
54static struct irqaction icu_cascade = {
55 .handler = no_action,
56 .mask = CPU_MASK_NONE,
57 .name = "cascade",
58};
59
60static unsigned char sysint1_assign[16] = {
61 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
62static unsigned char sysint2_assign[16] = {
63 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
64
65#define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
66#define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
67
68#define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
69#define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
70
71#define SYSINT1REG 0x00
72#define PIUINTREG 0x02
73#define INTASSIGN0 0x04
74#define INTASSIGN1 0x06
75#define GIUINTLREG 0x08
76#define DSIUINTREG 0x0a
77#define MSYSINT1REG 0x0c
78#define MPIUINTREG 0x0e
79#define MAIUINTREG 0x10
80#define MKIUINTREG 0x12
81#define MGIUINTLREG 0x14
82#define MDSIUINTREG 0x16
83#define NMIREG 0x18
84#define SOFTREG 0x1a
85#define INTASSIGN2 0x1c
86#define INTASSIGN3 0x1e
87
88#define SYSINT2REG 0x00
89#define GIUINTHREG 0x02
90#define FIRINTREG 0x04
91#define MSYSINT2REG 0x06
92#define MGIUINTHREG 0x08
93#define MFIRINTREG 0x0a
94#define PCIINTREG 0x0c
95 #define PCIINT0 0x0001
96#define SCUINTREG 0x0e
97 #define SCUINT0 0x0001
98#define CSIINTREG 0x10
99#define MPCIINTREG 0x12
100#define MSCUINTREG 0x14
101#define MCSIINTREG 0x16
102#define BCUINTREG 0x18
103 #define BCUINTR 0x0001
104#define MBCUINTREG 0x1a
105
106#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
107#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
108
109#define read_icu1(offset) readw(icu1_base + (offset))
110#define write_icu1(val, offset) writew((val), icu1_base + (offset))
111
112#define read_icu2(offset) readw(icu2_base + (offset))
113#define write_icu2(val, offset) writew((val), icu2_base + (offset))
114
115#define INTASSIGN_MAX 4
116#define INTASSIGN_MASK 0x0007
117
118static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
119{
120 uint16_t res;
121
122 res = read_icu1(offset);
123 res |= set;
124 write_icu1(res, offset);
125
126 return res;
127}
128
129static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
130{
131 uint16_t res;
132
133 res = read_icu1(offset);
134 res &= ~clear;
135 write_icu1(res, offset);
136
137 return res;
138}
139
140static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
141{
142 uint16_t res;
143
144 res = read_icu2(offset);
145 res |= set;
146 write_icu2(res, offset);
147
148 return res;
149}
150
151static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
152{
153 uint16_t res;
154
155 res = read_icu2(offset);
156 res &= ~clear;
157 write_icu2(res, offset);
158
159 return res;
160}
161
162/*=======================================================================*/
163
164void vr41xx_enable_piuint(uint16_t mask)
165{
166 irq_desc_t *desc = irq_desc + PIU_IRQ;
167 unsigned long flags;
168
169 if (current_cpu_data.cputype == CPU_VR4111 ||
170 current_cpu_data.cputype == CPU_VR4121) {
171 spin_lock_irqsave(&desc->lock, flags);
172 set_icu1(MPIUINTREG, mask);
173 spin_unlock_irqrestore(&desc->lock, flags);
174 }
175}
176
177EXPORT_SYMBOL(vr41xx_enable_piuint);
178
179void vr41xx_disable_piuint(uint16_t mask)
180{
181 irq_desc_t *desc = irq_desc + PIU_IRQ;
182 unsigned long flags;
183
184 if (current_cpu_data.cputype == CPU_VR4111 ||
185 current_cpu_data.cputype == CPU_VR4121) {
186 spin_lock_irqsave(&desc->lock, flags);
187 clear_icu1(MPIUINTREG, mask);
188 spin_unlock_irqrestore(&desc->lock, flags);
189 }
190}
191
192EXPORT_SYMBOL(vr41xx_disable_piuint);
193
194void vr41xx_enable_aiuint(uint16_t mask)
195{
196 irq_desc_t *desc = irq_desc + AIU_IRQ;
197 unsigned long flags;
198
199 if (current_cpu_data.cputype == CPU_VR4111 ||
200 current_cpu_data.cputype == CPU_VR4121) {
201 spin_lock_irqsave(&desc->lock, flags);
202 set_icu1(MAIUINTREG, mask);
203 spin_unlock_irqrestore(&desc->lock, flags);
204 }
205}
206
207EXPORT_SYMBOL(vr41xx_enable_aiuint);
208
209void vr41xx_disable_aiuint(uint16_t mask)
210{
211 irq_desc_t *desc = irq_desc + AIU_IRQ;
212 unsigned long flags;
213
214 if (current_cpu_data.cputype == CPU_VR4111 ||
215 current_cpu_data.cputype == CPU_VR4121) {
216 spin_lock_irqsave(&desc->lock, flags);
217 clear_icu1(MAIUINTREG, mask);
218 spin_unlock_irqrestore(&desc->lock, flags);
219 }
220}
221
222EXPORT_SYMBOL(vr41xx_disable_aiuint);
223
224void vr41xx_enable_kiuint(uint16_t mask)
225{
226 irq_desc_t *desc = irq_desc + KIU_IRQ;
227 unsigned long flags;
228
229 if (current_cpu_data.cputype == CPU_VR4111 ||
230 current_cpu_data.cputype == CPU_VR4121) {
231 spin_lock_irqsave(&desc->lock, flags);
232 set_icu1(MKIUINTREG, mask);
233 spin_unlock_irqrestore(&desc->lock, flags);
234 }
235}
236
237EXPORT_SYMBOL(vr41xx_enable_kiuint);
238
239void vr41xx_disable_kiuint(uint16_t mask)
240{
241 irq_desc_t *desc = irq_desc + KIU_IRQ;
242 unsigned long flags;
243
244 if (current_cpu_data.cputype == CPU_VR4111 ||
245 current_cpu_data.cputype == CPU_VR4121) {
246 spin_lock_irqsave(&desc->lock, flags);
247 clear_icu1(MKIUINTREG, mask);
248 spin_unlock_irqrestore(&desc->lock, flags);
249 }
250}
251
252EXPORT_SYMBOL(vr41xx_disable_kiuint);
253
254void vr41xx_enable_dsiuint(uint16_t mask)
255{
256 irq_desc_t *desc = irq_desc + DSIU_IRQ;
257 unsigned long flags;
258
259 spin_lock_irqsave(&desc->lock, flags);
260 set_icu1(MDSIUINTREG, mask);
261 spin_unlock_irqrestore(&desc->lock, flags);
262}
263
264EXPORT_SYMBOL(vr41xx_enable_dsiuint);
265
266void vr41xx_disable_dsiuint(uint16_t mask)
267{
268 irq_desc_t *desc = irq_desc + DSIU_IRQ;
269 unsigned long flags;
270
271 spin_lock_irqsave(&desc->lock, flags);
272 clear_icu1(MDSIUINTREG, mask);
273 spin_unlock_irqrestore(&desc->lock, flags);
274}
275
276EXPORT_SYMBOL(vr41xx_disable_dsiuint);
277
278void vr41xx_enable_firint(uint16_t mask)
279{
280 irq_desc_t *desc = irq_desc + FIR_IRQ;
281 unsigned long flags;
282
283 spin_lock_irqsave(&desc->lock, flags);
284 set_icu2(MFIRINTREG, mask);
285 spin_unlock_irqrestore(&desc->lock, flags);
286}
287
288EXPORT_SYMBOL(vr41xx_enable_firint);
289
290void vr41xx_disable_firint(uint16_t mask)
291{
292 irq_desc_t *desc = irq_desc + FIR_IRQ;
293 unsigned long flags;
294
295 spin_lock_irqsave(&desc->lock, flags);
296 clear_icu2(MFIRINTREG, mask);
297 spin_unlock_irqrestore(&desc->lock, flags);
298}
299
300EXPORT_SYMBOL(vr41xx_disable_firint);
301
302void vr41xx_enable_pciint(void)
303{
304 irq_desc_t *desc = irq_desc + PCI_IRQ;
305 unsigned long flags;
306
307 if (current_cpu_data.cputype == CPU_VR4122 ||
308 current_cpu_data.cputype == CPU_VR4131 ||
309 current_cpu_data.cputype == CPU_VR4133) {
310 spin_lock_irqsave(&desc->lock, flags);
311 write_icu2(PCIINT0, MPCIINTREG);
312 spin_unlock_irqrestore(&desc->lock, flags);
313 }
314}
315
316EXPORT_SYMBOL(vr41xx_enable_pciint);
317
318void vr41xx_disable_pciint(void)
319{
320 irq_desc_t *desc = irq_desc + PCI_IRQ;
321 unsigned long flags;
322
323 if (current_cpu_data.cputype == CPU_VR4122 ||
324 current_cpu_data.cputype == CPU_VR4131 ||
325 current_cpu_data.cputype == CPU_VR4133) {
326 spin_lock_irqsave(&desc->lock, flags);
327 write_icu2(0, MPCIINTREG);
328 spin_unlock_irqrestore(&desc->lock, flags);
329 }
330}
331
332EXPORT_SYMBOL(vr41xx_disable_pciint);
333
334void vr41xx_enable_scuint(void)
335{
336 irq_desc_t *desc = irq_desc + SCU_IRQ;
337 unsigned long flags;
338
339 if (current_cpu_data.cputype == CPU_VR4122 ||
340 current_cpu_data.cputype == CPU_VR4131 ||
341 current_cpu_data.cputype == CPU_VR4133) {
342 spin_lock_irqsave(&desc->lock, flags);
343 write_icu2(SCUINT0, MSCUINTREG);
344 spin_unlock_irqrestore(&desc->lock, flags);
345 }
346}
347
348EXPORT_SYMBOL(vr41xx_enable_scuint);
349
350void vr41xx_disable_scuint(void)
351{
352 irq_desc_t *desc = irq_desc + SCU_IRQ;
353 unsigned long flags;
354
355 if (current_cpu_data.cputype == CPU_VR4122 ||
356 current_cpu_data.cputype == CPU_VR4131 ||
357 current_cpu_data.cputype == CPU_VR4133) {
358 spin_lock_irqsave(&desc->lock, flags);
359 write_icu2(0, MSCUINTREG);
360 spin_unlock_irqrestore(&desc->lock, flags);
361 }
362}
363
364EXPORT_SYMBOL(vr41xx_disable_scuint);
365
366void vr41xx_enable_csiint(uint16_t mask)
367{
368 irq_desc_t *desc = irq_desc + CSI_IRQ;
369 unsigned long flags;
370
371 if (current_cpu_data.cputype == CPU_VR4122 ||
372 current_cpu_data.cputype == CPU_VR4131 ||
373 current_cpu_data.cputype == CPU_VR4133) {
374 spin_lock_irqsave(&desc->lock, flags);
375 set_icu2(MCSIINTREG, mask);
376 spin_unlock_irqrestore(&desc->lock, flags);
377 }
378}
379
380EXPORT_SYMBOL(vr41xx_enable_csiint);
381
382void vr41xx_disable_csiint(uint16_t mask)
383{
384 irq_desc_t *desc = irq_desc + CSI_IRQ;
385 unsigned long flags;
386
387 if (current_cpu_data.cputype == CPU_VR4122 ||
388 current_cpu_data.cputype == CPU_VR4131 ||
389 current_cpu_data.cputype == CPU_VR4133) {
390 spin_lock_irqsave(&desc->lock, flags);
391 clear_icu2(MCSIINTREG, mask);
392 spin_unlock_irqrestore(&desc->lock, flags);
393 }
394}
395
396EXPORT_SYMBOL(vr41xx_disable_csiint);
397
398void vr41xx_enable_bcuint(void)
399{
400 irq_desc_t *desc = irq_desc + BCU_IRQ;
401 unsigned long flags;
402
403 if (current_cpu_data.cputype == CPU_VR4122 ||
404 current_cpu_data.cputype == CPU_VR4131 ||
405 current_cpu_data.cputype == CPU_VR4133) {
406 spin_lock_irqsave(&desc->lock, flags);
407 write_icu2(BCUINTR, MBCUINTREG);
408 spin_unlock_irqrestore(&desc->lock, flags);
409 }
410}
411
412EXPORT_SYMBOL(vr41xx_enable_bcuint);
413
414void vr41xx_disable_bcuint(void)
415{
416 irq_desc_t *desc = irq_desc + BCU_IRQ;
417 unsigned long flags;
418
419 if (current_cpu_data.cputype == CPU_VR4122 ||
420 current_cpu_data.cputype == CPU_VR4131 ||
421 current_cpu_data.cputype == CPU_VR4133) {
422 spin_lock_irqsave(&desc->lock, flags);
423 write_icu2(0, MBCUINTREG);
424 spin_unlock_irqrestore(&desc->lock, flags);
425 }
426}
427
428EXPORT_SYMBOL(vr41xx_disable_bcuint);
429
430/*=======================================================================*/
431
432static unsigned int startup_sysint1_irq(unsigned int irq)
433{
434 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
435
436 return 0; /* never anything pending */
437}
438
439static void shutdown_sysint1_irq(unsigned int irq)
440{
441 clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
442}
443
444static void enable_sysint1_irq(unsigned int irq)
445{
446 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
447}
448
449#define disable_sysint1_irq shutdown_sysint1_irq
450#define ack_sysint1_irq shutdown_sysint1_irq
451
452static void end_sysint1_irq(unsigned int irq)
453{
454 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
455 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
456}
457
458static struct hw_interrupt_type sysint1_irq_type = {
459 .typename = "SYSINT1",
460 .startup = startup_sysint1_irq,
461 .shutdown = shutdown_sysint1_irq,
462 .enable = enable_sysint1_irq,
463 .disable = disable_sysint1_irq,
464 .ack = ack_sysint1_irq,
465 .end = end_sysint1_irq,
466};
467
468/*=======================================================================*/
469
470static unsigned int startup_sysint2_irq(unsigned int irq)
471{
472 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
473
474 return 0; /* never anything pending */
475}
476
477static void shutdown_sysint2_irq(unsigned int irq)
478{
479 clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
480}
481
482static void enable_sysint2_irq(unsigned int irq)
483{
484 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
485}
486
487#define disable_sysint2_irq shutdown_sysint2_irq
488#define ack_sysint2_irq shutdown_sysint2_irq
489
490static void end_sysint2_irq(unsigned int irq)
491{
492 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
493 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
494}
495
496static struct hw_interrupt_type sysint2_irq_type = {
497 .typename = "SYSINT2",
498 .startup = startup_sysint2_irq,
499 .shutdown = shutdown_sysint2_irq,
500 .enable = enable_sysint2_irq,
501 .disable = disable_sysint2_irq,
502 .ack = ack_sysint2_irq,
503 .end = end_sysint2_irq,
504};
505
506/*=======================================================================*/
507
508static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
509{
510 irq_desc_t *desc = irq_desc + irq;
511 uint16_t intassign0, intassign1;
512 unsigned int pin;
513
514 pin = SYSINT1_IRQ_TO_PIN(irq);
515
516 spin_lock_irq(&desc->lock);
517
518 intassign0 = read_icu1(INTASSIGN0);
519 intassign1 = read_icu1(INTASSIGN1);
520
521 switch (pin) {
522 case 0:
523 intassign0 &= ~INTASSIGN_MASK;
524 intassign0 |= (uint16_t)assign;
525 break;
526 case 1:
527 intassign0 &= ~(INTASSIGN_MASK << 3);
528 intassign0 |= (uint16_t)assign << 3;
529 break;
530 case 2:
531 intassign0 &= ~(INTASSIGN_MASK << 6);
532 intassign0 |= (uint16_t)assign << 6;
533 break;
534 case 3:
535 intassign0 &= ~(INTASSIGN_MASK << 9);
536 intassign0 |= (uint16_t)assign << 9;
537 break;
538 case 8:
539 intassign0 &= ~(INTASSIGN_MASK << 12);
540 intassign0 |= (uint16_t)assign << 12;
541 break;
542 case 9:
543 intassign1 &= ~INTASSIGN_MASK;
544 intassign1 |= (uint16_t)assign;
545 break;
546 case 11:
547 intassign1 &= ~(INTASSIGN_MASK << 6);
548 intassign1 |= (uint16_t)assign << 6;
549 break;
550 case 12:
551 intassign1 &= ~(INTASSIGN_MASK << 9);
552 intassign1 |= (uint16_t)assign << 9;
553 break;
554 default:
555 return -EINVAL;
556 }
557
558 sysint1_assign[pin] = assign;
559 write_icu1(intassign0, INTASSIGN0);
560 write_icu1(intassign1, INTASSIGN1);
561
562 spin_unlock_irq(&desc->lock);
563
564 return 0;
565}
566
567static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
568{
569 irq_desc_t *desc = irq_desc + irq;
570 uint16_t intassign2, intassign3;
571 unsigned int pin;
572
573 pin = SYSINT2_IRQ_TO_PIN(irq);
574
575 spin_lock_irq(&desc->lock);
576
577 intassign2 = read_icu1(INTASSIGN2);
578 intassign3 = read_icu1(INTASSIGN3);
579
580 switch (pin) {
581 case 0:
582 intassign2 &= ~INTASSIGN_MASK;
583 intassign2 |= (uint16_t)assign;
584 break;
585 case 1:
586 intassign2 &= ~(INTASSIGN_MASK << 3);
587 intassign2 |= (uint16_t)assign << 3;
588 break;
589 case 3:
590 intassign2 &= ~(INTASSIGN_MASK << 6);
591 intassign2 |= (uint16_t)assign << 6;
592 break;
593 case 4:
594 intassign2 &= ~(INTASSIGN_MASK << 9);
595 intassign2 |= (uint16_t)assign << 9;
596 break;
597 case 5:
598 intassign2 &= ~(INTASSIGN_MASK << 12);
599 intassign2 |= (uint16_t)assign << 12;
600 break;
601 case 6:
602 intassign3 &= ~INTASSIGN_MASK;
603 intassign3 |= (uint16_t)assign;
604 break;
605 case 7:
606 intassign3 &= ~(INTASSIGN_MASK << 3);
607 intassign3 |= (uint16_t)assign << 3;
608 break;
609 case 8:
610 intassign3 &= ~(INTASSIGN_MASK << 6);
611 intassign3 |= (uint16_t)assign << 6;
612 break;
613 case 9:
614 intassign3 &= ~(INTASSIGN_MASK << 9);
615 intassign3 |= (uint16_t)assign << 9;
616 break;
617 case 10:
618 intassign3 &= ~(INTASSIGN_MASK << 12);
619 intassign3 |= (uint16_t)assign << 12;
620 break;
621 default:
622 return -EINVAL;
623 }
624
625 sysint2_assign[pin] = assign;
626 write_icu1(intassign2, INTASSIGN2);
627 write_icu1(intassign3, INTASSIGN3);
628
629 spin_unlock_irq(&desc->lock);
630
631 return 0;
632}
633
634int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
635{
636 int retval = -EINVAL;
637
638 if (current_cpu_data.cputype != CPU_VR4133)
639 return -EINVAL;
640
641 if (intassign > INTASSIGN_MAX)
642 return -EINVAL;
643
644 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
645 retval = set_sysint1_assign(irq, intassign);
646 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
647 retval = set_sysint2_assign(irq, intassign);
648
649 return retval;
650}
651
652EXPORT_SYMBOL(vr41xx_set_intassign);
653
654/*=======================================================================*/
655
656asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
657{
658 uint16_t pend1, pend2;
659 uint16_t mask1, mask2;
660 int i;
661
662 pend1 = read_icu1(SYSINT1REG);
663 mask1 = read_icu1(MSYSINT1REG);
664
665 pend2 = read_icu2(SYSINT2REG);
666 mask2 = read_icu2(MSYSINT2REG);
667
668 mask1 &= pend1;
669 mask2 &= pend2;
670
671 if (mask1) {
672 for (i = 0; i < 16; i++) {
673 if (intnum == sysint1_assign[i] &&
674 (mask1 & ((uint16_t)1 << i))) {
675 if (i == 8)
676 giuint_irq_dispatch(regs);
677 else
678 do_IRQ(SYSINT1_IRQ(i), regs);
679 return;
680 }
681 }
682 }
683
684 if (mask2) {
685 for (i = 0; i < 16; i++) {
686 if (intnum == sysint2_assign[i] &&
687 (mask2 & ((uint16_t)1 << i))) {
688 do_IRQ(SYSINT2_IRQ(i), regs);
689 return;
690 }
691 }
692 }
693
694 printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
695
696 atomic_inc(&irq_err_count);
697}
698
699/*=======================================================================*/
700
701static int __init vr41xx_icu_init(void)
702{
703 switch (current_cpu_data.cputype) {
704 case CPU_VR4111:
705 case CPU_VR4121:
706 icu1_base = SYSINT1REG_TYPE1;
707 icu2_base = SYSINT2REG_TYPE1;
708 break;
709 case CPU_VR4122:
710 case CPU_VR4131:
711 case CPU_VR4133:
712 icu1_base = SYSINT1REG_TYPE2;
713 icu2_base = SYSINT2REG_TYPE2;
714 break;
715 default:
716 printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n");
717 return -EINVAL;
718 }
719
720 write_icu1(0, MSYSINT1REG);
721 write_icu1(0xffff, MGIUINTLREG);
722
723 write_icu2(0, MSYSINT2REG);
724 write_icu2(0xffff, MGIUINTHREG);
725
726 return 0;
727}
728
729early_initcall(vr41xx_icu_init);
730
731/*=======================================================================*/
732
733static inline void init_vr41xx_icu_irq(void)
734{
735 int i;
736
737 for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
738 irq_desc[i].handler = &sysint1_irq_type;
739
740 for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
741 irq_desc[i].handler = &sysint2_irq_type;
742
743 setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
744 setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
745 setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
746 setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
747 setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
748}
749
750void __init arch_init_irq(void)
751{
752 mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
753 init_vr41xx_icu_irq();
754 init_vr41xx_giuint_irq();
755
756 set_except_vector(0, vr41xx_handle_interrupt);
757}
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
new file mode 100644
index 000000000000..e03be896cbc4
--- /dev/null
+++ b/arch/mips/vr41xx/common/init.c
@@ -0,0 +1,85 @@
1/*
2 * init.c, Common initialization routines for NEC VR4100 series.
3 *
4 * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/init.h>
21#include <linux/ioport.h>
22#include <linux/irq.h>
23#include <linux/string.h>
24
25#include <asm/bootinfo.h>
26#include <asm/time.h>
27#include <asm/vr41xx/vr41xx.h>
28
29#define IO_MEM_RESOURCE_START 0UL
30#define IO_MEM_RESOURCE_END 0x1fffffffUL
31
32static void __init iomem_resource_init(void)
33{
34 iomem_resource.start = IO_MEM_RESOURCE_START;
35 iomem_resource.end = IO_MEM_RESOURCE_END;
36}
37
38static void __init setup_timer_frequency(void)
39{
40 unsigned long tclock;
41
42 tclock = vr41xx_get_tclock_frequency();
43 if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 ||
44 current_cpu_data.processor_id == PRID_VR4131_REV2_1)
45 mips_hpt_frequency = tclock / 2;
46 else
47 mips_hpt_frequency = tclock / 4;
48}
49
50static void __init setup_timer_irq(struct irqaction *irq)
51{
52 setup_irq(TIMER_IRQ, irq);
53}
54
55static void __init timer_init(void)
56{
57 board_time_init = setup_timer_frequency;
58 board_timer_setup = setup_timer_irq;
59}
60
61void __init prom_init(void)
62{
63 int argc, i;
64 char **argv;
65
66 argc = fw_arg0;
67 argv = (char **)fw_arg1;
68
69 for (i = 1; i < argc; i++) {
70 strcat(arcs_cmdline, argv[i]);
71 if (i < (argc - 1))
72 strcat(arcs_cmdline, " ");
73 }
74
75 vr41xx_calculate_clock_frequency();
76
77 timer_init();
78
79 iomem_resource_init();
80}
81
82unsigned long __init prom_free_prom_memory (void)
83{
84 return 0UL;
85}
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
new file mode 100644
index 000000000000..38ff89b505f2
--- /dev/null
+++ b/arch/mips/vr41xx/common/int-handler.S
@@ -0,0 +1,114 @@
1/*
2 * FILE NAME
3 * arch/mips/vr41xx/common/int-handler.S
4 *
5 * BRIEF MODULE DESCRIPTION
6 * Interrupt dispatcher for the NEC VR4100 series.
7 *
8 * Author: Yoichi Yuasa
9 * yyuasa@mvista.com or source@mvista.com
10 *
11 * Copyright 2001 MontaVista Software Inc.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33/*
34 * Changes:
35 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
36 * - New creation, NEC VR4100 series are supported.
37 *
38 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
39 * - Coped with INTASSIGN of NEC VR4133.
40 */
41#include <asm/asm.h>
42#include <asm/regdef.h>
43#include <asm/mipsregs.h>
44#include <asm/stackframe.h>
45
46 .text
47 .set noreorder
48
49 .align 5
50 NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
51 .set noat
52 SAVE_ALL
53 CLI
54 .set at
55 .set noreorder
56
57 /*
58 * Get the pending interrupts
59 */
60 mfc0 t0, CP0_CAUSE
61 mfc0 t1, CP0_STATUS
62 andi t0, 0xff00
63 and t0, t0, t1
64
65 andi t1, t0, CAUSEF_IP7 # MIPS timer interrupt
66 bnez t1, handle_irq
67 li a0, 7
68
69 andi t1, t0, 0x7800 # check for Int1-4
70 beqz t1, 1f
71
72 andi t1, t0, CAUSEF_IP3 # check for Int1
73 bnez t1, handle_int
74 li a0, 1
75
76 andi t1, t0, CAUSEF_IP4 # check for Int2
77 bnez t1, handle_int
78 li a0, 2
79
80 andi t1, t0, CAUSEF_IP5 # check for Int3
81 bnez t1, handle_int
82 li a0, 3
83
84 andi t1, t0, CAUSEF_IP6 # check for Int4
85 bnez t1, handle_int
86 li a0, 4
87
881:
89 andi t1, t0, CAUSEF_IP2 # check for Int0
90 bnez t1, handle_int
91 li a0, 0
92
93 andi t1, t0, CAUSEF_IP0 # check for IP0
94 bnez t1, handle_irq
95 li a0, 0
96
97 andi t1, t0, CAUSEF_IP1 # check for IP1
98 bnez t1, handle_irq
99 li a0, 1
100
101 j spurious_interrupt
102 nop
103
104handle_int:
105 jal irq_dispatch
106 move a1, sp
107 j ret_from_irq
108 nop
109
110handle_irq:
111 jal do_IRQ
112 move a1, sp
113 j ret_from_irq
114 END(vr41xx_handle_interrupt)
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
new file mode 100644
index 000000000000..c5f1043de938
--- /dev/null
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -0,0 +1,81 @@
1/*
2 * pmu.c, Power Management Unit routines for NEC VR4100 series.
3 *
4 * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/init.h>
21#include <linux/kernel.h>
22#include <linux/smp.h>
23#include <linux/types.h>
24
25#include <asm/cpu.h>
26#include <asm/io.h>
27#include <asm/reboot.h>
28#include <asm/system.h>
29
30#define PMUCNT2REG KSEG1ADDR(0x0f0000c6)
31 #define SOFTRST 0x0010
32
33static inline void software_reset(void)
34{
35 uint16_t val;
36
37 switch (current_cpu_data.cputype) {
38 case CPU_VR4122:
39 case CPU_VR4131:
40 case CPU_VR4133:
41 val = readw(PMUCNT2REG);
42 val |= SOFTRST;
43 writew(val, PMUCNT2REG);
44 break;
45 default:
46 break;
47 }
48}
49
50static void vr41xx_restart(char *command)
51{
52 local_irq_disable();
53 software_reset();
54 printk(KERN_NOTICE "\nYou can reset your system\n");
55 while (1) ;
56}
57
58static void vr41xx_halt(void)
59{
60 local_irq_disable();
61 printk(KERN_NOTICE "\nYou can turn off the power supply\n");
62 while (1) ;
63}
64
65static void vr41xx_power_off(void)
66{
67 local_irq_disable();
68 printk(KERN_NOTICE "\nYou can turn off the power supply\n");
69 while (1) ;
70}
71
72static int __init vr41xx_pmu_init(void)
73{
74 _machine_restart = vr41xx_restart;
75 _machine_halt = vr41xx_halt;
76 _machine_power_off = vr41xx_power_off;
77
78 return 0;
79}
80
81early_initcall(vr41xx_pmu_init);
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
new file mode 100644
index 000000000000..5475dd72e264
--- /dev/null
+++ b/arch/mips/vr41xx/common/vrc4173.c
@@ -0,0 +1,581 @@
1/*
2 * vrc4173.c, NEC VRC4173 base driver for NEC VR4122/VR4131.
3 *
4 * Copyright (C) 2001-2003 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
6 * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/interrupt.h>
26#include <linux/irq.h>
27#include <linux/pci.h>
28#include <linux/spinlock.h>
29#include <linux/types.h>
30
31#include <asm/vr41xx/vr41xx.h>
32#include <asm/vr41xx/vrc4173.h>
33
34MODULE_DESCRIPTION("NEC VRC4173 base driver for NEC VR4122/4131");
35MODULE_AUTHOR("Yoichi Yuasa <yyuasa@mvista.com>");
36MODULE_LICENSE("GPL");
37
38#define VRC4173_CMUCLKMSK 0x040
39 #define MSKPIU 0x0001
40 #define MSKKIU 0x0002
41 #define MSKAIU 0x0004
42 #define MSKPS2CH1 0x0008
43 #define MSKPS2CH2 0x0010
44 #define MSKUSB 0x0020
45 #define MSKCARD1 0x0040
46 #define MSKCARD2 0x0080
47 #define MSKAC97 0x0100
48 #define MSK48MUSB 0x0400
49 #define MSK48MPIN 0x0800
50 #define MSK48MOSC 0x1000
51#define VRC4173_CMUSRST 0x042
52 #define USBRST 0x0001
53 #define CARD1RST 0x0002
54 #define CARD2RST 0x0004
55 #define AC97RST 0x0008
56
57#define VRC4173_SYSINT1REG 0x060
58#define VRC4173_MSYSINT1REG 0x06c
59#define VRC4173_MPIUINTREG 0x06e
60#define VRC4173_MAIUINTREG 0x070
61#define VRC4173_MKIUINTREG 0x072
62
63#define VRC4173_SELECTREG 0x09e
64 #define SEL3 0x0008
65 #define SEL2 0x0004
66 #define SEL1 0x0002
67 #define SEL0 0x0001
68
69static struct pci_device_id vrc4173_id_table[] __devinitdata = {
70 { .vendor = PCI_VENDOR_ID_NEC,
71 .device = PCI_DEVICE_ID_NEC_VRC4173,
72 .subvendor = PCI_ANY_ID,
73 .subdevice = PCI_ANY_ID, },
74 { .vendor = 0, },
75};
76
77unsigned long vrc4173_io_offset = 0;
78
79EXPORT_SYMBOL(vrc4173_io_offset);
80
81static int vrc4173_initialized;
82static uint16_t vrc4173_cmuclkmsk;
83static uint16_t vrc4173_selectreg;
84static spinlock_t vrc4173_cmu_lock;
85static spinlock_t vrc4173_giu_lock;
86
87static inline void set_cmusrst(uint16_t val)
88{
89 uint16_t cmusrst;
90
91 cmusrst = vrc4173_inw(VRC4173_CMUSRST);
92 cmusrst |= val;
93 vrc4173_outw(cmusrst, VRC4173_CMUSRST);
94}
95
96static inline void clear_cmusrst(uint16_t val)
97{
98 uint16_t cmusrst;
99
100 cmusrst = vrc4173_inw(VRC4173_CMUSRST);
101 cmusrst &= ~val;
102 vrc4173_outw(cmusrst, VRC4173_CMUSRST);
103}
104
105void vrc4173_supply_clock(vrc4173_clock_t clock)
106{
107 if (vrc4173_initialized) {
108 spin_lock_irq(&vrc4173_cmu_lock);
109
110 switch (clock) {
111 case VRC4173_PIU_CLOCK:
112 vrc4173_cmuclkmsk |= MSKPIU;
113 break;
114 case VRC4173_KIU_CLOCK:
115 vrc4173_cmuclkmsk |= MSKKIU;
116 break;
117 case VRC4173_AIU_CLOCK:
118 vrc4173_cmuclkmsk |= MSKAIU;
119 break;
120 case VRC4173_PS2_CH1_CLOCK:
121 vrc4173_cmuclkmsk |= MSKPS2CH1;
122 break;
123 case VRC4173_PS2_CH2_CLOCK:
124 vrc4173_cmuclkmsk |= MSKPS2CH2;
125 break;
126 case VRC4173_USBU_PCI_CLOCK:
127 set_cmusrst(USBRST);
128 vrc4173_cmuclkmsk |= MSKUSB;
129 break;
130 case VRC4173_CARDU1_PCI_CLOCK:
131 set_cmusrst(CARD1RST);
132 vrc4173_cmuclkmsk |= MSKCARD1;
133 break;
134 case VRC4173_CARDU2_PCI_CLOCK:
135 set_cmusrst(CARD2RST);
136 vrc4173_cmuclkmsk |= MSKCARD2;
137 break;
138 case VRC4173_AC97U_PCI_CLOCK:
139 set_cmusrst(AC97RST);
140 vrc4173_cmuclkmsk |= MSKAC97;
141 break;
142 case VRC4173_USBU_48MHz_CLOCK:
143 set_cmusrst(USBRST);
144 vrc4173_cmuclkmsk |= MSK48MUSB;
145 break;
146 case VRC4173_EXT_48MHz_CLOCK:
147 if (vrc4173_cmuclkmsk & MSK48MOSC)
148 vrc4173_cmuclkmsk |= MSK48MPIN;
149 else
150 printk(KERN_WARNING
151 "vrc4173_supply_clock: "
152 "Please supply VRC4173_48MHz_CLOCK first "
153 "rather than VRC4173_EXT_48MHz_CLOCK.\n");
154 break;
155 case VRC4173_48MHz_CLOCK:
156 vrc4173_cmuclkmsk |= MSK48MOSC;
157 break;
158 default:
159 printk(KERN_WARNING
160 "vrc4173_supply_clock: Invalid CLOCK value %u\n", clock);
161 break;
162 }
163
164 vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK);
165
166 switch (clock) {
167 case VRC4173_USBU_PCI_CLOCK:
168 case VRC4173_USBU_48MHz_CLOCK:
169 clear_cmusrst(USBRST);
170 break;
171 case VRC4173_CARDU1_PCI_CLOCK:
172 clear_cmusrst(CARD1RST);
173 break;
174 case VRC4173_CARDU2_PCI_CLOCK:
175 clear_cmusrst(CARD2RST);
176 break;
177 case VRC4173_AC97U_PCI_CLOCK:
178 clear_cmusrst(AC97RST);
179 break;
180 default:
181 break;
182 }
183
184 spin_unlock_irq(&vrc4173_cmu_lock);
185 }
186}
187
188EXPORT_SYMBOL(vrc4173_supply_clock);
189
190void vrc4173_mask_clock(vrc4173_clock_t clock)
191{
192 if (vrc4173_initialized) {
193 spin_lock_irq(&vrc4173_cmu_lock);
194
195 switch (clock) {
196 case VRC4173_PIU_CLOCK:
197 vrc4173_cmuclkmsk &= ~MSKPIU;
198 break;
199 case VRC4173_KIU_CLOCK:
200 vrc4173_cmuclkmsk &= ~MSKKIU;
201 break;
202 case VRC4173_AIU_CLOCK:
203 vrc4173_cmuclkmsk &= ~MSKAIU;
204 break;
205 case VRC4173_PS2_CH1_CLOCK:
206 vrc4173_cmuclkmsk &= ~MSKPS2CH1;
207 break;
208 case VRC4173_PS2_CH2_CLOCK:
209 vrc4173_cmuclkmsk &= ~MSKPS2CH2;
210 break;
211 case VRC4173_USBU_PCI_CLOCK:
212 set_cmusrst(USBRST);
213 vrc4173_cmuclkmsk &= ~MSKUSB;
214 break;
215 case VRC4173_CARDU1_PCI_CLOCK:
216 set_cmusrst(CARD1RST);
217 vrc4173_cmuclkmsk &= ~MSKCARD1;
218 break;
219 case VRC4173_CARDU2_PCI_CLOCK:
220 set_cmusrst(CARD2RST);
221 vrc4173_cmuclkmsk &= ~MSKCARD2;
222 break;
223 case VRC4173_AC97U_PCI_CLOCK:
224 set_cmusrst(AC97RST);
225 vrc4173_cmuclkmsk &= ~MSKAC97;
226 break;
227 case VRC4173_USBU_48MHz_CLOCK:
228 set_cmusrst(USBRST);
229 vrc4173_cmuclkmsk &= ~MSK48MUSB;
230 break;
231 case VRC4173_EXT_48MHz_CLOCK:
232 vrc4173_cmuclkmsk &= ~MSK48MPIN;
233 break;
234 case VRC4173_48MHz_CLOCK:
235 vrc4173_cmuclkmsk &= ~MSK48MOSC;
236 break;
237 default:
238 printk(KERN_WARNING "vrc4173_mask_clock: Invalid CLOCK value %u\n", clock);
239 break;
240 }
241
242 vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK);
243
244 switch (clock) {
245 case VRC4173_USBU_PCI_CLOCK:
246 case VRC4173_USBU_48MHz_CLOCK:
247 clear_cmusrst(USBRST);
248 break;
249 case VRC4173_CARDU1_PCI_CLOCK:
250 clear_cmusrst(CARD1RST);
251 break;
252 case VRC4173_CARDU2_PCI_CLOCK:
253 clear_cmusrst(CARD2RST);
254 break;
255 case VRC4173_AC97U_PCI_CLOCK:
256 clear_cmusrst(AC97RST);
257 break;
258 default:
259 break;
260 }
261
262 spin_unlock_irq(&vrc4173_cmu_lock);
263 }
264}
265
266EXPORT_SYMBOL(vrc4173_mask_clock);
267
268static inline void vrc4173_cmu_init(void)
269{
270 vrc4173_cmuclkmsk = vrc4173_inw(VRC4173_CMUCLKMSK);
271
272 spin_lock_init(&vrc4173_cmu_lock);
273}
274
275void vrc4173_select_function(vrc4173_function_t function)
276{
277 if (vrc4173_initialized) {
278 spin_lock_irq(&vrc4173_giu_lock);
279
280 switch(function) {
281 case PS2_CHANNEL1:
282 vrc4173_selectreg |= SEL2;
283 break;
284 case PS2_CHANNEL2:
285 vrc4173_selectreg |= SEL1;
286 break;
287 case TOUCHPANEL:
288 vrc4173_selectreg &= SEL2 | SEL1 | SEL0;
289 break;
290 case KEYBOARD_8SCANLINES:
291 vrc4173_selectreg &= SEL3 | SEL2 | SEL1;
292 break;
293 case KEYBOARD_10SCANLINES:
294 vrc4173_selectreg &= SEL3 | SEL2;
295 break;
296 case KEYBOARD_12SCANLINES:
297 vrc4173_selectreg &= SEL3;
298 break;
299 case GPIO_0_15PINS:
300 vrc4173_selectreg |= SEL0;
301 break;
302 case GPIO_16_20PINS:
303 vrc4173_selectreg |= SEL3;
304 break;
305 }
306
307 vrc4173_outw(vrc4173_selectreg, VRC4173_SELECTREG);
308
309 spin_unlock_irq(&vrc4173_giu_lock);
310 }
311}
312
313EXPORT_SYMBOL(vrc4173_select_function);
314
315static inline void vrc4173_giu_init(void)
316{
317 vrc4173_selectreg = vrc4173_inw(VRC4173_SELECTREG);
318
319 spin_lock_init(&vrc4173_giu_lock);
320}
321
322void vrc4173_enable_piuint(uint16_t mask)
323{
324 irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
325 unsigned long flags;
326 uint16_t val;
327
328 spin_lock_irqsave(&desc->lock, flags);
329 val = vrc4173_inw(VRC4173_MPIUINTREG);
330 val |= mask;
331 vrc4173_outw(val, VRC4173_MPIUINTREG);
332 spin_unlock_irqrestore(&desc->lock, flags);
333}
334
335EXPORT_SYMBOL(vrc4173_enable_piuint);
336
337void vrc4173_disable_piuint(uint16_t mask)
338{
339 irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
340 unsigned long flags;
341 uint16_t val;
342
343 spin_lock_irqsave(&desc->lock, flags);
344 val = vrc4173_inw(VRC4173_MPIUINTREG);
345 val &= ~mask;
346 vrc4173_outw(val, VRC4173_MPIUINTREG);
347 spin_unlock_irqrestore(&desc->lock, flags);
348}
349
350EXPORT_SYMBOL(vrc4173_disable_piuint);
351
352void vrc4173_enable_aiuint(uint16_t mask)
353{
354 irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
355 unsigned long flags;
356 uint16_t val;
357
358 spin_lock_irqsave(&desc->lock, flags);
359 val = vrc4173_inw(VRC4173_MAIUINTREG);
360 val |= mask;
361 vrc4173_outw(val, VRC4173_MAIUINTREG);
362 spin_unlock_irqrestore(&desc->lock, flags);
363}
364
365EXPORT_SYMBOL(vrc4173_enable_aiuint);
366
367void vrc4173_disable_aiuint(uint16_t mask)
368{
369 irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
370 unsigned long flags;
371 uint16_t val;
372
373 spin_lock_irqsave(&desc->lock, flags);
374 val = vrc4173_inw(VRC4173_MAIUINTREG);
375 val &= ~mask;
376 vrc4173_outw(val, VRC4173_MAIUINTREG);
377 spin_unlock_irqrestore(&desc->lock, flags);
378}
379
380EXPORT_SYMBOL(vrc4173_disable_aiuint);
381
382void vrc4173_enable_kiuint(uint16_t mask)
383{
384 irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
385 unsigned long flags;
386 uint16_t val;
387
388 spin_lock_irqsave(&desc->lock, flags);
389 val = vrc4173_inw(VRC4173_MKIUINTREG);
390 val |= mask;
391 vrc4173_outw(val, VRC4173_MKIUINTREG);
392 spin_unlock_irqrestore(&desc->lock, flags);
393}
394
395EXPORT_SYMBOL(vrc4173_enable_kiuint);
396
397void vrc4173_disable_kiuint(uint16_t mask)
398{
399 irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
400 unsigned long flags;
401 uint16_t val;
402
403 spin_lock_irqsave(&desc->lock, flags);
404 val = vrc4173_inw(VRC4173_MKIUINTREG);
405 val &= ~mask;
406 vrc4173_outw(val, VRC4173_MKIUINTREG);
407 spin_unlock_irqrestore(&desc->lock, flags);
408}
409
410EXPORT_SYMBOL(vrc4173_disable_kiuint);
411
412static void enable_vrc4173_irq(unsigned int irq)
413{
414 uint16_t val;
415
416 val = vrc4173_inw(VRC4173_MSYSINT1REG);
417 val |= (uint16_t)1 << (irq - VRC4173_IRQ_BASE);
418 vrc4173_outw(val, VRC4173_MSYSINT1REG);
419}
420
421static void disable_vrc4173_irq(unsigned int irq)
422{
423 uint16_t val;
424
425 val = vrc4173_inw(VRC4173_MSYSINT1REG);
426 val &= ~((uint16_t)1 << (irq - VRC4173_IRQ_BASE));
427 vrc4173_outw(val, VRC4173_MSYSINT1REG);
428}
429
430static unsigned int startup_vrc4173_irq(unsigned int irq)
431{
432 enable_vrc4173_irq(irq);
433 return 0; /* never anything pending */
434}
435
436#define shutdown_vrc4173_irq disable_vrc4173_irq
437#define ack_vrc4173_irq disable_vrc4173_irq
438
439static void end_vrc4173_irq(unsigned int irq)
440{
441 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
442 enable_vrc4173_irq(irq);
443}
444
445static struct hw_interrupt_type vrc4173_irq_type = {
446 .typename = "VRC4173",
447 .startup = startup_vrc4173_irq,
448 .shutdown = shutdown_vrc4173_irq,
449 .enable = enable_vrc4173_irq,
450 .disable = disable_vrc4173_irq,
451 .ack = ack_vrc4173_irq,
452 .end = end_vrc4173_irq,
453};
454
455static int vrc4173_get_irq_number(int irq)
456{
457 uint16_t status, mask;
458 int i;
459
460 status = vrc4173_inw(VRC4173_SYSINT1REG);
461 mask = vrc4173_inw(VRC4173_MSYSINT1REG);
462
463 status &= mask;
464 if (status) {
465 for (i = 0; i < 16; i++)
466 if (status & (0x0001 << i))
467 return VRC4173_IRQ(i);
468 }
469
470 return -EINVAL;
471}
472
473static inline int vrc4173_icu_init(int cascade_irq)
474{
475 int i;
476
477 if (cascade_irq < GIU_IRQ(0) || cascade_irq > GIU_IRQ(15))
478 return -EINVAL;
479
480 vrc4173_outw(0, VRC4173_MSYSINT1REG);
481
482 vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq), TRIGGER_LEVEL, SIGNAL_THROUGH);
483 vr41xx_set_irq_level(GIU_IRQ_TO_PIN(cascade_irq), LEVEL_LOW);
484
485 for (i = VRC4173_IRQ_BASE; i <= VRC4173_IRQ_LAST; i++)
486 irq_desc[i].handler = &vrc4173_irq_type;
487
488 return 0;
489}
490
491static int __devinit vrc4173_probe(struct pci_dev *dev,
492 const struct pci_device_id *id)
493{
494 unsigned long start, flags;
495 int err;
496
497 err = pci_enable_device(dev);
498 if (err < 0) {
499 printk(KERN_ERR "vrc4173: Failed to enable PCI device, aborting\n");
500 return err;
501 }
502
503 pci_set_master(dev);
504
505 start = pci_resource_start(dev, 0);
506 if (start == 0) {
507 printk(KERN_ERR "vrc4173:No such PCI I/O resource, aborting\n");
508 return -ENXIO;
509 }
510
511 flags = pci_resource_flags(dev, 0);
512 if ((flags & IORESOURCE_IO) == 0) {
513 printk(KERN_ERR "vrc4173: No such PCI I/O resource, aborting\n");
514 return -ENXIO;
515 }
516
517 err = pci_request_regions(dev, "NEC VRC4173");
518 if (err < 0) {
519 printk(KERN_ERR "vrc4173: PCI resources are busy, aborting\n");
520 return err;
521 }
522
523 set_vrc4173_io_offset(start);
524
525 vrc4173_cmu_init();
526 vrc4173_giu_init();
527
528 err = vrc4173_icu_init(dev->irq);
529 if (err < 0) {
530 printk(KERN_ERR "vrc4173: Invalid IRQ %d, aborting\n", dev->irq);
531 return err;
532 }
533
534 err = vr41xx_cascade_irq(dev->irq, vrc4173_get_irq_number);
535 if (err < 0) {
536 printk(KERN_ERR "vrc4173: IRQ resource %d is busy, aborting\n", dev->irq);
537 return err;
538 }
539
540 printk(KERN_INFO
541 "NEC VRC4173 at 0x%#08lx, IRQ is cascaded to %d\n", start, dev->irq);
542
543 return 0;
544}
545
546static void vrc4173_remove(struct pci_dev *dev)
547{
548 free_irq(dev->irq, NULL);
549
550 pci_release_regions(dev);
551}
552
553static struct pci_driver vrc4173_driver = {
554 .name = "NEC VRC4173",
555 .probe = vrc4173_probe,
556 .remove = vrc4173_remove,
557 .id_table = vrc4173_id_table,
558};
559
560static int __devinit vrc4173_init(void)
561{
562 int err;
563
564 err = pci_module_init(&vrc4173_driver);
565 if (err < 0)
566 return err;
567
568 vrc4173_initialized = 1;
569
570 return 0;
571}
572
573static void __devexit vrc4173_exit(void)
574{
575 vrc4173_initialized = 0;
576
577 pci_unregister_driver(&vrc4173_driver);
578}
579
580module_init(vrc4173_init);
581module_exit(vrc4173_exit);
diff --git a/arch/mips/vr41xx/ibm-workpad/Makefile b/arch/mips/vr41xx/ibm-workpad/Makefile
new file mode 100644
index 000000000000..5ffaff0f0f89
--- /dev/null
+++ b/arch/mips/vr41xx/ibm-workpad/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the IBM WorkPad z50 specific parts of the kernel
3#
4
5obj-y += setup.o
diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c
new file mode 100644
index 000000000000..cff44602d3d4
--- /dev/null
+++ b/arch/mips/vr41xx/ibm-workpad/setup.c
@@ -0,0 +1,40 @@
1/*
2 * setup.c, Setup for the IBM WorkPad z50.
3 *
4 * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/init.h>
21#include <linux/ioport.h>
22
23#include <asm/io.h>
24#include <asm/vr41xx/workpad.h>
25
26const char *get_system_type(void)
27{
28 return "IBM WorkPad z50";
29}
30
31static int __init ibm_workpad_setup(void)
32{
33 set_io_port_base(IO_PORT_BASE);
34 ioport_resource.start = IO_PORT_RESOURCE_START;
35 ioport_resource.end = IO_PORT_RESOURCE_END;
36
37 return 0;
38}
39
40arch_initcall(ibm_workpad_setup);
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/Makefile b/arch/mips/vr41xx/nec-cmbvr4133/Makefile
new file mode 100644
index 000000000000..5835cae54aca
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the NEC-CMBVR4133
3#
4
5obj-y := init.o setup.o
6
7obj-$(CONFIG_PCI) += m1535plus.o
8obj-$(CONFIG_ROCKHOPPER) += irq.o
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/init.c b/arch/mips/vr41xx/nec-cmbvr4133/init.c
new file mode 100644
index 000000000000..87f06b3f5a9c
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/init.c
@@ -0,0 +1,78 @@
1/*
2 * arch/mips/vr41xx/nec-cmbvr4133/init.c
3 *
4 * PROM library initialisation code for NEC CMB-VR4133 board.
5 *
6 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
7 * Jun Sun <jsun@mvista.com, or source@mvista.com> and
8 * Alex Sapkov <asapkov@ru.mvista.com>
9 *
10 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
11 * the terms of the GNU General Public License version 2. This program
12 * is licensed "as is" without any warranty of any kind, whether express
13 * or implied.
14 *
15 * Support for NEC-CMBVR4133 in 2.6
16 * Manish Lachwani (mlachwani@mvista.com)
17 */
18#include <linux/config.h>
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/string.h>
22
23#include <asm/bootinfo.h>
24
25#ifdef CONFIG_ROCKHOPPER
26#include <asm/io.h>
27#include <linux/pci.h>
28
29#define PCICONFDREG 0xaf000c14
30#define PCICONFAREG 0xaf000c18
31#endif
32
33const char *get_system_type(void)
34{
35 return "NEC CMB-VR4133";
36}
37
38#ifdef CONFIG_ROCKHOPPER
39void disable_pcnet(void)
40{
41 u32 data;
42
43 /*
44 * Workaround for the bug in PMON on VR4133. PMON leaves
45 * AMD PCNet controller (on Rockhopper) initialized and running in
46 * bus master mode. We have do disable it before doing any
47 * further initialization. Or we get problems with PCI bus 2
48 * and random lockups and crashes.
49 */
50
51 writel((2 << 16) |
52 (PCI_DEVFN(1,0) << 8) |
53 (0 & 0xfc) |
54 1UL,
55 PCICONFAREG);
56
57 data = readl(PCICONFDREG);
58
59 writel((2 << 16) |
60 (PCI_DEVFN(1,0) << 8) |
61 (4 & 0xfc) |
62 1UL,
63 PCICONFAREG);
64
65 data = readl(PCICONFDREG);
66
67 writel((2 << 16) |
68 (PCI_DEVFN(1,0) << 8) |
69 (4 & 0xfc) |
70 1UL,
71 PCICONFAREG);
72
73 data &= ~4;
74
75 writel(data, PCICONFDREG);
76}
77#endif
78
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
new file mode 100644
index 000000000000..31db6b61a39e
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
@@ -0,0 +1,114 @@
1/*
2 * arch/mips/vr41xx/nec-cmbvr4133/irq.c
3 *
4 * Interrupt routines for the NEC CMB-VR4133 board.
5 *
6 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
7 * Alex Sapkov <asapkov@ru.mvista.com>
8 *
9 * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
12 * or implied.
13 *
14 * Support for NEC-CMBVR4133 in 2.6
15 * Manish Lachwani (mlachwani@mvista.com)
16 */
17#include <linux/bitops.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/ioport.h>
21#include <linux/interrupt.h>
22
23#include <asm/io.h>
24#include <asm/vr41xx/cmbvr4133.h>
25
26extern void enable_8259A_irq(unsigned int irq);
27extern void disable_8259A_irq(unsigned int irq);
28extern void mask_and_ack_8259A(unsigned int irq);
29extern void init_8259A(int hoge);
30
31extern int vr4133_rockhopper;
32
33static unsigned int startup_i8259_irq(unsigned int irq)
34{
35 enable_8259A_irq(irq - I8259_IRQ_BASE);
36 return 0;
37}
38
39static void shutdown_i8259_irq(unsigned int irq)
40{
41 disable_8259A_irq(irq - I8259_IRQ_BASE);
42}
43
44static void enable_i8259_irq(unsigned int irq)
45{
46 enable_8259A_irq(irq - I8259_IRQ_BASE);
47}
48
49static void disable_i8259_irq(unsigned int irq)
50{
51 disable_8259A_irq(irq - I8259_IRQ_BASE);
52}
53
54static void ack_i8259_irq(unsigned int irq)
55{
56 mask_and_ack_8259A(irq - I8259_IRQ_BASE);
57}
58
59static void end_i8259_irq(unsigned int irq)
60{
61 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
62 enable_8259A_irq(irq - I8259_IRQ_BASE);
63}
64
65static struct hw_interrupt_type i8259_irq_type = {
66 .typename = "XT-PIC",
67 .startup = startup_i8259_irq,
68 .shutdown = shutdown_i8259_irq,
69 .enable = enable_i8259_irq,
70 .disable = disable_i8259_irq,
71 .ack = ack_i8259_irq,
72 .end = end_i8259_irq,
73};
74
75static int i8259_get_irq_number(int irq)
76{
77 unsigned long isr;
78
79 isr = inb(0x20);
80 irq = ffz(~isr);
81 if (irq == 2) {
82 isr = inb(0xa0);
83 irq = 8 + ffz(~isr);
84 }
85
86 if (irq < 0 || irq > 15)
87 return -EINVAL;
88
89 return I8259_IRQ_BASE + irq;
90}
91
92static struct irqaction i8259_slave_cascade = {
93 .handler = &no_action,
94 .name = "cascade",
95};
96
97void __init rockhopper_init_irq(void)
98{
99 int i;
100
101 if(!vr4133_rockhopper) {
102 printk(KERN_ERR "Not a Rockhopper Board \n");
103 return;
104 }
105
106 for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
107 irq_desc[i].handler = &i8259_irq_type;
108
109 setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
110
111 vr41xx_set_irq_trigger(CMBVR41XX_INTC_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
112 vr41xx_set_irq_level(CMBVR41XX_INTC_PIN, LEVEL_HIGH);
113 vr41xx_cascade_irq(CMBVR41XX_INTC_IRQ, i8259_get_irq_number);
114}
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c b/arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c
new file mode 100644
index 000000000000..1f6b24ef8695
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c
@@ -0,0 +1,250 @@
1/*
2 * arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c
3 *
4 * Initialize for ALi M1535+(included M5229 and M5237).
5 *
6 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
7 * Alex Sapkov <asapkov@ru.mvista.com>
8 *
9 * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
12 * or implied.
13 *
14 * Support for NEC-CMBVR4133 in 2.6
15 * Author: Manish Lachwani (mlachwani@mvista.com)
16 */
17#include <linux/config.h>
18#include <linux/init.h>
19#include <linux/types.h>
20#include <linux/serial.h>
21
22#include <asm/vr41xx/cmbvr4133.h>
23#include <linux/pci.h>
24#include <asm/io.h>
25
26#define CONFIG_PORT(port) ((port) ? 0x3f0 : 0x370)
27#define DATA_PORT(port) ((port) ? 0x3f1 : 0x371)
28#define INDEX_PORT(port) CONFIG_PORT(port)
29
30#define ENTER_CONFIG_MODE(port) \
31 do { \
32 outb_p(0x51, CONFIG_PORT(port)); \
33 outb_p(0x23, CONFIG_PORT(port)); \
34 } while(0)
35
36#define SELECT_LOGICAL_DEVICE(port, dev_no) \
37 do { \
38 outb_p(0x07, INDEX_PORT(port)); \
39 outb_p((dev_no), DATA_PORT(port)); \
40 } while(0)
41
42#define WRITE_CONFIG_DATA(port,index,data) \
43 do { \
44 outb_p((index), INDEX_PORT(port)); \
45 outb_p((data), DATA_PORT(port)); \
46 } while(0)
47
48#define EXIT_CONFIG_MODE(port) outb(0xbb, CONFIG_PORT(port))
49
50#define PCI_CONFIG_ADDR KSEG1ADDR(0x0f000c18)
51#define PCI_CONFIG_DATA KSEG1ADDR(0x0f000c14)
52
53#ifdef CONFIG_BLK_DEV_FD
54
55void __devinit ali_m1535plus_fdc_init(int port)
56{
57 ENTER_CONFIG_MODE(port);
58 SELECT_LOGICAL_DEVICE(port, 0); /* FDC */
59 WRITE_CONFIG_DATA(port, 0x30, 0x01); /* FDC: enable */
60 WRITE_CONFIG_DATA(port, 0x60, 0x03); /* I/O port base: 0x3f0 */
61 WRITE_CONFIG_DATA(port, 0x61, 0xf0);
62 WRITE_CONFIG_DATA(port, 0x70, 0x06); /* IRQ: 6 */
63 WRITE_CONFIG_DATA(port, 0x74, 0x02); /* DMA: channel 2 */
64 WRITE_CONFIG_DATA(port, 0xf0, 0x08);
65 WRITE_CONFIG_DATA(port, 0xf1, 0x00);
66 WRITE_CONFIG_DATA(port, 0xf2, 0xff);
67 WRITE_CONFIG_DATA(port, 0xf4, 0x00);
68 EXIT_CONFIG_MODE(port);
69}
70
71#endif
72
73void __devinit ali_m1535plus_parport_init(int port)
74{
75 ENTER_CONFIG_MODE(port);
76 SELECT_LOGICAL_DEVICE(port, 3); /* Parallel Port */
77 WRITE_CONFIG_DATA(port, 0x30, 0x01);
78 WRITE_CONFIG_DATA(port, 0x60, 0x03); /* I/O port base: 0x378 */
79 WRITE_CONFIG_DATA(port, 0x61, 0x78);
80 WRITE_CONFIG_DATA(port, 0x70, 0x07); /* IRQ: 7 */
81 WRITE_CONFIG_DATA(port, 0x74, 0x04); /* DMA: None */
82 WRITE_CONFIG_DATA(port, 0xf0, 0x8c); /* IRQ polarity: Active Low */
83 WRITE_CONFIG_DATA(port, 0xf1, 0xc5);
84 EXIT_CONFIG_MODE(port);
85}
86
87void __devinit ali_m1535plus_keyboard_init(int port)
88{
89 ENTER_CONFIG_MODE(port);
90 SELECT_LOGICAL_DEVICE(port, 7); /* KEYBOARD */
91 WRITE_CONFIG_DATA(port, 0x30, 0x01); /* KEYBOARD: eable */
92 WRITE_CONFIG_DATA(port, 0x70, 0x01); /* IRQ: 1 */
93 WRITE_CONFIG_DATA(port, 0x72, 0x0c); /* PS/2 Mouse IRQ: 12 */
94 WRITE_CONFIG_DATA(port, 0xf0, 0x00);
95 EXIT_CONFIG_MODE(port);
96}
97
98void __devinit ali_m1535plus_hotkey_init(int port)
99{
100 ENTER_CONFIG_MODE(port);
101 SELECT_LOGICAL_DEVICE(port, 0xc); /* HOTKEY */
102 WRITE_CONFIG_DATA(port, 0x30, 0x00);
103 WRITE_CONFIG_DATA(port, 0xf0, 0x35);
104 WRITE_CONFIG_DATA(port, 0xf1, 0x14);
105 WRITE_CONFIG_DATA(port, 0xf2, 0x11);
106 WRITE_CONFIG_DATA(port, 0xf3, 0x71);
107 WRITE_CONFIG_DATA(port, 0xf5, 0x05);
108 EXIT_CONFIG_MODE(port);
109}
110
111void ali_m1535plus_init(struct pci_dev *dev)
112{
113 pci_write_config_byte(dev, 0x40, 0x18); /* PCI Interface Control */
114 pci_write_config_byte(dev, 0x41, 0xc0); /* PS2 keyb & mouse enable */
115 pci_write_config_byte(dev, 0x42, 0x41); /* ISA bus cycle control */
116 pci_write_config_byte(dev, 0x43, 0x00); /* ISA bus cycle control 2 */
117 pci_write_config_byte(dev, 0x44, 0x5d); /* IDE enable & IRQ 14 */
118 pci_write_config_byte(dev, 0x45, 0x0b); /* PCI int polling mode */
119 pci_write_config_byte(dev, 0x47, 0x00); /* BIOS chip select control */
120
121 /* IRQ routing */
122 pci_write_config_byte(dev, 0x48, 0x03); /* INTA IRQ10, INTB disable */
123 pci_write_config_byte(dev, 0x49, 0x00); /* INTC and INTD disable */
124 pci_write_config_byte(dev, 0x4a, 0x00); /* INTE and INTF disable */
125 pci_write_config_byte(dev, 0x4b, 0x90); /* Audio IRQ11, Modem disable */
126
127 pci_write_config_word(dev, 0x50, 0x4000); /* Parity check IDE enable */
128 pci_write_config_word(dev, 0x52, 0x0000); /* USB & RTC disable */
129 pci_write_config_word(dev, 0x54, 0x0002); /* ??? no info */
130 pci_write_config_word(dev, 0x56, 0x0002); /* PCS1J signal disable */
131
132 pci_write_config_byte(dev, 0x59, 0x00); /* PCSDS */
133 pci_write_config_byte(dev, 0x5a, 0x00);
134 pci_write_config_byte(dev, 0x5b, 0x00);
135 pci_write_config_word(dev, 0x5c, 0x0000);
136 pci_write_config_byte(dev, 0x5e, 0x00);
137 pci_write_config_byte(dev, 0x5f, 0x00);
138 pci_write_config_word(dev, 0x60, 0x0000);
139
140 pci_write_config_byte(dev, 0x6c, 0x00);
141 pci_write_config_byte(dev, 0x6d, 0x48); /* ROM address mapping */
142 pci_write_config_byte(dev, 0x6e, 0x00); /* ??? what for? */
143
144 pci_write_config_byte(dev, 0x70, 0x12); /* Serial IRQ control */
145 pci_write_config_byte(dev, 0x71, 0xEF); /* DMA channel select */
146 pci_write_config_byte(dev, 0x72, 0x03); /* USB IDSEL */
147 pci_write_config_byte(dev, 0x73, 0x00); /* ??? no info */
148
149 /*
150 * IRQ setup ALi M5237 USB Host Controller
151 * IRQ: 9
152 */
153 pci_write_config_byte(dev, 0x74, 0x01); /* USB IRQ9 */
154
155 pci_write_config_byte(dev, 0x75, 0x1f); /* IDE2 IRQ 15 */
156 pci_write_config_byte(dev, 0x76, 0x80); /* ACPI disable */
157 pci_write_config_byte(dev, 0x77, 0x40); /* Modem disable */
158 pci_write_config_dword(dev, 0x78, 0x20000000); /* Pin select 2 */
159 pci_write_config_byte(dev, 0x7c, 0x00); /* Pin select 3 */
160 pci_write_config_byte(dev, 0x81, 0x00); /* ID read/write control */
161 pci_write_config_byte(dev, 0x90, 0x00); /* PCI PM block control */
162 pci_write_config_word(dev, 0xa4, 0x0000); /* PMSCR */
163
164#ifdef CONFIG_BLK_DEV_FD
165 ali_m1535plus_fdc_init(1);
166#endif
167
168 ali_m1535plus_keyboard_init(1);
169 ali_m1535plus_hotkey_init(1);
170}
171
172static inline void ali_config_writeb(u8 reg, u8 val, int devfn)
173{
174 u32 data;
175 int shift;
176
177 writel((1 << 16) | (devfn << 8) | (reg & 0xfc) | 1UL, PCI_CONFIG_ADDR);
178 data = readl(PCI_CONFIG_DATA);
179
180 shift = (reg & 3) << 3;
181 data &= ~(0xff << shift);
182 data |= (((u32)val) << shift);
183
184 writel(data, PCI_CONFIG_DATA);
185}
186
187static inline u8 ali_config_readb(u8 reg, int devfn)
188{
189 u32 data;
190
191 writel((1 << 16) | (devfn << 8) | (reg & 0xfc) | 1UL, PCI_CONFIG_ADDR);
192 data = readl(PCI_CONFIG_DATA);
193
194 return (u8)(data >> ((reg & 3) << 3));
195}
196
197static inline u16 ali_config_readw(u8 reg, int devfn)
198{
199 u32 data;
200
201 writel((1 << 16) | (devfn << 8) | (reg & 0xfc) | 1UL, PCI_CONFIG_ADDR);
202 data = readl(PCI_CONFIG_DATA);
203
204 return (u16)(data >> ((reg & 2) << 3));
205}
206
207int vr4133_rockhopper = 0;
208void __init ali_m5229_preinit(void)
209{
210 if (ali_config_readw(PCI_VENDOR_ID,16) == PCI_VENDOR_ID_AL &&
211 ali_config_readw(PCI_DEVICE_ID,16) == PCI_DEVICE_ID_AL_M1533) {
212 printk(KERN_INFO "Found an NEC Rockhopper \n");
213 vr4133_rockhopper = 1;
214 /*
215 * Enable ALi M5229 IDE Controller (both channels)
216 * IDSEL: A27
217 */
218 ali_config_writeb(0x58, 0x4c, 16);
219 }
220}
221
222void __init ali_m5229_init(struct pci_dev *dev)
223{
224 /*
225 * Enable Primary/Secondary Channel Cable Detect 40-Pin
226 */
227 pci_write_config_word(dev, 0x4a, 0xc023);
228
229 /*
230 * Set only the 3rd byteis for the master IDE's cycle and
231 * enable Internal IDE Function
232 */
233 pci_write_config_byte(dev, 0x50, 0x23); /* Class code attr register */
234
235 pci_write_config_byte(dev, 0x09, 0xff); /* Set native mode & stuff */
236 pci_write_config_byte(dev, 0x52, 0x00); /* use timing registers */
237 pci_write_config_byte(dev, 0x58, 0x02); /* Primary addr setup timing */
238 pci_write_config_byte(dev, 0x59, 0x22); /* Primary cmd block timing */
239 pci_write_config_byte(dev, 0x5a, 0x22); /* Pr drv 0 R/W timing */
240 pci_write_config_byte(dev, 0x5b, 0x22); /* Pr drv 1 R/W timing */
241 pci_write_config_byte(dev, 0x5c, 0x02); /* Sec addr setup timing */
242 pci_write_config_byte(dev, 0x5d, 0x22); /* Sec cmd block timing */
243 pci_write_config_byte(dev, 0x5e, 0x22); /* Sec drv 0 R/W timing */
244 pci_write_config_byte(dev, 0x5f, 0x22); /* Sec drv 1 R/W timing */
245 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
246 pci_write_config_word(dev, PCI_COMMAND,
247 PCI_COMMAND_PARITY | PCI_COMMAND_MASTER |
248 PCI_COMMAND_IO);
249}
250
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/setup.c b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
new file mode 100644
index 000000000000..db686ce42e85
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
@@ -0,0 +1,96 @@
1/*
2 * arch/mips/vr41xx/nec-cmbvr4133/setup.c
3 *
4 * Setup for the NEC CMB-VR4133.
5 *
6 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
7 * Alex Sapkov <asapkov@ru.mvista.com>
8 *
9 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
12 * or implied.
13 *
14 * Support for CMBVR4133 board in 2.6
15 * Author: Manish Lachwani (mlachwani@mvista.com)
16 */
17#include <linux/config.h>
18#include <linux/init.h>
19#include <linux/ide.h>
20#include <linux/ioport.h>
21
22#include <asm/reboot.h>
23#include <asm/time.h>
24#include <asm/vr41xx/cmbvr4133.h>
25#include <asm/bootinfo.h>
26
27#ifdef CONFIG_MTD
28#include <linux/mtd/physmap.h>
29#include <linux/mtd/partitions.h>
30#include <linux/mtd/mtd.h>
31#include <linux/mtd/map.h>
32
33static struct mtd_partition cmbvr4133_mtd_parts[] = {
34 {
35 .name = "User FS",
36 .size = 0x1be0000,
37 .offset = 0,
38 .mask_flags = 0,
39 },
40 {
41 .name = "PMON",
42 .size = 0x140000,
43 .offset = MTDPART_OFS_APPEND,
44 .mask_flags = MTD_WRITEABLE, /* force read-only */
45 },
46 {
47 .name = "User FS2",
48 .size = MTDPART_SIZ_FULL,
49 .offset = MTDPART_OFS_APPEND,
50 .mask_flags = 0,
51 }
52};
53
54#define number_partitions (sizeof(cmbvr4133_mtd_parts)/sizeof(struct mtd_partition))
55#endif
56
57extern void i8259_init(void);
58
59static int __init nec_cmbvr4133_setup(void)
60{
61#ifdef CONFIG_ROCKHOPPER
62 extern void disable_pcnet(void);
63
64 disable_pcnet();
65#endif
66 set_io_port_base(KSEG1ADDR(0x16000000));
67
68 mips_machgroup = MACH_GROUP_NEC_VR41XX;
69 mips_machtype = MACH_NEC_CMBVR4133;
70
71#ifdef CONFIG_PCI
72#ifdef CONFIG_ROCKHOPPER
73 ali_m5229_preinit();
74#endif
75#endif
76
77#ifdef CONFIG_ROCKHOPPER
78 rockhopper_init_irq();
79#endif
80
81#ifdef CONFIG_MTD
82 /* we use generic physmap mapping driver and we use partitions */
83 physmap_configure(0x1C000000, 0x02000000, 4, NULL);
84 physmap_set_partitions(cmbvr4133_mtd_parts, number_partitions);
85#endif
86
87 /* 128 MB memory support */
88 add_memory_region(0, 0x08000000, BOOT_MEM_RAM);
89
90#ifdef CONFIG_ROCKHOPPER
91 i8259_init();
92#endif
93 return 0;
94}
95
96early_initcall(nec_cmbvr4133_setup);
diff --git a/arch/mips/vr41xx/tanbac-tb0226/Makefile b/arch/mips/vr41xx/tanbac-tb0226/Makefile
new file mode 100644
index 000000000000..372f953d240b
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0226/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the TANBAC TB0226 specific parts of the kernel
3#
4
5obj-y += setup.o
diff --git a/arch/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/tanbac-tb0226/setup.c
new file mode 100644
index 000000000000..60027e5dea25
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0226/setup.c
@@ -0,0 +1,24 @@
1/*
2 * setup.c, Setup for the TANBAC TB0226.
3 *
4 * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21const char *get_system_type(void)
22{
23 return "TANBAC TB0226";
24}
diff --git a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile
new file mode 100644
index 000000000000..9c6b864ef2ef
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0229/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the TANBAC TB0229(VR4131DIMM) specific parts of the kernel
3#
4
5obj-y := setup.o
diff --git a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c
new file mode 100644
index 000000000000..5c1b757bfb0c
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c
@@ -0,0 +1,27 @@
1/*
2 * setup.c, Setup for the TANBAC TB0229 (VR4131DIMM)
3 *
4 * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * Modified for TANBAC TB0229:
7 * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24const char *get_system_type(void)
25{
26 return "TANBAC TB0229";
27}
diff --git a/arch/mips/vr41xx/victor-mpc30x/Makefile b/arch/mips/vr41xx/victor-mpc30x/Makefile
new file mode 100644
index 000000000000..a2e8086a31a6
--- /dev/null
+++ b/arch/mips/vr41xx/victor-mpc30x/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the Victor MP-C303/304 specific parts of the kernel
3#
4
5obj-y += setup.o
diff --git a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c
new file mode 100644
index 000000000000..f591e36726e6
--- /dev/null
+++ b/arch/mips/vr41xx/victor-mpc30x/setup.c
@@ -0,0 +1,24 @@
1/*
2 * setup.c, Setup for the Victor MP-C303/304.
3 *
4 * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21const char *get_system_type(void)
22{
23 return "Victor MP-C303/304";
24}
diff --git a/arch/mips/vr41xx/zao-capcella/Makefile b/arch/mips/vr41xx/zao-capcella/Makefile
new file mode 100644
index 000000000000..cf420197cd23
--- /dev/null
+++ b/arch/mips/vr41xx/zao-capcella/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the ZAO Networks Capcella specific parts of the kernel
3#
4
5obj-y += setup.o
diff --git a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c
new file mode 100644
index 000000000000..17bade241fe2
--- /dev/null
+++ b/arch/mips/vr41xx/zao-capcella/setup.c
@@ -0,0 +1,24 @@
1/*
2 * setup.c, Setup for the ZAO Networks Capcella.
3 *
4 * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21const char *get_system_type(void)
22{
23 return "ZAO Networks Capcella";
24}