linux/drivers/tty/hvc/hvc_bfin_jtag.c
<<
>>
Prefs
   1/*
   2 * Console via Blackfin JTAG Communication
   3 *
   4 * Copyright 2008-2011 Analog Devices Inc.
   5 *
   6 * Enter bugs at http://blackfin.uclinux.org/
   7 *
   8 * Licensed under the GPL-2 or later.
   9 */
  10
  11#include <linux/console.h>
  12#include <linux/delay.h>
  13#include <linux/err.h>
  14#include <linux/init.h>
  15#include <linux/moduleparam.h>
  16#include <linux/types.h>
  17
  18#include "hvc_console.h"
  19
  20/* See the Debug/Emulation chapter in the HRM */
  21#define EMUDOF   0x00000001     /* EMUDAT_OUT full & valid */
  22#define EMUDIF   0x00000002     /* EMUDAT_IN full & valid */
  23#define EMUDOOVF 0x00000004     /* EMUDAT_OUT overflow */
  24#define EMUDIOVF 0x00000008     /* EMUDAT_IN overflow */
  25
  26/* Helper functions to glue the register API to simple C operations */
  27static inline uint32_t bfin_write_emudat(uint32_t emudat)
  28{
  29        __asm__ __volatile__("emudat = %0;" : : "d"(emudat));
  30        return emudat;
  31}
  32
  33static inline uint32_t bfin_read_emudat(void)
  34{
  35        uint32_t emudat;
  36        __asm__ __volatile__("%0 = emudat;" : "=d"(emudat));
  37        return emudat;
  38}
  39
  40/* Send data to the host */
  41static int hvc_bfin_put_chars(uint32_t vt, const char *buf, int count)
  42{
  43        static uint32_t outbound_len;
  44        uint32_t emudat;
  45        int ret;
  46
  47        if (bfin_read_DBGSTAT() & EMUDOF)
  48                return 0;
  49
  50        if (!outbound_len) {
  51                outbound_len = count;
  52                bfin_write_emudat(outbound_len);
  53                return 0;
  54        }
  55
  56        ret = min(outbound_len, (uint32_t)4);
  57        memcpy(&emudat, buf, ret);
  58        bfin_write_emudat(emudat);
  59        outbound_len -= ret;
  60
  61        return ret;
  62}
  63
  64/* Receive data from the host */
  65static int hvc_bfin_get_chars(uint32_t vt, char *buf, int count)
  66{
  67        static uint32_t inbound_len;
  68        uint32_t emudat;
  69        int ret;
  70
  71        if (!(bfin_read_DBGSTAT() & EMUDIF))
  72                return 0;
  73        emudat = bfin_read_emudat();
  74
  75        if (!inbound_len) {
  76                inbound_len = emudat;
  77                return 0;
  78        }
  79
  80        ret = min(inbound_len, (uint32_t)4);
  81        memcpy(buf, &emudat, ret);
  82        inbound_len -= ret;
  83
  84        return ret;
  85}
  86
  87/* Glue the HVC layers to the Blackfin layers */
  88static const struct hv_ops hvc_bfin_get_put_ops = {
  89        .get_chars = hvc_bfin_get_chars,
  90        .put_chars = hvc_bfin_put_chars,
  91};
  92
  93static int __init hvc_bfin_console_init(void)
  94{
  95        hvc_instantiate(0, 0, &hvc_bfin_get_put_ops);
  96        return 0;
  97}
  98console_initcall(hvc_bfin_console_init);
  99
 100static int __init hvc_bfin_init(void)
 101{
 102        hvc_alloc(0, 0, &hvc_bfin_get_put_ops, 128);
 103        return 0;
 104}
 105device_initcall(hvc_bfin_init);
 106