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 <unit/clock.h>
24 #include "mn10300-serial.h"
25 
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;
30 #else
31 struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2;
32 #endif
33 
34 
35 /*
36  * initialise the GDB stub I/O routines
37  */
gdbstub_io_init(void)38 void __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,
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);
67 
68 	*gdbstub_port->rx_icr |= GxICR_ENABLE;
69 	tmp = *gdbstub_port->rx_icr;
70 
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 */
77 		break;
78 
79 	case MNSCx_DIV_TIMER_8BIT:
80 		scxctr |= SC0CTR_CK_TM2UFLOW_8;
81 		break;
82 	}
83 
84 	scxctr |= SC01CTR_TXE | SC01CTR_RXE;
85 
86 	*gdbstub_port->_control = scxctr;
87 	tmp = *gdbstub_port->_control;
88 
89 	/* permit level 0 IRQs only */
90 	arch_local_change_intr_mask_level(
91 		NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
92 }
93 
94 /*
95  * set up the GDB stub serial port baud rate timers
96  */
gdbstub_io_set_baud(unsigned baud)97 void gdbstub_io_set_baud(unsigned baud)
98 {
99 	const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] +
100 				   * 1 [stop] */
101 	unsigned long ioclk = gdbstub_port->ioclk;
102 	unsigned xdiv, tmp;
103 	uint16_t tmxbr;
104 	uint8_t tmxmd;
105 
106 	if (!baud) {
107 		baud = 9600;
108 	} else if (baud == 134) {
109 		baud = 269;	/* 134 is really 134.5 */
110 		xdiv = 2;
111 	}
112 
113 try_alternative:
114 	xdiv = 1;
115 
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)
121 			goto timer_okay;
122 
123 		tmxmd = TM8MD_SRC_IOCLK_8;
124 		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
125 		if (tmp > 0 && tmp <= 65535)
126 			goto timer_okay;
127 
128 		tmxmd = TM8MD_SRC_IOCLK_32;
129 		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
130 		if (tmp > 0 && tmp <= 65535)
131 			goto timer_okay;
132 
133 		break;
134 
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)
139 			goto timer_okay;
140 
141 		tmxmd = TM2MD_SRC_IOCLK_8;
142 		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
143 		if (tmp > 0 && tmp <= 255)
144 			goto timer_okay;
145 
146 		tmxmd = TM2MD_SRC_IOCLK_32;
147 		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
148 		if (tmp > 0 && tmp <= 255)
149 			goto timer_okay;
150 		break;
151 	}
152 
153 	/* as a last resort, if the quotient is zero, default to 9600 bps */
154 	baud = 9600;
155 	goto try_alternative;
156 
157 timer_okay:
158 	gdbstub_port->uart.timeout = (2 * bits * HZ) / baud;
159 	gdbstub_port->uart.timeout += HZ / 50;
160 
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;
168 		break;
169 
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;
175 		break;
176 	}
177 }
178 
179 /*
180  * wait for a character to come from the debugger
181  */
gdbstub_io_rx_char(unsigned char * _ch,int nonblock)182 int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
183 {
184 	unsigned ix;
185 	u8 ch, st;
186 #if defined(CONFIG_MN10300_WD_TIMER)
187 	int cpu;
188 #endif
189 
190 	*_ch = 0xff;
191 
192 	if (gdbstub_rx_unget) {
193 		*_ch = gdbstub_rx_unget;
194 		gdbstub_rx_unget = 0;
195 		return 0;
196 	}
197 
198 try_again:
199 	/* pull chars out of the buffer */
200 	ix = gdbstub_rx_outp;
201 	barrier();
202 	if (ix == gdbstub_rx_inp) {
203 		if (nonblock)
204 			return -EAGAIN;
205 #ifdef CONFIG_MN10300_WD_TIMER
206 	for (cpu = 0; cpu < NR_CPUS; cpu++)
207 		watchdog_alert_counter[cpu] = 0;
208 #endif
209 		goto try_again;
210 	}
211 
212 	ch = gdbstub_rx_buffer[ix++];
213 	st = gdbstub_rx_buffer[ix++];
214 	barrier();
215 	gdbstub_rx_outp = ix & (PAGE_SIZE - 1);
216 
217 	st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF |
218 		SC01STR_OEF;
219 
220 	/* deal with what we've got
221 	 * - note that the UART doesn't do BREAK-detection for us
222 	 */
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;
227 		case 2:
228 			gdbstub_port->rx_brk = 3;
229 			gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
230 				      " ###\n");
231 			return -EINTR;
232 		default:
233 			goto try_again;
234 		}
235 	} else if (st & SC01STR_FEF) {
236 		if (gdbstub_port->rx_brk)
237 			goto try_again;
238 
239 		gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
240 		return -EIO;
241 	} else if (st & SC01STR_OEF) {
242 		if (gdbstub_port->rx_brk)
243 			goto try_again;
244 
245 		gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
246 		return -EIO;
247 	} else if (st & SC01STR_PEF) {
248 		if (gdbstub_port->rx_brk)
249 			goto try_again;
250 
251 		gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
252 		return -EIO;
253 	} else {
254 		/* look for the tail-end char on a break run */
255 		if (gdbstub_port->rx_brk == 3) {
256 			switch (ch) {
257 			case 0xFF:
258 			case 0xFE:
259 			case 0xFC:
260 			case 0xF8:
261 			case 0xF0:
262 			case 0xE0:
263 			case 0xC0:
264 			case 0x80:
265 			case 0x00:
266 				gdbstub_port->rx_brk = 0;
267 				goto try_again;
268 			default:
269 				break;
270 			}
271 		}
272 
273 		gdbstub_port->rx_brk = 0;
274 		gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st);
275 		*_ch = ch & 0x7f;
276 		return 0;
277 	}
278 }
279 
280 /*
281  * send a character to the debugger
282  */
gdbstub_io_tx_char(unsigned char ch)283 void gdbstub_io_tx_char(unsigned char ch)
284 {
285 	while (*gdbstub_port->_status & SC01STR_TBF)
286 		continue;
287 
288 	if (ch == 0x0a) {
289 		*(u8 *) gdbstub_port->_txb = 0x0d;
290 		while (*gdbstub_port->_status & SC01STR_TBF)
291 			continue;
292 	}
293 
294 	*(u8 *) gdbstub_port->_txb = ch;
295 }
296 
297 /*
298  * flush the transmission buffers
299  */
gdbstub_io_tx_flush(void)300 void gdbstub_io_tx_flush(void)
301 {
302 	while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
303 		continue;
304 }
305