diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2007-07-05 18:01:18 +0200 |
---|---|---|
committer | Sascha Hauer <sha@octopus.labnet.pengutronix.de> | 2007-07-05 18:01:18 +0200 |
commit | ae58483f5783f87253d4d8b90560540f17d464e1 (patch) | |
tree | 31a26e0c4908055e6f7ab88abe166fd8b3980bd1 /drivers/serial | |
parent | 7837210e23455a5b7fbcc6b55c539a134e953d89 (diff) | |
download | barebox-ae58483f5783f87253d4d8b90560540f17d464e1.tar.gz barebox-ae58483f5783f87253d4d8b90560540f17d464e1.tar.xz |
svn_rev_060
move serial drivers to drivers/serial
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/atmel_usart.c | 88 | ||||
-rw-r--r-- | drivers/serial/ns9750_serial.c | 214 | ||||
-rw-r--r-- | drivers/serial/s3c4510b_uart.c | 216 | ||||
-rw-r--r-- | drivers/serial/serial.c | 326 | ||||
-rw-r--r-- | drivers/serial/serial_max3100.c | 302 | ||||
-rw-r--r-- | drivers/serial/serial_pl010.c | 171 | ||||
-rw-r--r-- | drivers/serial/serial_pl011.c | 161 | ||||
-rw-r--r-- | drivers/serial/serial_xuartlite.c | 76 |
8 files changed, 1554 insertions, 0 deletions
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c new file mode 100644 index 0000000000..41c37683d7 --- /dev/null +++ b/drivers/serial/atmel_usart.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <common.h> + +#ifdef CONFIG_ATMEL_USART +#include <asm/io.h> +#include <asm/arch/platform.h> + +#include "atmel_usart.h" + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg(void) +{ + unsigned long divisor; + unsigned long usart_hz; + + /* + * Master Clock + * Baud Rate = -------------- + * 16 * CD + */ + usart_hz = pm_get_clock_freq(gd->console_uart->resource[0].u.clock.id); + divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; + usart3_writel(gd->console_uart, BRGR, USART3_BF(CD, divisor)); +} + +int serial_init(void) +{ + usart3_writel(gd->console_uart, CR, + USART3_BIT(RSTRX) | USART3_BIT(RSTTX)); + + serial_setbrg(); + + usart3_writel(gd->console_uart, CR, + USART3_BIT(RXEN) | USART3_BIT(TXEN)); + usart3_writel(gd->console_uart, MR, + USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) + | USART3_BF(USCLKS, USART3_USCLKS_MCK) + | USART3_BF(CHRL, USART3_CHRL_8) + | USART3_BF(PAR, USART3_PAR_NONE) + | USART3_BF(NBSTOP, USART3_NBSTOP_1)); + + return 0; +} + +void serial_putc(char c) +{ + if (c == '\n') + serial_putc('\r'); + + while (!(usart3_readl(gd->console_uart, CSR) & USART3_BIT(TXRDY))) ; + usart3_writel(gd->console_uart, THR, c); +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} + +int serial_getc(void) +{ + while (!(usart3_readl(gd->console_uart, CSR) & USART3_BIT(RXRDY))) ; + return usart3_readl(gd->console_uart, RHR); +} + +int serial_tstc(void) +{ + return (usart3_readl(gd->console_uart, CSR) & USART3_BIT(RXRDY)) != 0; +} + +#endif /* CONFIG_ATMEL_USART */ diff --git a/drivers/serial/ns9750_serial.c b/drivers/serial/ns9750_serial.c new file mode 100644 index 0000000000..02c0d39520 --- /dev/null +++ b/drivers/serial/ns9750_serial.c @@ -0,0 +1,214 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_serial.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Serial driver for the NS9750. Only one UART is supported yet. + * @References: [1] NS9750 Hardware Reference/December 2003 + * @TODO: Implement Character GAP Timer when chip is fixed for PLL bypass + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ***********************************************************************/ + +#include <common.h> + +#ifdef CFG_NS9750_UART + +#include "ns9750_bbus.h" /* for GPIOs */ +#include "ns9750_ser.h" /* for serial configuration */ + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_CONS_INDEX) +#error "No console index specified." +#endif + +#define CONSOLE CONFIG_CONS_INDEX + +static unsigned int calcBitrateRegister( void ); +static unsigned int calcRxCharGapRegister( void ); + +static char cCharsAvailable; /* Numbers of chars in unCharCache */ +static unsigned int unCharCache; /* unCharCache is only valid if + * cCharsAvailable > 0 */ + +/*********************************************************************** + * @Function: serial_init + * @Return: 0 + * @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off + ***********************************************************************/ + +int serial_init( void ) +{ + unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 }; + unsigned int aunGPIORxD[] = { 1, 9, 41, 45 }; + + cCharsAvailable = 0; + + /* configure TxD and RxD pins for their special function */ + set_gpio_cfg_reg_val( aunGPIOTxD[ CONSOLE ], + NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_OUTPUT ); + set_gpio_cfg_reg_val( aunGPIORxD[ CONSOLE ], + NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_INPUT ); + + /* configure serial engine */ + *get_ser_reg_addr_channel( NS9750_SER_CTRL_A, CONSOLE ) = + NS9750_SER_CTRL_A_CE | + NS9750_SER_CTRL_A_STOP | + NS9750_SER_CTRL_A_WLS_8; + + serial_setbrg(); + + *get_ser_reg_addr_channel( NS9750_SER_CTRL_B, CONSOLE ) = + NS9750_SER_CTRL_B_RCGT; + + return 0; +} + +/*********************************************************************** + * @Function: serial_putc + * @Return: n/a + * @Descr: writes one character to the FIFO. Blocks until FIFO is not full + ***********************************************************************/ + +void serial_putc( const char c ) +{ + if (c == '\n') + serial_putc( '\r' ); + + while (!(*get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE) & + NS9750_SER_STAT_A_TRDY ) ) { + /* do nothing, wait for characters in FIFO sent */ + } + + *(volatile char*) get_ser_reg_addr_channel( NS9750_SER_FIFO, + CONSOLE) = c; +} + +/*********************************************************************** + * @Function: serial_puts + * @Return: n/a + * @Descr: writes non-zero string to the FIFO. + ***********************************************************************/ + +void serial_puts( const char *s ) +{ + while (*s) { + serial_putc( *s++ ); + } +} + +/*********************************************************************** + * @Function: serial_getc + * @Return: the character read + * @Descr: performs only 8bit accesses to the FIFO. No error handling + ***********************************************************************/ + +int serial_getc( void ) +{ + int i; + + while (!serial_tstc() ) { + /* do nothing, wait for incoming characters */ + } + + /* at least one character in unCharCache */ + i = (int) (unCharCache & 0xff); + + unCharCache >>= 8; + cCharsAvailable--; + + return i; +} + +/*********************************************************************** + * @Function: serial_tstc + * @Return: 0 if no input available, otherwise != 0 + * @Descr: checks for incoming FIFO not empty. Stores the incoming chars in + * unCharCache and the numbers of characters in cCharsAvailable + ***********************************************************************/ + +int serial_tstc( void ) +{ + unsigned int unRegCache; + + if ( cCharsAvailable ) + return 1; + + unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,CONSOLE ); + if( unRegCache & NS9750_SER_STAT_A_RBC ) { + *get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE ) = + NS9750_SER_STAT_A_RBC; + unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A, + CONSOLE ); + } + + if ( unRegCache & NS9750_SER_STAT_A_RRDY ) { + cCharsAvailable = (unRegCache & NS9750_SER_STAT_A_RXFDB_MA)>>20; + if ( !cCharsAvailable ) + cCharsAvailable = 4; + + unCharCache = *get_ser_reg_addr_channel( NS9750_SER_FIFO, + CONSOLE ); + return 1; + } + + /* no chars available */ + return 0; +} + +void serial_setbrg( void ) +{ + *get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) = + calcBitrateRegister(); + *get_ser_reg_addr_channel( NS9750_SER_RX_CHAR_TIMER, CONSOLE ) = + calcRxCharGapRegister(); +} + +/*********************************************************************** + * @Function: calcBitrateRegister + * @Return: value for the serial bitrate register + * @Descr: register value depends on clock frequency and baudrate + ***********************************************************************/ + +static unsigned int calcBitrateRegister( void ) +{ + return ( NS9750_SER_BITRATE_EBIT | + NS9750_SER_BITRATE_CLKMUX_BCLK | + NS9750_SER_BITRATE_TMODE | + NS9750_SER_BITRATE_TCDR_16 | + NS9750_SER_BITRATE_RCDR_16 | + ( ( ( ( CONFIG_SYS_CLK_FREQ / 8 ) / /* BBUS clock,[1] Fig. 38 */ + ( gd->baudrate * 16 ) ) - 1 ) & + NS9750_SER_BITRATE_N_MA ) ); +} + +/*********************************************************************** + * @Function: calcRxCharGapRegister + * @Return: value for the character gap timer register + * @Descr: register value depends on clock frequency and baudrate. Currently 0 + * is used as there is a bug with the gap timer in PLL bypass mode. + ***********************************************************************/ + +static unsigned int calcRxCharGapRegister( void ) +{ + return NS9750_SER_RX_CHAR_TIMER_TRUN; +} + +#endif /* CFG_NS9750_UART */ diff --git a/drivers/serial/s3c4510b_uart.c b/drivers/serial/s3c4510b_uart.c new file mode 100644 index 0000000000..ddcd591f84 --- /dev/null +++ b/drivers/serial/s3c4510b_uart.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) + * Curt Brune <curt@cucy.com> + * + * (C) Copyright 2004 + * DAVE Srl + * http://www.dave-tech.it + * http://www.wawnet.biz + * mailto:info@wawnet.biz + * + * (C) Copyright 2002-2004 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * MODULE: $Id:$ + * Description: UART/Serial interface for Samsung S3C4510B SoC + * Runtime Env: ARM7TDMI + * Change History: + * 03-02-04 Create (Curt Brune) curt@cucy.com + * + */ + +#include <common.h> + +#ifdef CONFIG_DRIVER_S3C4510_UART + +#include <asm/hardware.h> +#include "s3c4510b_uart.h" + +DECLARE_GLOBAL_DATA_PTR; + +static UART *uart; + +/* flush serial input queue. returns 0 on success or negative error + * number otherwise + */ +static int serial_flush_input(void) +{ + volatile u32 tmp; + + /* keep on reading as long as the receiver is not empty */ + while( uart->m_stat.bf.rxReady) { + tmp = uart->m_rx; + } + + return 0; +} + + +/* flush output queue. returns 0 on success or negative error number + * otherwise + */ +static int serial_flush_output(void) +{ + /* wait until the transmitter is no longer busy */ + while( !uart->m_stat.bf.txBufEmpty); + + return 0; +} + + +void serial_setbrg (void) +{ + UART_LINE_CTRL ulctrl; + UART_CTRL uctrl; + UART_BAUD_DIV ubd; + + serial_flush_output(); + serial_flush_input(); + + /* control register */ + uctrl.ui = 0x0; + uctrl.bf.rxMode = 0x1; + uctrl.bf.rxIrq = 0x0; + uctrl.bf.txMode = 0x1; + uctrl.bf.DSR = 0x0; + uctrl.bf.sendBreak = 0x0; + uctrl.bf.loopBack = 0x0; + uart->m_ctrl.ui = uctrl.ui; + + /* line control register */ + ulctrl.ui = 0x0; + ulctrl.bf.wordLen = 0x3; /* 8 bit data */ + ulctrl.bf.nStop = 0x0; /* 1 stop bit */ + ulctrl.bf.parity = 0x0; /* no parity */ + ulctrl.bf.clk = 0x0; /* internal clock */ + ulctrl.bf.infra_red = 0x0; /* no infra_red */ + uart->m_lineCtrl.ui = ulctrl.ui; + + ubd.ui = 0x0; + + /* see table on page 10-15 in SAMSUNG S3C4510B manual */ + /* get correct divisor */ + switch(gd->baudrate) { + case 1200: ubd.bf.cnt0 = 1301; break; + case 2400: ubd.bf.cnt0 = 650; break; + case 4800: ubd.bf.cnt0 = 324; break; + case 9600: ubd.bf.cnt0 = 162; break; + case 19200: ubd.bf.cnt0 = 80; break; + case 38400: ubd.bf.cnt0 = 40; break; + case 57600: ubd.bf.cnt0 = 26; break; + case 115200: ubd.bf.cnt0 = 13; break; + } + + uart->m_baudDiv.ui = ubd.ui; + uart->m_baudCnt = 0x0; + uart->m_baudClk = 0x0; + +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + +#if CONFIG_SERIAL1 == 1 + uart = (UART *)UART0_BASE; +#elif CONFIG_SERIAL1 == 2 + uart = (UART *)UART1_BASE; +#else +#error CONFIG_SERIAL1 not equal to 1 or 2 +#endif + + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + /* wait for room in the transmit FIFO */ + while( !uart->m_stat.bf.txBufEmpty); + + uart->m_tx = c; + + /* + to be polite with serial console add a line feed + to the carriage return character + */ + if (c=='\n') + serial_putc('\r'); +} + +/* + * Test if an input byte is ready from the serial port. Returns non-zero on + * success, 0 otherwise. + */ +int serial_tstc (void) +{ + return uart->m_stat.bf.rxReady; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + int rv; + + for(;;) { + rv = serial_tstc(); + + if (rv) { + return uart->m_rx & 0xFF; + } + } +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } + + /* busy wait for tx complete */ + while ( !uart->m_stat.bf.txComplete); + + /* clear break */ + uart->m_ctrl.bf.sendBreak = 0; + +} + +#endif diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c new file mode 100644 index 0000000000..76425d8790 --- /dev/null +++ b/drivers/serial/serial.c @@ -0,0 +1,326 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#ifdef CFG_NS16550_SERIAL + +#include <ns16550.h> +#ifdef CFG_NS87308 +#include <ns87308.h> +#endif + +#if defined (CONFIG_SERIAL_MULTI) +#include <serial.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_CONS_INDEX) +#if defined (CONFIG_SERIAL_MULTI) +/* with CONFIG_SERIAL_MULTI we might have no console + * on these devices + */ +#else +#error "No console index specified." +#endif /* CONFIG_SERIAL_MULTI */ +#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4) +#error "Invalid console index value." +#endif + +#if CONFIG_CONS_INDEX == 1 && !defined(CFG_NS16550_COM1) +#error "Console port 1 defined but not configured." +#elif CONFIG_CONS_INDEX == 2 && !defined(CFG_NS16550_COM2) +#error "Console port 2 defined but not configured." +#elif CONFIG_CONS_INDEX == 3 && !defined(CFG_NS16550_COM3) +#error "Console port 3 defined but not configured." +#elif CONFIG_CONS_INDEX == 4 && !defined(CFG_NS16550_COM4) +#error "Console port 4 defined but not configured." +#endif + +/* Note: The port number specified in the functions is 1 based. + * the array is 0 based. + */ +static NS16550_t serial_ports[4] = { +#ifdef CFG_NS16550_COM1 + (NS16550_t)CFG_NS16550_COM1, +#else + NULL, +#endif +#ifdef CFG_NS16550_COM2 + (NS16550_t)CFG_NS16550_COM2, +#else + NULL, +#endif +#ifdef CFG_NS16550_COM3 + (NS16550_t)CFG_NS16550_COM3, +#else + NULL, +#endif +#ifdef CFG_NS16550_COM4 + (NS16550_t)CFG_NS16550_COM4 +#else + NULL +#endif +}; + +#define PORT serial_ports[port-1] +#if defined(CONFIG_CONS_INDEX) +#define CONSOLE (serial_ports[CONFIG_CONS_INDEX-1]) +#endif + +#if defined(CONFIG_SERIAL_MULTI) + +/* Multi serial device functions */ +#define DECLARE_ESERIAL_FUNCTIONS(port) \ + int eserial##port##_init (void) {\ + int clock_divisor; \ + clock_divisor = calc_divisor(serial_ports[port-1]); \ + NS16550_init(serial_ports[port-1], clock_divisor); \ + return(0);}\ + void eserial##port##_setbrg (void) {\ + serial_setbrg_dev(port);}\ + int eserial##port##_getc (void) {\ + return serial_getc_dev(port);}\ + int eserial##port##_tstc (void) {\ + return serial_tstc_dev(port);}\ + void eserial##port##_putc (const char c) {\ + serial_putc_dev(port, c);}\ + void eserial##port##_puts (const char *s) {\ + serial_puts_dev(port, s);} + +/* Serial device descriptor */ +#define INIT_ESERIAL_STRUCTURE(port,name,bus) {\ + name,\ + bus,\ + eserial##port##_init,\ + eserial##port##_setbrg,\ + eserial##port##_getc,\ + eserial##port##_tstc,\ + eserial##port##_putc,\ + eserial##port##_puts, } + +#endif /* CONFIG_SERIAL_MULTI */ + +static int calc_divisor (NS16550_t port) +{ +#ifdef CONFIG_OMAP1510 + /* If can't cleanly clock 115200 set div to 1 */ + if ((CFG_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) { + port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */ + return (1); /* return 1 for base divisor */ + } + port->osc_12m_sel = 0; /* clear if previsouly set */ +#endif +#ifdef CONFIG_OMAP1610 + /* If can't cleanly clock 115200 set div to 1 */ + if ((CFG_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) { + return (26); /* return 26 for base divisor */ + } +#endif + +#ifdef CONFIG_APTIX +#define MODE_X_DIV 13 +#else +#define MODE_X_DIV 16 +#endif + return (CFG_NS16550_CLK / MODE_X_DIV / gd->baudrate); + +} + +#if !defined(CONFIG_SERIAL_MULTI) +int serial_init (void) +{ + int clock_divisor; + +#ifdef CFG_NS87308 + initialise_ns87308(); +#endif + +#ifdef CFG_NS16550_COM1 + clock_divisor = calc_divisor(serial_ports[0]); + NS16550_init(serial_ports[0], clock_divisor); +#endif +#ifdef CFG_NS16550_COM2 + clock_divisor = calc_divisor(serial_ports[1]); + NS16550_init(serial_ports[1], clock_divisor); +#endif +#ifdef CFG_NS16550_COM3 + clock_divisor = calc_divisor(serial_ports[2]); + NS16550_init(serial_ports[2], clock_divisor); +#endif +#ifdef CFG_NS16550_COM4 + clock_divisor = calc_divisor(serial_ports[3]); + NS16550_init(serial_ports[3], clock_divisor); +#endif + + return (0); +} +#endif + +void +_serial_putc(const char c,const int port) +{ + if (c == '\n') + NS16550_putc(PORT, '\r'); + + NS16550_putc(PORT, c); +} + +void +_serial_putc_raw(const char c,const int port) +{ + NS16550_putc(PORT, c); +} + +void +_serial_puts (const char *s,const int port) +{ + while (*s) { + _serial_putc (*s++,port); + } +} + + +int +_serial_getc(const int port) +{ + return NS16550_getc(PORT); +} + +int +_serial_tstc(const int port) +{ + return NS16550_tstc(PORT); +} + +void +_serial_setbrg (const int port) +{ + int clock_divisor; + + clock_divisor = calc_divisor(PORT); + NS16550_reinit(PORT, clock_divisor); +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_putc_dev(unsigned int dev_index,const char c) +{ + _serial_putc(c,dev_index); +} +#else +void +serial_putc(const char c) +{ + _serial_putc(c,CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_putc_raw_dev(unsigned int dev_index,const char c) +{ + _serial_putc_raw(c,dev_index); +} +#else +void +serial_putc_raw(const char c) +{ + _serial_putc_raw(c,CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_puts_dev(unsigned int dev_index,const char *s) +{ + _serial_puts(s,dev_index); +} +#else +void +serial_puts(const char *s) +{ + _serial_puts(s,CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline int +serial_getc_dev(unsigned int dev_index) +{ + return _serial_getc(dev_index); +} +#else +int +serial_getc(void) +{ + return _serial_getc(CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline int +serial_tstc_dev(unsigned int dev_index) +{ + return _serial_tstc(dev_index); +} +#else +int +serial_tstc(void) +{ + return _serial_tstc(CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_setbrg_dev(unsigned int dev_index) +{ + _serial_setbrg(dev_index); +} +#else +void +serial_setbrg(void) +{ + _serial_setbrg(CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) + +DECLARE_ESERIAL_FUNCTIONS(1); +struct serial_device eserial1_device = + INIT_ESERIAL_STRUCTURE(1,"eserial0","EUART1"); +DECLARE_ESERIAL_FUNCTIONS(2); +struct serial_device eserial2_device = + INIT_ESERIAL_STRUCTURE(2,"eserial1","EUART2"); +DECLARE_ESERIAL_FUNCTIONS(3); +struct serial_device eserial3_device = + INIT_ESERIAL_STRUCTURE(3,"eserial2","EUART3"); +DECLARE_ESERIAL_FUNCTIONS(4); +struct serial_device eserial4_device = + INIT_ESERIAL_STRUCTURE(4,"eserial3","EUART4"); +#endif /* CONFIG_SERIAL_MULTI */ + +#endif diff --git a/drivers/serial/serial_max3100.c b/drivers/serial/serial_max3100.c new file mode 100644 index 0000000000..35c5596985 --- /dev/null +++ b/drivers/serial/serial_max3100.c @@ -0,0 +1,302 @@ +/* + * (C) Copyright 2003 + * + * Pantelis Antoniou <panto@intracom.gr> + * Intracom S.A. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <watchdog.h> + +#ifdef CONFIG_MAX3100_SERIAL + +DECLARE_GLOBAL_DATA_PTR; + +/**************************************************************/ + +/* convienient macros */ +#define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT) + +#define MAX3100_SPI_TXD(x) \ + do { \ + if (x) \ + MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \ + else \ + MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \ + } while(0) + +#define MAX3100_SPI_CLK(x) \ + do { \ + if (x) \ + MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \ + else \ + MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \ + } while(0) + +#define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT) + +#define MAX3100_CS(x) \ + do { \ + if (x) \ + MAX3100_CS_PORT |= MAX3100_CS_BIT; \ + else \ + MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \ + } while(0) + +/**************************************************************/ + +/* MAX3100 definitions */ + +#define MAX3100_WC (3 << 14) /* write configuration */ +#define MAX3100_RC (1 << 14) /* read configuration */ +#define MAX3100_WD (2 << 14) /* write data */ +#define MAX3100_RD (0 << 14) /* read data */ + +/* configuration register bits */ +#define MAX3100_FEN (1 << 13) /* FIFO enable */ +#define MAX3100_SHDN (1 << 12) /* shutdown bit */ +#define MAX3100_TM (1 << 11) /* T bit irq mask */ +#define MAX3100_RM (1 << 10) /* R bit irq mask */ +#define MAX3100_PM (1 << 9) /* P bit irq mask */ +#define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */ +#define MAX3100_IR (1 << 7) /* IRDA timing mode */ +#define MAX3100_ST (1 << 6) /* transmit stop bit */ +#define MAX3100_PE (1 << 5) /* parity enable bit */ +#define MAX3100_L (1 << 4) /* Length bit */ +#define MAX3100_B_MASK (0x000F) /* baud rate bits mask */ +#define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */ + +/* data register bits (write) */ +#define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */ +#define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */ + +/* data register bits (read) */ +#define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */ +#define MAX3100_FE (1 << 10) /* framing error when in normal mode */ +#define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */ + +/* data register bits (both directions) */ +#define MAX3100_R (1 << 15) /* receive bit */ +#define MAX3100_T (1 << 14) /* transmit bit */ +#define MAX3100_P (1 << 8) /* parity bit */ +#define MAX3100_D_MASK 0x00FF /* data bits mask */ +#define MAX3100_D(x) ((x) & 0x00FF) /* data bits */ + +/* these definitions are valid only for fOSC = 3.6864MHz */ +#define MAX3100_B_230400 MAX3100_B(0) +#define MAX3100_B_115200 MAX3100_B(1) +#define MAX3100_B_57600 MAX3100_B(2) +#define MAX3100_B_38400 MAX3100_B(9) +#define MAX3100_B_19200 MAX3100_B(10) +#define MAX3100_B_9600 MAX3100_B(11) +#define MAX3100_B_4800 MAX3100_B(12) +#define MAX3100_B_2400 MAX3100_B(13) +#define MAX3100_B_1200 MAX3100_B(14) +#define MAX3100_B_600 MAX3100_B(15) + +/**************************************************************/ + +static inline unsigned int max3100_transfer(unsigned int val) +{ + unsigned int rx; + int b; + + MAX3100_SPI_CLK(0); + MAX3100_CS(0); + + rx = 0; b = 16; + while (--b >= 0) { + MAX3100_SPI_TXD(val & 0x8000); + val <<= 1; + MAX3100_SPI_CLK_TOGGLE(); + udelay(1); + rx <<= 1; + if (MAX3100_SPI_RXD()) + rx |= 1; + MAX3100_SPI_CLK_TOGGLE(); + udelay(1); + } + + MAX3100_SPI_CLK(1); + MAX3100_CS(1); + + return rx; +} + +/**************************************************************/ + +/* must be power of 2 */ +#define RXFIFO_SZ 16 + +static int rxfifo_cnt; +static int rxfifo_in; +static int rxfifo_out; +static unsigned char rxfifo_buf[16]; + +static void max3100_putc(int c) +{ + unsigned int rx; + + while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0) + WATCHDOG_RESET(); + + rx = max3100_transfer(MAX3100_WD | (c & 0xff)); + if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) { + rxfifo_cnt++; + rxfifo_buf[rxfifo_in++] = rx & 0xff; + rxfifo_in &= RXFIFO_SZ - 1; + } +} + +static int max3100_getc(void) +{ + int c; + unsigned int rx; + + while (rxfifo_cnt == 0) { + rx = max3100_transfer(MAX3100_RD); + if ((rx & MAX3100_R) != 0) { + do { + rxfifo_cnt++; + rxfifo_buf[rxfifo_in++] = rx & 0xff; + rxfifo_in &= RXFIFO_SZ - 1; + + if (rxfifo_cnt >= RXFIFO_SZ) + break; + } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0); + } + WATCHDOG_RESET(); + } + + rxfifo_cnt--; + c = rxfifo_buf[rxfifo_out++]; + rxfifo_out &= RXFIFO_SZ - 1; + return c; +} + +static int max3100_tstc(void) +{ + unsigned int rx; + + if (rxfifo_cnt > 0) + return 1; + + rx = max3100_transfer(MAX3100_RD); + if ((rx & MAX3100_R) == 0) + return 0; + + do { + rxfifo_cnt++; + rxfifo_buf[rxfifo_in++] = rx & 0xff; + rxfifo_in &= RXFIFO_SZ - 1; + + if (rxfifo_cnt >= RXFIFO_SZ) + break; + } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0); + + return 1; +} + +int serial_init(void) +{ + unsigned int wconf, rconf; + int i; + + wconf = 0; + + /* Set baud rate */ + switch (gd->baudrate) { + case 1200: + wconf = MAX3100_B_1200; + break; + case 2400: + wconf = MAX3100_B_2400; + break; + case 4800: + wconf = MAX3100_B_4800; + break; + case 9600: + wconf = MAX3100_B_9600; + break; + case 19200: + wconf = MAX3100_B_19200; + break; + case 38400: + wconf = MAX3100_B_38400; + break; + case 57600: + wconf = MAX3100_B_57600; + break; + default: + case 115200: + wconf = MAX3100_B_115200; + break; + case 230400: + wconf = MAX3100_B_230400; + break; + } + + /* try for 10ms, with a 100us gap */ + for (i = 0; i < 10000; i += 100) { + + max3100_transfer(MAX3100_WC | wconf); + rconf = max3100_transfer(MAX3100_RC) & 0x3fff; + + if (rconf == wconf) + break; + udelay(100); + } + + rxfifo_in = rxfifo_out = rxfifo_cnt = 0; + + return (0); +} + +void serial_putc(const char c) +{ + if (c == '\n') + max3100_putc('\r'); + + max3100_putc(c); +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc (*s++); +} + +int serial_getc(void) +{ + return max3100_getc(); +} + +int serial_tstc(void) +{ + return max3100_tstc(); +} + +/* XXX WTF? */ +void serial_setbrg(void) +{ +} + +#endif diff --git a/drivers/serial/serial_pl010.c b/drivers/serial/serial_pl010.c new file mode 100644 index 0000000000..417b6aeda6 --- /dev/null +++ b/drivers/serial/serial_pl010.c @@ -0,0 +1,171 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Simple U-Boot driver for the PrimeCell PL011 UARTs on the IntegratorCP */ +/* Should be fairly simple to make it work with the PL010 as well */ + +#include <common.h> + +#ifdef CFG_PL010_SERIAL + +#include "serial_pl011.h" + +#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val)) +#define IO_READ(addr) (*(volatile unsigned int *)(addr)) + +/* Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 */ +#define CONSOLE_PORT CONFIG_CONS_INDEX +#define baudRate CONFIG_BAUDRATE +static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; +#define NUM_PORTS (sizeof(port)/sizeof(port[0])) + + +static void pl010_putc (int portnum, char c); +static int pl010_getc (int portnum); +static int pl010_tstc (int portnum); + + +int serial_init (void) +{ + unsigned int divisor; + + /* + ** First, disable everything. + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, 0x0); + + /* + ** Set baud rate + ** + */ + switch (baudRate) { + case 9600: + divisor = UART_PL010_BAUD_9600; + break; + + case 19200: + divisor = UART_PL010_BAUD_9600; + break; + + case 38400: + divisor = UART_PL010_BAUD_38400; + break; + + case 57600: + divisor = UART_PL010_BAUD_57600; + break; + + case 115200: + divisor = UART_PL010_BAUD_115200; + break; + + default: + divisor = UART_PL010_BAUD_38400; + } + + IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRM, + ((divisor & 0xf00) >> 8)); + IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRL, (divisor & 0xff)); + + /* + ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRH, + (UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN)); + + /* + ** Finally, enable the UART + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, (UART_PL010_CR_UARTEN)); + + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + pl010_putc (CONSOLE_PORT, '\r'); + + pl010_putc (CONSOLE_PORT, c); +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + return pl010_getc (CONSOLE_PORT); +} + +int serial_tstc (void) +{ + return pl010_tstc (CONSOLE_PORT); +} + +void serial_setbrg (void) +{ +} + +static void pl010_putc (int portnum, char c) +{ + /* Wait until there is space in the FIFO */ + while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF); + + /* Send the character */ + IO_WRITE (port[portnum] + UART_PL01x_DR, c); +} + +static int pl010_getc (int portnum) +{ + unsigned int data; + + /* Wait until there is data in the FIFO */ + while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); + + data = IO_READ (port[portnum] + UART_PL01x_DR); + + /* Check for an error flag */ + if (data & 0xFFFFFF00) { + /* Clear the error */ + IO_WRITE (port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF); + return -1; + } + + return (int) data; +} + +static int pl010_tstc (int portnum) +{ + return !(IO_READ (port[portnum] + UART_PL01x_FR) & + UART_PL01x_FR_RXFE); +} + +#endif diff --git a/drivers/serial/serial_pl011.c b/drivers/serial/serial_pl011.c new file mode 100644 index 0000000000..4d35fe5e9e --- /dev/null +++ b/drivers/serial/serial_pl011.c @@ -0,0 +1,161 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Simple U-Boot driver for the PrimeCell PL011 UARTs on the IntegratorCP */ +/* Should be fairly simple to make it work with the PL010 as well */ + +#include <common.h> + +#ifdef CFG_PL011_SERIAL + +#include "serial_pl011.h" + +#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val)) +#define IO_READ(addr) (*(volatile unsigned int *)(addr)) + +/* + * IntegratorCP has two UARTs, use the first one, at 38400-8-N-1 + * Versatile PB has four UARTs. + */ + +#define CONSOLE_PORT CONFIG_CONS_INDEX +#define baudRate CONFIG_BAUDRATE +static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; +#define NUM_PORTS (sizeof(port)/sizeof(port[0])) + +static void pl011_putc (int portnum, char c); +static int pl011_getc (int portnum); +static int pl011_tstc (int portnum); + + +int serial_init (void) +{ + unsigned int temp; + unsigned int divider; + unsigned int remainder; + unsigned int fraction; + + /* + ** First, disable everything. + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, 0x0); + + /* + ** Set baud rate + ** + ** IBRD = UART_CLK / (16 * BAUD_RATE) + ** FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE)) + */ + temp = 16 * baudRate; + divider = CONFIG_PL011_CLOCK / temp; + remainder = CONFIG_PL011_CLOCK % temp; + temp = (8 * remainder) / baudRate; + fraction = (temp >> 1) + (temp & 1); + + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_IBRD, divider); + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_FBRD, fraction); + + /* + ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_LCRH, + (UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN)); + + /* + ** Finally, enable the UART + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, + (UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | + UART_PL011_CR_RXE)); + + return 0; +} + +void serial_putc (const char c) +{ + if (c == '\n') + pl011_putc (CONSOLE_PORT, '\r'); + + pl011_putc (CONSOLE_PORT, c); +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + return pl011_getc (CONSOLE_PORT); +} + +int serial_tstc (void) +{ + return pl011_tstc (CONSOLE_PORT); +} + +void serial_setbrg (void) +{ +} + +static void pl011_putc (int portnum, char c) +{ + /* Wait until there is space in the FIFO */ + while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF); + + /* Send the character */ + IO_WRITE (port[portnum] + UART_PL01x_DR, c); +} + +static int pl011_getc (int portnum) +{ + unsigned int data; + + /* Wait until there is data in the FIFO */ + while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); + + data = IO_READ (port[portnum] + UART_PL01x_DR); + + /* Check for an error flag */ + if (data & 0xFFFFFF00) { + /* Clear the error */ + IO_WRITE (port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF); + return -1; + } + + return (int) data; +} + +static int pl011_tstc (int portnum) +{ + return !(IO_READ (port[portnum] + UART_PL01x_FR) & + UART_PL01x_FR_RXFE); +} + +#endif diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c new file mode 100644 index 0000000000..ed59abea86 --- /dev/null +++ b/drivers/serial/serial_xuartlite.c @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> + +#ifdef CONFIG_MICROBLAZE + +#include <asm/serial_xuartlite.h> + +/* FIXME: we should convert these to in32 and out32 */ +#define IO_WORD(offset) (*(volatile unsigned long *)(offset)) +#define IO_SERIAL(offset) IO_WORD(CONFIG_SERIAL_BASE + (offset)) + +#define IO_SERIAL_RX_FIFO IO_SERIAL(XUL_RX_FIFO_OFFSET) +#define IO_SERIAL_TX_FIFO IO_SERIAL(XUL_TX_FIFO_OFFSET) +#define IO_SERIAL_STATUS IO_SERIAL(XUL_STATUS_REG_OFFSET) +#define IO_SERIAL_CONTROL IO_SERIAL(XUL_CONTROL_REG_OFFSET) + +int serial_init(void) +{ + /* FIXME: Nothing for now. We should initialize fifo, etc */ + return 0; +} + +void serial_setbrg(void) +{ + /* FIXME: what's this for? */ +} + +void serial_putc(const char c) +{ + if (c == '\n') serial_putc('\r'); + while (IO_SERIAL_STATUS & XUL_SR_TX_FIFO_FULL); + IO_SERIAL_TX_FIFO = (unsigned char) (c & 0xff); +} + +void serial_puts(const char * s) +{ + while (*s) { + serial_putc(*s++); + } +} + +int serial_getc(void) +{ + while (!(IO_SERIAL_STATUS & XUL_SR_RX_FIFO_VALID_DATA)); + return IO_SERIAL_RX_FIFO & 0xff; +} + +int serial_tstc(void) +{ + return (IO_SERIAL_STATUS & XUL_SR_RX_FIFO_VALID_DATA); +} + +#endif /* CONFIG_MICROBLZE */ |