uboot/drivers/serial/serial_xuartlite.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2008 - 2015 Michal Simek <monstr@monstr.eu>
   4 * Clean driver and add xilinx constant from header file
   5 *
   6 * (C) Copyright 2004 Atmark Techno, Inc.
   7 * Yasushi SHOJI <yashi@atmark-techno.com>
   8 */
   9
  10#include <config.h>
  11#include <common.h>
  12#include <dm.h>
  13#include <asm/io.h>
  14#include <linux/compiler.h>
  15#include <serial.h>
  16
  17#define SR_TX_FIFO_FULL         BIT(3) /* transmit FIFO full */
  18#define SR_TX_FIFO_EMPTY        BIT(2) /* transmit FIFO empty */
  19#define SR_RX_FIFO_VALID_DATA   BIT(0) /* data in receive FIFO */
  20#define SR_RX_FIFO_FULL         BIT(1) /* receive FIFO full */
  21
  22#define ULITE_CONTROL_RST_TX    0x01
  23#define ULITE_CONTROL_RST_RX    0x02
  24
  25struct uartlite {
  26        unsigned int rx_fifo;
  27        unsigned int tx_fifo;
  28        unsigned int status;
  29        unsigned int control;
  30};
  31
  32struct uartlite_platdata {
  33        struct uartlite *regs;
  34};
  35
  36static int uartlite_serial_putc(struct udevice *dev, const char ch)
  37{
  38        struct uartlite_platdata *plat = dev_get_platdata(dev);
  39        struct uartlite *regs = plat->regs;
  40
  41        if (in_be32(&regs->status) & SR_TX_FIFO_FULL)
  42                return -EAGAIN;
  43
  44        out_be32(&regs->tx_fifo, ch & 0xff);
  45
  46        return 0;
  47}
  48
  49static int uartlite_serial_getc(struct udevice *dev)
  50{
  51        struct uartlite_platdata *plat = dev_get_platdata(dev);
  52        struct uartlite *regs = plat->regs;
  53
  54        if (!(in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA))
  55                return -EAGAIN;
  56
  57        return in_be32(&regs->rx_fifo) & 0xff;
  58}
  59
  60static int uartlite_serial_pending(struct udevice *dev, bool input)
  61{
  62        struct uartlite_platdata *plat = dev_get_platdata(dev);
  63        struct uartlite *regs = plat->regs;
  64
  65        if (input)
  66                return in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA;
  67
  68        return !(in_be32(&regs->status) & SR_TX_FIFO_EMPTY);
  69}
  70
  71static int uartlite_serial_probe(struct udevice *dev)
  72{
  73        struct uartlite_platdata *plat = dev_get_platdata(dev);
  74        struct uartlite *regs = plat->regs;
  75
  76        out_be32(&regs->control, 0);
  77        out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
  78        in_be32(&regs->control);
  79
  80        return 0;
  81}
  82
  83static int uartlite_serial_ofdata_to_platdata(struct udevice *dev)
  84{
  85        struct uartlite_platdata *plat = dev_get_platdata(dev);
  86
  87        plat->regs = (struct uartlite *)devfdt_get_addr(dev);
  88
  89        return 0;
  90}
  91
  92static const struct dm_serial_ops uartlite_serial_ops = {
  93        .putc = uartlite_serial_putc,
  94        .pending = uartlite_serial_pending,
  95        .getc = uartlite_serial_getc,
  96};
  97
  98static const struct udevice_id uartlite_serial_ids[] = {
  99        { .compatible = "xlnx,opb-uartlite-1.00.b", },
 100        { .compatible = "xlnx,xps-uartlite-1.00.a" },
 101        { }
 102};
 103
 104U_BOOT_DRIVER(serial_uartlite) = {
 105        .name   = "serial_uartlite",
 106        .id     = UCLASS_SERIAL,
 107        .of_match = uartlite_serial_ids,
 108        .ofdata_to_platdata = uartlite_serial_ofdata_to_platdata,
 109        .platdata_auto_alloc_size = sizeof(struct uartlite_platdata),
 110        .probe = uartlite_serial_probe,
 111        .ops    = &uartlite_serial_ops,
 112};
 113
 114#ifdef CONFIG_DEBUG_UART_UARTLITE
 115
 116#include <debug_uart.h>
 117
 118static inline void _debug_uart_init(void)
 119{
 120        struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
 121
 122        out_be32(&regs->control, 0);
 123        out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
 124        in_be32(&regs->control);
 125}
 126
 127static inline void _debug_uart_putc(int ch)
 128{
 129        struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
 130
 131        while (in_be32(&regs->status) & SR_TX_FIFO_FULL)
 132                ;
 133
 134        out_be32(&regs->tx_fifo, ch & 0xff);
 135}
 136
 137DEBUG_UART_FUNCS
 138#endif
 139