uboot/arch/sparc/cpu/leon3/serial.c
<<
>>
Prefs
   1/* GRLIB APBUART Serial controller driver
   2 *
   3 * (C) Copyright 2007, 2015
   4 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <asm/io.h>
  11#include <ambapp.h>
  12#include <grlib/apbuart.h>
  13#include <serial.h>
  14#include <watchdog.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18/* Select which UART that will become u-boot console */
  19#ifndef CONFIG_SYS_GRLIB_APBUART_INDEX
  20/* Try to use CONFIG_CONS_INDEX, if available, it is numbered from 1 */
  21#ifdef CONFIG_CONS_INDEX
  22#define CONFIG_SYS_GRLIB_APBUART_INDEX (CONFIG_CONS_INDEX - 1)
  23#else
  24#define CONFIG_SYS_GRLIB_APBUART_INDEX 0
  25#endif
  26#endif
  27
  28static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
  29{
  30        return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
  31}
  32
  33static int leon3_serial_init(void)
  34{
  35        ambapp_dev_apbuart *uart;
  36        ambapp_apbdev apbdev;
  37        unsigned int tmp;
  38
  39        /* find UART */
  40        if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
  41                CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1) {
  42                gd->flags &= ~GD_FLG_SERIAL_READY;
  43                panic("%s: apbuart not found!\n", __func__);
  44                return -1; /* didn't find hardware */
  45        }
  46
  47        /* found apbuart, let's init .. */
  48        uart = (ambapp_dev_apbuart *) apbdev.address;
  49
  50        /* APBUART Frequency is equal to bus frequency */
  51        gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
  52
  53        /* Set scaler / baud rate */
  54        tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
  55        writel(tmp, &uart->scaler);
  56
  57        /* Let bit 11 be unchanged (debug bit for GRMON) */
  58        tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
  59        /* Receiver & transmitter enable */
  60        tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
  61        writel(tmp, &uart->ctrl);
  62
  63        gd->arch.uart = uart;
  64        return 0;
  65}
  66
  67static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
  68{
  69        ambapp_dev_apbuart *uart = gd->arch.uart;
  70        return uart;
  71}
  72
  73static void leon3_serial_putc_raw(const char c)
  74{
  75        ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
  76
  77        if (!uart)
  78                return;
  79
  80        /* Wait for last character to go. */
  81        while (!(readl(&uart->status) & APBUART_STATUS_THE))
  82                WATCHDOG_RESET();
  83
  84        /* Send data */
  85        writel(c, &uart->data);
  86
  87#ifdef LEON_DEBUG
  88        /* Wait for data to be sent */
  89        while (!(readl(&uart->status) & APBUART_STATUS_TSE))
  90                WATCHDOG_RESET();
  91#endif
  92}
  93
  94static void leon3_serial_putc(const char c)
  95{
  96        if (c == '\n')
  97                leon3_serial_putc_raw('\r');
  98
  99        leon3_serial_putc_raw(c);
 100}
 101
 102static int leon3_serial_getc(void)
 103{
 104        ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
 105
 106        if (!uart)
 107                return 0;
 108
 109        /* Wait for a character to arrive. */
 110        while (!(readl(&uart->status) & APBUART_STATUS_DR))
 111                WATCHDOG_RESET();
 112
 113        /* Read character data */
 114        return readl(&uart->data);
 115}
 116
 117static int leon3_serial_tstc(void)
 118{
 119        ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
 120
 121        if (!uart)
 122                return 0;
 123
 124        return readl(&uart->status) & APBUART_STATUS_DR;
 125}
 126
 127/* set baud rate for uart */
 128static void leon3_serial_setbrg(void)
 129{
 130        ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
 131        unsigned int scaler;
 132
 133        if (!uart)
 134                return;
 135
 136        if (!gd->baudrate)
 137                gd->baudrate = CONFIG_BAUDRATE;
 138
 139        if (!gd->arch.uart_freq)
 140                gd->arch.uart_freq = CONFIG_SYS_CLK_FREQ;
 141
 142        scaler = apbuart_calc_scaler(gd->arch.uart_freq, gd->baudrate);
 143
 144        writel(scaler, &uart->scaler);
 145}
 146
 147static struct serial_device leon3_serial_drv = {
 148        .name   = "leon3_serial",
 149        .start  = leon3_serial_init,
 150        .stop   = NULL,
 151        .setbrg = leon3_serial_setbrg,
 152        .putc   = leon3_serial_putc,
 153        .puts   = default_serial_puts,
 154        .getc   = leon3_serial_getc,
 155        .tstc   = leon3_serial_tstc,
 156};
 157
 158void leon3_serial_initialize(void)
 159{
 160        serial_register(&leon3_serial_drv);
 161}
 162
 163__weak struct serial_device *default_serial_console(void)
 164{
 165        return &leon3_serial_drv;
 166}
 167
 168#ifdef CONFIG_DEBUG_UART_APBUART
 169
 170#include <debug_uart.h>
 171
 172static inline void _debug_uart_init(void)
 173{
 174        ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
 175        uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
 176        uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
 177}
 178
 179static inline void _debug_uart_putc(int ch)
 180{
 181        ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
 182        while (!(readl(&uart->status) & APBUART_STATUS_THE))
 183                WATCHDOG_RESET();
 184        writel(ch, &uart->data);
 185}
 186
 187DEBUG_UART_FUNCS
 188
 189#endif
 190