uboot/drivers/serial/s3c4510b_uart.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004   Cucy Systems (http://www.cucy.com)
   3 * Curt Brune <curt@cucy.com>
   4 *
   5 * (C) Copyright 2004
   6 * DAVE Srl
   7 * http://www.dave-tech.it
   8 * http://www.wawnet.biz
   9 * mailto:info@wawnet.biz
  10 *
  11 * (C) Copyright 2002-2004
  12 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
  13 *
  14 * (C) Copyright 2002
  15 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  16 * Marius Groeger <mgroeger@sysgo.de>
  17 *
  18 * (C) Copyright 2002
  19 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  20 * Alex Zuepke <azu@sysgo.de>
  21 *
  22 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
  23 *
  24 * This program is free software; you can redistribute it and/or modify
  25 * it under the terms of the GNU General Public License as published by
  26 * the Free Software Foundation; either version 2 of the License, or
  27 * (at your option) any later version.
  28 *
  29 * This program is distributed in the hope that it will be useful,
  30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  32 * GNU General Public License for more details.
  33 *
  34 * You should have received a copy of the GNU General Public License
  35 * along with this program; if not, write to the Free Software
  36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  37 *
  38 * MODULE:        $Id:$
  39 * Description:   UART/Serial interface for Samsung S3C4510B SoC
  40 * Runtime Env:   ARM7TDMI
  41 * Change History:
  42 *     03-02-04    Create (Curt Brune) curt@cucy.com
  43 *
  44 */
  45
  46#include <common.h>
  47
  48#include <asm/hardware.h>
  49#include "s3c4510b_uart.h"
  50
  51DECLARE_GLOBAL_DATA_PTR;
  52
  53static UART    *uart;
  54
  55/* flush serial input queue. returns 0 on success or negative error
  56 * number otherwise
  57 */
  58static int serial_flush_input(void)
  59{
  60        volatile u32 tmp;
  61
  62        /* keep on reading as long as the receiver is not empty */
  63        while( uart->m_stat.bf.rxReady) {
  64                tmp = uart->m_rx;
  65        }
  66
  67        return 0;
  68}
  69
  70
  71/* flush output queue. returns 0 on success or negative error number
  72 * otherwise
  73 */
  74static int serial_flush_output(void)
  75{
  76        /* wait until the transmitter is no longer busy */
  77        while( !uart->m_stat.bf.txBufEmpty);
  78
  79        return 0;
  80}
  81
  82
  83void serial_setbrg (void)
  84{
  85        UART_LINE_CTRL ulctrl;
  86        UART_CTRL      uctrl;
  87        UART_BAUD_DIV  ubd;
  88
  89        serial_flush_output();
  90        serial_flush_input();
  91
  92        /* control register */
  93        uctrl.ui = 0x0;
  94        uctrl.bf.rxMode = 0x1;
  95        uctrl.bf.rxIrq = 0x0;
  96        uctrl.bf.txMode = 0x1;
  97        uctrl.bf.DSR = 0x0;
  98        uctrl.bf.sendBreak = 0x0;
  99        uctrl.bf.loopBack = 0x0;
 100        uart->m_ctrl.ui = uctrl.ui;
 101
 102        /* line control register */
 103        ulctrl.ui  = 0x0;
 104        ulctrl.bf.wordLen   = 0x3; /* 8 bit data */
 105        ulctrl.bf.nStop     = 0x0; /* 1 stop bit */
 106        ulctrl.bf.parity    = 0x0; /* no parity */
 107        ulctrl.bf.clk       = 0x0; /* internal clock */
 108        ulctrl.bf.infra_red = 0x0; /* no infra_red */
 109        uart->m_lineCtrl.ui = ulctrl.ui;
 110
 111        ubd.ui = 0x0;
 112
 113        /* see table on page 10-15 in SAMSUNG S3C4510B manual */
 114        /* get correct divisor */
 115        switch(gd->baudrate) {
 116        case   1200:    ubd.bf.cnt0 = 1301;     break;
 117        case   2400:    ubd.bf.cnt0 =  650;     break;
 118        case   4800:    ubd.bf.cnt0 =  324;     break;
 119        case   9600:    ubd.bf.cnt0 =  162;     break;
 120        case  19200:    ubd.bf.cnt0 =   80;     break;
 121        case  38400:    ubd.bf.cnt0 =   40;     break;
 122        case  57600:    ubd.bf.cnt0 =   26;     break;
 123        case 115200:    ubd.bf.cnt0 =   13;     break;
 124        }
 125
 126        uart->m_baudDiv.ui = ubd.ui;
 127        uart->m_baudCnt = 0x0;
 128        uart->m_baudClk = 0x0;
 129
 130}
 131
 132
 133/*
 134 * Initialise the serial port with the given baudrate. The settings
 135 * are always 8 data bits, no parity, 1 stop bit, no start bits.
 136 *
 137 */
 138int serial_init (void)
 139{
 140
 141#if   CONFIG_SERIAL1 == 1
 142        uart = (UART *)UART0_BASE;
 143#elif CONFIG_SERIAL1 == 2
 144        uart = (UART *)UART1_BASE;
 145#else
 146#error CONFIG_SERIAL1 not equal to 1 or 2
 147#endif
 148
 149        serial_setbrg ();
 150
 151        return (0);
 152}
 153
 154
 155/*
 156 * Output a single byte to the serial port.
 157 */
 158void serial_putc (const char c)
 159{
 160        /* wait for room in the transmit FIFO */
 161        while( !uart->m_stat.bf.txBufEmpty);
 162
 163        uart->m_tx = c;
 164
 165        /*
 166                to be polite with serial console add a line feed
 167                to the carriage return character
 168        */
 169        if (c=='\n')
 170                serial_putc('\r');
 171}
 172
 173/*
 174 * Test if an input byte is ready from the serial port. Returns non-zero on
 175 * success, 0 otherwise.
 176 */
 177int serial_tstc (void)
 178{
 179        return uart->m_stat.bf.rxReady;
 180}
 181
 182/*
 183 * Read a single byte from the serial port. Returns 1 on success, 0
 184 * otherwise. When the function is succesfull, the character read is
 185 * written into its argument c.
 186 */
 187int serial_getc (void)
 188{
 189        int rv;
 190
 191        for(;;) {
 192                rv = serial_tstc();
 193
 194                if (rv) {
 195                        return uart->m_rx & 0xFF;
 196                }
 197        }
 198}
 199
 200void serial_puts (const char *s)
 201{
 202        while (*s) {
 203                serial_putc (*s++);
 204        }
 205
 206        /* busy wait for tx complete */
 207        while ( !uart->m_stat.bf.txComplete);
 208
 209        /* clear break */
 210        uart->m_ctrl.bf.sendBreak = 0;
 211
 212}
 213