Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4729d773 authored by Jesper Nilsson's avatar Jesper Nilsson
Browse files

CRISv32: Implement early console

parent 421d0852
Loading
Loading
Loading
Loading
+56 −26
Original line number Original line Diff line number Diff line
@@ -3,7 +3,9 @@
 */
 */


#include <linux/console.h>
#include <linux/console.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/string.h>
#include <hwregs/reg_rdwr.h>
#include <hwregs/reg_rdwr.h>
#include <hwregs/reg_map.h>
#include <hwregs/reg_map.h>
#include <hwregs/ser_defs.h>
#include <hwregs/ser_defs.h>
@@ -65,6 +67,7 @@ struct dbg_port ports[] =
  },
  },
#endif
#endif
};
};

static struct dbg_port *port =
static struct dbg_port *port =
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
	&ports[0];
	&ports[0];
@@ -97,14 +100,19 @@ static struct dbg_port *kgdb_port =
#endif
#endif
#endif
#endif


static void
static void start_port(struct dbg_port *p)
start_port(struct dbg_port* p)
{
{
	if (!p)
	/* Set up serial port registers */
		return;
	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->started)
	if (!p || p->started)
		return;
		return;

	p->started = 1;
	p->started = 1;


	if (p->nbr == 1)
	if (p->nbr == 1)
@@ -118,36 +126,24 @@ start_port(struct dbg_port* p)
		crisv32_pinmux_alloc_fixed(pinmux_ser4);
		crisv32_pinmux_alloc_fixed(pinmux_ser4);
#endif
#endif


	/* 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};

	tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493;
	tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493;
	tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no;
	tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no;
	tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8;
	tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8;
	tr_ctrl.en = rec_ctrl.en = 1;
	tr_ctrl.en = rec_ctrl.en = 1;


	if (p->parity == 'O')
	if (p->parity == 'O') {
	{
		tr_ctrl.par_en = regk_ser_yes;
		tr_ctrl.par_en = regk_ser_yes;
		tr_ctrl.par = regk_ser_odd;
		tr_ctrl.par = regk_ser_odd;
		rec_ctrl.par_en = regk_ser_yes;
		rec_ctrl.par_en = regk_ser_yes;
		rec_ctrl.par = regk_ser_odd;
		rec_ctrl.par = regk_ser_odd;
	}
	} else if (p->parity == 'E') {
	else if (p->parity == 'E')
	{
		tr_ctrl.par_en = regk_ser_yes;
		tr_ctrl.par_en = regk_ser_yes;
		tr_ctrl.par = regk_ser_even;
		tr_ctrl.par = regk_ser_even;
		rec_ctrl.par_en = regk_ser_yes;
		rec_ctrl.par_en = regk_ser_yes;
		rec_ctrl.par = regk_ser_odd;
		rec_ctrl.par = regk_ser_odd;
	}
	}


	if (p->bits == 7)
	if (p->bits == 7) {
	{
		tr_ctrl.data_bits = regk_ser_bits7;
		tr_ctrl.data_bits = regk_ser_bits7;
		rec_ctrl.data_bits = regk_ser_bits7;
		rec_ctrl.data_bits = regk_ser_bits7;
	}
	}
@@ -161,8 +157,7 @@ start_port(struct dbg_port* p)


#ifdef CONFIG_ETRAX_KGDB
#ifdef CONFIG_ETRAX_KGDB
/* Use polling to get a single character from the kernel debug port */
/* Use polling to get a single character from the kernel debug port */
int
int getDebugChar(void)
getDebugChar(void)
{
{
	reg_ser_rs_stat_din stat;
	reg_ser_rs_stat_din stat;
	reg_ser_rw_ack_intr ack_intr = { 0 };
	reg_ser_rw_ack_intr ack_intr = { 0 };
@@ -179,8 +174,7 @@ getDebugChar(void)
}
}


/* Use polling to put a single character to the kernel debug port */
/* Use polling to put a single character to the kernel debug port */
void
void putDebugChar(int val)
putDebugChar(int val)
{
{
	reg_ser_r_stat_din stat;
	reg_ser_r_stat_din stat;
	do {
	do {
@@ -190,12 +184,48 @@ putDebugChar(int val)
}
}
#endif /* CONFIG_ETRAX_KGDB */
#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. */
/* Register console for printk's, etc. */
int __init
int __init init_etrax_debug(void)
init_etrax_debug(void)
{
{
        start_port(port);
        start_port(port);


	/* Register an early console if a debug port was chosen.  */
	register_console(&early_console_dev);

#ifdef CONFIG_ETRAX_KGDB
#ifdef CONFIG_ETRAX_KGDB
	start_port(kgdb_port);
	start_port(kgdb_port);
#endif /* CONFIG_ETRAX_KGDB */
#endif /* CONFIG_ETRAX_KGDB */