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) 27struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0; 28#elif defined(CONFIG_GDBSTUB_ON_TTYSM1) 29struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1; 30#else 31struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2; 32#endif 33 34 35/* 36 * initialise the GDB stub I/O routines 37 */ 38void __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 */ 97void 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 113try_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 157timer_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 */ 182int 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 198try_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 */ 283void 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 */ 300void gdbstub_io_tx_flush(void) 301{ 302 while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF)) 303 continue; 304} 305