Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mn10300/kernel/gdb-io-ttysm.c
10817 views
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 ([email protected])
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
*/
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
*/
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
*/
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
*/
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
*/
300
void gdbstub_io_tx_flush(void)
301
{
302
while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
303
continue;
304
}
305
306