aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/kernel/gdb-io-ttysm.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-02-08 07:19:31 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:30 -0500
commitb920de1b77b72ca9432ac3f97edb26541e65e5dd (patch)
tree40fa9be1470e929c47927dea7eddf184c0204229 /arch/mn10300/kernel/gdb-io-ttysm.c
parentef3d534754f31fed9c3b976fee1ece1b3bc38282 (diff)
mn10300: add the MN10300/AM33 architecture to the kernel
Add architecture support for the MN10300/AM33 CPUs produced by MEI to the kernel. This patch also adds board support for the ASB2303 with the ASB2308 daughter board, and the ASB2305. The only processor supported is the MN103E010, which is an AM33v2 core plus on-chip devices. [akpm@linux-foundation.org: nuke cvs control strings] Signed-off-by: Masakazu Urade <urade.masakazu@jp.panasonic.com> Signed-off-by: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/mn10300/kernel/gdb-io-ttysm.c')
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c
new file mode 100644
index 000000000000..c5451592d403
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm.c
@@ -0,0 +1,299 @@
1/* MN10300 On-chip serial driver for gdbstub I/O
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
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.
10 */
11#include <linux/string.h>
12#include <linux/kernel.h>
13#include <linux/signal.h>
14#include <linux/sched.h>
15#include <linux/mm.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 <asm/unit/clock.h>
24#include "mn10300-serial.h"
25
26#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
27struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0;
28#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
29struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1;
30#else
31struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2;
32#endif
33
34
35/*
36 * initialise the GDB stub I/O routines
37 */
38void __init gdbstub_io_init(void)
39{
40 uint16_t scxctr;
41 int tmp;
42
43 switch (gdbstub_port->clock_src) {
44 case MNSCx_CLOCK_SRC_IOCLK:
45 gdbstub_port->ioclk = MN10300_IOCLK;
46 break;
47
48#ifdef MN10300_IOBCLK
49 case MNSCx_CLOCK_SRC_IOBCLK:
50 gdbstub_port->ioclk = MN10300_IOBCLK;
51 break;
52#endif
53 default:
54 BUG();
55 }
56
57 /* set up the serial port */
58 gdbstub_io_set_baud(115200);
59
60 /* we want to get serial receive interrupts */
61 set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0);
62 set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0);
63 set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
64
65 *gdbstub_port->rx_icr |= GxICR_ENABLE;
66 tmp = *gdbstub_port->rx_icr;
67
68 /* enable the device */
69 scxctr = SC01CTR_CLN_8BIT; /* 1N8 */
70 switch (gdbstub_port->div_timer) {
71 case MNSCx_DIV_TIMER_16BIT:
72 scxctr |= SC0CTR_CK_TM8UFLOW_8; /* == SC1CTR_CK_TM9UFLOW_8
73 == SC2CTR_CK_TM10UFLOW_8 */
74 break;
75
76 case MNSCx_DIV_TIMER_8BIT:
77 scxctr |= SC0CTR_CK_TM2UFLOW_8;
78 break;
79 }
80
81 scxctr |= SC01CTR_TXE | SC01CTR_RXE;
82
83 *gdbstub_port->_control = scxctr;
84 tmp = *gdbstub_port->_control;
85
86 /* permit level 0 IRQs only */
87 asm volatile(
88 " and %0,epsw \n"
89 " or %1,epsw \n"
90 :
91 : "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1)
92 );
93}
94
95/*
96 * set up the GDB stub serial port baud rate timers
97 */
98void gdbstub_io_set_baud(unsigned baud)
99{
100 const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] +
101 * 1 [stop] */
102 unsigned long ioclk = gdbstub_port->ioclk;
103 unsigned xdiv, tmp;
104 uint16_t tmxbr;
105 uint8_t tmxmd;
106
107 if (!baud) {
108 baud = 9600;
109 } else if (baud == 134) {
110 baud = 269; /* 134 is really 134.5 */
111 xdiv = 2;
112 }
113
114try_alternative:
115 xdiv = 1;
116
117 switch (gdbstub_port->div_timer) {
118 case MNSCx_DIV_TIMER_16BIT:
119 tmxmd = TM8MD_SRC_IOCLK;
120 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
121 if (tmp > 0 && tmp <= 65535)
122 goto timer_okay;
123
124 tmxmd = TM8MD_SRC_IOCLK_8;
125 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
126 if (tmp > 0 && tmp <= 65535)
127 goto timer_okay;
128
129 tmxmd = TM8MD_SRC_IOCLK_32;
130 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
131 if (tmp > 0 && tmp <= 65535)
132 goto timer_okay;
133
134 break;
135
136 case MNSCx_DIV_TIMER_8BIT:
137 tmxmd = TM2MD_SRC_IOCLK;
138 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
139 if (tmp > 0 && tmp <= 255)
140 goto timer_okay;
141
142 tmxmd = TM2MD_SRC_IOCLK_8;
143 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
144 if (tmp > 0 && tmp <= 255)
145 goto timer_okay;
146
147 tmxmd = TM2MD_SRC_IOCLK_32;
148 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
149 if (tmp > 0 && tmp <= 255)
150 goto timer_okay;
151 break;
152 }
153
154 /* as a last resort, if the quotient is zero, default to 9600 bps */
155 baud = 9600;
156 goto try_alternative;
157
158timer_okay:
159 gdbstub_port->uart.timeout = (2 * bits * HZ) / baud;
160 gdbstub_port->uart.timeout += HZ / 50;
161
162 /* set the timer to produce the required baud rate */
163 switch (gdbstub_port->div_timer) {
164 case MNSCx_DIV_TIMER_16BIT:
165 *gdbstub_port->_tmxmd = 0;
166 *gdbstub_port->_tmxbr = tmxbr;
167 *gdbstub_port->_tmxmd = TM8MD_INIT_COUNTER;
168 *gdbstub_port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
169 break;
170
171 case MNSCx_DIV_TIMER_8BIT:
172 *gdbstub_port->_tmxmd = 0;
173 *(volatile u8 *) gdbstub_port->_tmxbr = (u8)tmxbr;
174 *gdbstub_port->_tmxmd = TM2MD_INIT_COUNTER;
175 *gdbstub_port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
176 break;
177 }
178}
179
180/*
181 * wait for a character to come from the debugger
182 */
183int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
184{
185 unsigned ix;
186 u8 ch, st;
187
188 *_ch = 0xff;
189
190 if (gdbstub_rx_unget) {
191 *_ch = gdbstub_rx_unget;
192 gdbstub_rx_unget = 0;
193 return 0;
194 }
195
196try_again:
197 /* pull chars out of the buffer */
198 ix = gdbstub_rx_outp;
199 if (ix == gdbstub_rx_inp) {
200 if (nonblock)
201 return -EAGAIN;
202#ifdef CONFIG_MN10300_WD_TIMER
203 watchdog_alert_counter = 0;
204#endif /* CONFIG_MN10300_WD_TIMER */
205 goto try_again;
206 }
207
208 ch = gdbstub_rx_buffer[ix++];
209 st = gdbstub_rx_buffer[ix++];
210 gdbstub_rx_outp = ix & (PAGE_SIZE - 1);
211
212 st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF |
213 SC01STR_OEF;
214
215 /* deal with what we've got
216 * - note that the UART doesn't do BREAK-detection for us
217 */
218 if (st & SC01STR_FEF && ch == 0) {
219 switch (gdbstub_port->rx_brk) {
220 case 0: gdbstub_port->rx_brk = 1; goto try_again;
221 case 1: gdbstub_port->rx_brk = 2; goto try_again;
222 case 2:
223 gdbstub_port->rx_brk = 3;
224 gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
225 " ###\n");
226 return -EINTR;
227 default:
228 goto try_again;
229 }
230 } else if (st & SC01STR_FEF) {
231 if (gdbstub_port->rx_brk)
232 goto try_again;
233
234 gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
235 return -EIO;
236 } else if (st & SC01STR_OEF) {
237 if (gdbstub_port->rx_brk)
238 goto try_again;
239
240 gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
241 return -EIO;
242 } else if (st & SC01STR_PEF) {
243 if (gdbstub_port->rx_brk)
244 goto try_again;
245
246 gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
247 return -EIO;
248 } else {
249 /* look for the tail-end char on a break run */
250 if (gdbstub_port->rx_brk == 3) {
251 switch (ch) {
252 case 0xFF:
253 case 0xFE:
254 case 0xFC:
255 case 0xF8:
256 case 0xF0:
257 case 0xE0:
258 case 0xC0:
259 case 0x80:
260 case 0x00:
261 gdbstub_port->rx_brk = 0;
262 goto try_again;
263 default:
264 break;
265 }
266 }
267
268 gdbstub_port->rx_brk = 0;
269 gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st);
270 *_ch = ch & 0x7f;
271 return 0;
272 }
273}
274
275/*
276 * send a character to the debugger
277 */
278void gdbstub_io_tx_char(unsigned char ch)
279{
280 while (*gdbstub_port->_status & SC01STR_TBF)
281 continue;
282
283 if (ch == 0x0a) {
284 *(u8 *) gdbstub_port->_txb = 0x0d;
285 while (*gdbstub_port->_status & SC01STR_TBF)
286 continue;
287 }
288
289 *(u8 *) gdbstub_port->_txb = ch;
290}
291
292/*
293 * flush the transmission buffers
294 */
295void gdbstub_io_tx_flush(void)
296{
297 while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
298 continue;
299}