uboot/cpu/blackfin/jtag-console.c
<<
>>
Prefs
   1/*
   2 * jtag-console.c - console driver over Blackfin JTAG
   3 *
   4 * Copyright (c) 2008 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <common.h>
  10#include <stdio_dev.h>
  11#include <asm/blackfin.h>
  12
  13#ifndef CONFIG_JTAG_CONSOLE_TIMEOUT
  14# define CONFIG_JTAG_CONSOLE_TIMEOUT 500
  15#endif
  16
  17/* The Blackfin tends to be much much faster than the JTAG hardware. */
  18static void jtag_write_emudat(uint32_t emudat)
  19{
  20        static bool overflowed = false;
  21        ulong timeout = get_timer(0) + CONFIG_JTAG_CONSOLE_TIMEOUT;
  22        while (bfin_read_DBGSTAT() & 0x1) {
  23                if (overflowed)
  24                        return;
  25                if (timeout < get_timer(0))
  26                        overflowed = true;
  27        }
  28        overflowed = false;
  29        __asm__ __volatile__("emudat = %0;" : : "d"(emudat));
  30}
  31/* Transmit a buffer.  The format is:
  32 * [32bit length][actual data]
  33 */
  34static void jtag_send(const char *c, uint32_t len)
  35{
  36        uint32_t i;
  37
  38        if (len == 0)
  39                return;
  40
  41        /* First send the length */
  42        jtag_write_emudat(len);
  43
  44        /* Then send the data */
  45        for (i = 0; i < len; i += 4)
  46                jtag_write_emudat((c[i] << 0) | (c[i+1] << 8) | (c[i+2] << 16) | (c[i+3] << 24));
  47}
  48static void jtag_putc(const char c)
  49{
  50        jtag_send(&c, 1);
  51}
  52static void jtag_puts(const char *s)
  53{
  54        jtag_send(s, strlen(s));
  55}
  56
  57static size_t inbound_len, leftovers_len;
  58
  59/* Lower layers want to know when jtag has data */
  60static int jtag_tstc_dbg(void)
  61{
  62        return (bfin_read_DBGSTAT() & 0x2);
  63}
  64
  65/* Higher layers want to know when any data is available */
  66static int jtag_tstc(void)
  67{
  68        return jtag_tstc_dbg() || leftovers_len;
  69}
  70
  71/* Receive a buffer.  The format is:
  72 * [32bit length][actual data]
  73 */
  74static uint32_t leftovers;
  75static int jtag_getc(void)
  76{
  77        int ret;
  78        uint32_t emudat;
  79
  80        /* see if any data is left over */
  81        if (leftovers_len) {
  82                --leftovers_len;
  83                ret = leftovers & 0xff;
  84                leftovers >>= 8;
  85                return ret;
  86        }
  87
  88        /* wait for new data ! */
  89        while (!jtag_tstc_dbg())
  90                continue;
  91        __asm__("%0 = emudat;" : "=d"(emudat));
  92
  93        if (inbound_len == 0) {
  94                /* grab the length */
  95                inbound_len = emudat;
  96        } else {
  97                /* store the bytes */
  98                leftovers_len = min(4, inbound_len);
  99                inbound_len -= leftovers_len;
 100                leftovers = emudat;
 101        }
 102
 103        return jtag_getc();
 104}
 105
 106int drv_jtag_console_init(void)
 107{
 108        struct stdio_dev dev;
 109        int ret;
 110
 111        memset(&dev, 0x00, sizeof(dev));
 112        strcpy(dev.name, "jtag");
 113        dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
 114        dev.putc = jtag_putc;
 115        dev.puts = jtag_puts;
 116        dev.tstc = jtag_tstc;
 117        dev.getc = jtag_getc;
 118
 119        ret = stdio_register(&dev);
 120        return (ret == 0 ? 1 : ret);
 121}
 122
 123#ifdef CONFIG_UART_CONSOLE_IS_JTAG
 124/* Since the JTAG is always available (at power on), allow it to fake a UART */
 125void serial_set_baud(uint32_t baud) {}
 126void serial_setbrg(void)            {}
 127int serial_init(void)               { return 0; }
 128void serial_putc(const char c)      __attribute__((alias("jtag_putc")));
 129void serial_puts(const char *s)     __attribute__((alias("jtag_puts")));
 130int serial_tstc(void)               __attribute__((alias("jtag_tstc")));
 131int serial_getc(void)               __attribute__((alias("jtag_getc")));
 132#endif
 133