linux/arch/cris/arch-v32/kernel/debugport.c
<<
>>
Prefs
   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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.