*/
#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));
static bool jtag_write_emudat(uint32_t emudat)
{
static bool overflowed = false;
- ulong timeout = get_timer(0) + CONFIG_JTAG_CONSOLE_TIMEOUT;
+ ulong timeout = get_timer(0);
while (bfin_read_DBGSTAT() & 0x1) {
if (overflowed)
return overflowed;
- if (timeout < get_timer(0))
+ if (get_timer(timeout) > CONFIG_JTAG_CONSOLE_TIMEOUT)
overflowed = true;
}
overflowed = false;
/* Transmit a buffer. The format is:
* [32bit length][actual data]
*/
-static void jtag_send(const char *c, uint32_t len)
+static void jtag_send(const char *raw_str, uint32_t len)
{
- uint32_t i;
+ 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))
- return;
+ goto done;
/* Then send the data */
for (i = 0; i < len; i += 4) {
uint32_t emudat =
- (c[i + 0] << 0) |
- (c[i + 1] << 8) |
- (c[i + 2] << 16) |
- (c[i + 3] << 24);
+ (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);
- return;
+ goto done;
}
}
+
+ done:
+ if (cooked_str != raw_str)
+ free((char *)cooked_str);
}
static void jtag_putc(const char c)
{
/* Lower layers want to know when jtag has data */
static int jtag_tstc_dbg(void)
{
- return (bfin_read_DBGSTAT() & 0x2);
+ 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 */
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;
}
#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 serial_set_baud(uint32_t baud) {}
-void serial_setbrg(void) {}
-int serial_init(void) { return 0; }
-void serial_putc(const char c) __attribute__((alias("jtag_putc")));
-void serial_puts(const char *s) __attribute__((alias("jtag_puts")));
-int serial_tstc(void) __attribute__((alias("jtag_tstc")));
-int serial_getc(void) __attribute__((alias("jtag_getc")));
+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