1 /* MN10300 On-chip serial driver for gdbstub I/O
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
11 #include <linux/string.h>
12 #include <linux/kernel.h>
13 #include <linux/signal.h>
14 #include <linux/sched.h>
16 #include <linux/console.h>
17 #include <linux/init.h>
18 #include <linux/tty.h>
19 #include <asm/pgtable.h>
20 #include <asm/system.h>
21 #include <asm/gdb-stub.h>
22 #include <asm/exceptions.h>
23 #include <unit/clock.h>
24 #include "mn10300-serial.h"
26 #if defined(CONFIG_GDBSTUB_ON_TTYSM0)
27 struct mn10300_serial_port
*const gdbstub_port
= &mn10300_serial_port_sif0
;
28 #elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
29 struct mn10300_serial_port
*const gdbstub_port
= &mn10300_serial_port_sif1
;
31 struct mn10300_serial_port
*const gdbstub_port
= &mn10300_serial_port_sif2
;
36 * initialise the GDB stub I/O routines
38 void __init
gdbstub_io_init(void)
43 switch (gdbstub_port
->clock_src
) {
44 case MNSCx_CLOCK_SRC_IOCLK
:
45 gdbstub_port
->ioclk
= MN10300_IOCLK
;
49 case MNSCx_CLOCK_SRC_IOBCLK
:
50 gdbstub_port
->ioclk
= MN10300_IOBCLK
;
57 /* set up the serial port */
58 gdbstub_io_set_baud(115200);
60 /* we want to get serial receive interrupts */
61 set_intr_level(gdbstub_port
->rx_irq
,
62 NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL
));
63 set_intr_level(gdbstub_port
->tx_irq
,
64 NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL
));
65 set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL
),
66 gdbstub_io_rx_handler
);
68 *gdbstub_port
->rx_icr
|= GxICR_ENABLE
;
69 tmp
= *gdbstub_port
->rx_icr
;
71 /* enable the device */
72 scxctr
= SC01CTR_CLN_8BIT
; /* 1N8 */
73 switch (gdbstub_port
->div_timer
) {
74 case MNSCx_DIV_TIMER_16BIT
:
75 scxctr
|= SC0CTR_CK_TM8UFLOW_8
; /* == SC1CTR_CK_TM9UFLOW_8
76 == SC2CTR_CK_TM10UFLOW_8 */
79 case MNSCx_DIV_TIMER_8BIT
:
80 scxctr
|= SC0CTR_CK_TM2UFLOW_8
;
84 scxctr
|= SC01CTR_TXE
| SC01CTR_RXE
;
86 *gdbstub_port
->_control
= scxctr
;
87 tmp
= *gdbstub_port
->_control
;
89 /* permit level 0 IRQs only */
90 arch_local_change_intr_mask_level(
91 NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL
+ 1));
95 * set up the GDB stub serial port baud rate timers
97 void gdbstub_io_set_baud(unsigned baud
)
99 const unsigned bits
= 10; /* 1 [start] + 8 [data] + 0 [parity] +
101 unsigned long ioclk
= gdbstub_port
->ioclk
;
108 } else if (baud
== 134) {
109 baud
= 269; /* 134 is really 134.5 */
116 switch (gdbstub_port
->div_timer
) {
117 case MNSCx_DIV_TIMER_16BIT
:
118 tmxmd
= TM8MD_SRC_IOCLK
;
119 tmxbr
= tmp
= (ioclk
/ (baud
* xdiv
) + 4) / 8 - 1;
120 if (tmp
> 0 && tmp
<= 65535)
123 tmxmd
= TM8MD_SRC_IOCLK_8
;
124 tmxbr
= tmp
= (ioclk
/ (baud
* 8 * xdiv
) + 4) / 8 - 1;
125 if (tmp
> 0 && tmp
<= 65535)
128 tmxmd
= TM8MD_SRC_IOCLK_32
;
129 tmxbr
= tmp
= (ioclk
/ (baud
* 32 * xdiv
) + 4) / 8 - 1;
130 if (tmp
> 0 && tmp
<= 65535)
135 case MNSCx_DIV_TIMER_8BIT
:
136 tmxmd
= TM2MD_SRC_IOCLK
;
137 tmxbr
= tmp
= (ioclk
/ (baud
* xdiv
) + 4) / 8 - 1;
138 if (tmp
> 0 && tmp
<= 255)
141 tmxmd
= TM2MD_SRC_IOCLK_8
;
142 tmxbr
= tmp
= (ioclk
/ (baud
* 8 * xdiv
) + 4) / 8 - 1;
143 if (tmp
> 0 && tmp
<= 255)
146 tmxmd
= TM2MD_SRC_IOCLK_32
;
147 tmxbr
= tmp
= (ioclk
/ (baud
* 32 * xdiv
) + 4) / 8 - 1;
148 if (tmp
> 0 && tmp
<= 255)
153 /* as a last resort, if the quotient is zero, default to 9600 bps */
155 goto try_alternative
;
158 gdbstub_port
->uart
.timeout
= (2 * bits
* HZ
) / baud
;
159 gdbstub_port
->uart
.timeout
+= HZ
/ 50;
161 /* set the timer to produce the required baud rate */
162 switch (gdbstub_port
->div_timer
) {
163 case MNSCx_DIV_TIMER_16BIT
:
164 *gdbstub_port
->_tmxmd
= 0;
165 *gdbstub_port
->_tmxbr
= tmxbr
;
166 *gdbstub_port
->_tmxmd
= TM8MD_INIT_COUNTER
;
167 *gdbstub_port
->_tmxmd
= tmxmd
| TM8MD_COUNT_ENABLE
;
170 case MNSCx_DIV_TIMER_8BIT
:
171 *gdbstub_port
->_tmxmd
= 0;
172 *(volatile u8
*) gdbstub_port
->_tmxbr
= (u8
)tmxbr
;
173 *gdbstub_port
->_tmxmd
= TM2MD_INIT_COUNTER
;
174 *gdbstub_port
->_tmxmd
= tmxmd
| TM2MD_COUNT_ENABLE
;
180 * wait for a character to come from the debugger
182 int gdbstub_io_rx_char(unsigned char *_ch
, int nonblock
)
186 #if defined(CONFIG_MN10300_WD_TIMER)
192 if (gdbstub_rx_unget
) {
193 *_ch
= gdbstub_rx_unget
;
194 gdbstub_rx_unget
= 0;
199 /* pull chars out of the buffer */
200 ix
= gdbstub_rx_outp
;
202 if (ix
== gdbstub_rx_inp
) {
205 #ifdef CONFIG_MN10300_WD_TIMER
206 for (cpu
= 0; cpu
< NR_CPUS
; cpu
++)
207 watchdog_alert_counter
[cpu
] = 0;
212 ch
= gdbstub_rx_buffer
[ix
++];
213 st
= gdbstub_rx_buffer
[ix
++];
215 gdbstub_rx_outp
= ix
& (PAGE_SIZE
- 1);
217 st
&= SC01STR_RXF
| SC01STR_RBF
| SC01STR_FEF
| SC01STR_PEF
|
220 /* deal with what we've got
221 * - note that the UART doesn't do BREAK-detection for us
223 if (st
& SC01STR_FEF
&& ch
== 0) {
224 switch (gdbstub_port
->rx_brk
) {
225 case 0: gdbstub_port
->rx_brk
= 1; goto try_again
;
226 case 1: gdbstub_port
->rx_brk
= 2; goto try_again
;
228 gdbstub_port
->rx_brk
= 3;
229 gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
235 } else if (st
& SC01STR_FEF
) {
236 if (gdbstub_port
->rx_brk
)
239 gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
241 } else if (st
& SC01STR_OEF
) {
242 if (gdbstub_port
->rx_brk
)
245 gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
247 } else if (st
& SC01STR_PEF
) {
248 if (gdbstub_port
->rx_brk
)
251 gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
254 /* look for the tail-end char on a break run */
255 if (gdbstub_port
->rx_brk
== 3) {
266 gdbstub_port
->rx_brk
= 0;
273 gdbstub_port
->rx_brk
= 0;
274 gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch
, st
);
281 * send a character to the debugger
283 void gdbstub_io_tx_char(unsigned char ch
)
285 while (*gdbstub_port
->_status
& SC01STR_TBF
)
289 *(u8
*) gdbstub_port
->_txb
= 0x0d;
290 while (*gdbstub_port
->_status
& SC01STR_TBF
)
294 *(u8
*) gdbstub_port
->_txb
= ch
;
298 * flush the transmission buffers
300 void gdbstub_io_tx_flush(void)
302 while (*gdbstub_port
->_status
& (SC01STR_TBF
| SC01STR_TXF
))