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