diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-07-25 18:45:45 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:57 -0400 |
commit | 23fbee9dd5d2a41d36af49ff8e1669fb0c29fda8 (patch) | |
tree | 4e24699269b9d4d2655d961e7a0ffb29931e9b2d /arch/mips/tx4938/common | |
parent | 132940401174ed04f9e8f1ae2dad6f47da26ee0a (diff) |
Support for Toshiba's RBHMA4500 eval board for the TX4938.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/tx4938/common')
-rw-r--r-- | arch/mips/tx4938/common/Makefile | 11 | ||||
-rw-r--r-- | arch/mips/tx4938/common/dbgio.c | 50 | ||||
-rw-r--r-- | arch/mips/tx4938/common/irq.c | 424 | ||||
-rw-r--r-- | arch/mips/tx4938/common/irq_handler.S | 84 | ||||
-rw-r--r-- | arch/mips/tx4938/common/prom.c | 129 | ||||
-rw-r--r-- | arch/mips/tx4938/common/rtc_rx5c348.c | 202 | ||||
-rw-r--r-- | arch/mips/tx4938/common/setup.c | 91 |
7 files changed, 991 insertions, 0 deletions
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile new file mode 100644 index 000000000000..74c95c5bcdbf --- /dev/null +++ b/arch/mips/tx4938/common/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for common code for Toshiba TX4927 based systems | ||
3 | # | ||
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | # | ||
8 | |||
9 | obj-y += prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o | ||
10 | obj-$(CONFIG_KGDB) += dbgio.o | ||
11 | |||
diff --git a/arch/mips/tx4938/common/dbgio.c b/arch/mips/tx4938/common/dbgio.c new file mode 100644 index 000000000000..bea59ff1842a --- /dev/null +++ b/arch/mips/tx4938/common/dbgio.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/common/dbgio.c | ||
3 | * | ||
4 | * kgdb interface for gdb | ||
5 | * | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * source@mvista.com | ||
8 | * | ||
9 | * Copyright 2005 MontaVista Software Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
24 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
25 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License along | ||
28 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | * | ||
31 | * Support for TX4938 in 2.6 - Hiroshi DOYU <Hiroshi_DOYU@montavista.co.jp> | ||
32 | */ | ||
33 | |||
34 | #include <asm/mipsregs.h> | ||
35 | #include <asm/system.h> | ||
36 | #include <asm/tx4938/tx4938_mips.h> | ||
37 | |||
38 | extern u8 txx9_sio_kdbg_rd(void); | ||
39 | extern int txx9_sio_kdbg_wr( u8 ch ); | ||
40 | |||
41 | u8 getDebugChar(void) | ||
42 | { | ||
43 | return (txx9_sio_kdbg_rd()); | ||
44 | } | ||
45 | |||
46 | int putDebugChar(u8 byte) | ||
47 | { | ||
48 | return (txx9_sio_kdbg_wr(byte)); | ||
49 | } | ||
50 | |||
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c new file mode 100644 index 000000000000..4f90d7faf634 --- /dev/null +++ b/arch/mips/tx4938/common/irq.c | |||
@@ -0,0 +1,424 @@ | |||
1 | /* | ||
2 | * linux/arch/mps/tx4938/common/irq.c | ||
3 | * | ||
4 | * Common tx4938 irq handler | ||
5 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
6 | * | ||
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | * | ||
12 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
13 | */ | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel_stat.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/signal.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/timex.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/random.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <asm/bitops.h> | ||
28 | #include <asm/bootinfo.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/irq.h> | ||
31 | #include <asm/mipsregs.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/tx4938/rbtx4938.h> | ||
34 | |||
35 | /**********************************************************************************/ | ||
36 | /* Forwad definitions for all pic's */ | ||
37 | /**********************************************************************************/ | ||
38 | |||
39 | static unsigned int tx4938_irq_cp0_startup(unsigned int irq); | ||
40 | static void tx4938_irq_cp0_shutdown(unsigned int irq); | ||
41 | static void tx4938_irq_cp0_enable(unsigned int irq); | ||
42 | static void tx4938_irq_cp0_disable(unsigned int irq); | ||
43 | static void tx4938_irq_cp0_mask_and_ack(unsigned int irq); | ||
44 | static void tx4938_irq_cp0_end(unsigned int irq); | ||
45 | |||
46 | static unsigned int tx4938_irq_pic_startup(unsigned int irq); | ||
47 | static void tx4938_irq_pic_shutdown(unsigned int irq); | ||
48 | static void tx4938_irq_pic_enable(unsigned int irq); | ||
49 | static void tx4938_irq_pic_disable(unsigned int irq); | ||
50 | static void tx4938_irq_pic_mask_and_ack(unsigned int irq); | ||
51 | static void tx4938_irq_pic_end(unsigned int irq); | ||
52 | |||
53 | /**********************************************************************************/ | ||
54 | /* Kernel structs for all pic's */ | ||
55 | /**********************************************************************************/ | ||
56 | DEFINE_SPINLOCK(tx4938_cp0_lock); | ||
57 | DEFINE_SPINLOCK(tx4938_pic_lock); | ||
58 | |||
59 | #define TX4938_CP0_NAME "TX4938-CP0" | ||
60 | static struct hw_interrupt_type tx4938_irq_cp0_type = { | ||
61 | .typename = TX4938_CP0_NAME, | ||
62 | .startup = tx4938_irq_cp0_startup, | ||
63 | .shutdown = tx4938_irq_cp0_shutdown, | ||
64 | .enable = tx4938_irq_cp0_enable, | ||
65 | .disable = tx4938_irq_cp0_disable, | ||
66 | .ack = tx4938_irq_cp0_mask_and_ack, | ||
67 | .end = tx4938_irq_cp0_end, | ||
68 | .set_affinity = NULL | ||
69 | }; | ||
70 | |||
71 | #define TX4938_PIC_NAME "TX4938-PIC" | ||
72 | static struct hw_interrupt_type tx4938_irq_pic_type = { | ||
73 | .typename = TX4938_PIC_NAME, | ||
74 | .startup = tx4938_irq_pic_startup, | ||
75 | .shutdown = tx4938_irq_pic_shutdown, | ||
76 | .enable = tx4938_irq_pic_enable, | ||
77 | .disable = tx4938_irq_pic_disable, | ||
78 | .ack = tx4938_irq_pic_mask_and_ack, | ||
79 | .end = tx4938_irq_pic_end, | ||
80 | .set_affinity = NULL | ||
81 | }; | ||
82 | |||
83 | static struct irqaction tx4938_irq_pic_action = { | ||
84 | .handler = no_action, | ||
85 | .flags = 0, | ||
86 | .mask = CPU_MASK_NONE, | ||
87 | .name = TX4938_PIC_NAME | ||
88 | }; | ||
89 | |||
90 | /**********************************************************************************/ | ||
91 | /* Functions for cp0 */ | ||
92 | /**********************************************************************************/ | ||
93 | |||
94 | #define tx4938_irq_cp0_mask(irq) ( 1 << ( irq-TX4938_IRQ_CP0_BEG+8 ) ) | ||
95 | |||
96 | static void __init | ||
97 | tx4938_irq_cp0_init(void) | ||
98 | { | ||
99 | int i; | ||
100 | |||
101 | for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++) { | ||
102 | irq_desc[i].status = IRQ_DISABLED; | ||
103 | irq_desc[i].action = 0; | ||
104 | irq_desc[i].depth = 1; | ||
105 | irq_desc[i].handler = &tx4938_irq_cp0_type; | ||
106 | } | ||
107 | |||
108 | return; | ||
109 | } | ||
110 | |||
111 | static unsigned int | ||
112 | tx4938_irq_cp0_startup(unsigned int irq) | ||
113 | { | ||
114 | tx4938_irq_cp0_enable(irq); | ||
115 | |||
116 | return (0); | ||
117 | } | ||
118 | |||
119 | static void | ||
120 | tx4938_irq_cp0_shutdown(unsigned int irq) | ||
121 | { | ||
122 | tx4938_irq_cp0_disable(irq); | ||
123 | } | ||
124 | |||
125 | static void | ||
126 | tx4938_irq_cp0_enable(unsigned int irq) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | |||
130 | spin_lock_irqsave(&tx4938_cp0_lock, flags); | ||
131 | |||
132 | set_c0_status(tx4938_irq_cp0_mask(irq)); | ||
133 | |||
134 | spin_unlock_irqrestore(&tx4938_cp0_lock, flags); | ||
135 | } | ||
136 | |||
137 | static void | ||
138 | tx4938_irq_cp0_disable(unsigned int irq) | ||
139 | { | ||
140 | unsigned long flags; | ||
141 | |||
142 | spin_lock_irqsave(&tx4938_cp0_lock, flags); | ||
143 | |||
144 | clear_c0_status(tx4938_irq_cp0_mask(irq)); | ||
145 | |||
146 | spin_unlock_irqrestore(&tx4938_cp0_lock, flags); | ||
147 | |||
148 | return; | ||
149 | } | ||
150 | |||
151 | static void | ||
152 | tx4938_irq_cp0_mask_and_ack(unsigned int irq) | ||
153 | { | ||
154 | tx4938_irq_cp0_disable(irq); | ||
155 | |||
156 | return; | ||
157 | } | ||
158 | |||
159 | static void | ||
160 | tx4938_irq_cp0_end(unsigned int irq) | ||
161 | { | ||
162 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { | ||
163 | tx4938_irq_cp0_enable(irq); | ||
164 | } | ||
165 | |||
166 | return; | ||
167 | } | ||
168 | |||
169 | /**********************************************************************************/ | ||
170 | /* Functions for pic */ | ||
171 | /**********************************************************************************/ | ||
172 | |||
173 | u32 | ||
174 | tx4938_irq_pic_addr(int irq) | ||
175 | { | ||
176 | /* MVMCP -- need to formulize this */ | ||
177 | irq -= TX4938_IRQ_PIC_BEG; | ||
178 | |||
179 | switch (irq) { | ||
180 | case 17: | ||
181 | case 16: | ||
182 | case 1: | ||
183 | case 0:{ | ||
184 | return (TX4938_MKA(TX4938_IRC_IRLVL0)); | ||
185 | } | ||
186 | case 19: | ||
187 | case 18: | ||
188 | case 3: | ||
189 | case 2:{ | ||
190 | return (TX4938_MKA(TX4938_IRC_IRLVL1)); | ||
191 | } | ||
192 | case 21: | ||
193 | case 20: | ||
194 | case 5: | ||
195 | case 4:{ | ||
196 | return (TX4938_MKA(TX4938_IRC_IRLVL2)); | ||
197 | } | ||
198 | case 23: | ||
199 | case 22: | ||
200 | case 7: | ||
201 | case 6:{ | ||
202 | return (TX4938_MKA(TX4938_IRC_IRLVL3)); | ||
203 | } | ||
204 | case 25: | ||
205 | case 24: | ||
206 | case 9: | ||
207 | case 8:{ | ||
208 | return (TX4938_MKA(TX4938_IRC_IRLVL4)); | ||
209 | } | ||
210 | case 27: | ||
211 | case 26: | ||
212 | case 11: | ||
213 | case 10:{ | ||
214 | return (TX4938_MKA(TX4938_IRC_IRLVL5)); | ||
215 | } | ||
216 | case 29: | ||
217 | case 28: | ||
218 | case 13: | ||
219 | case 12:{ | ||
220 | return (TX4938_MKA(TX4938_IRC_IRLVL6)); | ||
221 | } | ||
222 | case 31: | ||
223 | case 30: | ||
224 | case 15: | ||
225 | case 14:{ | ||
226 | return (TX4938_MKA(TX4938_IRC_IRLVL7)); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | return (0); | ||
231 | } | ||
232 | |||
233 | u32 | ||
234 | tx4938_irq_pic_mask(int irq) | ||
235 | { | ||
236 | /* MVMCP -- need to formulize this */ | ||
237 | irq -= TX4938_IRQ_PIC_BEG; | ||
238 | |||
239 | switch (irq) { | ||
240 | case 31: | ||
241 | case 29: | ||
242 | case 27: | ||
243 | case 25: | ||
244 | case 23: | ||
245 | case 21: | ||
246 | case 19: | ||
247 | case 17:{ | ||
248 | return (0x07000000); | ||
249 | } | ||
250 | case 30: | ||
251 | case 28: | ||
252 | case 26: | ||
253 | case 24: | ||
254 | case 22: | ||
255 | case 20: | ||
256 | case 18: | ||
257 | case 16:{ | ||
258 | return (0x00070000); | ||
259 | } | ||
260 | case 15: | ||
261 | case 13: | ||
262 | case 11: | ||
263 | case 9: | ||
264 | case 7: | ||
265 | case 5: | ||
266 | case 3: | ||
267 | case 1:{ | ||
268 | return (0x00000700); | ||
269 | } | ||
270 | case 14: | ||
271 | case 12: | ||
272 | case 10: | ||
273 | case 8: | ||
274 | case 6: | ||
275 | case 4: | ||
276 | case 2: | ||
277 | case 0:{ | ||
278 | return (0x00000007); | ||
279 | } | ||
280 | } | ||
281 | return (0x00000000); | ||
282 | } | ||
283 | |||
284 | static void | ||
285 | tx4938_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, unsigned set_bits) | ||
286 | { | ||
287 | unsigned long val = 0; | ||
288 | |||
289 | val = TX4938_RD(pic_reg); | ||
290 | val &= (~clr_bits); | ||
291 | val |= (set_bits); | ||
292 | TX4938_WR(pic_reg, val); | ||
293 | mmiowb(); | ||
294 | TX4938_RD(pic_reg); | ||
295 | |||
296 | return; | ||
297 | } | ||
298 | |||
299 | static void __init | ||
300 | tx4938_irq_pic_init(void) | ||
301 | { | ||
302 | unsigned long flags; | ||
303 | int i; | ||
304 | |||
305 | for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++) { | ||
306 | irq_desc[i].status = IRQ_DISABLED; | ||
307 | irq_desc[i].action = 0; | ||
308 | irq_desc[i].depth = 2; | ||
309 | irq_desc[i].handler = &tx4938_irq_pic_type; | ||
310 | } | ||
311 | |||
312 | setup_irq(TX4938_IRQ_NEST_PIC_ON_CP0, &tx4938_irq_pic_action); | ||
313 | |||
314 | spin_lock_irqsave(&tx4938_pic_lock, flags); | ||
315 | |||
316 | TX4938_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */ | ||
317 | TX4938_WR(0xff1ff600, TX4938_RD(0xff1ff600) | 0x1); /* irq enable */ | ||
318 | |||
319 | spin_unlock_irqrestore(&tx4938_pic_lock, flags); | ||
320 | |||
321 | return; | ||
322 | } | ||
323 | |||
324 | static unsigned int | ||
325 | tx4938_irq_pic_startup(unsigned int irq) | ||
326 | { | ||
327 | tx4938_irq_pic_enable(irq); | ||
328 | |||
329 | return (0); | ||
330 | } | ||
331 | |||
332 | static void | ||
333 | tx4938_irq_pic_shutdown(unsigned int irq) | ||
334 | { | ||
335 | tx4938_irq_pic_disable(irq); | ||
336 | |||
337 | return; | ||
338 | } | ||
339 | |||
340 | static void | ||
341 | tx4938_irq_pic_enable(unsigned int irq) | ||
342 | { | ||
343 | unsigned long flags; | ||
344 | |||
345 | spin_lock_irqsave(&tx4938_pic_lock, flags); | ||
346 | |||
347 | tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), 0, | ||
348 | tx4938_irq_pic_mask(irq)); | ||
349 | |||
350 | spin_unlock_irqrestore(&tx4938_pic_lock, flags); | ||
351 | |||
352 | return; | ||
353 | } | ||
354 | |||
355 | static void | ||
356 | tx4938_irq_pic_disable(unsigned int irq) | ||
357 | { | ||
358 | unsigned long flags; | ||
359 | |||
360 | spin_lock_irqsave(&tx4938_pic_lock, flags); | ||
361 | |||
362 | tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), | ||
363 | tx4938_irq_pic_mask(irq), 0); | ||
364 | |||
365 | spin_unlock_irqrestore(&tx4938_pic_lock, flags); | ||
366 | |||
367 | return; | ||
368 | } | ||
369 | |||
370 | static void | ||
371 | tx4938_irq_pic_mask_and_ack(unsigned int irq) | ||
372 | { | ||
373 | tx4938_irq_pic_disable(irq); | ||
374 | |||
375 | return; | ||
376 | } | ||
377 | |||
378 | static void | ||
379 | tx4938_irq_pic_end(unsigned int irq) | ||
380 | { | ||
381 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { | ||
382 | tx4938_irq_pic_enable(irq); | ||
383 | } | ||
384 | |||
385 | return; | ||
386 | } | ||
387 | |||
388 | /**********************************************************************************/ | ||
389 | /* Main init functions */ | ||
390 | /**********************************************************************************/ | ||
391 | |||
392 | void __init | ||
393 | tx4938_irq_init(void) | ||
394 | { | ||
395 | extern asmlinkage void tx4938_irq_handler(void); | ||
396 | |||
397 | tx4938_irq_cp0_init(); | ||
398 | tx4938_irq_pic_init(); | ||
399 | set_except_vector(0, tx4938_irq_handler); | ||
400 | |||
401 | return; | ||
402 | } | ||
403 | |||
404 | int | ||
405 | tx4938_irq_nested(void) | ||
406 | { | ||
407 | int sw_irq = 0; | ||
408 | u32 level2; | ||
409 | |||
410 | level2 = TX4938_RD(0xff1ff6a0); | ||
411 | if ((level2 & 0x10000) == 0) { | ||
412 | level2 &= 0x1f; | ||
413 | sw_irq = TX4938_IRQ_PIC_BEG + level2; | ||
414 | if (sw_irq == 26) { | ||
415 | { | ||
416 | extern int toshiba_rbtx4938_irq_nested(int sw_irq); | ||
417 | sw_irq = toshiba_rbtx4938_irq_nested(sw_irq); | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | wbflush(); | ||
423 | return (sw_irq); | ||
424 | } | ||
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S new file mode 100644 index 000000000000..1b2f72bac42d --- /dev/null +++ b/arch/mips/tx4938/common/irq_handler.S | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/common/handler.S | ||
3 | * | ||
4 | * Primary interrupt handler for tx4938 based systems | ||
5 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
6 | * | ||
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | * | ||
12 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
13 | */ | ||
14 | #include <asm/asm.h> | ||
15 | #include <asm/mipsregs.h> | ||
16 | #include <asm/addrspace.h> | ||
17 | #include <asm/regdef.h> | ||
18 | #include <asm/stackframe.h> | ||
19 | #include <asm/tx4938/rbtx4938.h> | ||
20 | |||
21 | |||
22 | .align 5 | ||
23 | NESTED(tx4938_irq_handler, PT_SIZE, sp) | ||
24 | SAVE_ALL | ||
25 | CLI | ||
26 | .set at | ||
27 | |||
28 | mfc0 t0, CP0_CAUSE | ||
29 | mfc0 t1, CP0_STATUS | ||
30 | and t0, t1 | ||
31 | |||
32 | andi t1, t0, STATUSF_IP7 /* cpu timer */ | ||
33 | bnez t1, ll_ip7 | ||
34 | |||
35 | /* IP6..IP3 multiplexed -- do not use */ | ||
36 | |||
37 | andi t1, t0, STATUSF_IP2 /* tx4938 pic */ | ||
38 | bnez t1, ll_ip2 | ||
39 | |||
40 | andi t1, t0, STATUSF_IP1 /* user line 1 */ | ||
41 | bnez t1, ll_ip1 | ||
42 | |||
43 | andi t1, t0, STATUSF_IP0 /* user line 0 */ | ||
44 | bnez t1, ll_ip0 | ||
45 | |||
46 | .set reorder | ||
47 | |||
48 | nop | ||
49 | END(tx4938_irq_handler) | ||
50 | |||
51 | .align 5 | ||
52 | |||
53 | |||
54 | ll_ip7: | ||
55 | li a0, TX4938_IRQ_CPU_TIMER | ||
56 | move a1, sp | ||
57 | jal do_IRQ | ||
58 | j ret_from_irq | ||
59 | |||
60 | |||
61 | ll_ip2: | ||
62 | jal tx4938_irq_nested | ||
63 | nop | ||
64 | beqz v0, goto_spurious_interrupt | ||
65 | nop | ||
66 | move a0, v0 | ||
67 | move a1, sp | ||
68 | jal do_IRQ | ||
69 | j ret_from_irq | ||
70 | |||
71 | goto_spurious_interrupt: | ||
72 | j ret_from_irq | ||
73 | |||
74 | ll_ip1: | ||
75 | li a0, TX4938_IRQ_USER1 | ||
76 | move a1, sp | ||
77 | jal do_IRQ | ||
78 | j ret_from_irq | ||
79 | |||
80 | ll_ip0: | ||
81 | li a0, TX4938_IRQ_USER0 | ||
82 | move a1, sp | ||
83 | jal do_IRQ | ||
84 | j ret_from_irq | ||
diff --git a/arch/mips/tx4938/common/prom.c b/arch/mips/tx4938/common/prom.c new file mode 100644 index 000000000000..3189a65f7d7e --- /dev/null +++ b/arch/mips/tx4938/common/prom.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/common/prom.c | ||
3 | * | ||
4 | * common tx4938 memory interface | ||
5 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
6 | * | ||
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | * | ||
12 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/bootmem.h> | ||
19 | |||
20 | #include <asm/addrspace.h> | ||
21 | #include <asm/bootinfo.h> | ||
22 | #include <asm/tx4938/tx4938.h> | ||
23 | |||
24 | static unsigned int __init | ||
25 | tx4938_process_sdccr(u64 * addr) | ||
26 | { | ||
27 | u64 val; | ||
28 | unsigned int sdccr_ce; | ||
29 | unsigned int sdccr_rs; | ||
30 | unsigned int sdccr_cs; | ||
31 | unsigned int sdccr_mw; | ||
32 | unsigned int rs = 0; | ||
33 | unsigned int cs = 0; | ||
34 | unsigned int mw = 0; | ||
35 | unsigned int bc = 4; | ||
36 | unsigned int msize = 0; | ||
37 | |||
38 | val = (*((vu64 *) (addr))); | ||
39 | |||
40 | /* MVMCP -- need #defs for these bits masks */ | ||
41 | sdccr_ce = ((val & (1 << 10)) >> 10); | ||
42 | sdccr_rs = ((val & (3 << 5)) >> 5); | ||
43 | sdccr_cs = ((val & (7 << 2)) >> 2); | ||
44 | sdccr_mw = ((val & (1 << 0)) >> 0); | ||
45 | |||
46 | if (sdccr_ce) { | ||
47 | switch (sdccr_rs) { | ||
48 | case 0:{ | ||
49 | rs = 2048; | ||
50 | break; | ||
51 | } | ||
52 | case 1:{ | ||
53 | rs = 4096; | ||
54 | break; | ||
55 | } | ||
56 | case 2:{ | ||
57 | rs = 8192; | ||
58 | break; | ||
59 | } | ||
60 | default:{ | ||
61 | rs = 0; | ||
62 | break; | ||
63 | } | ||
64 | } | ||
65 | switch (sdccr_cs) { | ||
66 | case 0:{ | ||
67 | cs = 256; | ||
68 | break; | ||
69 | } | ||
70 | case 1:{ | ||
71 | cs = 512; | ||
72 | break; | ||
73 | } | ||
74 | case 2:{ | ||
75 | cs = 1024; | ||
76 | break; | ||
77 | } | ||
78 | case 3:{ | ||
79 | cs = 2048; | ||
80 | break; | ||
81 | } | ||
82 | case 4:{ | ||
83 | cs = 4096; | ||
84 | break; | ||
85 | } | ||
86 | default:{ | ||
87 | cs = 0; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | switch (sdccr_mw) { | ||
92 | case 0:{ | ||
93 | mw = 8; | ||
94 | break; | ||
95 | } /* 8 bytes = 64 bits */ | ||
96 | case 1:{ | ||
97 | mw = 4; | ||
98 | break; | ||
99 | } /* 4 bytes = 32 bits */ | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /* bytes per chip MB per chip bank count */ | ||
104 | msize = (((rs * cs * mw) / (1024 * 1024)) * (bc)); | ||
105 | |||
106 | /* MVMCP -- bc hard coded to 4 from table 9.3.1 */ | ||
107 | /* boad supports bc=2 but no way to detect */ | ||
108 | |||
109 | return (msize); | ||
110 | } | ||
111 | |||
112 | unsigned int __init | ||
113 | tx4938_get_mem_size(void) | ||
114 | { | ||
115 | unsigned int c0; | ||
116 | unsigned int c1; | ||
117 | unsigned int c2; | ||
118 | unsigned int c3; | ||
119 | unsigned int total; | ||
120 | |||
121 | /* MVMCP -- need #defs for these registers */ | ||
122 | c0 = tx4938_process_sdccr((u64 *) 0xff1f8000); | ||
123 | c1 = tx4938_process_sdccr((u64 *) 0xff1f8008); | ||
124 | c2 = tx4938_process_sdccr((u64 *) 0xff1f8010); | ||
125 | c3 = tx4938_process_sdccr((u64 *) 0xff1f8018); | ||
126 | total = c0 + c1 + c2 + c3; | ||
127 | |||
128 | return (total); | ||
129 | } | ||
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c new file mode 100644 index 000000000000..d249edbb6af4 --- /dev/null +++ b/arch/mips/tx4938/common/rtc_rx5c348.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * RTC routines for RICOH Rx5C348 SPI chip. | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/time.h> | ||
17 | #include <asm/time.h> | ||
18 | #include <asm/tx4938/spi.h> | ||
19 | |||
20 | #define EPOCH 2000 | ||
21 | |||
22 | /* registers */ | ||
23 | #define Rx5C348_REG_SECOND 0 | ||
24 | #define Rx5C348_REG_MINUTE 1 | ||
25 | #define Rx5C348_REG_HOUR 2 | ||
26 | #define Rx5C348_REG_WEEK 3 | ||
27 | #define Rx5C348_REG_DAY 4 | ||
28 | #define Rx5C348_REG_MONTH 5 | ||
29 | #define Rx5C348_REG_YEAR 6 | ||
30 | #define Rx5C348_REG_ADJUST 7 | ||
31 | #define Rx5C348_REG_ALARM_W_MIN 8 | ||
32 | #define Rx5C348_REG_ALARM_W_HOUR 9 | ||
33 | #define Rx5C348_REG_ALARM_W_WEEK 10 | ||
34 | #define Rx5C348_REG_ALARM_D_MIN 11 | ||
35 | #define Rx5C348_REG_ALARM_D_HOUR 12 | ||
36 | #define Rx5C348_REG_CTL1 14 | ||
37 | #define Rx5C348_REG_CTL2 15 | ||
38 | |||
39 | /* register bits */ | ||
40 | #define Rx5C348_BIT_PM 0x20 /* REG_HOUR */ | ||
41 | #define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */ | ||
42 | #define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */ | ||
43 | #define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 */ | ||
44 | |||
45 | /* commands */ | ||
46 | #define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */ | ||
47 | #define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */ | ||
48 | #define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */ | ||
49 | #define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */ | ||
50 | |||
51 | static struct spi_dev_desc srtc_dev_desc = { | ||
52 | .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */ | ||
53 | .tcss = 31, | ||
54 | .tcsh = 1, | ||
55 | .tcsr = 62, | ||
56 | /* 31us for Tcss (62us for Tcsr) is required for carry operation) */ | ||
57 | .byteorder = 1, /* MSB-First */ | ||
58 | .polarity = 0, /* High-Active */ | ||
59 | .phase = 1, /* Shift-Then-Sample */ | ||
60 | |||
61 | }; | ||
62 | static int srtc_chipid; | ||
63 | static int srtc_24h; | ||
64 | |||
65 | static inline int | ||
66 | spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count) | ||
67 | { | ||
68 | unsigned char *inbufs[1], *outbufs[1]; | ||
69 | unsigned int incounts[2], outcounts[2]; | ||
70 | inbufs[0] = inbuf; | ||
71 | incounts[0] = count; | ||
72 | incounts[1] = 0; | ||
73 | outbufs[0] = outbuf; | ||
74 | outcounts[0] = count; | ||
75 | outcounts[1] = 0; | ||
76 | return txx9_spi_io(srtc_chipid, &srtc_dev_desc, | ||
77 | inbufs, incounts, outbufs, outcounts, 0); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Conversion between binary and BCD. | ||
82 | */ | ||
83 | #ifndef BCD_TO_BIN | ||
84 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) | ||
85 | #endif | ||
86 | |||
87 | #ifndef BIN_TO_BCD | ||
88 | #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) | ||
89 | #endif | ||
90 | |||
91 | /* RTC-dependent code for time.c */ | ||
92 | |||
93 | static int | ||
94 | rtc_rx5c348_set_time(unsigned long t) | ||
95 | { | ||
96 | unsigned char inbuf[8]; | ||
97 | struct rtc_time tm; | ||
98 | u8 year, month, day, hour, minute, second, century; | ||
99 | |||
100 | /* convert */ | ||
101 | to_tm(t, &tm); | ||
102 | |||
103 | year = tm.tm_year % 100; | ||
104 | month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */ | ||
105 | day = tm.tm_mday; | ||
106 | hour = tm.tm_hour; | ||
107 | minute = tm.tm_min; | ||
108 | second = tm.tm_sec; | ||
109 | century = tm.tm_year / 100; | ||
110 | |||
111 | inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND); | ||
112 | BIN_TO_BCD(second); | ||
113 | inbuf[1] = second; | ||
114 | BIN_TO_BCD(minute); | ||
115 | inbuf[2] = minute; | ||
116 | |||
117 | if (srtc_24h) { | ||
118 | BIN_TO_BCD(hour); | ||
119 | inbuf[3] = hour; | ||
120 | } else { | ||
121 | /* hour 0 is AM12, noon is PM12 */ | ||
122 | inbuf[3] = 0; | ||
123 | if (hour >= 12) | ||
124 | inbuf[3] = Rx5C348_BIT_PM; | ||
125 | hour = (hour + 11) % 12 + 1; | ||
126 | BIN_TO_BCD(hour); | ||
127 | inbuf[3] |= hour; | ||
128 | } | ||
129 | inbuf[4] = 0; /* ignore week */ | ||
130 | BIN_TO_BCD(day); | ||
131 | inbuf[5] = day; | ||
132 | BIN_TO_BCD(month); | ||
133 | inbuf[6] = month; | ||
134 | if (century >= 20) | ||
135 | inbuf[6] |= Rx5C348_BIT_Y2K; | ||
136 | BIN_TO_BCD(year); | ||
137 | inbuf[7] = year; | ||
138 | /* write in one transfer to avoid data inconsistency */ | ||
139 | return spi_rtc_io(inbuf, NULL, 8); | ||
140 | } | ||
141 | |||
142 | static unsigned long | ||
143 | rtc_rx5c348_get_time(void) | ||
144 | { | ||
145 | unsigned char inbuf[8], outbuf[8]; | ||
146 | unsigned int year, month, day, hour, minute, second; | ||
147 | |||
148 | inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND); | ||
149 | memset(inbuf + 1, 0, 7); | ||
150 | /* read in one transfer to avoid data inconsistency */ | ||
151 | if (spi_rtc_io(inbuf, outbuf, 8)) | ||
152 | return 0; | ||
153 | second = outbuf[1]; | ||
154 | BCD_TO_BIN(second); | ||
155 | minute = outbuf[2]; | ||
156 | BCD_TO_BIN(minute); | ||
157 | if (srtc_24h) { | ||
158 | hour = outbuf[3]; | ||
159 | BCD_TO_BIN(hour); | ||
160 | } else { | ||
161 | hour = outbuf[3] & ~Rx5C348_BIT_PM; | ||
162 | BCD_TO_BIN(hour); | ||
163 | hour %= 12; | ||
164 | if (outbuf[3] & Rx5C348_BIT_PM) | ||
165 | hour += 12; | ||
166 | } | ||
167 | day = outbuf[5]; | ||
168 | BCD_TO_BIN(day); | ||
169 | month = outbuf[6] & ~Rx5C348_BIT_Y2K; | ||
170 | BCD_TO_BIN(month); | ||
171 | year = outbuf[7]; | ||
172 | BCD_TO_BIN(year); | ||
173 | year += EPOCH; | ||
174 | |||
175 | return mktime(year, month, day, hour, minute, second); | ||
176 | } | ||
177 | |||
178 | void __init | ||
179 | rtc_rx5c348_init(int chipid) | ||
180 | { | ||
181 | unsigned char inbuf[2], outbuf[2]; | ||
182 | srtc_chipid = chipid; | ||
183 | /* turn on RTC if it is not on */ | ||
184 | inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2); | ||
185 | inbuf[1] = 0; | ||
186 | spi_rtc_io(inbuf, outbuf, 2); | ||
187 | if (outbuf[1] & Rx5C348_BIT_XSTP) { | ||
188 | inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2); | ||
189 | inbuf[1] = 0; | ||
190 | spi_rtc_io(inbuf, NULL, 2); | ||
191 | } | ||
192 | |||
193 | inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1); | ||
194 | inbuf[1] = 0; | ||
195 | spi_rtc_io(inbuf, outbuf, 2); | ||
196 | if (outbuf[1] & Rx5C348_BIT_24H) | ||
197 | srtc_24h = 1; | ||
198 | |||
199 | /* set the function pointers */ | ||
200 | rtc_get_time = rtc_rx5c348_get_time; | ||
201 | rtc_set_time = rtc_rx5c348_set_time; | ||
202 | } | ||
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c new file mode 100644 index 000000000000..fc992953bf95 --- /dev/null +++ b/arch/mips/tx4938/common/setup.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/common/setup.c | ||
3 | * | ||
4 | * common tx4938 setup routines | ||
5 | * | ||
6 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
7 | * terms of the GNU General Public License version 2. This program is | ||
8 | * licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
12 | */ | ||
13 | |||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel_stat.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/signal.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/timex.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/random.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <asm/bitops.h> | ||
28 | #include <asm/bootinfo.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/irq.h> | ||
31 | #include <asm/mipsregs.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/time.h> | ||
34 | #include <asm/time.h> | ||
35 | #include <asm/tx4938/rbtx4938.h> | ||
36 | |||
37 | extern void toshiba_rbtx4938_setup(void); | ||
38 | extern void rbtx4938_time_init(void); | ||
39 | |||
40 | void __init tx4938_setup(void); | ||
41 | void __init tx4938_time_init(void); | ||
42 | void __init tx4938_timer_setup(struct irqaction *irq); | ||
43 | void dump_cp0(char *key); | ||
44 | |||
45 | void (*__wbflush) (void); | ||
46 | |||
47 | static void | ||
48 | tx4938_write_buffer_flush(void) | ||
49 | { | ||
50 | mmiowb(); | ||
51 | |||
52 | __asm__ __volatile__( | ||
53 | ".set push\n\t" | ||
54 | ".set noreorder\n\t" | ||
55 | "lw $0,%0\n\t" | ||
56 | "nop\n\t" | ||
57 | ".set pop" | ||
58 | : /* no output */ | ||
59 | : "m" (*(int *)KSEG1) | ||
60 | : "memory"); | ||
61 | } | ||
62 | |||
63 | void __init | ||
64 | plat_setup(void) | ||
65 | { | ||
66 | board_time_init = tx4938_time_init; | ||
67 | board_timer_setup = tx4938_timer_setup; | ||
68 | __wbflush = tx4938_write_buffer_flush; | ||
69 | toshiba_rbtx4938_setup(); | ||
70 | } | ||
71 | |||
72 | void __init | ||
73 | tx4938_time_init(void) | ||
74 | { | ||
75 | rbtx4938_time_init(); | ||
76 | } | ||
77 | |||
78 | void __init | ||
79 | tx4938_timer_setup(struct irqaction *irq) | ||
80 | { | ||
81 | u32 count; | ||
82 | u32 c1; | ||
83 | u32 c2; | ||
84 | |||
85 | setup_irq(TX4938_IRQ_CPU_TIMER, irq); | ||
86 | |||
87 | c1 = read_c0_count(); | ||
88 | count = c1 + (mips_hpt_frequency / HZ); | ||
89 | write_c0_compare(count); | ||
90 | c2 = read_c0_count(); | ||
91 | } | ||