/*
 * Simple serial driver for Cogent motherboard serial ports
 * for use during boot
 */

#include <common.h>
#include <board/cogent/serial.h>
#include <serial.h>
#include <linux/compiler.h>

DECLARE_GLOBAL_DATA_PTR;

#if (CMA_MB_CAPS & CMA_MB_CAP_SERPAR)

#if (defined(CONFIG_8xx) && defined(CONFIG_8xx_CONS_NONE)) || \
     (defined(CONFIG_8260) && defined(CONFIG_CONS_NONE))

#if CONFIG_CONS_INDEX == 1
#define CMA_MB_SERIAL_BASE	CMA_MB_SERIALA_BASE
#elif CONFIG_CONS_INDEX == 2
#define CMA_MB_SERIAL_BASE	CMA_MB_SERIALB_BASE
#elif CONFIG_CONS_INDEX == 3 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
#define CMA_MB_SERIAL_BASE	CMA_MB_SER2A_BASE
#elif CONFIG_CONS_INDEX == 4 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
#define CMA_MB_SERIAL_BASE	CMA_MB_SER2B_BASE
#else
#error CONFIG_CONS_INDEX must be configured for Cogent motherboard serial
#endif

static int cogent_serial_init(void)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_SERIAL_BASE;

	cma_mb_reg_write (&mbsp->ser_ier, 0x00);	/* turn off interrupts */
	serial_setbrg ();
	cma_mb_reg_write (&mbsp->ser_lcr, 0x03);	/* 8 data, 1 stop, no parity */
	cma_mb_reg_write (&mbsp->ser_mcr, 0x03);	/* RTS/DTR */
	cma_mb_reg_write (&mbsp->ser_fcr, 0x07);	/* Clear & enable FIFOs */

	return (0);
}

static void cogent_serial_setbrg(void)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_SERIAL_BASE;
	unsigned int divisor;
	unsigned char lcr;

	if ((divisor = br_to_div (gd->baudrate)) == 0)
		divisor = DEFDIV;

	lcr = cma_mb_reg_read (&mbsp->ser_lcr);
	cma_mb_reg_write (&mbsp->ser_lcr, lcr | 0x80);	/* Access baud rate(set DLAB) */
	cma_mb_reg_write (&mbsp->ser_brl, divisor & 0xff);
	cma_mb_reg_write (&mbsp->ser_brh, (divisor >> 8) & 0xff);
	cma_mb_reg_write (&mbsp->ser_lcr, lcr);	/* unset DLAB */
}

static void cogent_serial_putc(const char c)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_SERIAL_BASE;

	if (c == '\n')
		serial_putc ('\r');

	while ((cma_mb_reg_read (&mbsp->ser_lsr) & LSR_THRE) == 0);

	cma_mb_reg_write (&mbsp->ser_thr, c);
}

static int cogent_serial_getc(void)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_SERIAL_BASE;

	while ((cma_mb_reg_read (&mbsp->ser_lsr) & LSR_DR) == 0);

	return ((int) cma_mb_reg_read (&mbsp->ser_rhr) & 0x7f);
}

static int cogent_serial_tstc(void)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_SERIAL_BASE;

	return ((cma_mb_reg_read (&mbsp->ser_lsr) & LSR_DR) != 0);
}

static struct serial_device cogent_serial_drv = {
	.name	= "cogent_serial",
	.start	= cogent_serial_init,
	.stop	= NULL,
	.setbrg	= cogent_serial_setbrg,
	.putc	= cogent_serial_putc,
	.puts	= default_serial_puts,
	.getc	= cogent_serial_getc,
	.tstc	= cogent_serial_tstc,
};

void cogent_serial_initialize(void)
{
	serial_register(&cogent_serial_drv);
}

__weak struct serial_device *default_serial_console(void)
{
	return &cogent_serial_drv;
}
#endif /* CONS_NONE */

#if defined(CONFIG_CMD_KGDB) && \
    defined(CONFIG_KGDB_NONE)

#if CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
#error Console and kgdb are on the same serial port - this is not supported
#endif

#if CONFIG_KGDB_INDEX == 1
#define CMA_MB_KGDB_SER_BASE	CMA_MB_SERIALA_BASE
#elif CONFIG_KGDB_INDEX == 2
#define CMA_MB_KGDB_SER_BASE	CMA_MB_SERIALB_BASE
#elif CONFIG_KGDB_INDEX == 3 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
#define CMA_MB_KGDB_SER_BASE	CMA_MB_SER2A_BASE
#elif CONFIG_KGDB_INDEX == 4 && (CMA_MB_CAPS & CMA_MB_CAP_SER2)
#define CMA_MB_KGDB_SER_BASE	CMA_MB_SER2B_BASE
#else
#error CONFIG_KGDB_INDEX must be configured for Cogent motherboard serial
#endif

void kgdb_serial_init (void)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_KGDB_SER_BASE;
	unsigned int divisor;

	if ((divisor = br_to_div (CONFIG_KGDB_BAUDRATE)) == 0)
		divisor = DEFDIV;

	cma_mb_reg_write (&mbsp->ser_ier, 0x00);	/* turn off interrupts */
	cma_mb_reg_write (&mbsp->ser_lcr, 0x80);	/* Access baud rate(set DLAB) */
	cma_mb_reg_write (&mbsp->ser_brl, divisor & 0xff);
	cma_mb_reg_write (&mbsp->ser_brh, (divisor >> 8) & 0xff);
	cma_mb_reg_write (&mbsp->ser_lcr, 0x03);	/* 8 data, 1 stop, no parity */
	cma_mb_reg_write (&mbsp->ser_mcr, 0x03);	/* RTS/DTR */
	cma_mb_reg_write (&mbsp->ser_fcr, 0x07);	/* Clear & enable FIFOs */

	printf ("[on cma10x serial port B] ");
}

void putDebugChar (int c)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_KGDB_SER_BASE;

	while ((cma_mb_reg_read (&mbsp->ser_lsr) & LSR_THRE) == 0);

	cma_mb_reg_write (&mbsp->ser_thr, c & 0xff);
}

void putDebugStr (const char *str)
{
	while (*str != '\0') {
		if (*str == '\n')
			putDebugChar ('\r');
		putDebugChar (*str++);
	}
}

int getDebugChar (void)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_KGDB_SER_BASE;

	while ((cma_mb_reg_read (&mbsp->ser_lsr) & LSR_DR) == 0);

	return ((int) cma_mb_reg_read (&mbsp->ser_rhr) & 0x7f);
}

void kgdb_interruptible (int yes)
{
	cma_mb_serial *mbsp = (cma_mb_serial *) CMA_MB_KGDB_SER_BASE;

	if (yes == 1) {
		printf ("kgdb: turning serial ints on\n");
		cma_mb_reg_write (&mbsp->ser_ier, 0xf);
	} else {
		printf ("kgdb: turning serial ints off\n");
		cma_mb_reg_write (&mbsp->ser_ier, 0x0);
	}
}

#endif /* KGDB && KGDB_NONE */

#endif /* CAPS & SERPAR */
