uboot/drivers/serial/ns9750_serial.c
<<
>>
Prefs
   1/***********************************************************************
   2 *
   3 * Copyright (C) 2004 by FS Forth-Systeme GmbH.
   4 * All rights reserved.
   5 *
   6 * $Id: ns9750_serial.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $
   7 * @Author: Markus Pietrek
   8 * @Descr: Serial driver for the NS9750. Only one UART is supported yet.
   9 * @References: [1] NS9750 Hardware Reference/December 2003
  10 * @TODO: Implement Character GAP Timer when chip is fixed for PLL bypass
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License as
  14 * published by the Free Software Foundation; either version 2 of
  15 * the License, or (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25 * MA 02111-1307 USA
  26 *
  27 ***********************************************************************/
  28
  29#include <common.h>
  30
  31#include "ns9750_bbus.h"        /* for GPIOs */
  32#include "ns9750_ser.h"         /* for serial configuration */
  33
  34DECLARE_GLOBAL_DATA_PTR;
  35
  36#if !defined(CONFIG_CONS_INDEX)
  37#error "No console index specified."
  38#endif
  39
  40#define CONSOLE CONFIG_CONS_INDEX
  41
  42static unsigned int calcBitrateRegister( void );
  43static unsigned int calcRxCharGapRegister( void );
  44
  45static char cCharsAvailable; /* Numbers of chars in unCharCache */
  46static unsigned int unCharCache; /* unCharCache is only valid if
  47                                  * cCharsAvailable > 0 */
  48
  49/***********************************************************************
  50 * @Function: serial_init
  51 * @Return: 0
  52 * @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off
  53 ***********************************************************************/
  54
  55int serial_init( void )
  56{
  57        unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 };
  58        unsigned int aunGPIORxD[] = { 1, 9, 41, 45 };
  59
  60        cCharsAvailable = 0;
  61
  62        /* configure TxD and RxD pins for their special function */
  63        set_gpio_cfg_reg_val( aunGPIOTxD[ CONSOLE ],
  64                              NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_OUTPUT );
  65        set_gpio_cfg_reg_val( aunGPIORxD[ CONSOLE ],
  66                              NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_INPUT );
  67
  68        /* configure serial engine */
  69        *get_ser_reg_addr_channel( NS9750_SER_CTRL_A, CONSOLE ) =
  70                NS9750_SER_CTRL_A_CE |
  71                NS9750_SER_CTRL_A_STOP |
  72                NS9750_SER_CTRL_A_WLS_8;
  73
  74        serial_setbrg();
  75
  76        *get_ser_reg_addr_channel( NS9750_SER_CTRL_B, CONSOLE ) =
  77                NS9750_SER_CTRL_B_RCGT;
  78
  79        return 0;
  80}
  81
  82/***********************************************************************
  83 * @Function: serial_putc
  84 * @Return: n/a
  85 * @Descr: writes one character to the FIFO. Blocks until FIFO is not full
  86 ***********************************************************************/
  87
  88void serial_putc( const char c )
  89{
  90        if (c == '\n')
  91                serial_putc( '\r' );
  92
  93        while (!(*get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE) &
  94                 NS9750_SER_STAT_A_TRDY ) ) {
  95                /* do nothing, wait for characters in FIFO sent */
  96        }
  97
  98        *(volatile char*) get_ser_reg_addr_channel( NS9750_SER_FIFO,
  99                                                    CONSOLE) = c;
 100}
 101
 102/***********************************************************************
 103 * @Function: serial_puts
 104 * @Return: n/a
 105 * @Descr: writes non-zero string to the FIFO.
 106 ***********************************************************************/
 107
 108void serial_puts( const char *s )
 109{
 110        while (*s) {
 111                serial_putc( *s++ );
 112        }
 113}
 114
 115/***********************************************************************
 116 * @Function: serial_getc
 117 * @Return: the character read
 118 * @Descr: performs only 8bit accesses to the FIFO. No error handling
 119 ***********************************************************************/
 120
 121int serial_getc( void )
 122{
 123        int i;
 124
 125        while (!serial_tstc() ) {
 126                /* do nothing, wait for incoming characters */
 127        }
 128
 129        /*  at least one character in unCharCache */
 130        i = (int) (unCharCache & 0xff);
 131
 132        unCharCache >>= 8;
 133        cCharsAvailable--;
 134
 135        return i;
 136}
 137
 138/***********************************************************************
 139 * @Function: serial_tstc
 140 * @Return: 0 if no input available, otherwise != 0
 141 * @Descr: checks for incoming FIFO not empty. Stores the incoming chars in
 142 *         unCharCache and the numbers of characters in cCharsAvailable
 143 ***********************************************************************/
 144
 145int serial_tstc( void )
 146{
 147        unsigned int unRegCache;
 148
 149        if ( cCharsAvailable )
 150                return 1;
 151
 152        unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,CONSOLE );
 153        if( unRegCache & NS9750_SER_STAT_A_RBC ) {
 154                *get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE ) =
 155                        NS9750_SER_STAT_A_RBC;
 156                unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,
 157                                                        CONSOLE );
 158        }
 159
 160        if ( unRegCache & NS9750_SER_STAT_A_RRDY ) {
 161                cCharsAvailable = (unRegCache & NS9750_SER_STAT_A_RXFDB_MA)>>20;
 162                if ( !cCharsAvailable )
 163                        cCharsAvailable = 4;
 164
 165                unCharCache = *get_ser_reg_addr_channel( NS9750_SER_FIFO,
 166                                                         CONSOLE );
 167                return 1;
 168        }
 169
 170        /* no chars available */
 171        return 0;
 172}
 173
 174void serial_setbrg( void )
 175{
 176        *get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) =
 177                calcBitrateRegister();
 178        *get_ser_reg_addr_channel( NS9750_SER_RX_CHAR_TIMER, CONSOLE ) =
 179                calcRxCharGapRegister();
 180}
 181
 182/***********************************************************************
 183 * @Function: calcBitrateRegister
 184 * @Return: value for the serial bitrate register
 185 * @Descr: register value depends on clock frequency and baudrate
 186 ***********************************************************************/
 187
 188static unsigned int calcBitrateRegister( void )
 189{
 190        return ( NS9750_SER_BITRATE_EBIT |
 191                 NS9750_SER_BITRATE_CLKMUX_BCLK |
 192                 NS9750_SER_BITRATE_TMODE |
 193                 NS9750_SER_BITRATE_TCDR_16 |
 194                 NS9750_SER_BITRATE_RCDR_16 |
 195                 ( ( ( ( CONFIG_SYS_CLK_FREQ / 8 ) / /* BBUS clock,[1] Fig. 38 */
 196                       ( gd->baudrate * 16 ) ) - 1 ) &
 197                   NS9750_SER_BITRATE_N_MA ) );
 198}
 199
 200/***********************************************************************
 201 * @Function: calcRxCharGapRegister
 202 * @Return: value for the character gap timer register
 203 * @Descr: register value depends on clock frequency and baudrate. Currently 0
 204 *         is used as there is a bug with the gap timer in PLL bypass mode.
 205 ***********************************************************************/
 206
 207static unsigned int calcRxCharGapRegister( void )
 208{
 209        return NS9750_SER_RX_CHAR_TIMER_TRUN;
 210}
 211