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/gdb-stub.h> 21#include <asm/exceptions.h> 22#include <unit/clock.h> 23#include "mn10300-serial.h" 24 25#if defined(CONFIG_GDBSTUB_ON_TTYSM0) 26struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0; 27#elif defined(CONFIG_GDBSTUB_ON_TTYSM1) 28struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1; 29#else 30struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2; 31#endif 32 33 34/* 35 * initialise the GDB stub I/O routines 36 */ 37void __init gdbstub_io_init(void) 38{ 39 uint16_t scxctr; 40 int tmp; 41 42 switch (gdbstub_port->clock_src) { 43 case MNSCx_CLOCK_SRC_IOCLK: 44 gdbstub_port->ioclk = MN10300_IOCLK; 45 break; 46 47#ifdef MN10300_IOBCLK 48 case MNSCx_CLOCK_SRC_IOBCLK: 49 gdbstub_port->ioclk = MN10300_IOBCLK; 50 break; 51#endif 52 default: 53 BUG(); 54 } 55 56 /* set up the serial port */ 57 gdbstub_io_set_baud(115200); 58 59 /* we want to get serial receive interrupts */ 60 set_intr_level(gdbstub_port->rx_irq, 61 NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL)); 62 set_intr_level(gdbstub_port->tx_irq, 63 NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL)); 64 set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL), 65 gdbstub_io_rx_handler); 66 67 *gdbstub_port->rx_icr |= GxICR_ENABLE; 68 tmp = *gdbstub_port->rx_icr; 69 70 /* enable the device */ 71 scxctr = SC01CTR_CLN_8BIT; /* 1N8 */ 72 switch (gdbstub_port->div_timer) { 73 case MNSCx_DIV_TIMER_16BIT: 74 scxctr |= SC0CTR_CK_TM8UFLOW_8; /* == SC1CTR_CK_TM9UFLOW_8 75 == SC2CTR_CK_TM10UFLOW_8 */ 76 break; 77 78 case MNSCx_DIV_TIMER_8BIT: 79 scxctr |= SC0CTR_CK_TM2UFLOW_8; 80 break; 81 } 82 83 scxctr |= SC01CTR_TXE | SC01CTR_RXE; 84 85 *gdbstub_port->_control = scxctr; 86 tmp = *gdbstub_port->_control; 87 88 /* permit level 0 IRQs only */ 89 arch_local_change_intr_mask_level( 90 NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1)); 91} 92 93/* 94 * set up the GDB stub serial port baud rate timers 95 */ 96void gdbstub_io_set_baud(unsigned baud) 97{ 98 const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] + 99 * 1 [stop] */ 100 unsigned long ioclk = gdbstub_port->ioclk; 101 unsigned xdiv, tmp; 102 uint16_t tmxbr; 103 uint8_t tmxmd; 104 105 if (!baud) { 106 baud = 9600; 107 } else if (baud == 134) { 108 baud = 269; /* 134 is really 134.5 */ 109 xdiv = 2; 110 } 111 112try_alternative: 113 xdiv = 1; 114 115 switch (gdbstub_port->div_timer) { 116 case MNSCx_DIV_TIMER_16BIT: 117 tmxmd = TM8MD_SRC_IOCLK; 118 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1; 119 if (tmp > 0 && tmp <= 65535) 120 goto timer_okay; 121 122 tmxmd = TM8MD_SRC_IOCLK_8; 123 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1; 124 if (tmp > 0 && tmp <= 65535) 125 goto timer_okay; 126 127 tmxmd = TM8MD_SRC_IOCLK_32; 128 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1; 129 if (tmp > 0 && tmp <= 65535) 130 goto timer_okay; 131 132 break; 133 134 case MNSCx_DIV_TIMER_8BIT: 135 tmxmd = TM2MD_SRC_IOCLK; 136 tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1; 137 if (tmp > 0 && tmp <= 255) 138 goto timer_okay; 139 140 tmxmd = TM2MD_SRC_IOCLK_8; 141 tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1; 142 if (tmp > 0 && tmp <= 255) 143 goto timer_okay; 144 145 tmxmd = TM2MD_SRC_IOCLK_32; 146 tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1; 147 if (tmp > 0 && tmp <= 255) 148 goto timer_okay; 149 break; 150 } 151 152 /* as a last resort, if the quotient is zero, default to 9600 bps */ 153 baud = 9600; 154 goto try_alternative; 155 156timer_okay: 157 gdbstub_port->uart.timeout = (2 * bits * HZ) / baud; 158 gdbstub_port->uart.timeout += HZ / 50; 159 160 /* set the timer to produce the required baud rate */ 161 switch (gdbstub_port->div_timer) { 162 case MNSCx_DIV_TIMER_16BIT: 163 *gdbstub_port->_tmxmd = 0; 164 *gdbstub_port->_tmxbr = tmxbr; 165 *gdbstub_port->_tmxmd = TM8MD_INIT_COUNTER; 166 *gdbstub_port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE; 167 break; 168 169 case MNSCx_DIV_TIMER_8BIT: 170 *gdbstub_port->_tmxmd = 0; 171 *(volatile u8 *) gdbstub_port->_tmxbr = (u8)tmxbr; 172 *gdbstub_port->_tmxmd = TM2MD_INIT_COUNTER; 173 *gdbstub_port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE; 174 break; 175 } 176} 177 178/* 179 * wait for a character to come from the debugger 180 */ 181int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) 182{ 183 unsigned ix; 184 u8 ch, st; 185#if defined(CONFIG_MN10300_WD_TIMER) 186 int cpu; 187#endif 188 189 *_ch = 0xff; 190 191 if (gdbstub_rx_unget) { 192 *_ch = gdbstub_rx_unget; 193 gdbstub_rx_unget = 0; 194 return 0; 195 } 196 197try_again: 198 /* pull chars out of the buffer */ 199 ix = gdbstub_rx_outp; 200 barrier(); 201 if (ix == gdbstub_rx_inp) { 202 if (nonblock) 203 return -EAGAIN; 204#ifdef CONFIG_MN10300_WD_TIMER 205 for (cpu = 0; cpu < NR_CPUS; cpu++) 206 watchdog_alert_counter[cpu] = 0; 207#endif 208 goto try_again; 209 } 210 211 ch = gdbstub_rx_buffer[ix++]; 212 st = gdbstub_rx_buffer[ix++]; 213 barrier(); 214 gdbstub_rx_outp = ix & (PAGE_SIZE - 1); 215 216 st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF | 217 SC01STR_OEF; 218 219 /* deal with what we've got 220 * - note that the UART doesn't do BREAK-detection for us 221 */ 222 if (st & SC01STR_FEF && ch == 0) { 223 switch (gdbstub_port->rx_brk) { 224 case 0: gdbstub_port->rx_brk = 1; goto try_again; 225 case 1: gdbstub_port->rx_brk = 2; goto try_again; 226 case 2: 227 gdbstub_port->rx_brk = 3; 228 gdbstub_proto("### GDB MNSERIAL Rx Break Detected" 229 " ###\n"); 230 return -EINTR; 231 default: 232 goto try_again; 233 } 234 } else if (st & SC01STR_FEF) { 235 if (gdbstub_port->rx_brk) 236 goto try_again; 237 238 gdbstub_proto("### GDB MNSERIAL Framing Error ###\n"); 239 return -EIO; 240 } else if (st & SC01STR_OEF) { 241 if (gdbstub_port->rx_brk) 242 goto try_again; 243 244 gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n"); 245 return -EIO; 246 } else if (st & SC01STR_PEF) { 247 if (gdbstub_port->rx_brk) 248 goto try_again; 249 250 gdbstub_proto("### GDB MNSERIAL Parity Error ###\n"); 251 return -EIO; 252 } else { 253 /* look for the tail-end char on a break run */ 254 if (gdbstub_port->rx_brk == 3) { 255 switch (ch) { 256 case 0xFF: 257 case 0xFE: 258 case 0xFC: 259 case 0xF8: 260 case 0xF0: 261 case 0xE0: 262 case 0xC0: 263 case 0x80: 264 case 0x00: 265 gdbstub_port->rx_brk = 0; 266 goto try_again; 267 default: 268 break; 269 } 270 } 271 272 gdbstub_port->rx_brk = 0; 273 gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st); 274 *_ch = ch & 0x7f; 275 return 0; 276 } 277} 278 279/* 280 * send a character to the debugger 281 */ 282void gdbstub_io_tx_char(unsigned char ch) 283{ 284 while (*gdbstub_port->_status & SC01STR_TBF) 285 continue; 286 287 if (ch == 0x0a) { 288 *(u8 *) gdbstub_port->_txb = 0x0d; 289 while (*gdbstub_port->_status & SC01STR_TBF) 290 continue; 291 } 292 293 *(u8 *) gdbstub_port->_txb = ch; 294} 295 296/* 297 * flush the transmission buffers 298 */ 299void gdbstub_io_tx_flush(void) 300{ 301 while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF)) 302 continue; 303} 304