uboot/drivers/serial/altera_jtag_uart.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
   4 * Scott McNutt <smcnutt@psyent.com>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <serial.h>
  11#include <asm/io.h>
  12
  13/* data register */
  14#define ALTERA_JTAG_RVALID      BIT(15) /* Read valid */
  15
  16/* control register */
  17#define ALTERA_JTAG_AC          BIT(10) /* activity indicator */
  18#define ALTERA_JTAG_RRDY        BIT(12) /* read available */
  19#define ALTERA_JTAG_WSPACE(d)   ((d) >> 16)     /* Write space avail */
  20/* Write fifo size. FIXME: this should be extracted with sopc2dts */
  21#define ALTERA_JTAG_WRITE_DEPTH 64
  22
  23struct altera_jtaguart_regs {
  24        u32     data;                   /* Data register */
  25        u32     control;                /* Control register */
  26};
  27
  28struct altera_jtaguart_platdata {
  29        struct altera_jtaguart_regs *regs;
  30};
  31
  32static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate)
  33{
  34        return 0;
  35}
  36
  37static int altera_jtaguart_putc(struct udevice *dev, const char ch)
  38{
  39        struct altera_jtaguart_platdata *plat = dev->platdata;
  40        struct altera_jtaguart_regs *const regs = plat->regs;
  41        u32 st = readl(&regs->control);
  42
  43#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
  44        if (!(st & ALTERA_JTAG_AC)) /* no connection yet */
  45                return -ENETUNREACH;
  46#endif
  47
  48        if (ALTERA_JTAG_WSPACE(st) == 0)
  49                return -EAGAIN;
  50
  51        writel(ch, &regs->data);
  52
  53        return 0;
  54}
  55
  56static int altera_jtaguart_pending(struct udevice *dev, bool input)
  57{
  58        struct altera_jtaguart_platdata *plat = dev->platdata;
  59        struct altera_jtaguart_regs *const regs = plat->regs;
  60        u32 st = readl(&regs->control);
  61
  62        if (input)
  63                return st & ALTERA_JTAG_RRDY ? 1 : 0;
  64        else
  65                return !(ALTERA_JTAG_WSPACE(st) == ALTERA_JTAG_WRITE_DEPTH);
  66}
  67
  68static int altera_jtaguart_getc(struct udevice *dev)
  69{
  70        struct altera_jtaguart_platdata *plat = dev->platdata;
  71        struct altera_jtaguart_regs *const regs = plat->regs;
  72        u32 val;
  73
  74        val = readl(&regs->data);
  75
  76        if (!(val & ALTERA_JTAG_RVALID))
  77                return -EAGAIN;
  78
  79        return val & 0xff;
  80}
  81
  82static int altera_jtaguart_probe(struct udevice *dev)
  83{
  84#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
  85        struct altera_jtaguart_platdata *plat = dev->platdata;
  86        struct altera_jtaguart_regs *const regs = plat->regs;
  87
  88        writel(ALTERA_JTAG_AC, &regs->control); /* clear AC flag */
  89#endif
  90        return 0;
  91}
  92
  93static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev)
  94{
  95        struct altera_jtaguart_platdata *plat = dev_get_platdata(dev);
  96
  97        plat->regs = map_physmem(devfdt_get_addr(dev),
  98                                 sizeof(struct altera_jtaguart_regs),
  99                                 MAP_NOCACHE);
 100
 101        return 0;
 102}
 103
 104static const struct dm_serial_ops altera_jtaguart_ops = {
 105        .putc = altera_jtaguart_putc,
 106        .pending = altera_jtaguart_pending,
 107        .getc = altera_jtaguart_getc,
 108        .setbrg = altera_jtaguart_setbrg,
 109};
 110
 111static const struct udevice_id altera_jtaguart_ids[] = {
 112        { .compatible = "altr,juart-1.0" },
 113        {}
 114};
 115
 116U_BOOT_DRIVER(altera_jtaguart) = {
 117        .name   = "altera_jtaguart",
 118        .id     = UCLASS_SERIAL,
 119        .of_match = altera_jtaguart_ids,
 120        .ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata,
 121        .platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata),
 122        .probe = altera_jtaguart_probe,
 123        .ops    = &altera_jtaguart_ops,
 124};
 125
 126#ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART
 127
 128#include <debug_uart.h>
 129
 130static inline void _debug_uart_init(void)
 131{
 132}
 133
 134static inline void _debug_uart_putc(int ch)
 135{
 136        struct altera_jtaguart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE;
 137
 138        while (1) {
 139                u32 st = readl(&regs->control);
 140
 141                if (ALTERA_JTAG_WSPACE(st))
 142                        break;
 143        }
 144
 145        writel(ch, &regs->data);
 146}
 147
 148DEBUG_UART_FUNCS
 149
 150#endif
 151