uboot/arch/sparc/cpu/leon2/serial.c
<<
>>
Prefs
   1/* GRLIB APBUART Serial controller driver
   2 *
   3 * (C) Copyright 2008
   4 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 *
  24 */
  25
  26#include <common.h>
  27#include <asm/processor.h>
  28#include <asm/leon.h>
  29#include <serial.h>
  30#include <linux/compiler.h>
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34static int leon2_serial_init(void)
  35{
  36        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
  37        LEON2_Uart_regs *regs;
  38        unsigned int tmp;
  39
  40        /* Init LEON2 UART
  41         *
  42         * Set scaler / baud rate
  43         *
  44         * Receiver & transmitter enable
  45         */
  46#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
  47        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
  48#else
  49        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
  50#endif
  51
  52        regs->UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER;
  53
  54        /* Let bit 11 be unchanged (debug bit for GRMON) */
  55        tmp = READ_WORD(regs->UART_Control);
  56
  57        regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) |
  58                              (LEON2_UART1_LOOPBACK_ENABLE << 7) |
  59                              (LEON2_UART1_FLOWCTRL_ENABLE << 6) |
  60                              (LEON2_UART1_PARITY_ENABLE << 5) |
  61                              (LEON2_UART1_ODDPAR_ENABLE << 4) |
  62                              LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE);
  63
  64        return 0;
  65}
  66
  67static void leon2_serial_putc_raw(const char c)
  68{
  69        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
  70        LEON2_Uart_regs *regs;
  71
  72#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
  73        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
  74#else
  75        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
  76#endif
  77
  78        /* Wait for last character to go. */
  79        while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ;
  80
  81        /* Send data */
  82        regs->UART_Channel = c;
  83
  84#ifdef LEON_DEBUG
  85        /* Wait for data to be sent */
  86        while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ;
  87#endif
  88}
  89
  90static void leon2_serial_putc(const char c)
  91{
  92        if (c == '\n')
  93                leon2_serial_putc_raw('\r');
  94
  95        leon2_serial_putc_raw(c);
  96}
  97
  98static int leon2_serial_getc(void)
  99{
 100        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
 101        LEON2_Uart_regs *regs;
 102
 103#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
 104        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
 105#else
 106        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
 107#endif
 108
 109        /* Wait for a character to arrive. */
 110        while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ;
 111
 112        /* read data */
 113        return READ_WORD(regs->UART_Channel);
 114}
 115
 116static int leon2_serial_tstc(void)
 117{
 118        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
 119        LEON2_Uart_regs *regs;
 120
 121#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
 122        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
 123#else
 124        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
 125#endif
 126
 127        return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR);
 128}
 129
 130/* set baud rate for uart */
 131static void leon2_serial_setbrg(void)
 132{
 133        /* update baud rate settings, read it from gd->baudrate */
 134        unsigned int scaler;
 135        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
 136        LEON2_Uart_regs *regs;
 137
 138#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
 139        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
 140#else
 141        regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
 142#endif
 143
 144        if (gd->baudrate > 0) {
 145                scaler =
 146                    (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) -
 147                     5) / 10;
 148                regs->UART_Scaler = scaler;
 149        }
 150}
 151
 152static struct serial_device leon2_serial_drv = {
 153        .name   = "leon2_serial",
 154        .start  = leon2_serial_init,
 155        .stop   = NULL,
 156        .setbrg = leon2_serial_setbrg,
 157        .putc   = leon2_serial_putc,
 158        .puts   = default_serial_puts,
 159        .getc   = leon2_serial_getc,
 160        .tstc   = leon2_serial_tstc,
 161};
 162
 163void leon2_serial_initialize(void)
 164{
 165        serial_register(&leon2_serial_drv);
 166}
 167
 168__weak struct serial_device *default_serial_console(void)
 169{
 170        return &leon2_serial_drv;
 171}
 172