1/* 2 * Copyright (C) 2003, Axis Communications AB. 3 */ 4 5#include <linux/console.h> 6#include <linux/init.h> 7#include <linux/major.h> 8#include <linux/delay.h> 9#include <linux/tty.h> 10#include <asm/system.h> 11#include <asm/io.h> 12#include <asm/arch/hwregs/ser_defs.h> 13#include <asm/arch/hwregs/dma_defs.h> 14#include <asm/arch/pinmux.h> 15 16#include <asm/irq.h> 17#include <asm/arch/hwregs/intr_vect_defs.h> 18 19struct dbg_port 20{ 21 unsigned char nbr; 22 unsigned long instance; 23 unsigned int started; 24 unsigned long baudrate; 25 unsigned char parity; 26 unsigned int bits; 27}; 28 29struct dbg_port ports[] = 30{ 31 { 32 0, 33 regi_ser0, 34 0, 35 115200, 36 'N', 37 8 38 }, 39 { 40 1, 41 regi_ser1, 42 0, 43 115200, 44 'N', 45 8 46 }, 47 { 48 2, 49 regi_ser2, 50 0, 51 115200, 52 'N', 53 8 54 }, 55 { 56 3, 57 regi_ser3, 58 0, 59 115200, 60 'N', 61 8 62 } 63}; 64static struct dbg_port *port = 65#if defined(CONFIG_ETRAX_DEBUG_PORT0) 66&ports[0]; 67#elif defined(CONFIG_ETRAX_DEBUG_PORT1) 68&ports[1]; 69#elif defined(CONFIG_ETRAX_DEBUG_PORT2) 70&ports[2]; 71#elif defined(CONFIG_ETRAX_DEBUG_PORT3) 72&ports[3]; 73#else 74NULL; 75#endif 76 77#ifdef CONFIG_ETRAX_KGDB 78static struct dbg_port *kgdb_port = 79#if defined(CONFIG_ETRAX_KGDB_PORT0) 80&ports[0]; 81#elif defined(CONFIG_ETRAX_KGDB_PORT1) 82&ports[1]; 83#elif defined(CONFIG_ETRAX_KGDB_PORT2) 84&ports[2]; 85#elif defined(CONFIG_ETRAX_KGDB_PORT3) 86&ports[3]; 87#else 88NULL; 89#endif 90#endif 91 92#ifdef CONFIG_ETRAXFS_SIM 93extern void print_str( const char *str ); 94static char buffer[1024]; 95static char msg[] = "Debug: "; 96static int buffer_pos = sizeof(msg) - 1; 97#endif 98 99extern struct tty_driver *serial_driver; 100 101static void 102start_port(struct dbg_port* p) 103{ 104 if (!p) 105 return; 106 107 if (p->started) 108 return; 109 p->started = 1; 110 111 if (p->nbr == 1) 112 crisv32_pinmux_alloc_fixed(pinmux_ser1); 113 else if (p->nbr == 2) 114 crisv32_pinmux_alloc_fixed(pinmux_ser2); 115 else if (p->nbr == 3) 116 crisv32_pinmux_alloc_fixed(pinmux_ser3); 117 118 /* Set up serial port registers */ 119 reg_ser_rw_tr_ctrl tr_ctrl = {0}; 120 reg_ser_rw_tr_dma_en tr_dma_en = {0}; 121 122 reg_ser_rw_rec_ctrl rec_ctrl = {0}; 123 reg_ser_rw_tr_baud_div tr_baud_div = {0}; 124 reg_ser_rw_rec_baud_div rec_baud_div = {0}; 125 126 tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493; 127 tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no; 128 tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8; 129 tr_ctrl.en = rec_ctrl.en = 1; 130 131 if (p->parity == 'O') 132 { 133 tr_ctrl.par_en = regk_ser_yes; 134 tr_ctrl.par = regk_ser_odd; 135 rec_ctrl.par_en = regk_ser_yes; 136 rec_ctrl.par = regk_ser_odd; 137 } 138 else if (p->parity == 'E') 139 { 140 tr_ctrl.par_en = regk_ser_yes; 141 tr_ctrl.par = regk_ser_even; 142 rec_ctrl.par_en = regk_ser_yes; 143 rec_ctrl.par = regk_ser_odd; 144 } 145 146 if (p->bits == 7) 147 { 148 tr_ctrl.data_bits = regk_ser_bits7; 149 rec_ctrl.data_bits = regk_ser_bits7; 150 } 151 152 REG_WR (ser, p->instance, rw_tr_baud_div, tr_baud_div); 153 REG_WR (ser, p->instance, rw_rec_baud_div, rec_baud_div); 154 REG_WR (ser, p->instance, rw_tr_dma_en, tr_dma_en); 155 REG_WR (ser, p->instance, rw_tr_ctrl, tr_ctrl); 156 REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); 157} 158 159/* No debug */ 160#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL 161 162static void 163console_write(struct console *co, const char *buf, unsigned int len) 164{ 165 return; 166} 167 168/* Target debug */ 169#elif !defined(CONFIG_ETRAXFS_SIM) 170 171static void 172console_write_direct(struct console *co, const char *buf, unsigned int len) 173{ 174 int i; 175 reg_ser_r_stat_din stat; 176 reg_ser_rw_tr_dma_en tr_dma_en, old; 177 178 /* Switch to manual mode */ 179 tr_dma_en = old = REG_RD (ser, port->instance, rw_tr_dma_en); 180 if (tr_dma_en.en == regk_ser_yes) { 181 tr_dma_en.en = regk_ser_no; 182 REG_WR(ser, port->instance, rw_tr_dma_en, tr_dma_en); 183 } 184 185 /* Send data */ 186 for (i = 0; i < len; i++) { 187 /* LF -> CRLF */ 188 if (buf[i] == '\n') { 189 do { 190 stat = REG_RD (ser, port->instance, r_stat_din); 191 } while (!stat.tr_rdy); 192 REG_WR_INT (ser, port->instance, rw_dout, '\r'); 193 } 194 /* Wait until transmitter is ready and send.*/ 195 do { 196 stat = REG_RD (ser, port->instance, r_stat_din); 197 } while (!stat.tr_rdy); 198 REG_WR_INT (ser, port->instance, rw_dout, buf[i]); 199 } 200 201 /* Restore mode */ 202 if (tr_dma_en.en != old.en) 203 REG_WR(ser, port->instance, rw_tr_dma_en, old); 204} 205 206static void 207console_write(struct console *co, const char *buf, unsigned int len) 208{ 209 if (!port) 210 return; 211 console_write_direct(co, buf, len); 212} 213 214 215 216#else 217 218/* VCS debug */ 219 220static void 221console_write(struct console *co, const char *buf, unsigned int len) 222{ 223 char* pos; 224 pos = memchr(buf, '\n', len); 225 if (pos) { 226 int l = ++pos - buf; 227 memcpy(buffer + buffer_pos, buf, l); 228 memcpy(buffer, msg, sizeof(msg) - 1); 229 buffer[buffer_pos + l] = '\0'; 230 print_str(buffer); 231 buffer_pos = sizeof(msg) - 1; 232 if (pos - buf != len) { 233 memcpy(buffer + buffer_pos, pos, len - l); 234 buffer_pos += len - l; 235 } 236 } else { 237 memcpy(buffer + buffer_pos, buf, len); 238 buffer_pos += len; 239 } 240} 241 242#endif 243 244int raw_printk(const char *fmt, ...) 245{ 246 static char buf[1024]; 247 int printed_len; 248 va_list args; 249 va_start(args, fmt); 250 printed_len = vsnprintf(buf, sizeof(buf), fmt, args); 251 va_end(args); 252 console_write(NULL, buf, strlen(buf)); 253 return printed_len; 254} 255 256void 257stupid_debug(char* buf) 258{ 259 console_write(NULL, buf, strlen(buf)); 260} 261 262#ifdef CONFIG_ETRAX_KGDB 263/* Use polling to get a single character from the kernel debug port */ 264int 265getDebugChar(void) 266{ 267 reg_ser_rs_status_data stat; 268 reg_ser_rw_ack_intr ack_intr = { 0 }; 269 270 do { 271 stat = REG_RD(ser, kgdb_instance, rs_status_data); 272 } while (!stat.data_avail); 273 274 /* Ack the data_avail interrupt. */ 275 ack_intr.data_avail = 1; 276 REG_WR(ser, kgdb_instance, rw_ack_intr, ack_intr); 277 278 return stat.data; 279} 280 281/* Use polling to put a single character to the kernel debug port */ 282void 283putDebugChar(int val) 284{ 285 reg_ser_r_status_data stat; 286 do { 287 stat = REG_RD (ser, kgdb_instance, r_status_data); 288 } while (!stat.tr_ready); 289 REG_WR (ser, kgdb_instance, rw_data_out, REG_TYPE_CONV(reg_ser_rw_data_out, int, val)); 290} 291#endif /* CONFIG_ETRAX_KGDB */ 292 293static int __init 294console_setup(struct console *co, char *options) 295{ 296 char* s; 297 298 if (options) { 299 port = &ports[co->index]; 300 port->baudrate = 115200; 301 port->parity = 'N'; 302 port->bits = 8; 303 port->baudrate = simple_strtoul(options, NULL, 10); 304 s = options; 305 while(*s >= '0' && *s <= '9') 306 s++; 307 if (*s) port->parity = *s++; 308 if (*s) port->bits = *s++ - '0'; 309 port->started = 0; 310 start_port(port); 311 } 312 return 0; 313} 314 315/* This is a dummy serial device that throws away anything written to it. 316 * This is used when no debug output is wanted. 317 */ 318static struct tty_driver dummy_driver; 319 320static int dummy_open(struct tty_struct *tty, struct file * filp) 321{ 322 return 0; 323} 324 325static void dummy_close(struct tty_struct *tty, struct file * filp) 326{ 327} 328 329static int dummy_write(struct tty_struct * tty, 330 const unsigned char *buf, int count) 331{ 332 return count; 333} 334 335static int 336dummy_write_room(struct tty_struct *tty) 337{ 338 return 8192; 339} 340 341void __init 342init_dummy_console(void) 343{ 344 memset(&dummy_driver, 0, sizeof(struct tty_driver)); 345 dummy_driver.driver_name = "serial"; 346 dummy_driver.name = "ttyS"; 347 dummy_driver.major = TTY_MAJOR; 348 dummy_driver.minor_start = 68; 349 dummy_driver.num = 1; /* etrax100 has 4 serial ports */ 350 dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; 351 dummy_driver.subtype = SERIAL_TYPE_NORMAL; 352 dummy_driver.init_termios = tty_std_termios; 353 dummy_driver.init_termios.c_cflag = 354 B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ 355 dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 356 357 dummy_driver.open = dummy_open; 358 dummy_driver.close = dummy_close; 359 dummy_driver.write = dummy_write; 360 dummy_driver.write_room = dummy_write_room; 361 if (tty_register_driver(&dummy_driver)) 362 panic("Couldn't register dummy serial driver\n"); 363} 364 365static struct tty_driver* 366crisv32_console_device(struct console* co, int *index) 367{ 368 if (port) 369 *index = port->nbr; 370 return port ? serial_driver : &dummy_driver; 371} 372 373static struct console sercons = { 374 name : "ttyS", 375 write: console_write, 376 read : NULL, 377 device : crisv32_console_device, 378 unblank : NULL, 379 setup : console_setup, 380 flags : CON_PRINTBUFFER, 381 index : -1, 382 cflag : 0, 383 next : NULL 384}; 385static struct console sercons0 = { 386 name : "ttyS", 387 write: console_write, 388 read : NULL, 389 device : crisv32_console_device, 390 unblank : NULL, 391 setup : console_setup, 392 flags : CON_PRINTBUFFER, 393 index : 0, 394 cflag : 0, 395 next : NULL 396}; 397 398static struct console sercons1 = { 399 name : "ttyS", 400 write: console_write, 401 read : NULL, 402 device : crisv32_console_device, 403 unblank : NULL, 404 setup : console_setup, 405 flags : CON_PRINTBUFFER, 406 index : 1, 407 cflag : 0, 408 next : NULL 409}; 410static struct console sercons2 = { 411 name : "ttyS", 412 write: console_write, 413 read : NULL, 414 device : crisv32_console_device, 415 unblank : NULL, 416 setup : console_setup, 417 flags : CON_PRINTBUFFER, 418 index : 2, 419 cflag : 0, 420 next : NULL 421}; 422static struct console sercons3 = { 423 name : "ttyS", 424 write: console_write, 425 read : NULL, 426 device : crisv32_console_device, 427 unblank : NULL, 428 setup : console_setup, 429 flags : CON_PRINTBUFFER, 430 index : 3, 431 cflag : 0, 432 next : NULL 433}; 434 435/* Register console for printk's, etc. */ 436int __init 437init_etrax_debug(void) 438{ 439 static int first = 1; 440 441 if (!first) { 442 unregister_console(&sercons); 443 register_console(&sercons0); 444 register_console(&sercons1); 445 register_console(&sercons2); 446 register_console(&sercons3); 447 init_dummy_console(); 448 return 0; 449 } 450 first = 0; 451 register_console(&sercons); 452 start_port(port); 453 454#ifdef CONFIG_ETRAX_KGDB 455 start_port(kgdb_port); 456#endif /* CONFIG_ETRAX_KGDB */ 457 return 0; 458} 459 460__initcall(init_etrax_debug); 461