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