]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - arch/mn10300/kernel/gdb-io-ttysm.c
MN10300: Fix interrupt mask alteration function call name in gdbstub
[~shefty/rdma-dev.git] / arch / mn10300 / kernel / gdb-io-ttysm.c
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  */
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_GDBSTUB_IRQ_LEVEL));
63         set_intr_level(gdbstub_port->tx_irq,
64                 NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
65         set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_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_GDBSTUB_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 }