/*
 * jtag-console.c - console driver over Blackfin JTAG
 *
 * Copyright (c) 2008-2010 Analog Devices Inc.
 *
 * Licensed under the GPL-2 or later.
 */

#include <common.h>
#include <malloc.h>
#include <stdio_dev.h>
#include <asm/blackfin.h>

#ifdef DEBUG
# define dprintf(...) serial_printf(__VA_ARGS__)
#else
# define dprintf(...) do { if (0) printf(__VA_ARGS__); } while (0)
#endif

static inline void dprintf_decode(const char *s, uint32_t len)
{
	uint32_t i;
	for (i = 0; i < len; ++i)
		if (s[i] < 0x20 || s[i] >= 0x7f)
			dprintf("\\%o", s[i]);
		else
			dprintf("%c", s[i]);
}

static inline uint32_t bfin_write_emudat(uint32_t emudat)
{
	__asm__ __volatile__("emudat = %0;" : : "d"(emudat));
	return emudat;
}

static inline uint32_t bfin_read_emudat(void)
{
	uint32_t emudat;
	__asm__ __volatile__("%0 = emudat;" : "=d"(emudat));
	return emudat;
}

#ifndef CONFIG_JTAG_CONSOLE_TIMEOUT
# define CONFIG_JTAG_CONSOLE_TIMEOUT 500
#endif

/* The Blackfin tends to be much much faster than the JTAG hardware. */
static bool jtag_write_emudat(uint32_t emudat)
{
	static bool overflowed = false;
	ulong timeout = get_timer(0);
	while (bfin_read_DBGSTAT() & 0x1) {
		if (overflowed)
			return overflowed;
		if (get_timer(timeout) > CONFIG_JTAG_CONSOLE_TIMEOUT)
			overflowed = true;
	}
	overflowed = false;
	bfin_write_emudat(emudat);
	return overflowed;
}
/* Transmit a buffer.  The format is:
 * [32bit length][actual data]
 */
static void jtag_send(const char *raw_str, uint32_t len)
{
	const char *cooked_str;
	uint32_t i, ex;

	if (len == 0)
		return;

	/* Ugh, need to output \r after \n */
	ex = 0;
	for (i = 0; i < len; ++i)
		if (raw_str[i] == '\n')
			++ex;
	if (ex) {
		char *c = malloc(len + ex);
		cooked_str = c;
		for (i = 0; i < len; ++i) {
			*c++ = raw_str[i];
			if (raw_str[i] == '\n')
				*c++ = '\r';
		}
		len += ex;
	} else
		cooked_str = raw_str;

	dprintf("%s(\"", __func__);
	dprintf_decode(cooked_str, len);
	dprintf("\", %i)\n", len);

	/* First send the length */
	if (jtag_write_emudat(len))
		goto done;

	/* Then send the data */
	for (i = 0; i < len; i += 4) {
		uint32_t emudat =
			(cooked_str[i + 0] <<  0) |
			(cooked_str[i + 1] <<  8) |
			(cooked_str[i + 2] << 16) |
			(cooked_str[i + 3] << 24);
		if (jtag_write_emudat(emudat)) {
			bfin_write_emudat(0);
			goto done;
		}
	}

 done:
	if (cooked_str != raw_str)
		free((char *)cooked_str);
}
static void jtag_putc(struct stdio_dev *dev, const char c)
{
	jtag_send(&c, 1);
}
static void jtag_puts(struct stdio_dev *dev, const char *s)
{
	jtag_send(s, strlen(s));
}

static size_t inbound_len, leftovers_len;

/* Lower layers want to know when jtag has data */
static int jtag_tstc_dbg(void)
{
	int ret = (bfin_read_DBGSTAT() & 0x2);
	if (ret)
		dprintf("%s: ret:%i\n", __func__, ret);
	return ret;
}

/* Higher layers want to know when any data is available */
static int jtag_tstc(struct stdio_dev *dev)
{
	return jtag_tstc_dbg() || leftovers_len;
}

/* Receive a buffer.  The format is:
 * [32bit length][actual data]
 */
static uint32_t leftovers;
static int jtag_getc(struct stdio_dev *dev)
{
	int ret;
	uint32_t emudat;

	dprintf("%s: inlen:%zu leftlen:%zu left:%x\n", __func__,
		inbound_len, leftovers_len, leftovers);

	/* see if any data is left over */
	if (leftovers_len) {
		--leftovers_len;
		ret = leftovers & 0xff;
		leftovers >>= 8;
		return ret;
	}

	/* wait for new data ! */
	while (!jtag_tstc_dbg())
		continue;
	emudat = bfin_read_emudat();

	if (inbound_len == 0) {
		/* grab the length */
		inbound_len = emudat;
	} else {
		/* store the bytes */
		leftovers_len = min((size_t)4, inbound_len);
		inbound_len -= leftovers_len;
		leftovers = emudat;
	}

	return jtag_getc(dev);
}

int drv_jtag_console_init(void)
{
	struct stdio_dev dev;
	int ret;

	memset(&dev, 0x00, sizeof(dev));
	strcpy(dev.name, "jtag");
	dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
	dev.putc = jtag_putc;
	dev.puts = jtag_puts;
	dev.tstc = jtag_tstc;
	dev.getc = jtag_getc;

	ret = stdio_register(&dev);
	return (ret == 0 ? 1 : ret);
}

#ifdef CONFIG_UART_CONSOLE_IS_JTAG
#include <serial.h>
/* Since the JTAG is always available (at power on), allow it to fake a UART */
void jtag_serial_setbrg(void)
{
}

int jtag_serial_init(void)
{
	return 0;
}

static struct serial_device serial_jtag_drv = {
	.name	= "jtag",
	.start	= jtag_serial_init,
	.stop	= NULL,
	.setbrg	= jtag_serial_setbrg,
	.putc	= jtag_putc,
	.puts	= jtag_puts,
	.tstc	= jtag_tstc,
	.getc	= jtag_getc,
};

void bfin_jtag_initialize(void)
{
	serial_register(&serial_jtag_drv);
}

struct serial_device *default_serial_console(void)
{
	return &serial_jtag_drv;
}
#endif
