ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / syslib / ppc4xx_serial.c
1 /*
2  * arch/ppc/syslib/ppc405_serial.c
3  *
4  * Author: MontaVista Software, Inc.
5  *              frank_rowand@mvista.com or source@mvista.com
6  *              debbie_chu@mvista.com
7  *
8  * This is a fairly standard 165xx type device that will eventually
9  * be merged with other similar processor/boards.       -- Dan
10  *
11  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
12  * the terms of the GNU General Public License version 2.  This program
13  * is licensed "as is" without any warranty of any kind, whether express
14  * or implied.
15  *
16  * Console I/O support for Early kernel bringup.
17  */
18
19 #include <linux/config.h>
20
21 #if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR)
22
23 #ifdef CONFIG_KGDB
24 #include <asm/kgdb.h>
25 #include <linux/init.h>
26 #endif
27
28 #ifdef CONFIG_DEBUG_BRINGUP
29
30 #include <linux/console.h>
31
32 extern void ftr_reset_preferred_console(void);
33
34
35 static int ppc405_sercons_setup(struct console *co, char *options)
36 {
37 #ifdef CONFIG_UART0_DEBUG_CONSOLE
38     volatile unsigned char *uart_dll  = (char *)0xef600300;
39     volatile unsigned char *uart_fcr  = (char *)0xef600302;
40     volatile unsigned char *uart_lcr  = (char *)0xef600303;
41 #endif
42
43 #ifdef CONFIG_UART1_DEBUG_CONSOLE
44     volatile unsigned char *uart_dll  = (char *)0xef600400;
45     volatile unsigned char *uart_fcr  = (char *)0xef600402;
46     volatile unsigned char *uart_lcr  = (char *)0xef600403;
47 #endif
48
49     *uart_lcr = *uart_lcr | 0x80;   /* DLAB on  */
50
51 /* ftr revisit - there is no config option for this
52 **  also see include/asm-ppc/ppc405_serial.h
53 **
54 ** #define CONFIG_IBM405GP_INTERNAL_CLOCK
55 */
56
57
58 #ifdef  CONFIG_IBM405GP_INTERNAL_CLOCK
59     /* ftr revisit
60     ** why is bit 19 of chcr0 (0x1000) being set?
61     */
62     /* 0x2a results in data corruption, kgdb works with 0x28 */
63     *uart_dll = 0x28;               /* 9600 baud */
64     _put_CHCR0((_get_CHCR0() & 0xffffe000) | 0x103e);
65 #else
66     *uart_dll = 0x48;               /* 9600 baud */
67 #endif
68     *uart_lcr = *uart_lcr & 0x7f;   /* DLAB off */
69
70     return 0;
71 }
72
73
74 /*
75  * This is a bringup hack, writing directly to uart0 or uart1
76  */
77
78 static void
79 ppc405_sercons_write(struct console *co, const char *ptr,
80             unsigned nb)
81 {
82     int i;
83
84 #ifdef CONFIG_UART0_DEBUG_CONSOLE
85     volatile unsigned char *uart_xmit = (char *)0xef600300;
86     volatile unsigned char *uart_lsr  = (char *)0xef600305;
87 #endif
88
89 #ifdef CONFIG_UART1_DEBUG_CONSOLE
90     volatile unsigned char *uart_xmit = (char *)0xef600400;
91     volatile unsigned char *uart_lsr  = (char *)0xef600405;
92 #endif
93
94     for (i = 0; i < nb; ++i) {
95
96         /* wait for transmit reg (possibly fifo) to empty */
97         while ((*uart_lsr & 0x40) == 0)
98             ;
99
100         *uart_xmit = (ptr[i] & 0xff);
101
102         if (ptr[i] == '\n') {
103
104             /* add a carriage return */
105
106             /* wait for transmit reg (possibly fifo) to empty */
107             while ((*uart_lsr & 0x40) == 0)
108                 ;
109
110             *uart_xmit = '\r';
111         }
112     }
113
114     return;
115 }
116
117
118 static int
119 ppc405_sercons_read(struct console *co, char *ptr, unsigned nb)
120 {
121 #ifdef CONFIG_UART0_DEBUG_CONSOLE
122     volatile unsigned char *uart_rcv  = (char *)0xef600300;
123     volatile unsigned char *uart_lsr  = (char *)0xef600305;
124 #endif
125
126 #ifdef CONFIG_UART1_DEBUG_CONSOLE
127     volatile unsigned char *uart_rcv  = (char *)0xef600400;
128     volatile unsigned char *uart_lsr  = (char *)0xef600405;
129 #endif
130
131
132     /* ftr revisit: not tested */
133
134     if (nb == 0)
135         return(0);
136
137     if (!ptr)
138         return(-1);
139
140     /* wait for receive reg (possibly fifo) to contain data */
141     while ((*uart_lsr & 0x01) == 0)
142         ;
143
144     *ptr = *uart_rcv;
145
146     return(1);
147 }
148
149 static struct console ppc405_sercons = {
150         .name =         "dbg_cons",
151         .write =        ppc405_console_write,
152         .setup =        ppc405_console_setup,
153         .flags =        CON_PRINTBUFFER,
154         .index =        -1,
155 };
156
157 void
158 register_debug_console(void)
159 {
160         register_console(&ppc405_sercons);
161 }
162
163 void
164 unregister_debug_console(void)
165 {
166         unregister_console(&ppc405_sercons);
167 }
168
169 #endif  /* CONFIG_DEBUG_BRINGUP */
170
171 #endif  /* #if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR) */