diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/vr4181 |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/mips/vr4181')
-rw-r--r-- | arch/mips/vr4181/common/Makefile | 7 | ||||
-rw-r--r-- | arch/mips/vr4181/common/int_handler.S | 206 | ||||
-rw-r--r-- | arch/mips/vr4181/common/irq.c | 239 | ||||
-rw-r--r-- | arch/mips/vr4181/common/serial.c | 51 | ||||
-rw-r--r-- | arch/mips/vr4181/common/time.c | 145 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/Makefile | 7 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/dbg_io.c | 136 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/prom.c | 49 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/reset.c | 40 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/setup.c | 68 |
10 files changed, 948 insertions, 0 deletions
diff --git a/arch/mips/vr4181/common/Makefile b/arch/mips/vr4181/common/Makefile new file mode 100644 index 000000000000..f7587ca64ead --- /dev/null +++ b/arch/mips/vr4181/common/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for common code of NEC vr4181 based boards | ||
3 | # | ||
4 | |||
5 | obj-y := irq.o int_handler.o serial.o time.o | ||
6 | |||
7 | EXTRA_AFLAGS := $(CFLAGS) | ||
diff --git a/arch/mips/vr4181/common/int_handler.S b/arch/mips/vr4181/common/int_handler.S new file mode 100644 index 000000000000..2c041b8ee52b --- /dev/null +++ b/arch/mips/vr4181/common/int_handler.S | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * arch/mips/vr4181/common/int_handler.S | ||
3 | * | ||
4 | * Adapted to the VR4181 and almost entirely rewritten: | ||
5 | * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar | ||
6 | * | ||
7 | * Clean up to conform to the new IRQ | ||
8 | * Copyright (C) 2001 MontaVista Software Inc. | ||
9 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
10 | * | ||
11 | * This file is subject to the terms and conditions of the GNU General Public | ||
12 | * License. See the file "COPYING" in the main directory of this archive | ||
13 | * for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <asm/asm.h> | ||
18 | #include <asm/regdef.h> | ||
19 | #include <asm/mipsregs.h> | ||
20 | #include <asm/stackframe.h> | ||
21 | |||
22 | #include <asm/vr4181/vr4181.h> | ||
23 | |||
24 | /* | ||
25 | * [jsun] | ||
26 | * See include/asm/vr4181/irq.h for IRQ assignment and strategy. | ||
27 | */ | ||
28 | |||
29 | .text | ||
30 | .set noreorder | ||
31 | |||
32 | .align 5 | ||
33 | NESTED(vr4181_handle_irq, PT_SIZE, ra) | ||
34 | |||
35 | .set noat | ||
36 | SAVE_ALL | ||
37 | CLI | ||
38 | |||
39 | .set at | ||
40 | .set noreorder | ||
41 | |||
42 | mfc0 t0, CP0_CAUSE | ||
43 | mfc0 t2, CP0_STATUS | ||
44 | |||
45 | and t0, t2 | ||
46 | |||
47 | /* we check IP3 first; it happens most frequently */ | ||
48 | andi t1, t0, STATUSF_IP3 | ||
49 | bnez t1, ll_cpu_ip3 | ||
50 | andi t1, t0, STATUSF_IP2 | ||
51 | bnez t1, ll_cpu_ip2 | ||
52 | andi t1, t0, STATUSF_IP7 /* cpu timer */ | ||
53 | bnez t1, ll_cputimer_irq | ||
54 | andi t1, t0, STATUSF_IP4 | ||
55 | bnez t1, ll_cpu_ip4 | ||
56 | andi t1, t0, STATUSF_IP5 | ||
57 | bnez t1, ll_cpu_ip5 | ||
58 | andi t1, t0, STATUSF_IP6 | ||
59 | bnez t1, ll_cpu_ip6 | ||
60 | andi t1, t0, STATUSF_IP0 /* software int 0 */ | ||
61 | bnez t1, ll_cpu_ip0 | ||
62 | andi t1, t0, STATUSF_IP1 /* software int 1 */ | ||
63 | bnez t1, ll_cpu_ip1 | ||
64 | nop | ||
65 | |||
66 | .set reorder | ||
67 | do_spurious: | ||
68 | j spurious_interrupt | ||
69 | |||
70 | /* | ||
71 | * regular CPU irqs | ||
72 | */ | ||
73 | ll_cputimer_irq: | ||
74 | li a0, VR4181_IRQ_TIMER | ||
75 | move a1, sp | ||
76 | jal do_IRQ | ||
77 | j ret_from_irq | ||
78 | |||
79 | |||
80 | ll_cpu_ip0: | ||
81 | li a0, VR4181_IRQ_SW1 | ||
82 | move a1, sp | ||
83 | jal do_IRQ | ||
84 | j ret_from_irq | ||
85 | |||
86 | ll_cpu_ip1: | ||
87 | li a0, VR4181_IRQ_SW2 | ||
88 | move a1, sp | ||
89 | jal do_IRQ | ||
90 | j ret_from_irq | ||
91 | |||
92 | ll_cpu_ip3: | ||
93 | li a0, VR4181_IRQ_INT1 | ||
94 | move a1, sp | ||
95 | jal do_IRQ | ||
96 | j ret_from_irq | ||
97 | |||
98 | ll_cpu_ip4: | ||
99 | li a0, VR4181_IRQ_INT2 | ||
100 | move a1, sp | ||
101 | jal do_IRQ | ||
102 | j ret_from_irq | ||
103 | |||
104 | ll_cpu_ip5: | ||
105 | li a0, VR4181_IRQ_INT3 | ||
106 | move a1, sp | ||
107 | jal do_IRQ | ||
108 | j ret_from_irq | ||
109 | |||
110 | ll_cpu_ip6: | ||
111 | li a0, VR4181_IRQ_INT4 | ||
112 | move a1, sp | ||
113 | jal do_IRQ | ||
114 | j ret_from_irq | ||
115 | |||
116 | /* | ||
117 | * One of the sys irq has happend. | ||
118 | * | ||
119 | * In the interest of speed, we first determine in the following order | ||
120 | * which 16-irq block have pending interrupts: | ||
121 | * sysint1 (16 sources, including cascading intrs from GPIO) | ||
122 | * sysint2 | ||
123 | * gpio (16 intr sources) | ||
124 | * | ||
125 | * Then we do binary search to find the exact interrupt source. | ||
126 | */ | ||
127 | ll_cpu_ip2: | ||
128 | |||
129 | lui t3,%hi(VR4181_SYSINT1REG) | ||
130 | lhu t0,%lo(VR4181_SYSINT1REG)(t3) | ||
131 | lhu t2,%lo(VR4181_MSYSINT1REG)(t3) | ||
132 | and t0, 0xfffb /* hack - remove RTC Long 1 intr */ | ||
133 | and t0, t2 | ||
134 | beqz t0, check_sysint2 | ||
135 | |||
136 | /* check for GPIO interrupts */ | ||
137 | andi t1, t0, 0x0100 | ||
138 | bnez t1, check_gpio_int | ||
139 | |||
140 | /* so we have an interrupt in sysint1 which is not gpio int */ | ||
141 | li a0, VR4181_SYS_IRQ_BASE - 1 | ||
142 | j check_16 | ||
143 | |||
144 | check_sysint2: | ||
145 | |||
146 | lhu t0,%lo(VR4181_SYSINT2REG)(t3) | ||
147 | lhu t2,%lo(VR4181_MSYSINT2REG)(t3) | ||
148 | and t0, 0xfffe /* hack - remove RTC Long 2 intr */ | ||
149 | and t0, t2 | ||
150 | li a0, VR4181_SYS_IRQ_BASE + 16 - 1 | ||
151 | j check_16 | ||
152 | |||
153 | check_gpio_int: | ||
154 | lui t3,%hi(VR4181_GPINTMSK) | ||
155 | lhu t0,%lo(VR4181_GPINTMSK)(t3) | ||
156 | lhu t2,%lo(VR4181_GPINTSTAT)(t3) | ||
157 | xori t0, 0xffff /* why? reverse logic? */ | ||
158 | and t0, t2 | ||
159 | li a0, VR4181_GPIO_IRQ_BASE - 1 | ||
160 | j check_16 | ||
161 | |||
162 | /* | ||
163 | * When we reach check_16, we have 16-bit status in t0 and base irq number | ||
164 | * in a0. | ||
165 | */ | ||
166 | check_16: | ||
167 | andi t1, t0, 0xff | ||
168 | bnez t1, check_8 | ||
169 | |||
170 | srl t0, 8 | ||
171 | addi a0, 8 | ||
172 | j check_8 | ||
173 | |||
174 | /* | ||
175 | * When we reach check_8, we have 8-bit status in t0 and base irq number | ||
176 | * in a0. | ||
177 | */ | ||
178 | check_8: | ||
179 | andi t1, t0, 0xf | ||
180 | bnez t1, check_4 | ||
181 | |||
182 | srl t0, 4 | ||
183 | addi a0, 4 | ||
184 | j check_4 | ||
185 | |||
186 | /* | ||
187 | * When we reach check_4, we have 4-bit status in t0 and base irq number | ||
188 | * in a0. | ||
189 | */ | ||
190 | check_4: | ||
191 | andi t0, t0, 0xf | ||
192 | beqz t0, do_spurious | ||
193 | |||
194 | loop: | ||
195 | andi t2, t0, 0x1 | ||
196 | srl t0, 1 | ||
197 | addi a0, 1 | ||
198 | beqz t2, loop | ||
199 | |||
200 | found_it: | ||
201 | move a1, sp | ||
202 | jal do_IRQ | ||
203 | |||
204 | j ret_from_irq | ||
205 | |||
206 | END(vr4181_handle_irq) | ||
diff --git a/arch/mips/vr4181/common/irq.c b/arch/mips/vr4181/common/irq.c new file mode 100644 index 000000000000..2cdf77c5cb3e --- /dev/null +++ b/arch/mips/vr4181/common/irq.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 MontaVista Software Inc. | ||
3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) | ||
5 | * | ||
6 | * linux/arch/mips/vr4181/common/irq.c | ||
7 | * Completely re-written to use the new irq.c | ||
8 | * | ||
9 | * Credits to Bradley D. LaRonde and Michael Klar for writing the original | ||
10 | * irq.c file which was derived from the common irq.c file. | ||
11 | * | ||
12 | * This file is subject to the terms and conditions of the GNU General Public | ||
13 | * License. See the file "COPYING" in the main directory of this archive | ||
14 | * for more details. | ||
15 | */ | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel_stat.h> | ||
19 | #include <linux/signal.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/random.h> | ||
24 | |||
25 | #include <asm/irq.h> | ||
26 | #include <asm/mipsregs.h> | ||
27 | #include <asm/gdb-stub.h> | ||
28 | |||
29 | #include <asm/vr4181/vr4181.h> | ||
30 | |||
31 | /* | ||
32 | * Strategy: | ||
33 | * | ||
34 | * We essentially have three irq controllers, CPU, system, and gpio. | ||
35 | * | ||
36 | * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and | ||
37 | * CONFIG_IRQ_CPU config option. | ||
38 | * | ||
39 | * We here provide sys_irq and gpio_irq controller code. | ||
40 | */ | ||
41 | |||
42 | static int sys_irq_base; | ||
43 | static int gpio_irq_base; | ||
44 | |||
45 | /* ---------------------- sys irq ------------------------ */ | ||
46 | static void | ||
47 | sys_irq_enable(unsigned int irq) | ||
48 | { | ||
49 | irq -= sys_irq_base; | ||
50 | if (irq < 16) { | ||
51 | *VR4181_MSYSINT1REG |= (u16)(1 << irq); | ||
52 | } else { | ||
53 | irq -= 16; | ||
54 | *VR4181_MSYSINT2REG |= (u16)(1 << irq); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static void | ||
59 | sys_irq_disable(unsigned int irq) | ||
60 | { | ||
61 | irq -= sys_irq_base; | ||
62 | if (irq < 16) { | ||
63 | *VR4181_MSYSINT1REG &= ~((u16)(1 << irq)); | ||
64 | } else { | ||
65 | irq -= 16; | ||
66 | *VR4181_MSYSINT2REG &= ~((u16)(1 << irq)); | ||
67 | } | ||
68 | |||
69 | } | ||
70 | |||
71 | static unsigned int | ||
72 | sys_irq_startup(unsigned int irq) | ||
73 | { | ||
74 | sys_irq_enable(irq); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | #define sys_irq_shutdown sys_irq_disable | ||
79 | #define sys_irq_ack sys_irq_disable | ||
80 | |||
81 | static void | ||
82 | sys_irq_end(unsigned int irq) | ||
83 | { | ||
84 | if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | ||
85 | sys_irq_enable(irq); | ||
86 | } | ||
87 | |||
88 | static hw_irq_controller sys_irq_controller = { | ||
89 | "vr4181_sys_irq", | ||
90 | sys_irq_startup, | ||
91 | sys_irq_shutdown, | ||
92 | sys_irq_enable, | ||
93 | sys_irq_disable, | ||
94 | sys_irq_ack, | ||
95 | sys_irq_end, | ||
96 | NULL /* no affinity stuff for UP */ | ||
97 | }; | ||
98 | |||
99 | /* ---------------------- gpio irq ------------------------ */ | ||
100 | /* gpio irq lines use reverse logic */ | ||
101 | static void | ||
102 | gpio_irq_enable(unsigned int irq) | ||
103 | { | ||
104 | irq -= gpio_irq_base; | ||
105 | *VR4181_GPINTMSK &= ~((u16)(1 << irq)); | ||
106 | } | ||
107 | |||
108 | static void | ||
109 | gpio_irq_disable(unsigned int irq) | ||
110 | { | ||
111 | irq -= gpio_irq_base; | ||
112 | *VR4181_GPINTMSK |= (u16)(1 << irq); | ||
113 | } | ||
114 | |||
115 | static unsigned int | ||
116 | gpio_irq_startup(unsigned int irq) | ||
117 | { | ||
118 | gpio_irq_enable(irq); | ||
119 | |||
120 | irq -= gpio_irq_base; | ||
121 | *VR4181_GPINTEN |= (u16)(1 << irq ); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static void | ||
127 | gpio_irq_shutdown(unsigned int irq) | ||
128 | { | ||
129 | gpio_irq_disable(irq); | ||
130 | |||
131 | irq -= gpio_irq_base; | ||
132 | *VR4181_GPINTEN &= ~((u16)(1 << irq )); | ||
133 | } | ||
134 | |||
135 | static void | ||
136 | gpio_irq_ack(unsigned int irq) | ||
137 | { | ||
138 | u16 irqtype; | ||
139 | u16 irqshift; | ||
140 | |||
141 | gpio_irq_disable(irq); | ||
142 | |||
143 | /* we clear interrupt if it is edge triggered */ | ||
144 | irq -= gpio_irq_base; | ||
145 | if (irq < 8) { | ||
146 | irqtype = *VR4181_GPINTTYPL; | ||
147 | irqshift = 2 << (irq*2); | ||
148 | } else { | ||
149 | irqtype = *VR4181_GPINTTYPH; | ||
150 | irqshift = 2 << ((irq-8)*2); | ||
151 | } | ||
152 | if ( ! (irqtype & irqshift) ) { | ||
153 | *VR4181_GPINTSTAT = (u16) (1 << irq); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static void | ||
158 | gpio_irq_end(unsigned int irq) | ||
159 | { | ||
160 | if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | ||
161 | gpio_irq_enable(irq); | ||
162 | } | ||
163 | |||
164 | static hw_irq_controller gpio_irq_controller = { | ||
165 | "vr4181_gpio_irq", | ||
166 | gpio_irq_startup, | ||
167 | gpio_irq_shutdown, | ||
168 | gpio_irq_enable, | ||
169 | gpio_irq_disable, | ||
170 | gpio_irq_ack, | ||
171 | gpio_irq_end, | ||
172 | NULL /* no affinity stuff for UP */ | ||
173 | }; | ||
174 | |||
175 | /* --------------------- IRQ init stuff ---------------------- */ | ||
176 | |||
177 | extern asmlinkage void vr4181_handle_irq(void); | ||
178 | extern void breakpoint(void); | ||
179 | extern int setup_irq(unsigned int irq, struct irqaction *irqaction); | ||
180 | extern void mips_cpu_irq_init(u32 irq_base); | ||
181 | |||
182 | static struct irqaction cascade = | ||
183 | { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL }; | ||
184 | static struct irqaction reserved = | ||
185 | { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL }; | ||
186 | |||
187 | void __init arch_init_irq(void) | ||
188 | { | ||
189 | int i; | ||
190 | |||
191 | set_except_vector(0, vr4181_handle_irq); | ||
192 | |||
193 | /* init CPU irqs */ | ||
194 | mips_cpu_irq_init(VR4181_CPU_IRQ_BASE); | ||
195 | |||
196 | /* init sys irqs */ | ||
197 | sys_irq_base = VR4181_SYS_IRQ_BASE; | ||
198 | for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) { | ||
199 | irq_desc[i].status = IRQ_DISABLED; | ||
200 | irq_desc[i].action = NULL; | ||
201 | irq_desc[i].depth = 1; | ||
202 | irq_desc[i].handler = &sys_irq_controller; | ||
203 | } | ||
204 | |||
205 | /* init gpio irqs */ | ||
206 | gpio_irq_base = VR4181_GPIO_IRQ_BASE; | ||
207 | for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) { | ||
208 | irq_desc[i].status = IRQ_DISABLED; | ||
209 | irq_desc[i].action = NULL; | ||
210 | irq_desc[i].depth = 1; | ||
211 | irq_desc[i].handler = &gpio_irq_controller; | ||
212 | } | ||
213 | |||
214 | /* Default all ICU IRQs to off ... */ | ||
215 | *VR4181_MSYSINT1REG = 0; | ||
216 | *VR4181_MSYSINT2REG = 0; | ||
217 | |||
218 | /* We initialize the level 2 ICU registers to all bits disabled. */ | ||
219 | *VR4181_MPIUINTREG = 0; | ||
220 | *VR4181_MAIUINTREG = 0; | ||
221 | *VR4181_MKIUINTREG = 0; | ||
222 | |||
223 | /* disable all GPIO intrs */ | ||
224 | *VR4181_GPINTMSK = 0xffff; | ||
225 | |||
226 | /* vector handler. What these do is register the IRQ as non-sharable */ | ||
227 | setup_irq(VR4181_IRQ_INT0, &cascade); | ||
228 | setup_irq(VR4181_IRQ_GIU, &cascade); | ||
229 | |||
230 | /* | ||
231 | * RTC interrupts are interesting. They have two destinations. | ||
232 | * One is at sys irq controller, and the other is at CPU IP3 and IP4. | ||
233 | * RTC timer is used as system timer. | ||
234 | * We enable them here, but timer routine will register later | ||
235 | * with CPU IP3/IP4. | ||
236 | */ | ||
237 | setup_irq(VR4181_IRQ_RTCL1, &reserved); | ||
238 | setup_irq(VR4181_IRQ_RTCL2, &reserved); | ||
239 | } | ||
diff --git a/arch/mips/vr4181/common/serial.c b/arch/mips/vr4181/common/serial.c new file mode 100644 index 000000000000..3f62c62b107f --- /dev/null +++ b/arch/mips/vr4181/common/serial.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * arch/mips/vr4181/common/serial.c | ||
6 | * initialize serial port on vr4181. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * [jsun, 010925] | ||
17 | * You need to make sure rs_table has at least one element in | ||
18 | * drivers/char/serial.c file. There is no good way to do it right | ||
19 | * now. A workaround is to include CONFIG_SERIAL_MANY_PORTS in your | ||
20 | * configure file, which would gives you 64 ports and wastes 11K ram. | ||
21 | */ | ||
22 | |||
23 | #include <linux/types.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/serial.h> | ||
27 | |||
28 | #include <asm/vr4181/vr4181.h> | ||
29 | |||
30 | void __init vr4181_init_serial(void) | ||
31 | { | ||
32 | struct serial_struct s; | ||
33 | |||
34 | /* turn on UART clock */ | ||
35 | *VR4181_CMUCLKMSK |= VR4181_CMUCLKMSK_MSKSIU; | ||
36 | |||
37 | /* clear memory */ | ||
38 | memset(&s, 0, sizeof(s)); | ||
39 | |||
40 | s.line = 0; /* we set the first one */ | ||
41 | s.baud_base = 1152000; | ||
42 | s.irq = VR4181_IRQ_SIU; | ||
43 | s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; /* STD_COM_FLAGS */ | ||
44 | s.iomem_base = (u8*)VR4181_SIURB; | ||
45 | s.iomem_reg_shift = 0; | ||
46 | s.io_type = SERIAL_IO_MEM; | ||
47 | if (early_serial_setup(&s) != 0) { | ||
48 | panic("vr4181_init_serial() failed!"); | ||
49 | } | ||
50 | } | ||
51 | |||
diff --git a/arch/mips/vr4181/common/time.c b/arch/mips/vr4181/common/time.c new file mode 100644 index 000000000000..17814076b6f4 --- /dev/null +++ b/arch/mips/vr4181/common/time.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * rtc and time ops for vr4181. Part of code is drived from | ||
6 | * linux-vr, originally written by Bradley D. LaRonde & Michael Klar. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/param.h> /* for HZ */ | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/time.h> | ||
23 | |||
24 | #include <asm/vr4181/vr4181.h> | ||
25 | |||
26 | #define COUNTS_PER_JIFFY ((32768 + HZ/2) / HZ) | ||
27 | |||
28 | /* | ||
29 | * RTC ops | ||
30 | */ | ||
31 | |||
32 | DEFINE_SPINLOCK(rtc_lock); | ||
33 | |||
34 | /* per VR41xx docs, bad data can be read if between 2 counts */ | ||
35 | static inline unsigned short | ||
36 | read_time_reg(volatile unsigned short *reg) | ||
37 | { | ||
38 | unsigned short value; | ||
39 | do { | ||
40 | value = *reg; | ||
41 | barrier(); | ||
42 | } while (value != *reg); | ||
43 | return value; | ||
44 | } | ||
45 | |||
46 | static unsigned long | ||
47 | vr4181_rtc_get_time(void) | ||
48 | { | ||
49 | unsigned short regh, regm, regl; | ||
50 | |||
51 | // why this crazy order, you ask? to guarantee that neither m | ||
52 | // nor l wrap before all 3 read | ||
53 | do { | ||
54 | regm = read_time_reg(VR4181_ETIMEMREG); | ||
55 | barrier(); | ||
56 | regh = read_time_reg(VR4181_ETIMEHREG); | ||
57 | barrier(); | ||
58 | regl = read_time_reg(VR4181_ETIMELREG); | ||
59 | } while (regm != read_time_reg(VR4181_ETIMEMREG)); | ||
60 | return ((regh << 17) | (regm << 1) | (regl >> 15)); | ||
61 | } | ||
62 | |||
63 | static int | ||
64 | vr4181_rtc_set_time(unsigned long timeval) | ||
65 | { | ||
66 | unsigned short intreg; | ||
67 | unsigned long flags; | ||
68 | |||
69 | spin_lock_irqsave(&rtc_lock, flags); | ||
70 | intreg = *VR4181_RTCINTREG & 0x05; | ||
71 | barrier(); | ||
72 | *VR4181_ETIMELREG = timeval << 15; | ||
73 | *VR4181_ETIMEMREG = timeval >> 1; | ||
74 | *VR4181_ETIMEHREG = timeval >> 17; | ||
75 | barrier(); | ||
76 | // assume that any ints that just triggered are invalid, since the | ||
77 | // time value is written non-atomically in 3 separate regs | ||
78 | *VR4181_RTCINTREG = 0x05 ^ intreg; | ||
79 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | |||
85 | /* | ||
86 | * timer interrupt routine (wrapper) | ||
87 | * | ||
88 | * we need our own interrupt routine because we need to clear | ||
89 | * RTC1 interrupt. | ||
90 | */ | ||
91 | static void | ||
92 | vr4181_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
93 | { | ||
94 | /* Clear the interrupt. */ | ||
95 | *VR4181_RTCINTREG = 0x2; | ||
96 | |||
97 | /* call the generic one */ | ||
98 | timer_interrupt(irq, dev_id, regs); | ||
99 | } | ||
100 | |||
101 | |||
102 | /* | ||
103 | * vr4181_time_init: | ||
104 | * | ||
105 | * We pick the following choices: | ||
106 | * . we use elapsed timer as the RTC. We set some reasonable init data since | ||
107 | * it does not persist across reset | ||
108 | * . we use RTC1 as the system timer interrupt source. | ||
109 | * . we use CPU counter for fast_gettimeoffset and we calivrate the cpu | ||
110 | * frequency. In other words, we use calibrate_div64_gettimeoffset(). | ||
111 | * . we use our own timer interrupt routine which clears the interrupt | ||
112 | * and then calls the generic high-level timer interrupt routine. | ||
113 | * | ||
114 | */ | ||
115 | |||
116 | extern int setup_irq(unsigned int irq, struct irqaction *irqaction); | ||
117 | |||
118 | static void | ||
119 | vr4181_timer_setup(struct irqaction *irq) | ||
120 | { | ||
121 | /* over-write the handler to be our own one */ | ||
122 | irq->handler = vr4181_timer_interrupt; | ||
123 | |||
124 | /* sets up the frequency */ | ||
125 | *VR4181_RTCL1LREG = COUNTS_PER_JIFFY; | ||
126 | *VR4181_RTCL1HREG = 0; | ||
127 | |||
128 | /* and ack any pending ints */ | ||
129 | *VR4181_RTCINTREG = 0x2; | ||
130 | |||
131 | /* setup irqaction */ | ||
132 | setup_irq(VR4181_IRQ_INT1, irq); | ||
133 | |||
134 | } | ||
135 | |||
136 | void | ||
137 | vr4181_init_time(void) | ||
138 | { | ||
139 | /* setup hookup functions */ | ||
140 | rtc_get_time = vr4181_rtc_get_time; | ||
141 | rtc_set_time = vr4181_rtc_set_time; | ||
142 | |||
143 | board_timer_setup = vr4181_timer_setup; | ||
144 | } | ||
145 | |||
diff --git a/arch/mips/vr4181/osprey/Makefile b/arch/mips/vr4181/osprey/Makefile new file mode 100644 index 000000000000..34be05790883 --- /dev/null +++ b/arch/mips/vr4181/osprey/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for common code of NEC Osprey board | ||
3 | # | ||
4 | |||
5 | obj-y := setup.o prom.o reset.o | ||
6 | |||
7 | obj-$(CONFIG_KGDB) += dbg_io.o | ||
diff --git a/arch/mips/vr4181/osprey/dbg_io.c b/arch/mips/vr4181/osprey/dbg_io.c new file mode 100644 index 000000000000..5e8a84072d5b --- /dev/null +++ b/arch/mips/vr4181/osprey/dbg_io.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * kgdb io functions for osprey. We use the serial port on debug board. | ||
3 | * | ||
4 | * Copyright (C) 2001 MontaVista Software Inc. | ||
5 | * Author: jsun@mvista.com or jsun@junsun.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* ======================= CONFIG ======================== */ | ||
15 | |||
16 | /* [jsun] we use the second serial port for kdb */ | ||
17 | #define BASE 0xb7fffff0 | ||
18 | #define MAX_BAUD 115200 | ||
19 | |||
20 | /* distance in bytes between two serial registers */ | ||
21 | #define REG_OFFSET 1 | ||
22 | |||
23 | /* | ||
24 | * 0 - kgdb does serial init | ||
25 | * 1 - kgdb skip serial init | ||
26 | */ | ||
27 | static int remoteDebugInitialized = 1; | ||
28 | |||
29 | /* | ||
30 | * the default baud rate *if* kgdb does serial init | ||
31 | */ | ||
32 | #define BAUD_DEFAULT UART16550_BAUD_38400 | ||
33 | |||
34 | /* ======================= END OF CONFIG ======================== */ | ||
35 | |||
36 | typedef unsigned char uint8; | ||
37 | typedef unsigned int uint32; | ||
38 | |||
39 | #define UART16550_BAUD_2400 2400 | ||
40 | #define UART16550_BAUD_4800 4800 | ||
41 | #define UART16550_BAUD_9600 9600 | ||
42 | #define UART16550_BAUD_19200 19200 | ||
43 | #define UART16550_BAUD_38400 38400 | ||
44 | #define UART16550_BAUD_57600 57600 | ||
45 | #define UART16550_BAUD_115200 115200 | ||
46 | |||
47 | #define UART16550_PARITY_NONE 0 | ||
48 | #define UART16550_PARITY_ODD 0x08 | ||
49 | #define UART16550_PARITY_EVEN 0x18 | ||
50 | #define UART16550_PARITY_MARK 0x28 | ||
51 | #define UART16550_PARITY_SPACE 0x38 | ||
52 | |||
53 | #define UART16550_DATA_5BIT 0x0 | ||
54 | #define UART16550_DATA_6BIT 0x1 | ||
55 | #define UART16550_DATA_7BIT 0x2 | ||
56 | #define UART16550_DATA_8BIT 0x3 | ||
57 | |||
58 | #define UART16550_STOP_1BIT 0x0 | ||
59 | #define UART16550_STOP_2BIT 0x4 | ||
60 | |||
61 | /* register offset */ | ||
62 | #define OFS_RCV_BUFFER 0 | ||
63 | #define OFS_TRANS_HOLD 0 | ||
64 | #define OFS_SEND_BUFFER 0 | ||
65 | #define OFS_INTR_ENABLE (1*REG_OFFSET) | ||
66 | #define OFS_INTR_ID (2*REG_OFFSET) | ||
67 | #define OFS_DATA_FORMAT (3*REG_OFFSET) | ||
68 | #define OFS_LINE_CONTROL (3*REG_OFFSET) | ||
69 | #define OFS_MODEM_CONTROL (4*REG_OFFSET) | ||
70 | #define OFS_RS232_OUTPUT (4*REG_OFFSET) | ||
71 | #define OFS_LINE_STATUS (5*REG_OFFSET) | ||
72 | #define OFS_MODEM_STATUS (6*REG_OFFSET) | ||
73 | #define OFS_RS232_INPUT (6*REG_OFFSET) | ||
74 | #define OFS_SCRATCH_PAD (7*REG_OFFSET) | ||
75 | |||
76 | #define OFS_DIVISOR_LSB (0*REG_OFFSET) | ||
77 | #define OFS_DIVISOR_MSB (1*REG_OFFSET) | ||
78 | |||
79 | |||
80 | /* memory-mapped read/write of the port */ | ||
81 | #define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) | ||
82 | #define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) | ||
83 | |||
84 | void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) | ||
85 | { | ||
86 | /* disable interrupts */ | ||
87 | UART16550_WRITE(OFS_INTR_ENABLE, 0); | ||
88 | |||
89 | /* set up buad rate */ | ||
90 | { | ||
91 | uint32 divisor; | ||
92 | |||
93 | /* set DIAB bit */ | ||
94 | UART16550_WRITE(OFS_LINE_CONTROL, 0x80); | ||
95 | |||
96 | /* set divisor */ | ||
97 | divisor = MAX_BAUD / baud; | ||
98 | UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); | ||
99 | UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); | ||
100 | |||
101 | /* clear DIAB bit */ | ||
102 | UART16550_WRITE(OFS_LINE_CONTROL, 0x0); | ||
103 | } | ||
104 | |||
105 | /* set data format */ | ||
106 | UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); | ||
107 | } | ||
108 | |||
109 | |||
110 | uint8 getDebugChar(void) | ||
111 | { | ||
112 | if (!remoteDebugInitialized) { | ||
113 | remoteDebugInitialized = 1; | ||
114 | debugInit(BAUD_DEFAULT, | ||
115 | UART16550_DATA_8BIT, | ||
116 | UART16550_PARITY_NONE, UART16550_STOP_1BIT); | ||
117 | } | ||
118 | |||
119 | while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); | ||
120 | return UART16550_READ(OFS_RCV_BUFFER); | ||
121 | } | ||
122 | |||
123 | |||
124 | int putDebugChar(uint8 byte) | ||
125 | { | ||
126 | if (!remoteDebugInitialized) { | ||
127 | remoteDebugInitialized = 1; | ||
128 | debugInit(BAUD_DEFAULT, | ||
129 | UART16550_DATA_8BIT, | ||
130 | UART16550_PARITY_NONE, UART16550_STOP_1BIT); | ||
131 | } | ||
132 | |||
133 | while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); | ||
134 | UART16550_WRITE(OFS_SEND_BUFFER, byte); | ||
135 | return 1; | ||
136 | } | ||
diff --git a/arch/mips/vr4181/osprey/prom.c b/arch/mips/vr4181/osprey/prom.c new file mode 100644 index 000000000000..af0d14561619 --- /dev/null +++ b/arch/mips/vr4181/osprey/prom.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * arch/mips/vr4181/osprey/prom.c | ||
6 | * prom code for osprey. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/bootmem.h> | ||
19 | #include <asm/bootinfo.h> | ||
20 | #include <asm/addrspace.h> | ||
21 | |||
22 | const char *get_system_type(void) | ||
23 | { | ||
24 | return "NEC_Vr41xx Osprey"; | ||
25 | } | ||
26 | |||
27 | /* | ||
28 | * [jsun] right now we assume it is the nec debug monitor, which does | ||
29 | * not pass any arguments. | ||
30 | */ | ||
31 | void __init prom_init(void) | ||
32 | { | ||
33 | // cmdline is now set in default config | ||
34 | // strcpy(arcs_cmdline, "ip=bootp "); | ||
35 | // strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 "); | ||
36 | // strcpy(arcs_cmdline, "ether=0,0x0300,eth0 " | ||
37 | // strcat(arcs_cmdline, "video=vr4181fb:xres:240,yres:320,bpp:8 "); | ||
38 | |||
39 | mips_machgroup = MACH_GROUP_NEC_VR41XX; | ||
40 | mips_machtype = MACH_NEC_OSPREY; | ||
41 | |||
42 | /* 16MB fixed */ | ||
43 | add_memory_region(0, 16 << 20, BOOT_MEM_RAM); | ||
44 | } | ||
45 | |||
46 | unsigned long __init prom_free_prom_memory(void) | ||
47 | { | ||
48 | return 0; | ||
49 | } | ||
diff --git a/arch/mips/vr4181/osprey/reset.c b/arch/mips/vr4181/osprey/reset.c new file mode 100644 index 000000000000..036ae83d89d6 --- /dev/null +++ b/arch/mips/vr4181/osprey/reset.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2 of the License, or (at your | ||
5 | * option) any later version. | ||
6 | * | ||
7 | * Copyright (C) 1997, 2001 Ralf Baechle | ||
8 | * Copyright 2001 MontaVista Software Inc. | ||
9 | * Author: jsun@mvista.com or jsun@junsun.net | ||
10 | */ | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <asm/io.h> | ||
14 | #include <asm/cacheflush.h> | ||
15 | #include <asm/processor.h> | ||
16 | #include <asm/reboot.h> | ||
17 | #include <asm/system.h> | ||
18 | |||
19 | void nec_osprey_restart(char *command) | ||
20 | { | ||
21 | set_c0_status(ST0_ERL); | ||
22 | change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); | ||
23 | flush_cache_all(); | ||
24 | write_c0_wired(0); | ||
25 | __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); | ||
26 | } | ||
27 | |||
28 | void nec_osprey_halt(void) | ||
29 | { | ||
30 | printk(KERN_NOTICE "\n** You can safely turn off the power\n"); | ||
31 | while (1) | ||
32 | __asm__(".set\tmips3\n\t" | ||
33 | "wait\n\t" | ||
34 | ".set\tmips0"); | ||
35 | } | ||
36 | |||
37 | void nec_osprey_power_off(void) | ||
38 | { | ||
39 | nec_osprey_halt(); | ||
40 | } | ||
diff --git a/arch/mips/vr4181/osprey/setup.c b/arch/mips/vr4181/osprey/setup.c new file mode 100644 index 000000000000..2ff7140e7ed7 --- /dev/null +++ b/arch/mips/vr4181/osprey/setup.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/vr4181/setup.c | ||
3 | * | ||
4 | * VR41xx setup routines | ||
5 | * | ||
6 | * Copyright (C) 1999 Bradley D. LaRonde | ||
7 | * Copyright (C) 1999, 2000 Michael Klar | ||
8 | * | ||
9 | * Copyright 2001 MontaVista Software Inc. | ||
10 | * Author: jsun@mvista.com or jsun@junsun.net | ||
11 | * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General Public | ||
14 | * License. See the file "COPYING" in the main directory of this archive | ||
15 | * for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/ide.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <asm/reboot.h> | ||
23 | #include <asm/vr4181/vr4181.h> | ||
24 | #include <asm/io.h> | ||
25 | |||
26 | |||
27 | extern void nec_osprey_restart(char* c); | ||
28 | extern void nec_osprey_halt(void); | ||
29 | extern void nec_osprey_power_off(void); | ||
30 | |||
31 | extern void vr4181_init_serial(void); | ||
32 | extern void vr4181_init_time(void); | ||
33 | |||
34 | static void __init nec_osprey_setup(void) | ||
35 | { | ||
36 | set_io_port_base(VR4181_PORT_BASE); | ||
37 | isa_slot_offset = VR4181_ISAMEM_BASE; | ||
38 | |||
39 | vr4181_init_serial(); | ||
40 | vr4181_init_time(); | ||
41 | |||
42 | _machine_restart = nec_osprey_restart; | ||
43 | _machine_halt = nec_osprey_halt; | ||
44 | _machine_power_off = nec_osprey_power_off; | ||
45 | |||
46 | /* setup resource limit */ | ||
47 | ioport_resource.end = 0xffffffff; | ||
48 | iomem_resource.end = 0xffffffff; | ||
49 | |||
50 | /* [jsun] hack */ | ||
51 | /* | ||
52 | printk("[jsun] hack to change external ISA control register, %x -> %x\n", | ||
53 | (*VR4181_XISACTL), | ||
54 | (*VR4181_XISACTL) | 0x2); | ||
55 | *VR4181_XISACTL |= 0x2; | ||
56 | */ | ||
57 | |||
58 | // *VR4181_GPHIBSTH = 0x2000; | ||
59 | // *VR4181_GPMD0REG = 0x00c0; | ||
60 | // *VR4181_GPINTEN = 1<<6; | ||
61 | |||
62 | /* [jsun] I believe this will get the interrupt type right | ||
63 | * for the ether port. | ||
64 | */ | ||
65 | *VR4181_GPINTTYPL = 0x3000; | ||
66 | } | ||
67 | |||
68 | early_initcall(nec_osprey_setup); | ||