Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/frv/kernel/gdb-io.c
10817 views
1
/* gdb-io.c: FR403 GDB stub I/O
2
*
3
* Copyright (C) 2003 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 License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
10
*/
11
12
#include <linux/string.h>
13
#include <linux/kernel.h>
14
#include <linux/signal.h>
15
#include <linux/sched.h>
16
#include <linux/mm.h>
17
#include <linux/console.h>
18
#include <linux/init.h>
19
#include <linux/serial_reg.h>
20
21
#include <asm/pgtable.h>
22
#include <asm/system.h>
23
#include <asm/irc-regs.h>
24
#include <asm/timer-regs.h>
25
#include <asm/gdb-stub.h>
26
#include "gdb-io.h"
27
28
#ifdef CONFIG_GDBSTUB_UART0
29
#define __UART(X) (*(volatile uint8_t *)(UART0_BASE + (UART_##X)))
30
#define __UART_IRR_NMI 0xff0f0000
31
#else /* CONFIG_GDBSTUB_UART1 */
32
#define __UART(X) (*(volatile uint8_t *)(UART1_BASE + (UART_##X)))
33
#define __UART_IRR_NMI 0xfff00000
34
#endif
35
36
#define LSR_WAIT_FOR(STATE) \
37
do { \
38
gdbstub_do_rx(); \
39
} while (!(__UART(LSR) & UART_LSR_##STATE))
40
41
#define FLOWCTL_QUERY(LINE) ({ __UART(MSR) & UART_MSR_##LINE; })
42
#define FLOWCTL_CLEAR(LINE) do { __UART(MCR) &= ~UART_MCR_##LINE; mb(); } while (0)
43
#define FLOWCTL_SET(LINE) do { __UART(MCR) |= UART_MCR_##LINE; mb(); } while (0)
44
45
#define FLOWCTL_WAIT_FOR(LINE) \
46
do { \
47
gdbstub_do_rx(); \
48
} while(!FLOWCTL_QUERY(LINE))
49
50
/*****************************************************************************/
51
/*
52
* initialise the GDB stub
53
* - called with PSR.ET==0, so can't incur external interrupts
54
*/
55
void gdbstub_io_init(void)
56
{
57
/* set up the serial port */
58
__UART(LCR) = UART_LCR_WLEN8; /* 1N8 */
59
__UART(FCR) =
60
UART_FCR_ENABLE_FIFO |
61
UART_FCR_CLEAR_RCVR |
62
UART_FCR_CLEAR_XMIT |
63
UART_FCR_TRIGGER_1;
64
65
FLOWCTL_CLEAR(DTR);
66
FLOWCTL_SET(RTS);
67
68
// gdbstub_set_baud(115200);
69
70
/* we want to get serial receive interrupts */
71
__UART(IER) = UART_IER_RDI | UART_IER_RLSI;
72
mb();
73
74
__set_IRR(6, __UART_IRR_NMI); /* map ERRs and UARTx to NMI */
75
76
} /* end gdbstub_io_init() */
77
78
/*****************************************************************************/
79
/*
80
* set up the GDB stub serial port baud rate timers
81
*/
82
void gdbstub_set_baud(unsigned baud)
83
{
84
unsigned value, high, low;
85
u8 lcr;
86
87
/* work out the divisor to give us the nearest higher baud rate */
88
value = __serial_clock_speed_HZ / 16 / baud;
89
90
/* determine the baud rate range */
91
high = __serial_clock_speed_HZ / 16 / value;
92
low = __serial_clock_speed_HZ / 16 / (value + 1);
93
94
/* pick the nearest bound */
95
if (low + (high - low) / 2 > baud)
96
value++;
97
98
lcr = __UART(LCR);
99
__UART(LCR) |= UART_LCR_DLAB;
100
mb();
101
__UART(DLL) = value & 0xff;
102
__UART(DLM) = (value >> 8) & 0xff;
103
mb();
104
__UART(LCR) = lcr;
105
mb();
106
107
} /* end gdbstub_set_baud() */
108
109
/*****************************************************************************/
110
/*
111
* receive characters into the receive FIFO
112
*/
113
void gdbstub_do_rx(void)
114
{
115
unsigned ix, nix;
116
117
ix = gdbstub_rx_inp;
118
119
while (__UART(LSR) & UART_LSR_DR) {
120
nix = (ix + 2) & 0xfff;
121
if (nix == gdbstub_rx_outp)
122
break;
123
124
gdbstub_rx_buffer[ix++] = __UART(LSR);
125
gdbstub_rx_buffer[ix++] = __UART(RX);
126
ix = nix;
127
}
128
129
gdbstub_rx_inp = ix;
130
131
__clr_RC(15);
132
__clr_IRL();
133
134
} /* end gdbstub_do_rx() */
135
136
/*****************************************************************************/
137
/*
138
* wait for a character to come from the debugger
139
*/
140
int gdbstub_rx_char(unsigned char *_ch, int nonblock)
141
{
142
unsigned ix;
143
u8 ch, st;
144
145
*_ch = 0xff;
146
147
if (gdbstub_rx_unget) {
148
*_ch = gdbstub_rx_unget;
149
gdbstub_rx_unget = 0;
150
return 0;
151
}
152
153
try_again:
154
gdbstub_do_rx();
155
156
/* pull chars out of the buffer */
157
ix = gdbstub_rx_outp;
158
if (ix == gdbstub_rx_inp) {
159
if (nonblock)
160
return -EAGAIN;
161
//watchdog_alert_counter = 0;
162
goto try_again;
163
}
164
165
st = gdbstub_rx_buffer[ix++];
166
ch = gdbstub_rx_buffer[ix++];
167
gdbstub_rx_outp = ix & 0x00000fff;
168
169
if (st & UART_LSR_BI) {
170
gdbstub_proto("### GDB Rx Break Detected ###\n");
171
return -EINTR;
172
}
173
else if (st & (UART_LSR_FE|UART_LSR_OE|UART_LSR_PE)) {
174
gdbstub_io("### GDB Rx Error (st=%02x) ###\n",st);
175
return -EIO;
176
}
177
else {
178
gdbstub_io("### GDB Rx %02x (st=%02x) ###\n",ch,st);
179
*_ch = ch & 0x7f;
180
return 0;
181
}
182
183
} /* end gdbstub_rx_char() */
184
185
/*****************************************************************************/
186
/*
187
* send a character to the debugger
188
*/
189
void gdbstub_tx_char(unsigned char ch)
190
{
191
FLOWCTL_SET(DTR);
192
LSR_WAIT_FOR(THRE);
193
// FLOWCTL_WAIT_FOR(CTS);
194
195
if (ch == 0x0a) {
196
__UART(TX) = 0x0d;
197
mb();
198
LSR_WAIT_FOR(THRE);
199
// FLOWCTL_WAIT_FOR(CTS);
200
}
201
__UART(TX) = ch;
202
mb();
203
204
FLOWCTL_CLEAR(DTR);
205
} /* end gdbstub_tx_char() */
206
207
/*****************************************************************************/
208
/*
209
* send a character to the debugger
210
*/
211
void gdbstub_tx_flush(void)
212
{
213
LSR_WAIT_FOR(TEMT);
214
LSR_WAIT_FOR(THRE);
215
FLOWCTL_CLEAR(DTR);
216
} /* end gdbstub_tx_flush() */
217
218