uboot/drivers/serial/serial_arc.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <serial.h>
  13
  14DECLARE_GLOBAL_DATA_PTR;
  15
  16struct arc_serial_regs {
  17        unsigned int id0;
  18        unsigned int id1;
  19        unsigned int id2;
  20        unsigned int id3;
  21        unsigned int data;
  22        unsigned int status;
  23        unsigned int baudl;
  24        unsigned int baudh;
  25};
  26
  27
  28struct arc_serial_platdata {
  29        struct arc_serial_regs *reg;
  30        unsigned int uartclk;
  31};
  32
  33/* Bit definitions of STATUS register */
  34#define UART_RXEMPTY            (1 << 5)
  35#define UART_OVERFLOW_ERR       (1 << 1)
  36#define UART_TXEMPTY            (1 << 7)
  37
  38static int arc_serial_setbrg(struct udevice *dev, int baudrate)
  39{
  40        struct arc_serial_platdata *plat = dev->platdata;
  41        struct arc_serial_regs *const regs = plat->reg;
  42        int arc_console_baud = gd->cpu_clk / (baudrate * 4) - 1;
  43
  44        writeb(arc_console_baud & 0xff, &regs->baudl);
  45        writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
  46
  47        return 0;
  48}
  49
  50static int arc_serial_putc(struct udevice *dev, const char c)
  51{
  52        struct arc_serial_platdata *plat = dev->platdata;
  53        struct arc_serial_regs *const regs = plat->reg;
  54
  55        while (!(readb(&regs->status) & UART_TXEMPTY))
  56                ;
  57
  58        writeb(c, &regs->data);
  59
  60        return 0;
  61}
  62
  63static int arc_serial_tstc(struct arc_serial_regs *const regs)
  64{
  65        return !(readb(&regs->status) & UART_RXEMPTY);
  66}
  67
  68static int arc_serial_pending(struct udevice *dev, bool input)
  69{
  70        struct arc_serial_platdata *plat = dev->platdata;
  71        struct arc_serial_regs *const regs = plat->reg;
  72        uint32_t status = readb(&regs->status);
  73
  74        if (input)
  75                return status & UART_RXEMPTY ? 0 : 1;
  76        else
  77                return status & UART_TXEMPTY ? 0 : 1;
  78}
  79
  80static int arc_serial_getc(struct udevice *dev)
  81{
  82        struct arc_serial_platdata *plat = dev->platdata;
  83        struct arc_serial_regs *const regs = plat->reg;
  84
  85        while (!arc_serial_tstc(regs))
  86                ;
  87
  88        /* Check for overflow errors */
  89        if (readb(&regs->status) & UART_OVERFLOW_ERR)
  90                return 0;
  91
  92        return readb(&regs->data) & 0xFF;
  93}
  94
  95static int arc_serial_probe(struct udevice *dev)
  96{
  97        return 0;
  98}
  99
 100static const struct dm_serial_ops arc_serial_ops = {
 101        .putc = arc_serial_putc,
 102        .pending = arc_serial_pending,
 103        .getc = arc_serial_getc,
 104        .setbrg = arc_serial_setbrg,
 105};
 106
 107static const struct udevice_id arc_serial_ids[] = {
 108        { .compatible = "snps,arc-uart" },
 109        { }
 110};
 111
 112static int arc_serial_ofdata_to_platdata(struct udevice *dev)
 113{
 114        struct arc_serial_platdata *plat = dev_get_platdata(dev);
 115        DECLARE_GLOBAL_DATA_PTR;
 116
 117        plat->reg = dev_read_addr_ptr(dev);
 118        plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 119                                       "clock-frequency", 0);
 120
 121        return 0;
 122}
 123
 124U_BOOT_DRIVER(serial_arc) = {
 125        .name   = "serial_arc",
 126        .id     = UCLASS_SERIAL,
 127        .of_match = arc_serial_ids,
 128        .ofdata_to_platdata = arc_serial_ofdata_to_platdata,
 129        .platdata_auto_alloc_size = sizeof(struct arc_serial_platdata),
 130        .probe = arc_serial_probe,
 131        .ops    = &arc_serial_ops,
 132};
 133
 134#ifdef CONFIG_DEBUG_ARC_SERIAL
 135#include <debug_uart.h>
 136
 137static inline void _debug_uart_init(void)
 138{
 139        struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_DEBUG_UART_BASE;
 140        int arc_console_baud = CONFIG_DEBUG_UART_CLOCK / (CONFIG_BAUDRATE * 4) - 1;
 141
 142        writeb(arc_console_baud & 0xff, &regs->baudl);
 143        writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
 144}
 145
 146static inline void _debug_uart_putc(int c)
 147{
 148        struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_DEBUG_UART_BASE;
 149
 150        while (!(readb(&regs->status) & UART_TXEMPTY))
 151                ;
 152
 153        writeb(c, &regs->data);
 154}
 155
 156DEBUG_UART_FUNCS
 157
 158#endif
 159