• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/gdb-stub.h>
21 #include <asm/exceptions.h>
22 #include <unit/clock.h>
23 #include "mn10300-serial.h"
24 
25 #if defined(CONFIG_GDBSTUB_ON_TTYSM0)
26 struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0;
27 #elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
28 struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1;
29 #else
30 struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2;
31 #endif
32 
33 
34 /*
35  * initialise the GDB stub I/O routines
36  */
gdbstub_io_init(void)37 void __init gdbstub_io_init(void)
38 {
39 	uint16_t scxctr;
40 	int tmp;
41 
42 	switch (gdbstub_port->clock_src) {
43 	case MNSCx_CLOCK_SRC_IOCLK:
44 		gdbstub_port->ioclk = MN10300_IOCLK;
45 		break;
46 
47 #ifdef MN10300_IOBCLK
48 	case MNSCx_CLOCK_SRC_IOBCLK:
49 		gdbstub_port->ioclk = MN10300_IOBCLK;
50 		break;
51 #endif
52 	default:
53 		BUG();
54 	}
55 
56 	/* set up the serial port */
57 	gdbstub_io_set_baud(115200);
58 
59 	/* we want to get serial receive interrupts */
60 	set_intr_level(gdbstub_port->rx_irq,
61 		NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
62 	set_intr_level(gdbstub_port->tx_irq,
63 		NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
64 	set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL),
65 		gdbstub_io_rx_handler);
66 
67 	*gdbstub_port->rx_icr |= GxICR_ENABLE;
68 	tmp = *gdbstub_port->rx_icr;
69 
70 	/* enable the device */
71 	scxctr = SC01CTR_CLN_8BIT;	/* 1N8 */
72 	switch (gdbstub_port->div_timer) {
73 	case MNSCx_DIV_TIMER_16BIT:
74 		scxctr |= SC0CTR_CK_TM8UFLOW_8; /* == SC1CTR_CK_TM9UFLOW_8
75 						   == SC2CTR_CK_TM10UFLOW_8 */
76 		break;
77 
78 	case MNSCx_DIV_TIMER_8BIT:
79 		scxctr |= SC0CTR_CK_TM2UFLOW_8;
80 		break;
81 	}
82 
83 	scxctr |= SC01CTR_TXE | SC01CTR_RXE;
84 
85 	*gdbstub_port->_control = scxctr;
86 	tmp = *gdbstub_port->_control;
87 
88 	/* permit level 0 IRQs only */
89 	arch_local_change_intr_mask_level(
90 		NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
91 }
92 
93 /*
94  * set up the GDB stub serial port baud rate timers
95  */
gdbstub_io_set_baud(unsigned baud)96 void gdbstub_io_set_baud(unsigned baud)
97 {
98 	const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] +
99 				   * 1 [stop] */
100 	unsigned long ioclk = gdbstub_port->ioclk;
101 	unsigned xdiv, tmp;
102 	uint16_t tmxbr;
103 	uint8_t tmxmd;
104 
105 	if (!baud) {
106 		baud = 9600;
107 	} else if (baud == 134) {
108 		baud = 269;	/* 134 is really 134.5 */
109 		xdiv = 2;
110 	}
111 
112 try_alternative:
113 	xdiv = 1;
114 
115 	switch (gdbstub_port->div_timer) {
116 	case MNSCx_DIV_TIMER_16BIT:
117 		tmxmd = TM8MD_SRC_IOCLK;
118 		tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
119 		if (tmp > 0 && tmp <= 65535)
120 			goto timer_okay;
121 
122 		tmxmd = TM8MD_SRC_IOCLK_8;
123 		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
124 		if (tmp > 0 && tmp <= 65535)
125 			goto timer_okay;
126 
127 		tmxmd = TM8MD_SRC_IOCLK_32;
128 		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
129 		if (tmp > 0 && tmp <= 65535)
130 			goto timer_okay;
131 
132 		break;
133 
134 	case MNSCx_DIV_TIMER_8BIT:
135 		tmxmd = TM2MD_SRC_IOCLK;
136 		tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
137 		if (tmp > 0 && tmp <= 255)
138 			goto timer_okay;
139 
140 		tmxmd = TM2MD_SRC_IOCLK_8;
141 		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
142 		if (tmp > 0 && tmp <= 255)
143 			goto timer_okay;
144 
145 		tmxmd = TM2MD_SRC_IOCLK_32;
146 		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
147 		if (tmp > 0 && tmp <= 255)
148 			goto timer_okay;
149 		break;
150 	}
151 
152 	/* as a last resort, if the quotient is zero, default to 9600 bps */
153 	baud = 9600;
154 	goto try_alternative;
155 
156 timer_okay:
157 	gdbstub_port->uart.timeout = (2 * bits * HZ) / baud;
158 	gdbstub_port->uart.timeout += HZ / 50;
159 
160 	/* set the timer to produce the required baud rate */
161 	switch (gdbstub_port->div_timer) {
162 	case MNSCx_DIV_TIMER_16BIT:
163 		*gdbstub_port->_tmxmd = 0;
164 		*gdbstub_port->_tmxbr = tmxbr;
165 		*gdbstub_port->_tmxmd = TM8MD_INIT_COUNTER;
166 		*gdbstub_port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
167 		break;
168 
169 	case MNSCx_DIV_TIMER_8BIT:
170 		*gdbstub_port->_tmxmd = 0;
171 		*(volatile u8 *) gdbstub_port->_tmxbr = (u8)tmxbr;
172 		*gdbstub_port->_tmxmd = TM2MD_INIT_COUNTER;
173 		*gdbstub_port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
174 		break;
175 	}
176 }
177 
178 /*
179  * wait for a character to come from the debugger
180  */
gdbstub_io_rx_char(unsigned char * _ch,int nonblock)181 int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
182 {
183 	unsigned ix;
184 	u8 ch, st;
185 #if defined(CONFIG_MN10300_WD_TIMER)
186 	int cpu;
187 #endif
188 
189 	*_ch = 0xff;
190 
191 	if (gdbstub_rx_unget) {
192 		*_ch = gdbstub_rx_unget;
193 		gdbstub_rx_unget = 0;
194 		return 0;
195 	}
196 
197 try_again:
198 	/* pull chars out of the buffer */
199 	ix = gdbstub_rx_outp;
200 	barrier();
201 	if (ix == gdbstub_rx_inp) {
202 		if (nonblock)
203 			return -EAGAIN;
204 #ifdef CONFIG_MN10300_WD_TIMER
205 	for (cpu = 0; cpu < NR_CPUS; cpu++)
206 		watchdog_alert_counter[cpu] = 0;
207 #endif
208 		goto try_again;
209 	}
210 
211 	ch = gdbstub_rx_buffer[ix++];
212 	st = gdbstub_rx_buffer[ix++];
213 	barrier();
214 	gdbstub_rx_outp = ix & (PAGE_SIZE - 1);
215 
216 	st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF |
217 		SC01STR_OEF;
218 
219 	/* deal with what we've got
220 	 * - note that the UART doesn't do BREAK-detection for us
221 	 */
222 	if (st & SC01STR_FEF && ch == 0) {
223 		switch (gdbstub_port->rx_brk) {
224 		case 0:	gdbstub_port->rx_brk = 1;	goto try_again;
225 		case 1:	gdbstub_port->rx_brk = 2;	goto try_again;
226 		case 2:
227 			gdbstub_port->rx_brk = 3;
228 			gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
229 				      " ###\n");
230 			return -EINTR;
231 		default:
232 			goto try_again;
233 		}
234 	} else if (st & SC01STR_FEF) {
235 		if (gdbstub_port->rx_brk)
236 			goto try_again;
237 
238 		gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
239 		return -EIO;
240 	} else if (st & SC01STR_OEF) {
241 		if (gdbstub_port->rx_brk)
242 			goto try_again;
243 
244 		gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
245 		return -EIO;
246 	} else if (st & SC01STR_PEF) {
247 		if (gdbstub_port->rx_brk)
248 			goto try_again;
249 
250 		gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
251 		return -EIO;
252 	} else {
253 		/* look for the tail-end char on a break run */
254 		if (gdbstub_port->rx_brk == 3) {
255 			switch (ch) {
256 			case 0xFF:
257 			case 0xFE:
258 			case 0xFC:
259 			case 0xF8:
260 			case 0xF0:
261 			case 0xE0:
262 			case 0xC0:
263 			case 0x80:
264 			case 0x00:
265 				gdbstub_port->rx_brk = 0;
266 				goto try_again;
267 			default:
268 				break;
269 			}
270 		}
271 
272 		gdbstub_port->rx_brk = 0;
273 		gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st);
274 		*_ch = ch & 0x7f;
275 		return 0;
276 	}
277 }
278 
279 /*
280  * send a character to the debugger
281  */
gdbstub_io_tx_char(unsigned char ch)282 void gdbstub_io_tx_char(unsigned char ch)
283 {
284 	while (*gdbstub_port->_status & SC01STR_TBF)
285 		continue;
286 
287 	if (ch == 0x0a) {
288 		*(u8 *) gdbstub_port->_txb = 0x0d;
289 		while (*gdbstub_port->_status & SC01STR_TBF)
290 			continue;
291 	}
292 
293 	*(u8 *) gdbstub_port->_txb = ch;
294 }
295 
296 /*
297  * flush the transmission buffers
298  */
gdbstub_io_tx_flush(void)299 void gdbstub_io_tx_flush(void)
300 {
301 	while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
302 		continue;
303 }
304