From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- arch/cris/arch-v32/kernel/debugport.c | 233 ++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 arch/cris/arch-v32/kernel/debugport.c (limited to 'arch/cris/arch-v32/kernel/debugport.c') diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c new file mode 100644 index 000000000..02e33ebe5 --- /dev/null +++ b/arch/cris/arch-v32/kernel/debugport.c @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2003, Axis Communications AB. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct dbg_port +{ + unsigned char nbr; + unsigned long instance; + unsigned int started; + unsigned long baudrate; + unsigned char parity; + unsigned int bits; +}; + +struct dbg_port ports[] = +{ + { + 0, + regi_ser0, + 0, + 115200, + 'N', + 8 + }, + { + 1, + regi_ser1, + 0, + 115200, + 'N', + 8 + }, + { + 2, + regi_ser2, + 0, + 115200, + 'N', + 8 + }, + { + 3, + regi_ser3, + 0, + 115200, + 'N', + 8 + }, +#if CONFIG_ETRAX_SERIAL_PORTS == 5 + { + 4, + regi_ser4, + 0, + 115200, + 'N', + 8 + }, +#endif +}; + +static struct dbg_port *port = +#if defined(CONFIG_ETRAX_DEBUG_PORT0) + &ports[0]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT1) + &ports[1]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT2) + &ports[2]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT3) + &ports[3]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT4) + &ports[4]; +#else + NULL; +#endif + +#ifdef CONFIG_ETRAX_KGDB +static struct dbg_port *kgdb_port = +#if defined(CONFIG_ETRAX_KGDB_PORT0) + &ports[0]; +#elif defined(CONFIG_ETRAX_KGDB_PORT1) + &ports[1]; +#elif defined(CONFIG_ETRAX_KGDB_PORT2) + &ports[2]; +#elif defined(CONFIG_ETRAX_KGDB_PORT3) + &ports[3]; +#elif defined(CONFIG_ETRAX_KGDB_PORT4) + &ports[4]; +#else + NULL; +#endif +#endif + +static void start_port(struct dbg_port *p) +{ + /* Set up serial port registers */ + reg_ser_rw_tr_ctrl tr_ctrl = {0}; + reg_ser_rw_tr_dma_en tr_dma_en = {0}; + + reg_ser_rw_rec_ctrl rec_ctrl = {0}; + reg_ser_rw_tr_baud_div tr_baud_div = {0}; + reg_ser_rw_rec_baud_div rec_baud_div = {0}; + + if (!p || p->started) + return; + + p->started = 1; + + if (p->nbr == 1) + crisv32_pinmux_alloc_fixed(pinmux_ser1); + else if (p->nbr == 2) + crisv32_pinmux_alloc_fixed(pinmux_ser2); + else if (p->nbr == 3) + crisv32_pinmux_alloc_fixed(pinmux_ser3); +#if CONFIG_ETRAX_SERIAL_PORTS == 5 + else if (p->nbr == 4) + crisv32_pinmux_alloc_fixed(pinmux_ser4); +#endif + + tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493; + tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no; + tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8; + tr_ctrl.en = rec_ctrl.en = 1; + + if (p->parity == 'O') { + tr_ctrl.par_en = regk_ser_yes; + tr_ctrl.par = regk_ser_odd; + rec_ctrl.par_en = regk_ser_yes; + rec_ctrl.par = regk_ser_odd; + } else if (p->parity == 'E') { + tr_ctrl.par_en = regk_ser_yes; + tr_ctrl.par = regk_ser_even; + rec_ctrl.par_en = regk_ser_yes; + rec_ctrl.par = regk_ser_odd; + } + + if (p->bits == 7) { + tr_ctrl.data_bits = regk_ser_bits7; + rec_ctrl.data_bits = regk_ser_bits7; + } + + REG_WR (ser, p->instance, rw_tr_baud_div, tr_baud_div); + REG_WR (ser, p->instance, rw_rec_baud_div, rec_baud_div); + REG_WR (ser, p->instance, rw_tr_dma_en, tr_dma_en); + REG_WR (ser, p->instance, rw_tr_ctrl, tr_ctrl); + REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); +} + +#ifdef CONFIG_ETRAX_KGDB +/* Use polling to get a single character from the kernel debug port */ +int getDebugChar(void) +{ + reg_ser_rs_stat_din stat; + reg_ser_rw_ack_intr ack_intr = { 0 }; + + do { + stat = REG_RD(ser, kgdb_port->instance, rs_stat_din); + } while (!stat.dav); + + /* Ack the data_avail interrupt. */ + ack_intr.dav = 1; + REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr); + + return stat.data; +} + +/* Use polling to put a single character to the kernel debug port */ +void putDebugChar(int val) +{ + reg_ser_r_stat_din stat; + do { + stat = REG_RD(ser, kgdb_port->instance, r_stat_din); + } while (!stat.tr_rdy); + REG_WR_INT(ser, kgdb_port->instance, rw_dout, val); +} +#endif /* CONFIG_ETRAX_KGDB */ + +static void __init early_putch(int c) +{ + reg_ser_r_stat_din stat; + /* Wait until transmitter is ready and send. */ + do + stat = REG_RD(ser, port->instance, r_stat_din); + while (!stat.tr_rdy); + REG_WR_INT(ser, port->instance, rw_dout, c); +} + +static void __init +early_console_write(struct console *con, const char *s, unsigned n) +{ + extern void reset_watchdog(void); + int i; + + /* Send data. */ + for (i = 0; i < n; i++) { + /* TODO: the '\n' -> '\n\r' translation should be done at the + receiver. Remove it when the serial driver removes it. */ + if (s[i] == '\n') + early_putch('\r'); + early_putch(s[i]); + reset_watchdog(); + } +} + +static struct console early_console_dev __initdata = { + .name = "early", + .write = early_console_write, + .flags = CON_PRINTBUFFER | CON_BOOT, + .index = -1 +}; + +/* Register console for printk's, etc. */ +int __init init_etrax_debug(void) +{ + start_port(port); + + /* Register an early console if a debug port was chosen. */ + register_console(&early_console_dev); + +#ifdef CONFIG_ETRAX_KGDB + start_port(kgdb_port); +#endif /* CONFIG_ETRAX_KGDB */ + return 0; +} -- cgit v1.2.3-54-g00ecf