http://www.hht-eu.com/pls/hht/docs/F3140/bcm963xx_Speedport500V.0.09.04L.300L01.V27_c...
[bcm963xx.git] / kernel / linux / arch / mips / brcm-boards / generic / dbg_io.c
1 /*
2 <:copyright-gpl 
3  Copyright 2003 Broadcom Corp. All Rights Reserved. 
4  
5  This program is free software; you can distribute it and/or modify it 
6  under the terms of the GNU General Public License (Version 2) as 
7  published by the Free Software Foundation. 
8  
9  This program is distributed in the hope it will be useful, but WITHOUT 
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
11  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
12  for more details. 
13  
14  You should have received a copy of the GNU General Public License along 
15  with this program; if not, write to the Free Software Foundation, Inc., 
16  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 
17 :>
18 */
19
20 #include <linux/config.h>
21 #include <linux/tty.h>
22 #include <linux/major.h>
23 #include <linux/init.h>
24 #include <linux/console.h>
25 #include <linux/fs.h>
26 #include <linux/interrupt.h>
27 #include <linux/kernel.h>
28 #include <linux/types.h>
29 #include <linux/sched.h>
30
31 #include <bcm_map_part.h>
32
33 #undef  PRNT                            /* define for debug printing */
34
35 #define         UART16550_BAUD_2400             2400
36 #define         UART16550_BAUD_4800             4800
37 #define         UART16550_BAUD_9600             9600
38 #define         UART16550_BAUD_19200            19200
39 #define         UART16550_BAUD_38400            38400
40 #define         UART16550_BAUD_57600            57600
41 #define         UART16550_BAUD_115200           115200
42
43 #define         UART16550_PARITY_NONE           0
44 #define         UART16550_PARITY_ODD            0x08
45 #define         UART16550_PARITY_EVEN           0x18
46 #define         UART16550_PARITY_MARK           0x28
47 #define         UART16550_PARITY_SPACE          0x38
48
49 #define         UART16550_DATA_5BIT             0x0
50 #define         UART16550_DATA_6BIT             0x1
51 #define         UART16550_DATA_7BIT             0x2
52 #define         UART16550_DATA_8BIT             0x3
53
54 #define         UART16550_STOP_1BIT             0x0
55 #define         UART16550_STOP_2BIT             0x4
56
57 volatile Uart * stUart =  UART_BASE;
58
59 #define WRITE16(addr, value)        ((*(volatile UINT16 *)((ULONG)&addr)) = value)
60
61 /* Low level UART routines from promcon.c */
62 extern void prom_putc(char c);
63 extern char prom_getc(void);
64 extern int prom_getc_nowait(void);
65 extern int prom_testc(void);
66
67 extern void set_debug_traps(void);
68 extern void breakpoint(void);
69 extern void enable_brcm_irq(unsigned int);
70 extern void set_async_breakpoint(unsigned int epc);
71
72 #ifdef CONFIG_GDB_CONSOLE
73 extern void register_gdb_console(void);
74 #endif
75
76 int gdb_initialized = 0;
77
78 #define GDB_BUF_SIZE    512             /* power of 2, please */
79
80 static char     gdb_buf[GDB_BUF_SIZE] ;
81 static int      gdb_buf_in_inx ;
82 static atomic_t gdb_buf_in_cnt ;
83 static int      gdb_buf_out_inx ;
84
85 void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
86 {
87         /* Do nothing, assume boot loader has already set up serial port */
88         printk("debugInit called\n");
89 }
90
91 /*
92  * Get a char if available, return -1 if nothing available.
93  * Empty the receive buffer first, then look at the interface hardware.
94  */
95 static int      read_char(void)
96 {
97     if (atomic_read(&gdb_buf_in_cnt) != 0)      /* intr routine has q'd chars */
98     {
99         int             chr ;
100
101         chr = gdb_buf[gdb_buf_out_inx++] ;
102         gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ;
103         atomic_dec(&gdb_buf_in_cnt) ;
104         return(chr) ;
105     }
106     return(prom_getc_nowait()) ;        /* read from hardware */
107 } /* read_char */
108
109 /*
110  * This is the receiver interrupt routine for the GDB stub.
111  * It will receive a limited number of characters of input
112  * from the gdb  host machine and save them up in a buffer.
113  *
114  * When the gdb stub routine getDebugChar() is called it
115  * draws characters out of the buffer until it is empty and
116  * then reads directly from the serial port.
117  *
118  * We do not attempt to write chars from the interrupt routine
119  * since the stubs do all of that via putDebugChar() which
120  * writes one byte after waiting for the interface to become
121  * ready.
122  *
123  * The debug stubs like to run with interrupts disabled since,
124  * after all, they run as a consequence of a breakpoint in
125  * the kernel.
126  *
127  * Perhaps someone who knows more about the tty driver than I
128  * care to learn can make this work for any low level serial
129  * driver.
130  */
131 static void gdb_interrupt(int irq, void *dev_id, struct pt_regs * regs)
132 {
133     int  chr ;
134     int more;
135     do
136     {
137         chr = prom_getc_nowait() ;
138         more = prom_testc();
139         if (chr < 0) continue ;
140
141         /* If we receive a Ctrl-C then this is GDB trying to break in */
142         if (chr == 3)
143         {
144             /* Replace current instruction with breakpoint */
145             set_async_breakpoint(regs->cp0_epc);
146             //breakpoint();
147         }
148                 
149 #ifdef PRNT
150         printk("gdb_interrupt: chr=%02x '%c', more = %x\n",
151                 chr, chr > ' ' && chr < 0x7F ? chr : ' ', more) ;
152 #endif
153
154         if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE)
155         {                               /* buffer overflow, clear it */
156             gdb_buf_in_inx = 0 ;
157             atomic_set(&gdb_buf_in_cnt, 0) ;
158             gdb_buf_out_inx = 0 ;
159             break ;
160         }
161
162         gdb_buf[gdb_buf_in_inx++] = chr ;
163         gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ;
164         atomic_inc(&gdb_buf_in_cnt) ;
165     }
166     while (more !=0);
167
168 } /* gdb_interrupt */
169
170 /*
171  * getDebugChar
172  *
173  * This is a GDB stub routine.  It waits for a character from the
174  * serial interface and then returns it.  If there is no serial
175  * interface connection then it returns a bogus value which will
176  * almost certainly cause the system to hang.
177  */
178 int     getDebugChar(void)
179 {
180     volatile int        chr ;
181
182 #ifdef PRNT
183     printk("getDebugChar: ") ;
184 #endif
185
186     while ( (chr = read_char()) < 0 ) ;
187
188 #ifdef PRNT
189     printk("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ') ;
190 #endif
191     return(chr) ;
192
193 } /* getDebugChar */
194
195 /*
196  * putDebugChar
197  *
198  * This is a GDB stub routine.  It waits until the interface is ready
199  * to transmit a char and then sends it.  If there is no serial
200  * interface connection then it simply returns to its caller, having
201  * pretended to send the char.
202  */
203 int putDebugChar(unsigned char chr)
204 {
205 #ifdef PRNT
206     printk("putDebugChar: chr=%02x '%c'\n", chr,
207                 chr > ' ' && chr < 0x7F ? chr : ' ') ;
208 #endif
209
210     prom_putc(chr) ;    /* this routine will wait */
211      return 1;
212
213 } /* putDebugChar */
214
215 /* Just a NULL routine for testing. */
216 void gdb_null(void)
217 {
218 }
219
220 void rs_kgdb_hook(int tty_no)
221 {
222     printk("rs_kgdb_hook: tty %d\n", tty_no);
223
224     /* Call GDB routine to setup the exception vectors for the debugger */
225    set_debug_traps();
226
227    printk("Breaking into debugger...\n");
228    breakpoint();
229    gdb_null() ;
230    printk("Connected.\n");
231
232    gdb_initialized = 1;
233
234 #ifdef CONFIG_GDB_CONSOLE
235     register_gdb_console();
236 #endif
237 }
238
239 void kgdb_hook_irq()
240 {
241     int         retval ;
242     uint16 uMask;
243
244     printk("GDB: Hooking UART interrupt\n");
245
246     retval = request_irq(INTERRUPT_ID_UART,
247                          gdb_interrupt,
248                          SA_INTERRUPT,
249                          "GDB-stub", NULL);
250
251     if (retval != 0)
252         printk("gdb_hook: request_irq(irq=%d) failed: %d\n", INTERRUPT_ID_UART, retval);
253
254       // Enable UART config Rx not empty IRQ
255      uMask = READ16(stUart->intMask) ;
256       //     printk("intMask: 0x%x\n", uMask);
257      WRITE16(stUart->intMask, uMask | RXFIFONE);
258 }
259
260