uboot/arch/mips/mach-au1x00/au1x00_serial.c
<<
>>
Prefs
   1/*
   2 * AU1X00 UART support
   3 *
   4 * Hardcoded to UART 0 for now
   5 * Speed and options also hardcoded to 115200 8N1
   6 *
   7 *  Copyright (c) 2003  Thomas.Lange@corelatus.se
   8 *
   9 * SPDX-License-Identifier:     GPL-2.0+
  10 */
  11
  12#include <config.h>
  13#include <common.h>
  14#include <mach/au1x00.h>
  15#include <serial.h>
  16#include <linux/compiler.h>
  17
  18/******************************************************************************
  19*
  20* serial_init - initialize a channel
  21*
  22* This routine initializes the number of data bits, parity
  23* and set the selected baud rate. Interrupts are disabled.
  24* Set the modem control signals if the option is selected.
  25*
  26* RETURNS: N/A
  27*/
  28
  29static int au1x00_serial_init(void)
  30{
  31        volatile u32 *uart_fifoctl = (volatile u32*)(UART0_ADDR+UART_FCR);
  32        volatile u32 *uart_enable = (volatile u32*)(UART0_ADDR+UART_ENABLE);
  33
  34        /* Enable clocks first */
  35        *uart_enable = UART_EN_CE;
  36
  37        /* Then release reset */
  38        /* Must release reset before setting other regs */
  39        *uart_enable = UART_EN_CE|UART_EN_E;
  40
  41        /* Activate fifos, reset tx and rx */
  42        /* Set tx trigger level to 12 */
  43        *uart_fifoctl = UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|
  44                UART_FCR_CLEAR_XMIT|UART_FCR_T_TRIGGER_12;
  45
  46        serial_setbrg();
  47
  48        return 0;
  49}
  50
  51
  52static void au1x00_serial_setbrg(void)
  53{
  54        volatile u32 *uart_clk = (volatile u32*)(UART0_ADDR+UART_CLK);
  55        volatile u32 *uart_lcr = (volatile u32*)(UART0_ADDR+UART_LCR);
  56        volatile u32 *sys_powerctrl = (u32 *)SYS_POWERCTRL;
  57        int sd;
  58        int divisorx2;
  59
  60        /* sd is system clock divisor                   */
  61        /* see section 10.4.5 in au1550 datasheet       */
  62        sd = (*sys_powerctrl & 0x03) + 2;
  63
  64        /* calulate 2x baudrate and round */
  65        divisorx2 = ((CONFIG_SYS_MIPS_TIMER_FREQ/(sd * 16 * CONFIG_BAUDRATE)));
  66
  67        if (divisorx2 & 0x01)
  68                divisorx2 = divisorx2 + 1;
  69
  70        *uart_clk = divisorx2 / 2;
  71
  72        /* Set parity, stop bits and word length to 8N1 */
  73        *uart_lcr = UART_LCR_WLEN8;
  74}
  75
  76static void au1x00_serial_putc(const char c)
  77{
  78        volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR);
  79        volatile u32 *uart_tx = (volatile u32*)(UART0_ADDR+UART_TX);
  80
  81        if (c == '\n')
  82                au1x00_serial_putc('\r');
  83
  84        /* Wait for fifo to shift out some bytes */
  85        while((*uart_lsr&UART_LSR_THRE)==0);
  86
  87        *uart_tx = (u32)c;
  88}
  89
  90static int au1x00_serial_getc(void)
  91{
  92        volatile u32 *uart_rx = (volatile u32*)(UART0_ADDR+UART_RX);
  93        char c;
  94
  95        while (!serial_tstc());
  96
  97        c = (*uart_rx&0xFF);
  98        return c;
  99}
 100
 101static int au1x00_serial_tstc(void)
 102{
 103        volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR);
 104
 105        if(*uart_lsr&UART_LSR_DR){
 106                /* Data in rfifo */
 107                return(1);
 108        }
 109        return 0;
 110}
 111
 112static struct serial_device au1x00_serial_drv = {
 113        .name   = "au1x00_serial",
 114        .start  = au1x00_serial_init,
 115        .stop   = NULL,
 116        .setbrg = au1x00_serial_setbrg,
 117        .putc   = au1x00_serial_putc,
 118        .puts   = default_serial_puts,
 119        .getc   = au1x00_serial_getc,
 120        .tstc   = au1x00_serial_tstc,
 121};
 122
 123void au1x00_serial_initialize(void)
 124{
 125        serial_register(&au1x00_serial_drv);
 126}
 127
 128__weak struct serial_device *default_serial_console(void)
 129{
 130        return &au1x00_serial_drv;
 131}
 132