/************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the * file LICENSE at the top level of this repository. * You may also obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ************************************************************************** * * FILENAME_HERE * * Generic (hopefully) 16550 uart code for use as a MicroMonitor * console serial port driver. * * The baud-rate divisor can be derived in one of two ways: * If BRD_115200 is defined, then this code assumes that the full * set of BRD_XXX definitions are defined (in config.h) and they * are used. If BRD_115200 is not defined, then this driver assumes * the getUartDivisor() function is externally provided by the * port-specific code. * * The base address of the UART used as the console port must be * defined as CONSOLE_UART_BASE (also in config.h). * * Also, if the uart is configured in the memory map such that the * gap between registers is not 1, then set SIO_STEP (see uart16550.h) * to 2 or 4 appropriately. * * Original author: Ed Sutter (ed.sutter@alcatel-lucent.com) * */ #include "config.h" #include "uart16550.h" #define CONSOLE(offset) *(volatile unsigned char *)(CONSOLE_UART_BASE+offset) #ifdef MORE_GOTACHAR extern void MORE_GOTACHAR(); #endif #ifdef MORE_GETCHAR extern void MORE_GETCHAR(); #endif #ifdef MORE_PUTCHAR extern void MORE_PUTCHAR(); #endif /* Establish default initialization values that can be overridden * in config.h: */ #ifndef MCTL_DEFAULT #define MCTL_DEFAULT (SIO_MCTL_DTR | SIO_MCTL_RTS) #endif #ifndef FCTL_DEFAULT #define FCTL_DEFAULT (SIO_FCTL_FEN | SIO_FCTL_RXDC | SIO_FCTL_TXDC) #endif #ifndef SPR_DEFAULT #define SPR_DEFAULT 0x00 // Clear scratchpad #endif #ifndef IEN_DEFAULT #define IEN_DEFAULT 0x00 // Ints used #endif #ifndef LCTL_DEFAULT #define LCTL_DEFAULT SIO_LCTL_W8 #endif /* getDlLsb(): * Populate hi & lo, default to 9600... */ #ifdef BRD_115200 int getUartDivisor(int baud, unsigned char *hi, unsigned char *lo) { switch(baud) { case 115200: *lo = BRD_115200; break; case 57600: *lo = BRD_57600; break; case 38400: *lo = BRD_38400; break; case 19200: *lo = BRD_19200; break; case 9600: *lo = BRD_9600; break; default: return(-1); } *hi = 0; return(0); } #endif int ConsoleBaudSet(int baud) { unsigned char tmp, hi, lo; /* If either getDivisor returns -1 or both hi & lo are zero we * return failure to indicate that the requested baud rate could * not be established. */ if(getUartDivisor(baud,&hi,&lo) == -1) { return(-1); } if((hi == 0) && (lo == 0)) { return(-1); } tmp = CONSOLE(SIO_LCTL); /* Save linectl reg */ CONSOLE(SIO_LCTL) = SIO_LCTL_DLAB; CONSOLE(SIO_BAUDLO) = lo; /* Set baud */ CONSOLE(SIO_BAUDHI) = hi; CONSOLE(SIO_LCTL) = tmp; /* Restore linectl reg */ return(0); } void InitUART(int baud) { unsigned char tmp, hi, lo; getUartDivisor(baud,&hi,&lo); CONSOLE(SIO_LCTL) = SIO_LCTL_DLAB; CONSOLE(SIO_BAUDLO) = lo; /* Set baud */ CONSOLE(SIO_BAUDHI) = hi; CONSOLE(SIO_LCTL) = LCTL_DEFAULT; /* 8-bits, no parity */ CONSOLE(SIO_MCTL) = MCTL_DEFAULT; tmp = CONSOLE(SIO_LSTAT); /* clear line stat */ tmp = CONSOLE(SIO_RXD); /* read receive buffer */ tmp = tmp; /* eliminate unused warning */ CONSOLE(SIO_IEN) = IEN_DEFAULT; CONSOLE(SIO_FCTL) = FCTL_DEFAULT; CONSOLE(SIO_SPR) = SPR_DEFAULT; } int target_console_empty(void) { if(CONSOLE(SIO_LSTAT) & SIO_LSTAT_TRDY) { return(0); } return(1); } int target_putchar(char c) { while(!(CONSOLE(SIO_LSTAT) & SIO_LSTAT_TRDY)); CONSOLE(SIO_TXD) = c; #ifdef MORE_PUTCHAR MORE_PUTCHAR(c); #endif return((int)c); } int target_getchar(void) { char c; #ifdef MORE_GETCHAR if(MORE_GOTACHAR()) { c = MORE_GETCHAR(); } else #endif c = CONSOLE(SIO_RXD); return((int)c); } int target_gotachar(void) { #if INCLUDE_BLINKLED extern void TARGET_BLINKLED(void); TARGET_BLINKLED(); #endif if(CONSOLE(SIO_LSTAT) & SIO_LSTAT_RRDY) { return(1); } #ifdef MORE_GOTACHAR if(MORE_GOTACHAR()) { return(1); } #endif return(0); }