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