aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/tx4938/common
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-07-25 18:45:45 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:57 -0400
commit23fbee9dd5d2a41d36af49ff8e1669fb0c29fda8 (patch)
tree4e24699269b9d4d2655d961e7a0ffb29931e9b2d /arch/mips/tx4938/common
parent132940401174ed04f9e8f1ae2dad6f47da26ee0a (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/Makefile11
-rw-r--r--arch/mips/tx4938/common/dbgio.c50
-rw-r--r--arch/mips/tx4938/common/irq.c424
-rw-r--r--arch/mips/tx4938/common/irq_handler.S84
-rw-r--r--arch/mips/tx4938/common/prom.c129
-rw-r--r--arch/mips/tx4938/common/rtc_rx5c348.c202
-rw-r--r--arch/mips/tx4938/common/setup.c91
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
9obj-y += prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o
10obj-$(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
38extern u8 txx9_sio_kdbg_rd(void);
39extern int txx9_sio_kdbg_wr( u8 ch );
40
41u8 getDebugChar(void)
42{
43 return (txx9_sio_kdbg_rd());
44}
45
46int 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
39static unsigned int tx4938_irq_cp0_startup(unsigned int irq);
40static void tx4938_irq_cp0_shutdown(unsigned int irq);
41static void tx4938_irq_cp0_enable(unsigned int irq);
42static void tx4938_irq_cp0_disable(unsigned int irq);
43static void tx4938_irq_cp0_mask_and_ack(unsigned int irq);
44static void tx4938_irq_cp0_end(unsigned int irq);
45
46static unsigned int tx4938_irq_pic_startup(unsigned int irq);
47static void tx4938_irq_pic_shutdown(unsigned int irq);
48static void tx4938_irq_pic_enable(unsigned int irq);
49static void tx4938_irq_pic_disable(unsigned int irq);
50static void tx4938_irq_pic_mask_and_ack(unsigned int irq);
51static void tx4938_irq_pic_end(unsigned int irq);
52
53/**********************************************************************************/
54/* Kernel structs for all pic's */
55/**********************************************************************************/
56DEFINE_SPINLOCK(tx4938_cp0_lock);
57DEFINE_SPINLOCK(tx4938_pic_lock);
58
59#define TX4938_CP0_NAME "TX4938-CP0"
60static 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"
72static 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
83static 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
96static void __init
97tx4938_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
111static unsigned int
112tx4938_irq_cp0_startup(unsigned int irq)
113{
114 tx4938_irq_cp0_enable(irq);
115
116 return (0);
117}
118
119static void
120tx4938_irq_cp0_shutdown(unsigned int irq)
121{
122 tx4938_irq_cp0_disable(irq);
123}
124
125static void
126tx4938_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
137static void
138tx4938_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
151static void
152tx4938_irq_cp0_mask_and_ack(unsigned int irq)
153{
154 tx4938_irq_cp0_disable(irq);
155
156 return;
157}
158
159static void
160tx4938_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
173u32
174tx4938_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
233u32
234tx4938_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
284static void
285tx4938_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
299static void __init
300tx4938_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
324static unsigned int
325tx4938_irq_pic_startup(unsigned int irq)
326{
327 tx4938_irq_pic_enable(irq);
328
329 return (0);
330}
331
332static void
333tx4938_irq_pic_shutdown(unsigned int irq)
334{
335 tx4938_irq_pic_disable(irq);
336
337 return;
338}
339
340static void
341tx4938_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
355static void
356tx4938_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
370static void
371tx4938_irq_pic_mask_and_ack(unsigned int irq)
372{
373 tx4938_irq_pic_disable(irq);
374
375 return;
376}
377
378static void
379tx4938_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
392void __init
393tx4938_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
404int
405tx4938_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
54ll_ip7:
55 li a0, TX4938_IRQ_CPU_TIMER
56 move a1, sp
57 jal do_IRQ
58 j ret_from_irq
59
60
61ll_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
71goto_spurious_interrupt:
72 j ret_from_irq
73
74ll_ip1:
75 li a0, TX4938_IRQ_USER1
76 move a1, sp
77 jal do_IRQ
78 j ret_from_irq
79
80ll_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
24static unsigned int __init
25tx4938_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
112unsigned int __init
113tx4938_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
51static 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};
62static int srtc_chipid;
63static int srtc_24h;
64
65static inline int
66spi_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
93static int
94rtc_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
142static unsigned long
143rtc_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
178void __init
179rtc_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
37extern void toshiba_rbtx4938_setup(void);
38extern void rbtx4938_time_init(void);
39
40void __init tx4938_setup(void);
41void __init tx4938_time_init(void);
42void __init tx4938_timer_setup(struct irqaction *irq);
43void dump_cp0(char *key);
44
45void (*__wbflush) (void);
46
47static void
48tx4938_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
63void __init
64plat_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
72void __init
73tx4938_time_init(void)
74{
75 rbtx4938_time_init();
76}
77
78void __init
79tx4938_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}