diff options
Diffstat (limited to 'drivers/serial')
32 files changed, 1539 insertions, 602 deletions
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f234e..3c32f97ab 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -25,6 +25,8 @@ include $(TOPDIR)/config.mk  LIB	:= $(obj)libserial.o +COBJS-y += serial.o +  COBJS-$(CONFIG_ALTERA_UART) += altera_uart.o  COBJS-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o  COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o @@ -37,7 +39,7 @@ COBJS-$(CONFIG_SYS_NS16550) += ns16550.o  COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o  COBJS-$(CONFIG_S3C64XX) += s3c64xx.o  COBJS-$(CONFIG_S5P) += serial_s5p.o -COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial.o +COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o  COBJS-$(CONFIG_CLPS7111_SERIAL) += serial_clps7111.o  COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o  COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o @@ -56,6 +58,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o  COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o  COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o  COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o +COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o  ifndef CONFIG_SPL_BUILD  COBJS-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c index 2980e4d07..654b5019e 100644 --- a/drivers/serial/altera_jtag_uart.c +++ b/drivers/serial/altera_jtag_uart.c @@ -25,6 +25,8 @@  #include <watchdog.h>  #include <asm/io.h>  #include <nios2-io.h> +#include <linux/compiler.h> +#include <serial.h>  DECLARE_GLOBAL_DATA_PTR; @@ -33,10 +35,16 @@ DECLARE_GLOBAL_DATA_PTR;   *-----------------------------------------------------------------*/  static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; -void serial_setbrg( void ){ return; } -int serial_init( void ) { return(0);} +static void altera_jtag_serial_setbrg(void) +{ +} + +static int altera_jtag_serial_init(void) +{ +	return 0; +} -void serial_putc (char c) +static void altera_jtag_serial_putc(char c)  {  	while (1) {  		unsigned st = readl(&jtag->control); @@ -51,18 +59,18 @@ void serial_putc (char c)  	writel ((unsigned char)c, &jtag->data);  } -void serial_puts (const char *s) +static void altera_jtag_serial_puts(const char *s)  {  	while (*s != 0)  		serial_putc (*s++);  } -int serial_tstc (void) +static int altera_jtag_serial_tstc(void)  {  	return ( readl (&jtag->control) & NIOS_JTAG_RRDY);  } -int serial_getc (void) +static int altera_jtag_serial_getc(void)  {  	int c;  	unsigned val; @@ -76,3 +84,24 @@ int serial_getc (void)  	c = val & 0x0ff;  	return (c);  } + +static struct serial_device altera_jtag_serial_drv = { +	.name	= "altera_jtag_uart", +	.start	= altera_jtag_serial_init, +	.stop	= NULL, +	.setbrg	= altera_jtag_serial_setbrg, +	.putc	= altera_jtag_serial_putc, +	.puts	= altera_jtag_serial_puts, +	.getc	= altera_jtag_serial_getc, +	.tstc	= altera_jtag_serial_tstc, +}; + +void altera_jtag_serial_initialize(void) +{ +	serial_register(&altera_jtag_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &altera_jtag_serial_drv; +} diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 045f1197a..27550ed48 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -26,6 +26,8 @@  #include <watchdog.h>  #include <asm/io.h>  #include <nios2-io.h> +#include <linux/compiler.h> +#include <serial.h>  DECLARE_GLOBAL_DATA_PTR; @@ -37,27 +39,33 @@ static nios_uart_t *uart = (nios_uart_t *) CONFIG_SYS_NIOS_CONSOLE;  #if defined(CONFIG_SYS_NIOS_FIXEDBAUD) -/* Everything's already setup for fixed-baud PTF +/* + * Everything's already setup for fixed-baud PTF   * assignment   */ -void serial_setbrg (void){ return; } -int serial_init (void) { return (0);} +static void altera_serial_setbrg(void) +{ +} + +static int altera_serial_init(void) +{ +	return 0; +}  #else -void serial_setbrg (void) +static void altera_serial_setbrg(void)  {  	unsigned div;  	div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1;  	writel (div, &uart->divisor); -	return;  } -int serial_init (void) +static int altera_serial_init(void)  { -	serial_setbrg (); -	return (0); +	serial_setbrg(); +	return 0;  }  #endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ @@ -65,7 +73,7 @@ int serial_init (void)  /*-----------------------------------------------------------------------   * UART CONSOLE   *---------------------------------------------------------------------*/ -void serial_putc (char c) +static void altera_serial_putc(char c)  {  	if (c == '\n')  		serial_putc ('\r'); @@ -74,21 +82,42 @@ void serial_putc (char c)  	writel ((unsigned char)c, &uart->txdata);  } -void serial_puts (const char *s) +static void altera_serial_puts(const char *s)  {  	while (*s != 0) {  		serial_putc (*s++);  	}  } -int serial_tstc (void) +static int altera_serial_tstc(void)  {  	return (readl (&uart->status) & NIOS_UART_RRDY);  } -int serial_getc (void) +static int altera_serial_getc(void)  {  	while (serial_tstc () == 0)  		WATCHDOG_RESET ();  	return (readl (&uart->rxdata) & 0x00ff );  } + +static struct serial_device altera_serial_drv = { +	.name	= "altera_serial", +	.start	= altera_serial_init, +	.stop	= NULL, +	.setbrg	= altera_serial_setbrg, +	.putc	= altera_serial_putc, +	.puts	= altera_serial_puts, +	.getc	= altera_serial_getc, +	.tstc	= altera_serial_tstc, +}; + +void altera_serial_initialize(void) +{ +	serial_register(&altera_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &altera_serial_drv; +} diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index 943ef70fa..130303129 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -20,6 +20,8 @@   */  #include <common.h>  #include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h>  #include <asm/io.h>  #include <asm/arch/clk.h> @@ -29,7 +31,7 @@  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg(void) +static void atmel_serial_setbrg(void)  {  	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;  	unsigned long divisor; @@ -45,7 +47,7 @@ void serial_setbrg(void)  	writel(USART3_BF(CD, divisor), &usart->brgr);  } -int serial_init(void) +static int atmel_serial_init(void)  {  	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; @@ -73,7 +75,7 @@ int serial_init(void)  	return 0;  } -void serial_putc(char c) +static void atmel_serial_putc(char c)  {  	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; @@ -84,13 +86,13 @@ void serial_putc(char c)  	writel(c, &usart->thr);  } -void serial_puts(const char *s) +static void atmel_serial_puts(const char *s)  {  	while (*s)  		serial_putc(*s++);  } -int serial_getc(void) +static int atmel_serial_getc(void)  {  	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; @@ -99,8 +101,29 @@ int serial_getc(void)  	return readl(&usart->rhr);  } -int serial_tstc(void) +static int atmel_serial_tstc(void)  {  	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;  	return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;  } + +static struct serial_device atmel_serial_drv = { +	.name	= "atmel_serial", +	.start	= atmel_serial_init, +	.stop	= NULL, +	.setbrg	= atmel_serial_setbrg, +	.putc	= atmel_serial_putc, +	.puts	= atmel_serial_puts, +	.getc	= atmel_serial_getc, +	.tstc	= atmel_serial_tstc, +}; + +void atmel_serial_initialize(void) +{ +	serial_register(&atmel_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &atmel_serial_drv; +} diff --git a/drivers/serial/lpc32xx_hsuart.c b/drivers/serial/lpc32xx_hsuart.c index 8ce3382d8..02429b554 100644 --- a/drivers/serial/lpc32xx_hsuart.c +++ b/drivers/serial/lpc32xx_hsuart.c @@ -22,12 +22,14 @@  #include <asm/arch/clk.h>  #include <asm/arch/uart.h>  #include <asm/io.h> +#include <serial.h> +#include <linux/compiler.h>  DECLARE_GLOBAL_DATA_PTR;  static struct hsuart_regs *hsuart = (struct hsuart_regs *)HS_UART_BASE; -static void lpc32xx_hsuart_set_baudrate(void) +static void lpc32xx_serial_setbrg(void)  {  	u32 div; @@ -39,7 +41,7 @@ static void lpc32xx_hsuart_set_baudrate(void)  	writel(div, &hsuart->rate);  } -static int lpc32xx_hsuart_getc(void) +static int lpc32xx_serial_getc(void)  {  	while (!(readl(&hsuart->level) & HSUART_LEVEL_RX))  		/* NOP */; @@ -47,7 +49,7 @@ static int lpc32xx_hsuart_getc(void)  	return readl(&hsuart->rx) & HSUART_RX_DATA;  } -static void lpc32xx_hsuart_putc(const char c) +static void lpc32xx_serial_putc(const char c)  {  	writel(c, &hsuart->tx); @@ -56,7 +58,7 @@ static void lpc32xx_hsuart_putc(const char c)  		/* NOP */;  } -static int lpc32xx_hsuart_tstc(void) +static int lpc32xx_serial_tstc(void)  {  	if (readl(&hsuart->level) & HSUART_LEVEL_RX)  		return 1; @@ -64,49 +66,40 @@ static int lpc32xx_hsuart_tstc(void)  	return 0;  } -static void lpc32xx_hsuart_init(void) +static int lpc32xx_serial_init(void)  { -	lpc32xx_hsuart_set_baudrate(); +	lpc32xx_serial_setbrg();  	/* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */  	writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) |  	       HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0,  	       &hsuart->ctrl); +	return 0;  } -void serial_setbrg(void) -{ -	return lpc32xx_hsuart_set_baudrate(); -} - -void serial_putc(const char c) -{ -	lpc32xx_hsuart_putc(c); - -	/* If \n, also do \r */ -	if (c == '\n') -		lpc32xx_hsuart_putc('\r'); -} - -int serial_getc(void) -{ -	return lpc32xx_hsuart_getc(); -} - -void serial_puts(const char *s) +static void lpc32xx_serial_puts(const char *s)  {  	while (*s)  		serial_putc(*s++);  } -int serial_tstc(void) +static struct serial_device lpc32xx_serial_drv = { +	.name	= "lpc32xx_serial", +	.start	= lpc32xx_serial_init, +	.stop	= NULL, +	.setbrg	= lpc32xx_serial_setbrg, +	.putc	= lpc32xx_serial_putc, +	.puts	= lpc32xx_serial_puts, +	.getc	= lpc32xx_serial_getc, +	.tstc	= lpc32xx_serial_tstc, +}; + +void lpc32xx_serial_initialize(void)  { -	return lpc32xx_hsuart_tstc(); +	serial_register(&lpc32xx_serial_drv);  } -int serial_init(void) +__weak struct serial_device *default_serial_console(void)  { -	lpc32xx_hsuart_init(); - -	return 0; +	return &lpc32xx_serial_drv;  } diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c index d93b24b89..00a711469 100644 --- a/drivers/serial/mcfuart.c +++ b/drivers/serial/mcfuart.c @@ -36,7 +36,7 @@ DECLARE_GLOBAL_DATA_PTR;  extern void uart_port_conf(int port); -int serial_init(void) +static int mcf_serial_init(void)  {  	volatile uart_t *uart;  	u32 counter; @@ -74,7 +74,7 @@ int serial_init(void)  	return (0);  } -void serial_putc(const char c) +static void mcf_serial_putc(const char c)  {  	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); @@ -87,14 +87,14 @@ void serial_putc(const char c)  	uart->utb = c;  } -void serial_puts(const char *s) +static void mcf_serial_puts(const char *s)  {  	while (*s) {  		serial_putc(*s++);  	}  } -int serial_getc(void) +static int mcf_serial_getc(void)  {  	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); @@ -103,14 +103,14 @@ int serial_getc(void)  	return uart->urb;  } -int serial_tstc(void) +static int mcf_serial_tstc(void)  {  	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);  	return (uart->usr & UART_USR_RXRDY);  } -void serial_setbrg(void) +static void mcf_serial_setbrg(void)  {  	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);  	u32 counter; @@ -129,3 +129,24 @@ void serial_setbrg(void)  	uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED;  } + +static struct serial_device mcf_serial_drv = { +	.name	= "mcf_serial", +	.start	= mcf_serial_init, +	.stop	= NULL, +	.setbrg	= mcf_serial_setbrg, +	.putc	= mcf_serial_putc, +	.puts	= mcf_serial_puts, +	.getc	= mcf_serial_getc, +	.tstc	= mcf_serial_tstc, +}; + +void mcf_serial_initialize(void) +{ +	serial_register(&mcf_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &mcf_serial_drv; +} diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index facadd2f5..902778144 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -101,7 +101,7 @@ void NS16550_putc(NS16550_t com_port, char c)  char NS16550_getc(NS16550_t com_port)  {  	while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { -#ifdef CONFIG_USB_TTY +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY)  		extern void usbtty_poll(void);  		usbtty_poll();  #endif diff --git a/drivers/serial/ns9750_serial.c b/drivers/serial/ns9750_serial.c index e9645a053..cb545c406 100644 --- a/drivers/serial/ns9750_serial.c +++ b/drivers/serial/ns9750_serial.c @@ -52,7 +52,7 @@ static unsigned int unCharCache; /* unCharCache is only valid if   * @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off   ***********************************************************************/ -int serial_init( void ) +static int ns9750_serial_init(void)  {  	unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 };  	unsigned int aunGPIORxD[] = { 1, 9, 41, 45 }; @@ -85,7 +85,7 @@ int serial_init( void )   * @Descr: writes one character to the FIFO. Blocks until FIFO is not full   ***********************************************************************/ -void serial_putc( const char c ) +static void ns9750_serial_putc(const char c)  {  	if (c == '\n')  		serial_putc( '\r' ); @@ -105,7 +105,7 @@ void serial_putc( const char c )   * @Descr: writes non-zero string to the FIFO.   ***********************************************************************/ -void serial_puts( const char *s ) +static void ns9750_serial_puts(const char *s)  {  	while (*s) {  		serial_putc( *s++ ); @@ -118,7 +118,7 @@ void serial_puts( const char *s )   * @Descr: performs only 8bit accesses to the FIFO. No error handling   ***********************************************************************/ -int serial_getc( void ) +static int ns9750_serial_getc(void)  {  	int i; @@ -142,7 +142,7 @@ int serial_getc( void )   *	   unCharCache and the numbers of characters in cCharsAvailable   ***********************************************************************/ -int serial_tstc( void ) +static int ns9750_serial_tstc(void)  {  	unsigned int unRegCache; @@ -171,7 +171,7 @@ int serial_tstc( void )  	return 0;  } -void serial_setbrg( void ) +static void ns9750_serial_setbrg(void)  {  	*get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) =  		calcBitrateRegister(); @@ -208,3 +208,24 @@ static unsigned int calcRxCharGapRegister( void )  {  	return NS9750_SER_RX_CHAR_TIMER_TRUN;  } + +static struct serial_device ns9750_serial_drv = { +	.name	= "ns9750_serial", +	.start	= ns9750_serial_init, +	.stop	= NULL, +	.setbrg	= ns9750_serial_setbrg, +	.putc	= ns9750_serial_putc, +	.puts	= ns9750_serial_puts, +	.getc	= ns9750_serial_getc, +	.tstc	= ns9750_serial_tstc, +}; + +void ns9750_serial_initialize(void) +{ +	serial_register(&ns9750_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &ns9750_serial_drv; +} diff --git a/drivers/serial/opencores_yanu.c b/drivers/serial/opencores_yanu.c index f3830112a..49bccf3a6 100644 --- a/drivers/serial/opencores_yanu.c +++ b/drivers/serial/opencores_yanu.c @@ -37,7 +37,7 @@ static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE;  /* Everything's already setup for fixed-baud PTF assignment*/ -void serial_setbrg (void) +static void oc_serial_setbrg(void)  {  	int n, k;  	const unsigned max_uns = 0xFFFFFFFF; @@ -68,7 +68,7 @@ void serial_setbrg (void)  #else -void serial_setbrg (void) +static void oc_serial_setbrg(void)  {  	int n, k;  	const unsigned max_uns = 0xFFFFFFFF; @@ -100,7 +100,7 @@ void serial_setbrg (void)  #endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ -int serial_init (void) +static int oc_serial_init(void)  {  	unsigned action,control; @@ -141,7 +141,7 @@ int serial_init (void)  /*-----------------------------------------------------------------------   * YANU CONSOLE   *---------------------------------------------------------------------*/ -void serial_putc (char c) +static void oc_serial_putc(char c)  {  	int tx_chars;  	unsigned status; @@ -161,7 +161,7 @@ void serial_putc (char c)  	writel((unsigned char)c, &uart->data);  } -void serial_puts (const char *s) +static void oc_serial_puts(const char *s)  {  	while (*s != 0) {  		serial_putc (*s++); @@ -169,7 +169,7 @@ void serial_puts (const char *s)  } -int serial_tstc(void) +static int oc_serial_tstc(void)  {  	unsigned status ; @@ -178,7 +178,7 @@ int serial_tstc(void)  		 ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0);  } -int serial_getc (void) +statoc int oc_serial_getc(void)  {  	while (serial_tstc() == 0)  		WATCHDOG_RESET (); @@ -188,3 +188,24 @@ int serial_getc (void)  	return(readl(&uart->data) & YANU_DATA_CHAR_MASK);  } + +static struct serial_device oc_serial_drv = { +	.name	= "oc_serial", +	.start	= oc_serial_init, +	.stop	= NULL, +	.setbrg	= oc_serial_setbrg, +	.putc	= oc_serial_putc, +	.puts	= oc_serial_puts, +	.getc	= oc_serial_getc, +	.tstc	= oc_serial_tstc, +}; + +void oc_serial_initialize(void) +{ +	serial_register(&oc_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &oc_serial_drv; +} diff --git a/drivers/serial/s3c4510b_uart.c b/drivers/serial/s3c4510b_uart.c index aa378e1ac..423d26e67 100644 --- a/drivers/serial/s3c4510b_uart.c +++ b/drivers/serial/s3c4510b_uart.c @@ -80,7 +80,7 @@ static int serial_flush_output(void)  } -void serial_setbrg (void) +static void s3c4510b_serial_setbrg(void)  {  	UART_LINE_CTRL ulctrl;  	UART_CTRL      uctrl; @@ -135,7 +135,7 @@ void serial_setbrg (void)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int s3c4510b_serial_init(void)  {  #if   CONFIG_SERIAL1 == 1 @@ -155,7 +155,7 @@ int serial_init (void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void s3c4510_serial_putc(const char c)  {  	/* wait for room in the transmit FIFO */  	while( !uart->m_stat.bf.txBufEmpty); @@ -174,7 +174,7 @@ void serial_putc (const char c)   * Test if an input byte is ready from the serial port. Returns non-zero on   * success, 0 otherwise.   */ -int serial_tstc (void) +static int s3c4510b_serial_tstc(void)  {  	return uart->m_stat.bf.rxReady;  } @@ -184,7 +184,7 @@ int serial_tstc (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int s3c4510b_serial_getc(void)  {  	int rv; @@ -197,7 +197,7 @@ int serial_getc (void)  	}  } -void serial_puts (const char *s) +static void s3c4510b_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++); @@ -210,3 +210,24 @@ void serial_puts (const char *s)  	uart->m_ctrl.bf.sendBreak = 0;  } + +static struct serial_device s3c4510b_serial_drv = { +	.name	= "s3c4510b_serial", +	.start	= s3c4510b_serial_init, +	.stop	= NULL, +	.setbrg	= s3c4510b_serial_setbrg, +	.putc	= s3c4510b_serial_putc, +	.puts	= s3c4510b_serial_puts, +	.getc	= s3c4510b_serial_getc, +	.tstc	= s3c4510b_serial_tstc, +}; + +void s3c4510b_serial_initialize(void) +{ +	serial_register(&s3c4510b_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &s3c4510b_serial_drv; +} diff --git a/drivers/serial/s3c64xx.c b/drivers/serial/s3c64xx.c index a88e93094..9ab8a28d8 100644 --- a/drivers/serial/s3c64xx.c +++ b/drivers/serial/s3c64xx.c @@ -68,7 +68,7 @@ static const int udivslot[] = {  	0xffdf,  }; -void serial_setbrg(void) +static void s3c64xx_serial_setbrg(void)  {  	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);  	u32 pclk = get_PCLK(); @@ -88,7 +88,7 @@ void serial_setbrg(void)   * 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) +static int s3c64xx_serial_init(void)  {  	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); @@ -110,7 +110,7 @@ int serial_init(void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc(void) +static int s3c64xx_serial_getc(void)  {  	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); @@ -137,7 +137,7 @@ void enable_putc(void)  /*   * Output a single byte to the serial port.   */ -void serial_putc(const char c) +static void s3c64xx_serial_putc(const char c)  {  	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); @@ -159,15 +159,36 @@ void serial_putc(const char c)  /*   * Test whether a character is in the RX buffer   */ -int serial_tstc(void) +static int s3c64xx_serial_tstc(void)  {  	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);  	return uart->UTRSTAT & 0x1;  } -void serial_puts(const char *s) +static void s3c64xx_serial_puts(const char *s)  {  	while (*s)  		serial_putc(*s++);  } + +static struct serial_device s3c64xx_serial_drv = { +	.name	= "s3c64xx_serial", +	.start	= s3c64xx_serial_init, +	.stop	= NULL, +	.setbrg	= s3c64xx_serial_setbrg, +	.putc	= s3c64xx_serial_putc, +	.puts	= s3c64xx_serial_puts, +	.getc	= s3c64xx_serial_getc, +	.tstc	= s3c64xx_serial_tstc, +}; + +void s3c64xx_serial_initialize(void) +{ +	serial_register(&s3c64xx_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &s3c64xx_serial_drv; +} diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index 1927c167b..cb19401df 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -27,28 +27,30 @@  #include <common.h>  #include <os.h> +#include <serial.h> +#include <linux/compiler.h> -int serial_init(void) +static int sandbox_serial_init(void)  {  	os_tty_raw(0);  	return 0;  } -void serial_setbrg(void) +static void sandbox_serial_setbrg(void)  {  } -void serial_putc(const char ch) +static void sandbox_serial_putc(const char ch)  {  	os_write(1, &ch, 1);  } -void serial_puts(const char *str) +static void sandbox_serial_puts(const char *str)  {  	os_write(1, str, strlen(str));  } -int serial_getc(void) +static int sandbox_serial_getc(void)  {  	char buf;  	ssize_t count; @@ -57,7 +59,28 @@ int serial_getc(void)  	return count == 1 ? buf : 0;  } -int serial_tstc(void) +static int sandbox_serial_tstc(void)  {  	return 0;  } + +static struct serial_device sandbox_serial_drv = { +	.name	= "sandbox_serial", +	.start	= sandbox_serial_init, +	.stop	= NULL, +	.setbrg	= sandbox_serial_setbrg, +	.putc	= sandbox_serial_putc, +	.puts	= sandbox_serial_puts, +	.getc	= sandbox_serial_getc, +	.tstc	= sandbox_serial_tstc, +}; + +void sandbox_serial_initialize(void) +{ +	serial_register(&sandbox_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &sandbox_serial_drv; +} diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index b10bab70d..5bbf3aeb4 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -1,6 +1,6 @@  /* - * (C) Copyright 2000 - * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * (C) Copyright 2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   *   * See file CREDITS for list of people who contributed to this   * project. @@ -22,321 +22,341 @@   */  #include <common.h> -#include <linux/compiler.h> - -#include <ns16550.h> -#ifdef CONFIG_NS87308 -#include <ns87308.h> -#endif - -#if defined (CONFIG_SERIAL_MULTI)  #include <serial.h> -#endif +#include <stdio_dev.h> +#include <post.h> +#include <linux/compiler.h>  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(CONFIG_SYS_NS16550_COM1) -#error	"Console port 1 defined but not configured." -#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2) -#error	"Console port 2 defined but not configured." -#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3) -#error	"Console port 3 defined but not configured." -#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_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 CONFIG_SYS_NS16550_COM1 -	(NS16550_t)CONFIG_SYS_NS16550_COM1, -#else -	NULL, -#endif -#ifdef CONFIG_SYS_NS16550_COM2 -	(NS16550_t)CONFIG_SYS_NS16550_COM2, -#else -	NULL, -#endif -#ifdef CONFIG_SYS_NS16550_COM3 -	(NS16550_t)CONFIG_SYS_NS16550_COM3, -#else -	NULL, -#endif -#ifdef CONFIG_SYS_NS16550_COM4 -	(NS16550_t)CONFIG_SYS_NS16550_COM4 -#else -	NULL -#endif -}; - -#define PORT	serial_ports[port-1] - -#if defined(CONFIG_SERIAL_MULTI) +static struct serial_device *serial_devices; +static struct serial_device *serial_current; -/* 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);} +static void serial_null(void) +{ +} -/* Serial device descriptor */ -#define INIT_ESERIAL_STRUCTURE(port, name) {\ -	name,\ -	eserial##port##_init,\ -	NULL,\ -	eserial##port##_setbrg,\ -	eserial##port##_getc,\ -	eserial##port##_tstc,\ -	eserial##port##_putc,\ -	eserial##port##_puts, } +#define serial_initfunc(name)					\ +	void name(void)						\ +		__attribute__((weak, alias("serial_null"))); -#endif /* CONFIG_SERIAL_MULTI */ +serial_initfunc(mpc8xx_serial_initialize); +serial_initfunc(ns16550_serial_initialize); +serial_initfunc(pxa_serial_initialize); +serial_initfunc(s3c24xx_serial_initialize); +serial_initfunc(s5p_serial_initialize); +serial_initfunc(zynq_serial_initalize); +serial_initfunc(bfin_serial_initialize); +serial_initfunc(bfin_jtag_initialize); +serial_initfunc(mpc512x_serial_initialize); +serial_initfunc(uartlite_serial_initialize); +serial_initfunc(au1x00_serial_initialize); +serial_initfunc(asc_serial_initialize); +serial_initfunc(jz_serial_initialize); +serial_initfunc(mpc5xx_serial_initialize); +serial_initfunc(mpc8220_serial_initialize); +serial_initfunc(mpc8260_scc_serial_initialize); +serial_initfunc(mpc8260_smc_serial_initialize); +serial_initfunc(mpc85xx_serial_initialize); +serial_initfunc(iop480_serial_initialize); +serial_initfunc(leon2_serial_initialize); +serial_initfunc(leon3_serial_initialize); +serial_initfunc(marvell_serial_initialize); +serial_initfunc(amirix_serial_initialize); +serial_initfunc(bmw_serial_initialize); +serial_initfunc(cogent_serial_initialize); +serial_initfunc(cpci750_serial_initialize); +serial_initfunc(evb64260_serial_initialize); +serial_initfunc(ml2_serial_initialize); +serial_initfunc(sconsole_serial_initialize); +serial_initfunc(p3mx_serial_initialize); +serial_initfunc(altera_jtag_serial_initialize); +serial_initfunc(altera_serial_initialize); +serial_initfunc(atmel_serial_initialize); +serial_initfunc(lpc32xx_serial_initialize); +serial_initfunc(mcf_serial_initialize); +serial_initfunc(ns9750_serial_initialize); +serial_initfunc(oc_serial_initialize); +serial_initfunc(s3c4510b_serial_initialize); +serial_initfunc(s3c64xx_serial_initialize); +serial_initfunc(sandbox_serial_initialize); +serial_initfunc(clps7111_serial_initialize); +serial_initfunc(imx_serial_initialize); +serial_initfunc(ixp_serial_initialize); +serial_initfunc(ks8695_serial_initialize); +serial_initfunc(lh7a40x_serial_initialize); +serial_initfunc(lpc2292_serial_initialize); +serial_initfunc(max3100_serial_initialize); +serial_initfunc(mxc_serial_initialize); +serial_initfunc(netarm_serial_initialize); +serial_initfunc(pl01x_serial_initialize); +serial_initfunc(s3c44b0_serial_initialize); +serial_initfunc(sa1100_serial_initialize); +serial_initfunc(sh_serial_initialize); -static int calc_divisor (NS16550_t port) +void serial_register(struct serial_device *dev)  { -#ifdef CONFIG_OMAP1510 -	/* If can't cleanly clock 115200 set div to 1 */ -	if ((CONFIG_SYS_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 ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) { -		return (26);		/* return 26 for base divisor */ -	} +#ifdef CONFIG_NEEDS_MANUAL_RELOC +	if (dev->start) +		dev->start += gd->reloc_off; +	if (dev->stop) +		dev->stop += gd->reloc_off; +	if (dev->setbrg) +		dev->setbrg += gd->reloc_off; +	if (dev->getc) +		dev->getc += gd->reloc_off; +	if (dev->tstc) +		dev->tstc += gd->reloc_off; +	if (dev->putc) +		dev->putc += gd->reloc_off; +	if (dev->puts) +		dev->puts += gd->reloc_off;  #endif -#ifdef CONFIG_APTIX -#define MODE_X_DIV 13 -#else -#define MODE_X_DIV 16 -#endif +	dev->next = serial_devices; +	serial_devices = dev; +} + +void serial_initialize(void) +{ +	mpc8xx_serial_initialize(); +	ns16550_serial_initialize(); +	pxa_serial_initialize(); +	s3c24xx_serial_initialize(); +	s5p_serial_initialize(); +	mpc512x_serial_initialize(); +	bfin_serial_initialize(); +	bfin_jtag_initialize(); +	uartlite_serial_initialize(); +	zynq_serial_initalize(); +	au1x00_serial_initialize(); +	asc_serial_initialize(); +	jz_serial_initialize(); +	mpc5xx_serial_initialize(); +	mpc8220_serial_initialize(); +	mpc8260_scc_serial_initialize(); +	mpc8260_smc_serial_initialize(); +	mpc85xx_serial_initialize(); +	iop480_serial_initialize(); +	leon2_serial_initialize(); +	leon3_serial_initialize(); +	marvell_serial_initialize(); +	amirix_serial_initialize(); +	bmw_serial_initialize(); +	cogent_serial_initialize(); +	cpci750_serial_initialize(); +	evb64260_serial_initialize(); +	ml2_serial_initialize(); +	sconsole_serial_initialize(); +	p3mx_serial_initialize(); +	altera_jtag_serial_initialize(); +	altera_serial_initialize(); +	atmel_serial_initialize(); +	lpc32xx_serial_initialize(); +	mcf_serial_initialize(); +	ns9750_serial_initialize(); +	oc_serial_initialize(); +	s3c4510b_serial_initialize(); +	s3c64xx_serial_initialize(); +	sandbox_serial_initialize(); +	clps7111_serial_initialize(); +	imx_serial_initialize(); +	ixp_serial_initialize(); +	ks8695_serial_initialize(); +	lh7a40x_serial_initialize(); +	lpc2292_serial_initialize(); +	max3100_serial_initialize(); +	mxc_serial_initialize(); +	netarm_serial_initialize(); +	pl01x_serial_initialize(); +	s3c44b0_serial_initialize(); +	sa1100_serial_initialize(); +	sh_serial_initialize(); -	/* Compute divisor value. Normally, we should simply return: -	 *   CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate -	 * but we need to round that value by adding 0.5. -	 * Rounding is especially important at high baud rates. -	 */ -	return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) / -		(MODE_X_DIV * gd->baudrate); +	serial_assign(default_serial_console()->name);  } -#if !defined(CONFIG_SERIAL_MULTI) -int serial_init (void) +void serial_stdio_init(void)  { -	int clock_divisor; +	struct stdio_dev dev; +	struct serial_device *s = serial_devices; -#ifdef CONFIG_NS87308 -	initialise_ns87308(); -#endif +	while (s) { +		memset(&dev, 0, sizeof(dev)); -#ifdef CONFIG_SYS_NS16550_COM1 -	clock_divisor = calc_divisor(serial_ports[0]); -	NS16550_init(serial_ports[0], clock_divisor); -#endif -#ifdef CONFIG_SYS_NS16550_COM2 -	clock_divisor = calc_divisor(serial_ports[1]); -	NS16550_init(serial_ports[1], clock_divisor); -#endif -#ifdef CONFIG_SYS_NS16550_COM3 -	clock_divisor = calc_divisor(serial_ports[2]); -	NS16550_init(serial_ports[2], clock_divisor); -#endif -#ifdef CONFIG_SYS_NS16550_COM4 -	clock_divisor = calc_divisor(serial_ports[3]); -	NS16550_init(serial_ports[3], clock_divisor); -#endif +		strcpy(dev.name, s->name); +		dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; -	return (0); -} -#endif +		dev.start = s->start; +		dev.stop = s->stop; +		dev.putc = s->putc; +		dev.puts = s->puts; +		dev.getc = s->getc; +		dev.tstc = s->tstc; -void -_serial_putc(const char c,const int port) -{ -	if (c == '\n') -		NS16550_putc(PORT, '\r'); +		stdio_register(&dev); -	NS16550_putc(PORT, c); +		s = s->next; +	}  } -void -_serial_putc_raw(const char c,const int port) +int serial_assign(const char *name)  { -	NS16550_putc(PORT, c); -} +	struct serial_device *s; -void -_serial_puts (const char *s,const int port) -{ -	while (*s) { -		_serial_putc (*s++,port); +	for (s = serial_devices; s; s = s->next) { +		if (strcmp(s->name, name) == 0) { +			serial_current = s; +			return 0; +		}  	} -} - -int -_serial_getc(const int port) -{ -	return NS16550_getc(PORT); +	return 1;  } -int -_serial_tstc(const int port) +void serial_reinit_all(void)  { -	return NS16550_tstc(PORT); +	struct serial_device *s; + +	for (s = serial_devices; s; s = s->next) +		s->start();  } -void -_serial_setbrg (const int port) +static struct serial_device *get_current(void)  { -	int clock_divisor; +	struct serial_device *dev; -	clock_divisor = calc_divisor(PORT); -	NS16550_reinit(PORT, clock_divisor); -} +	if (!(gd->flags & GD_FLG_RELOC) || !serial_current) { +		dev = default_serial_console(); -#if defined(CONFIG_SERIAL_MULTI) -static inline void -serial_putc_dev(unsigned int dev_index,const char c) -{ -	_serial_putc(c,dev_index); -} +		/* We must have a console device */ +		if (!dev) { +#ifdef CONFIG_SPL_BUILD +			puts("Cannot find console\n"); +			hang();  #else -void -serial_putc(const char c) -{ -	_serial_putc(c,CONFIG_CONS_INDEX); -} +			panic("Cannot find console\n");  #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); +		} +	} else +		dev = serial_current; +	return dev;  } -#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) +int serial_init(void)  { -	_serial_puts(s,CONFIG_CONS_INDEX); +	return get_current()->start();  } -#endif -#if defined(CONFIG_SERIAL_MULTI) -static inline int -serial_getc_dev(unsigned int dev_index) +void serial_setbrg(void)  { -	return _serial_getc(dev_index); +	get_current()->setbrg();  } -#else -int -serial_getc(void) + +int serial_getc(void)  { -	return _serial_getc(CONFIG_CONS_INDEX); +	return get_current()->getc();  } -#endif -#if defined(CONFIG_SERIAL_MULTI) -static inline int -serial_tstc_dev(unsigned int dev_index) +int serial_tstc(void)  { -	return _serial_tstc(dev_index); +	return get_current()->tstc();  } -#else -int -serial_tstc(void) + +void serial_putc(const char c)  { -	return _serial_tstc(CONFIG_CONS_INDEX); +	get_current()->putc(c);  } -#endif -#if defined(CONFIG_SERIAL_MULTI) -static inline void -serial_setbrg_dev(unsigned int dev_index) +void serial_puts(const char *s)  { -	_serial_setbrg(dev_index); +	get_current()->puts(s);  } -#else -void -serial_setbrg(void) + +#if CONFIG_POST & CONFIG_SYS_POST_UART +static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE; + +/* Mark weak until post/cpu/.../uart.c migrate over */ +__weak +int uart_post_test(int flags)  { -	_serial_setbrg(CONFIG_CONS_INDEX); -} -#endif +	unsigned char c; +	int ret, saved_baud, b; +	struct serial_device *saved_dev, *s; +	bd_t *bd = gd->bd; -#if defined(CONFIG_SERIAL_MULTI) +	/* Save current serial state */ +	ret = 0; +	saved_dev = serial_current; +	saved_baud = bd->bi_baudrate; -DECLARE_ESERIAL_FUNCTIONS(1); -struct serial_device eserial1_device = -	INIT_ESERIAL_STRUCTURE(1, "eserial0"); -DECLARE_ESERIAL_FUNCTIONS(2); -struct serial_device eserial2_device = -	INIT_ESERIAL_STRUCTURE(2, "eserial1"); -DECLARE_ESERIAL_FUNCTIONS(3); -struct serial_device eserial3_device = -	INIT_ESERIAL_STRUCTURE(3, "eserial2"); -DECLARE_ESERIAL_FUNCTIONS(4); -struct serial_device eserial4_device = -	INIT_ESERIAL_STRUCTURE(4, "eserial3"); +	for (s = serial_devices; s; s = s->next) { +		/* If this driver doesn't support loop back, skip it */ +		if (!s->loop) +			continue; -__weak struct serial_device *default_serial_console(void) -{ -#if CONFIG_CONS_INDEX == 1 -	return &eserial1_device; -#elif CONFIG_CONS_INDEX == 2 -	return &eserial2_device; -#elif CONFIG_CONS_INDEX == 3 -	return &eserial3_device; -#elif CONFIG_CONS_INDEX == 4 -	return &eserial4_device; -#else -#error "Bad CONFIG_CONS_INDEX." -#endif -} +		/* Test the next device */ +		serial_current = s; + +		ret = serial_init(); +		if (ret) +			goto done; + +		/* Consume anything that happens to be queued */ +		while (serial_tstc()) +			serial_getc(); -#endif /* CONFIG_SERIAL_MULTI */ +		/* Enable loop back */ +		s->loop(1); + +		/* Test every available baud rate */ +		for (b = 0; b < ARRAY_SIZE(bauds); ++b) { +			bd->bi_baudrate = bauds[b]; +			serial_setbrg(); + +			/* +			 * Stick to printable chars to avoid issues: +			 *  - terminal corruption +			 *  - serial program reacting to sequences and sending +			 *    back random extra data +			 *  - most serial drivers add in extra chars (like \r\n) +			 */ +			for (c = 0x20; c < 0x7f; ++c) { +				/* Send it out */ +				serial_putc(c); + +				/* Make sure it's the same one */ +				ret = (c != serial_getc()); +				if (ret) { +					s->loop(0); +					goto done; +				} + +				/* Clean up the output in case it was sent */ +				serial_putc('\b'); +				ret = ('\b' != serial_getc()); +				if (ret) { +					s->loop(0); +					goto done; +				} +			} +		} + +		/* Disable loop back */ +		s->loop(0); + +		/* XXX: There is no serial_stop() !? */ +		if (s->stop) +			s->stop(); +	} + + done: +	/* Restore previous serial state */ +	serial_current = saved_dev; +	bd->bi_baudrate = saved_baud; +	serial_reinit_all(); +	serial_setbrg(); + +	return ret; +} +#endif diff --git a/drivers/serial/serial_clps7111.c b/drivers/serial/serial_clps7111.c index a6aecadd1..65473e860 100644 --- a/drivers/serial/serial_clps7111.c +++ b/drivers/serial/serial_clps7111.c @@ -33,7 +33,7 @@  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg (void) +static void clps7111_serial_setbrg(void)  {  	unsigned int reg = 0; @@ -63,7 +63,7 @@ void serial_setbrg (void)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int clps7111_serial_init(void)  {  	serial_setbrg (); @@ -74,7 +74,7 @@ int serial_init (void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void clps7111_serial_putc(const char c)  {  	int tmo; @@ -95,7 +95,7 @@ void serial_putc (const char c)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_tstc (void) +static int clps7111_serial_tstc(void)  {  	return !(IO_SYSFLG1 & SYSFLG1_URXFE);  } @@ -105,17 +105,37 @@ int serial_tstc (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int clps7111_serial_getc(void)  {  	while (IO_SYSFLG1 & SYSFLG1_URXFE);  	return IO_UARTDR1 & 0xff;  } -void -serial_puts (const char *s) +static void clps7111_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device clps7111_serial_drv = { +	.name	= "clps7111_serial", +	.start	= clps7111_serial_init, +	.stop	= NULL, +	.setbrg	= clps7111_serial_setbrg, +	.putc	= clps7111_serial_putc, +	.puts	= clps7111_serial_puts, +	.getc	= clps7111_serial_getc, +	.tstc	= clps7111_serial_tstc, +}; + +void clps7111_serial_initialize(void) +{ +	serial_register(&clps7111_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &clps7111_serial_drv; +} diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c index b9ca748f6..6c075b5b9 100644 --- a/drivers/serial/serial_imx.c +++ b/drivers/serial/serial_imx.c @@ -19,6 +19,8 @@  #include <common.h>  #include <asm/arch/imx-regs.h> +#include <serial.h> +#include <linux/compiler.h>  #if defined CONFIG_IMX_SERIAL1  #define UART_BASE IMX_UART1_BASE @@ -50,7 +52,7 @@ struct imx_serial {  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg (void) +static void imx_serial_setbrg(void)  {  	serial_init();  } @@ -62,7 +64,7 @@ extern void imx_gpio_mode(int gpio_mode);   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int imx_serial_init(void)  {  	volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;  	unsigned int ufcr_rfdiv; @@ -163,7 +165,7 @@ int serial_init (void)   * otherwise. When the function is successful, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int imx_serial_getc(void)  {  	volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;  	unsigned char ch; @@ -185,7 +187,7 @@ int hwflow_onoff(int on)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void imx_serial_putc(const char c)  {  	volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; @@ -202,7 +204,7 @@ void serial_putc (const char c)  /*   * Test whether a character is in the RX buffer   */ -int serial_tstc (void) +static int imx_serial_tstc(void)  {  	volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; @@ -212,10 +214,30 @@ int serial_tstc (void)  	return 1;  } -void -serial_puts (const char *s) +static void imx_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device imx_serial_drv = { +	.name	= "imx_serial", +	.start	= imx_serial_init, +	.stop	= NULL, +	.setbrg	= imx_serial_setbrg, +	.putc	= imx_serial_putc, +	.puts	= imx_serial_puts, +	.getc	= imx_serial_getc, +	.tstc	= imx_serial_tstc, +}; + +void imx_serial_initialize(void) +{ +	serial_register(&imx_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &imx_serial_drv; +} diff --git a/drivers/serial/serial_ixp.c b/drivers/serial/serial_ixp.c index a9acd476c..c8b3658d4 100644 --- a/drivers/serial/serial_ixp.c +++ b/drivers/serial/serial_ixp.c @@ -31,6 +31,8 @@  #include <common.h>  #include <asm/arch/ixp425.h>  #include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h>  /*   *               14.7456 MHz @@ -41,7 +43,7 @@  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg (void) +static void ixp_serial_setbrg(void)  {  	unsigned int quot = 0;  	int uart = CONFIG_SYS_IXP425_CONSOLE; @@ -72,7 +74,7 @@ void serial_setbrg (void)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int ixp_serial_init(void)  {  	serial_setbrg (); @@ -83,7 +85,7 @@ int serial_init (void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void ixp_serial_putc(const char c)  {  	/* wait for room in the tx FIFO on UART */  	while ((LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_TEMT) == 0) @@ -101,7 +103,7 @@ void serial_putc (const char c)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_tstc (void) +static int ixp_serial_tstc(void)  {  	return LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR;  } @@ -111,7 +113,7 @@ int serial_tstc (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int ixp_serial_getc(void)  {  	while (!(LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR))  		WATCHDOG_RESET();	/* Reset HW Watchdog, if needed */ @@ -119,10 +121,30 @@ int serial_getc (void)  	return (char) RBR(CONFIG_SYS_IXP425_CONSOLE) & 0xff;  } -void -serial_puts (const char *s) +static void ixp_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device ixp_serial_drv = { +	.name	= "ixp_serial", +	.start	= ixp_serial_init, +	.stop	= NULL, +	.setbrg	= ixp_serial_setbrg, +	.putc	= ixp_serial_putc, +	.puts	= ixp_serial_puts, +	.getc	= ixp_serial_getc, +	.tstc	= ixp_serial_tstc, +}; + +void ixp_serial_initialize(void) +{ +	serial_register(&ixp_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &ixp_serial_drv; +} diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c index aacd1be63..60e800720 100644 --- a/drivers/serial/serial_ks8695.c +++ b/drivers/serial/serial_ks8695.c @@ -20,6 +20,8 @@  #include <common.h>  #include <asm/arch/platform.h> +#include <serial.h> +#include <linux/compiler.h>  #ifndef CONFIG_SERIAL1  #error "Bad: you didn't configure serial ..." @@ -54,7 +56,7 @@ struct ks8695uart {  int serial_console = 1; -void serial_setbrg(void) +static void ks8695_serial_setbrg(void)  {  	volatile struct ks8695uart *uartp = KS8695_UART_ADDR; @@ -63,14 +65,14 @@ void serial_setbrg(void)  	uartp->LCR = KS8695_UART_LINEC_WLEN8;  } -int serial_init(void) +static int ks8695_serial_init(void)  {  	serial_console = 1;  	serial_setbrg();  	return 0;  } -void serial_raw_putc(const char c) +static void ks8695_serial_raw_putc(const char c)  {  	volatile struct ks8695uart *uartp = KS8695_UART_ADDR;  	int i; @@ -83,16 +85,16 @@ void serial_raw_putc(const char c)  	uartp->TX = c;  } -void serial_putc(const char c) +static void ks8695_serial_putc(const char c)  {  	if (serial_console) { -		serial_raw_putc(c); +		ks8695_serial_raw_putc(c);  		if (c == '\n') -			serial_raw_putc('\r'); +			ks8695_serial_raw_putc('\r');  	}  } -int serial_tstc(void) +static int ks8695_serial_tstc(void)  {  	volatile struct ks8695uart *uartp = KS8695_UART_ADDR;  	if (serial_console) @@ -100,14 +102,14 @@ int serial_tstc(void)  	return 0;  } -void serial_puts(const char *s) +static void ks8695_serial_puts(const char *s)  {  	char c;  	while ((c = *s++) != 0)  		serial_putc(c);  } -int serial_getc(void) +static int ks8695_serial_getc(void)  {  	volatile struct ks8695uart *uartp = KS8695_UART_ADDR; @@ -115,3 +117,24 @@ int serial_getc(void)  		;  	return (uartp->RX);  } + +static struct serial_device ks8695_serial_drv = { +	.name	= "ks8695_serial", +	.start	= ks8695_serial_init, +	.stop	= NULL, +	.setbrg	= ks8695_serial_setbrg, +	.putc	= ks8695_serial_putc, +	.puts	= ks8695_serial_puts, +	.getc	= ks8695_serial_getc, +	.tstc	= ks8695_serial_tstc, +}; + +void ks8695_serial_initialize(void) +{ +	serial_register(&ks8695_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &ks8695_serial_drv; +} diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 4767489ae..6c9628581 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -33,7 +33,7 @@ DECLARE_GLOBAL_DATA_PTR;  # error "No console configured ... "  #endif -void serial_setbrg (void) +static void lh7a40x_serial_setbrg(void)  {  	lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);  	int i; @@ -61,7 +61,7 @@ void serial_setbrg (void)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int lh7a40x_serial_init(void)  {  	lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); @@ -95,7 +95,7 @@ int serial_init (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int lh7a40x_serial_getc(void)  {  	lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); @@ -141,7 +141,7 @@ void enable_putc(void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void lh7a40x_serial_putc(const char c)  {  	lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); @@ -168,17 +168,37 @@ void serial_putc (const char c)  /*   * Test whether a character is in the RX buffer   */ -int serial_tstc (void) +static int lh7a40x_serial_tstc(void)  {  	lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);  	return(!(uart->status & UART_RXFE));  } -void -serial_puts (const char *s) +static void lh7a40x_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device lh7a40x_serial_drv = { +	.name	= "lh7a40x_serial", +	.start	= lh7a40x_serial_init, +	.stop	= NULL, +	.setbrg	= lh7a40x_serial_setbrg, +	.putc	= lh7a40x_serial_putc, +	.puts	= lh7a40x_serial_puts, +	.getc	= lh7a40x_serial_getc, +	.tstc	= lh7a40x_serial_tstc, +}; + +void lh7a40x_serial_initialize(void) +{ +	serial_register(&lh7a40x_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &lh7a40x_serial_drv; +} diff --git a/drivers/serial/serial_lpc2292.c b/drivers/serial/serial_lpc2292.c index e3a60b6cb..fcab20280 100644 --- a/drivers/serial/serial_lpc2292.c +++ b/drivers/serial/serial_lpc2292.c @@ -33,7 +33,7 @@  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg (void) +static void lpc2292_serial_setbrg(void)  {  	unsigned short divisor = 0; @@ -57,7 +57,7 @@ void serial_setbrg (void)  	PUT8(U0FCR, 1);		/* Enable RX and TX FIFOs */  } -int serial_init (void) +static int lpc2292_serial_init(void)  {  	unsigned long pinsel0; @@ -71,7 +71,7 @@ int serial_init (void)  	return (0);  } -void serial_putc (const char c) +static void lpc2292_serial_putc(const char c)  {  	if (c == '\n')  	{ @@ -83,14 +83,13 @@ void serial_putc (const char c)  	PUT8(U0THR, c);  } -int serial_getc (void) +static int lpc2292_serial_getc(void)  {  	while((GET8(U0LSR) & 1) == 0);  	return GET8(U0RBR);  } -void -serial_puts (const char *s) +static void lpc2292_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++); @@ -98,7 +97,28 @@ serial_puts (const char *s)  }  /* Test if there is a byte to read */ -int serial_tstc (void) +static int lpc2292_serial_tstc(void)  {  	return (GET8(U0LSR) & 1);  } + +static struct serial_device lpc2292_serial_drv = { +	.name	= "lpc2292_serial", +	.start	= lpc2292_serial_init, +	.stop	= NULL, +	.setbrg	= lpc2292_serial_setbrg, +	.putc	= lpc2292_serial_putc, +	.puts	= lpc2292_serial_puts, +	.getc	= lpc2292_serial_getc, +	.tstc	= lpc2292_serial_tstc, +}; + +void lpc2292_serial_initialize(void) +{ +	serial_register(&lpc2292_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &lpc2292_serial_drv; +} diff --git a/drivers/serial/serial_max3100.c b/drivers/serial/serial_max3100.c index 4abc27109..3533cfc6d 100644 --- a/drivers/serial/serial_max3100.c +++ b/drivers/serial/serial_max3100.c @@ -25,6 +25,8 @@  #include <common.h>  #include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h>  DECLARE_GLOBAL_DATA_PTR; @@ -149,7 +151,7 @@ static int rxfifo_in;  static int rxfifo_out;  static unsigned char rxfifo_buf[16]; -static void max3100_putc(int c) +static void max3100_serial_putc_raw(int c)  {  	unsigned int rx; @@ -164,7 +166,7 @@ static void max3100_putc(int c)  	}  } -static int max3100_getc(void) +static int max3100_serial_getc(void)  {  	int c;  	unsigned int rx; @@ -190,7 +192,7 @@ static int max3100_getc(void)  	return c;  } -static int max3100_tstc(void) +static int max3100_serial_tstc(void)  {  	unsigned int rx; @@ -213,7 +215,7 @@ static int max3100_tstc(void)  	return 1;  } -int serial_init(void) +static int max3100_serial_init(void)  {  	unsigned int wconf, rconf;  	int i; @@ -268,31 +270,41 @@ int serial_init(void)  	return (0);  } -void serial_putc(const char c) +static void max3100_serial_putc(const char c)  {  	if (c == '\n') -		max3100_putc('\r'); +		max3100_serial_putc_raw('\r'); -	max3100_putc(c); +	max3100_serial_putc_raw(c);  } -void serial_puts(const char *s) +static void max3100_serial_puts(const char *s)  {  	while (*s) -		serial_putc (*s++); +		max3100_serial_putc_raw(*s++);  } -int serial_getc(void) +static void max3100_serial_setbrg(void)  { -	return max3100_getc();  } -int serial_tstc(void) +static struct serial_device max3100_serial_drv = { +	.name	= "max3100_serial", +	.start	= max3100_serial_init, +	.stop	= NULL, +	.setbrg	= max3100_serial_setbrg, +	.putc	= max3100_serial_putc, +	.puts	= max3100_serial_puts, +	.getc	= max3100_serial_getc, +	.tstc	= max3100_serial_tstc, +}; + +void max3100_serial_initialize(void)  { -	return max3100_tstc(); +	serial_register(&max3100_serial_drv);  } -/* XXX WTF? */ -void serial_setbrg(void) +__weak struct serial_device *default_serial_console(void)  { +	return &max3100_serial_drv;  } diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index af00b9c0e..b0612f5ac 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -21,6 +21,8 @@  #include <watchdog.h>  #include <asm/arch/imx-regs.h>  #include <asm/arch/clock.h> +#include <serial.h> +#include <linux/compiler.h>  #define __REG(x)     (*((volatile u32 *)(x))) @@ -30,10 +32,6 @@  #define UART_PHYS	CONFIG_MXC_UART_BASE -#ifdef CONFIG_SERIAL_MULTI -#warning "MXC driver does not support MULTI serials." -#endif -  /* Register definitions */  #define URXD  0x0  /* Receiver Register */  #define UTXD  0x40 /* Transmitter Register */ @@ -145,7 +143,7 @@  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg (void) +static void mxc_serial_setbrg(void)  {  	u32 clk = imx_get_uartclk(); @@ -158,14 +156,14 @@ void serial_setbrg (void)  } -int serial_getc (void) +static int mxc_serial_getc(void)  {  	while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY)  		WATCHDOG_RESET();  	return (__REG(UART_PHYS + URXD) & URXD_RX_DATA); /* mask out status from upper word */  } -void serial_putc (const char c) +static void mxc_serial_putc(const char c)  {  	__REG(UART_PHYS + UTXD) = c; @@ -181,7 +179,7 @@ void serial_putc (const char c)  /*   * Test whether a character is in the RX buffer   */ -int serial_tstc (void) +static int mxc_serial_tstc(void)  {  	/* If receive fifo is empty, return false */  	if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) @@ -189,8 +187,7 @@ int serial_tstc (void)  	return 1;  } -void -serial_puts (const char *s) +static void mxc_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++); @@ -202,7 +199,7 @@ serial_puts (const char *s)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int mxc_serial_init(void)  {  	__REG(UART_PHYS + UCR1) = 0x0;  	__REG(UART_PHYS + UCR2) = 0x0; @@ -224,3 +221,24 @@ int serial_init (void)  	return 0;  } + +static struct serial_device mxc_serial_drv = { +	.name	= "mxc_serial", +	.start	= mxc_serial_init, +	.stop	= NULL, +	.setbrg	= mxc_serial_setbrg, +	.putc	= mxc_serial_putc, +	.puts	= mxc_serial_puts, +	.getc	= mxc_serial_getc, +	.tstc	= mxc_serial_tstc, +}; + +void mxc_serial_initialize(void) +{ +	serial_register(&mxc_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &mxc_serial_drv; +} diff --git a/drivers/serial/serial_netarm.c b/drivers/serial/serial_netarm.c index d04790d27..d30adc318 100644 --- a/drivers/serial/serial_netarm.c +++ b/drivers/serial/serial_netarm.c @@ -59,7 +59,7 @@ extern void _netarm_led_FAIL1(void);  /*   * Setup both serial i/f with given baudrate   */ -void serial_setbrg (void) +static void netarm_serial_setbrg(void)  {  	/* set 0 ... make sure pins are configured for serial */  #if !defined(CONFIG_NETARM_NS7520) @@ -108,7 +108,7 @@ void serial_setbrg (void)   * 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) +static int netarm_serial_init(void)  {  	serial_setbrg ();  	return 0; @@ -118,7 +118,7 @@ int serial_init (void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void netarm_serial_putc(const char c)  {  	volatile unsigned char *fifo; @@ -135,7 +135,7 @@ void serial_putc (const char c)   * Test of a single byte from the serial port. Returns 1 on success, 0   * otherwise.   */ -int serial_tstc(void) +static int netarm_serial_tstc(void)  {  	return serial_reg_ch1->status_a & NETARM_SER_STATA_RX_RDY;  } @@ -144,7 +144,7 @@ int serial_tstc(void)   * Read a single byte from the serial port. Returns 1 on success, 0   * otherwise.   */ -int serial_getc (void) +static int netarm_serial_getc(void)  {  	unsigned int ch_uint;  	volatile unsigned int *fifo; @@ -182,9 +182,30 @@ int serial_getc (void)  	return ch_uint & 0xff;  } -void serial_puts (const char *s) +static void netarm_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device netarm_serial_drv = { +	.name	= "netarm_serial", +	.start	= netarm_serial_init, +	.stop	= NULL, +	.setbrg	= netarm_serial_setbrg, +	.putc	= netarm_serial_putc, +	.puts	= netarm_serial_puts, +	.getc	= netarm_serial_getc, +	.tstc	= netarm_serial_tstc, +}; + +void netarm_serial_initialize(void) +{ +	serial_register(&netarm_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &netarm_serial_drv; +} diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c new file mode 100644 index 000000000..b5d12481c --- /dev/null +++ b/drivers/serial/serial_ns16550.c @@ -0,0 +1,264 @@ +/* + * (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> +#include <linux/compiler.h> + +#include <ns16550.h> +#ifdef CONFIG_NS87308 +#include <ns87308.h> +#endif + +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_CONS_INDEX) +#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4) +#error	"Invalid console index value." +#endif + +#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1) +#error	"Console port 1 defined but not configured." +#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2) +#error	"Console port 2 defined but not configured." +#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3) +#error	"Console port 3 defined but not configured." +#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_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 CONFIG_SYS_NS16550_COM1 +	(NS16550_t)CONFIG_SYS_NS16550_COM1, +#else +	NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM2 +	(NS16550_t)CONFIG_SYS_NS16550_COM2, +#else +	NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM3 +	(NS16550_t)CONFIG_SYS_NS16550_COM3, +#else +	NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM4 +	(NS16550_t)CONFIG_SYS_NS16550_COM4 +#else +	NULL +#endif +}; + +#define PORT	serial_ports[port-1] + +/* 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) {	\ +	.name	= __name,			\ +	.start	= eserial##port##_init,		\ +	.stop	= NULL,				\ +	.setbrg	= eserial##port##_setbrg,	\ +	.getc	= eserial##port##_getc,		\ +	.tstc	= eserial##port##_tstc,		\ +	.putc	= eserial##port##_putc,		\ +	.puts	= eserial##port##_puts,		\ +} + +static int calc_divisor (NS16550_t port) +{ +#ifdef CONFIG_OMAP1510 +	/* If can't cleanly clock 115200 set div to 1 */ +	if ((CONFIG_SYS_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 ((CONFIG_SYS_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 + +	/* Compute divisor value. Normally, we should simply return: +	 *   CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate +	 * but we need to round that value by adding 0.5. +	 * Rounding is especially important at high baud rates. +	 */ +	return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) / +		(MODE_X_DIV * gd->baudrate); +} + +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); +} + +static inline void +serial_putc_dev(unsigned int dev_index,const char c) +{ +	_serial_putc(c,dev_index); +} + +static inline void +serial_putc_raw_dev(unsigned int dev_index,const char c) +{ +	_serial_putc_raw(c,dev_index); +} + +static inline void +serial_puts_dev(unsigned int dev_index,const char *s) +{ +	_serial_puts(s,dev_index); +} + +static inline int +serial_getc_dev(unsigned int dev_index) +{ +	return _serial_getc(dev_index); +} + +static inline int +serial_tstc_dev(unsigned int dev_index) +{ +	return _serial_tstc(dev_index); +} + +static inline void +serial_setbrg_dev(unsigned int dev_index) +{ +	_serial_setbrg(dev_index); +} + +DECLARE_ESERIAL_FUNCTIONS(1); +struct serial_device eserial1_device = +	INIT_ESERIAL_STRUCTURE(1, "eserial0"); +DECLARE_ESERIAL_FUNCTIONS(2); +struct serial_device eserial2_device = +	INIT_ESERIAL_STRUCTURE(2, "eserial1"); +DECLARE_ESERIAL_FUNCTIONS(3); +struct serial_device eserial3_device = +	INIT_ESERIAL_STRUCTURE(3, "eserial2"); +DECLARE_ESERIAL_FUNCTIONS(4); +struct serial_device eserial4_device = +	INIT_ESERIAL_STRUCTURE(4, "eserial3"); + +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_CONS_INDEX == 1 +	return &eserial1_device; +#elif CONFIG_CONS_INDEX == 2 +	return &eserial2_device; +#elif CONFIG_CONS_INDEX == 3 +	return &eserial3_device; +#elif CONFIG_CONS_INDEX == 4 +	return &eserial4_device; +#else +#error "Bad CONFIG_CONS_INDEX." +#endif +} + +void ns16550_serial_initialize(void) +{ +#if defined(CONFIG_SYS_NS16550_COM1) +	serial_register(&eserial1_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM2) +	serial_register(&eserial2_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM3) +	serial_register(&eserial3_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM4) +	serial_register(&eserial4_device); +#endif +} diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index d4c513709..7db7b65c3 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -30,6 +30,8 @@  #include <common.h>  #include <watchdog.h>  #include <asm/io.h> +#include <serial.h> +#include <linux/compiler.h>  #include "serial_pl01x.h"  /* @@ -54,7 +56,7 @@ static struct pl01x_regs *pl01x_get_regs(int portnum)  #ifdef CONFIG_PL010_SERIAL -int serial_init (void) +static int pl01x_serial_init(void)  {  	struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);  	unsigned int divisor; @@ -104,7 +106,7 @@ int serial_init (void)  #ifdef CONFIG_PL011_SERIAL -int serial_init (void) +static int pl01x_serial_init(void)  {  	struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);  	unsigned int temp; @@ -169,7 +171,7 @@ int serial_init (void)  #endif /* CONFIG_PL011_SERIAL */ -void serial_putc (const char c) +static void pl01x_serial_putc(const char c)  {  	if (c == '\n')  		pl01x_putc (CONSOLE_PORT, '\r'); @@ -177,24 +179,24 @@ void serial_putc (const char c)  	pl01x_putc (CONSOLE_PORT, c);  } -void serial_puts (const char *s) +static void pl01x_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } -int serial_getc (void) +static int pl01x_serial_getc(void)  {  	return pl01x_getc (CONSOLE_PORT);  } -int serial_tstc (void) +static int pl01x_serial_tstc(void)  {  	return pl01x_tstc (CONSOLE_PORT);  } -void serial_setbrg (void) +static void pl01x_serial_setbrg(void)  {  	struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); @@ -250,3 +252,24 @@ static int pl01x_tstc (int portnum)  	WATCHDOG_RESET();  	return !(readl(®s->fr) & UART_PL01x_FR_RXFE);  } + +static struct serial_device pl01x_serial_drv = { +	.name	= "pl01x_serial", +	.start	= pl01x_serial_init, +	.stop	= NULL, +	.setbrg	= pl01x_serial_setbrg, +	.putc	= pl01x_serial_putc, +	.puts	= pl01x_serial_puts, +	.getc	= pl01x_serial_getc, +	.tstc	= pl01x_serial_tstc, +}; + +void pl01x_serial_initialize(void) +{ +	serial_register(&pl01x_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &pl01x_serial_drv; +} diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c index a9976d709..ad391004b 100644 --- a/drivers/serial/serial_pxa.c +++ b/drivers/serial/serial_pxa.c @@ -36,6 +36,7 @@  #include <asm/arch/pxa-regs.h>  #include <asm/arch/regs-uart.h>  #include <asm/io.h> +#include <linux/compiler.h>  DECLARE_GLOBAL_DATA_PTR; @@ -72,21 +73,7 @@ DECLARE_GLOBAL_DATA_PTR;  #define	HWUART_INDEX	0xff  #endif -#ifndef CONFIG_SERIAL_MULTI -#if defined(CONFIG_FFUART) -#define UART_INDEX	FFUART_INDEX -#elif defined(CONFIG_BTUART) -#define UART_INDEX	BTUART_INDEX -#elif defined(CONFIG_STUART) -#define UART_INDEX	STUART_INDEX -#elif defined(CONFIG_HWUART) -#define UART_INDEX	HWUART_INDEX -#else -#error "Please select CONFIG_(FF|BT|ST|HW)UART in board config file." -#endif -#endif - -uint32_t pxa_uart_get_baud_divider(void) +static uint32_t pxa_uart_get_baud_divider(void)  {  	if (gd->baudrate == 1200)  		return 768; @@ -104,7 +91,7 @@ uint32_t pxa_uart_get_baud_divider(void)  		return 0;  } -struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index) +static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)  {  	switch (uart_index) {  	case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE; @@ -116,7 +103,7 @@ struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)  	}  } -void pxa_uart_toggle_clock(uint32_t uart_index, int enable) +static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)  {  	uint32_t clk_reg, clk_offset, reg; @@ -269,14 +256,14 @@ void pxa_puts_dev(unsigned int uart_index, const char *s)  #define	pxa_uart_desc(uart)						\  	struct serial_device serial_##uart##_device =			\  	{								\ -		"serial_"#uart,						\ -		uart##_init,						\ -		NULL,							\ -		uart##_setbrg,						\ -		uart##_getc,						\ -		uart##_tstc,						\ -		uart##_putc,						\ -		uart##_puts,						\ +		.name	= "serial_"#uart,				\ +		.start	= uart##_init,					\ +		.stop	= NULL,						\ +		.setbrg	= uart##_setbrg,				\ +		.getc	= uart##_getc,					\ +		.tstc	= uart##_tstc,					\ +		.putc	= uart##_putc,					\ +		.puts	= uart##_puts,					\  	};  #define	pxa_uart_multi(uart, UART)					\ @@ -296,6 +283,30 @@ void pxa_puts_dev(unsigned int uart_index, const char *s)  	pxa_uart_multi(btuart, BTUART)  #endif -#ifndef	CONFIG_SERIAL_MULTI -	pxa_uart(serial, UART) +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_CONS_INDEX == 1 +	return &serial_hwuart_device; +#elif CONFIG_CONS_INDEX == 2 +	return &serial_stuart_device; +#elif CONFIG_CONS_INDEX == 3 +	return &serial_ffuart_device; +#elif CONFIG_CONS_INDEX == 4 +	return &serial_btuart_device; +#else +#error "Bad CONFIG_CONS_INDEX."  #endif +} + +void pxa_serial_initialize(void) +{ +#if defined(CONFIG_FFUART) +	serial_register(&serial_ffuart_device); +#endif +#if defined(CONFIG_BTUART) +	serial_register(&serial_btuart_device); +#endif +#if defined(CONFIG_STUART) +	serial_register(&serial_stuart_device); +#endif +} diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c index 12bcdd3db..4d214c396 100644 --- a/drivers/serial/serial_s3c24x0.c +++ b/drivers/serial/serial_s3c24x0.c @@ -38,8 +38,6 @@ DECLARE_GLOBAL_DATA_PTR;  #endif  #include <asm/io.h> - -#if defined(CONFIG_SERIAL_MULTI)  #include <serial.h>  /* Multi serial device functions */ @@ -69,19 +67,17 @@ DECLARE_GLOBAL_DATA_PTR;  		serial_puts_dev(port, s); \  	} -#define INIT_S3C_SERIAL_STRUCTURE(port, name) { \ -	name, \ -	s3serial##port##_init, \ -	NULL,\ -	s3serial##port##_setbrg, \ -	s3serial##port##_getc, \ -	s3serial##port##_tstc, \ -	s3serial##port##_putc, \ -	s3serial##port##_puts, \ +#define INIT_S3C_SERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,				\ +	.start	= s3serial##port##_init,		\ +	.stop	= NULL,					\ +	.setbrg	= s3serial##port##_setbrg,		\ +	.getc	= s3serial##port##_getc,		\ +	.tstc	= s3serial##port##_tstc,		\ +	.putc	= s3serial##port##_putc,		\ +	.puts	= s3serial##port##_puts,		\  } -#endif /* CONFIG_SERIAL_MULTI */ -  #ifdef CONFIG_HWFLOW  static int hwflow;  #endif @@ -100,18 +96,10 @@ void _serial_setbrg(const int dev_index)  		/* Delay */ ;  } -#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(UART_NR); -} -#endif -  /* Initialise the serial port. The settings are always 8 data bits, no parity,   * 1 stop bit, no start bits. @@ -151,16 +139,6 @@ static int serial_init_dev(const int dev_index)  	return (0);  } -#if !defined(CONFIG_SERIAL_MULTI) -/* Initialise the serial port. The settings are always 8 data bits, no parity, - * 1 stop bit, no start bits. - */ -int serial_init(void) -{ -	return serial_init_dev(UART_NR); -} -#endif -  /*   * Read a single byte from the serial port. Returns 1 on success, 0   * otherwise. When the function is succesfull, the character read is @@ -176,17 +154,10 @@ int _serial_getc(const int dev_index)  	return readb(&uart->urxh) & 0xff;  } -#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(UART_NR); -} -#endif  #ifdef CONFIG_HWFLOW  int hwflow_onoff(int on) @@ -246,18 +217,10 @@ void _serial_putc(const char c, const int dev_index)  		serial_putc('\r');  } -#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, UART_NR); -} -#endif -  /*   * Test whether a character is in the RX buffer @@ -269,17 +232,10 @@ int _serial_tstc(const int dev_index)  	return readl(&uart->utrstat) & 0x1;  } -#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(UART_NR); -} -#endif  void _serial_puts(const char *s, const int dev_index)  { @@ -288,19 +244,11 @@ void _serial_puts(const char *s, const int dev_index)  	}  } -#if defined(CONFIG_SERIAL_MULTI)  static inline void serial_puts_dev(int dev_index, const char *s)  {  	_serial_puts(s, dev_index);  } -#else -void serial_puts(const char *s) -{ -	_serial_puts(s, UART_NR); -} -#endif -#if defined(CONFIG_SERIAL_MULTI)  DECLARE_S3C_SERIAL_FUNCTIONS(0);  struct serial_device s3c24xx_serial0_device =  INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0"); @@ -323,4 +271,10 @@ __weak struct serial_device *default_serial_console(void)  #error "CONFIG_SERIAL? missing."  #endif  } -#endif /* CONFIG_SERIAL_MULTI */ + +void s3c24xx_serial_initialize(void) +{ +	serial_register(&s3c24xx_serial0_device); +	serial_register(&s3c24xx_serial1_device); +	serial_register(&s3c24xx_serial2_device); +} diff --git a/drivers/serial/serial_s3c44b0.c b/drivers/serial/serial_s3c44b0.c index 95d0266c6..a4428e0f4 100644 --- a/drivers/serial/serial_s3c44b0.c +++ b/drivers/serial/serial_s3c44b0.c @@ -68,7 +68,7 @@ static int serial_flush_output(void)  } -void serial_setbrg (void) +static void s3c44b0_serial_setbrg(void)  {  	u32 divisor = 0; @@ -156,7 +156,7 @@ void serial_setbrg (void)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int s3c44b0_serial_init(void)  {  	serial_setbrg (); @@ -167,7 +167,7 @@ int serial_init (void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void s3c44b0_serial_putc(const char c)  {  	/* wait for room in the transmit FIFO */  	while(!(UTRSTAT0 & 0x02)); @@ -187,7 +187,7 @@ void serial_putc (const char c)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_tstc (void) +static int s3c44b0_serial_tstc(void)  {  	return (UTRSTAT0 & 0x01);  } @@ -197,22 +197,42 @@ int serial_tstc (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int s3c44b0_serial_getc(void)  {  	int rv;  	for(;;) { -		rv = serial_tstc(); +		rv = s3c44b0_serial_tstc();  		if(rv > 0)  			return URXH0;  	}  } -void -serial_puts (const char *s) +static void s3c44b0_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device s3c44b0_serial_drv = { +	.name	= "s3c44b0_serial", +	.start	= s3c44b0_serial_init, +	.stop	= NULL, +	.setbrg	= s3c44b0_serial_setbrg, +	.putc	= s3c44b0_serial_putc, +	.puts	= s3c44b0_serial_puts, +	.getc	= s3c44b0_serial_getc, +	.tstc	= s3c44b0_serial_tstc, +}; + +void s3c44b0_serial_initialize(void) +{ +	serial_register(&s3c44b0_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &s3c44b0_serial_drv; +} diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index 6819bb07b..3c41242a8 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -183,15 +183,16 @@ int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \  void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \  void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); } -#define INIT_S5P_SERIAL_STRUCTURE(port, name) { \ -	name, \ -	s5p_serial##port##_init, \ -	NULL, \ -	s5p_serial##port##_setbrg, \ -	s5p_serial##port##_getc, \ -	s5p_serial##port##_tstc, \ -	s5p_serial##port##_putc, \ -	s5p_serial##port##_puts, } +#define INIT_S5P_SERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,				\ +	.start	= s5p_serial##port##_init,		\ +	.stop	= NULL,					\ +	.setbrg	= s5p_serial##port##_setbrg,		\ +	.getc	= s5p_serial##port##_getc,		\ +	.tstc	= s5p_serial##port##_tstc,		\ +	.putc	= s5p_serial##port##_putc,		\ +	.puts	= s5p_serial##port##_puts,		\ +}  DECLARE_S5P_SERIAL_FUNCTIONS(0);  struct serial_device s5p_serial0_device = @@ -220,3 +221,11 @@ __weak struct serial_device *default_serial_console(void)  #error "CONFIG_SERIAL? missing."  #endif  } + +void s5p_serial_initialize(void) +{ +	serial_register(&s5p_serial0_device); +	serial_register(&s5p_serial1_device); +	serial_register(&s5p_serial2_device); +	serial_register(&s5p_serial3_device); +} diff --git a/drivers/serial/serial_sa1100.c b/drivers/serial/serial_sa1100.c index 5d1887580..c6b34db7c 100644 --- a/drivers/serial/serial_sa1100.c +++ b/drivers/serial/serial_sa1100.c @@ -30,10 +30,12 @@  #include <common.h>  #include <SA-1100.h> +#include <serial.h> +#include <linux/compiler.h>  DECLARE_GLOBAL_DATA_PTR; -void serial_setbrg (void) +static void sa1100_serial_setbrg(void)  {  	unsigned int reg = 0; @@ -89,7 +91,7 @@ void serial_setbrg (void)   * are always 8 data bits, no parity, 1 stop bit, no start bits.   *   */ -int serial_init (void) +static int sa1100_serial_init(void)  {  	serial_setbrg (); @@ -100,7 +102,7 @@ int serial_init (void)  /*   * Output a single byte to the serial port.   */ -void serial_putc (const char c) +static void sa1100_serial_putc(const char c)  {  #ifdef CONFIG_SERIAL1  	/* wait for room in the tx FIFO on SERIAL1 */ @@ -124,7 +126,7 @@ void serial_putc (const char c)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_tstc (void) +static int sa1100_serial_tstc(void)  {  #ifdef CONFIG_SERIAL1  	return Ser1UTSR1 & UTSR1_RNE; @@ -138,7 +140,7 @@ int serial_tstc (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ -int serial_getc (void) +static int sa1100_serial_getc(void)  {  #ifdef CONFIG_SERIAL1  	while (!(Ser1UTSR1 & UTSR1_RNE)); @@ -151,10 +153,30 @@ int serial_getc (void)  #endif  } -void -serial_puts (const char *s) +static void sa1100_serial_puts(const char *s)  {  	while (*s) {  		serial_putc (*s++);  	}  } + +static struct serial_device sa1100_serial_drv = { +	.name	= "sa1100_serial", +	.start	= sa1100_serial_init, +	.stop	= NULL, +	.setbrg	= sa1100_serial_setbrg, +	.putc	= sa1100_serial_putc, +	.puts	= sa1100_serial_puts, +	.getc	= sa1100_serial_getc, +	.tstc	= sa1100_serial_tstc, +}; + +void sa1100_serial_initialize(void) +{ +	serial_register(&sa1100_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &sa1100_serial_drv; +} diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 13919c623..1ddfc7d87 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -22,6 +22,8 @@  #include <asm/io.h>  #include <asm/processor.h>  #include "serial_sh.h" +#include <serial.h> +#include <linux/compiler.h>  #if defined(CONFIG_CONS_SCIF0)  # define SCIF_BASE	SCIF0_BASE @@ -55,13 +57,13 @@ static struct uart_port sh_sci = {  	.type		= SCIF_BASE_PORT,  }; -void serial_setbrg(void) +static void sh_serial_setbrg(void)  {  	DECLARE_GLOBAL_DATA_PTR;  	sci_out(&sh_sci, SCBRR, SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ));  } -int serial_init(void) +static int sh_serial_init(void)  {  	sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci));  	sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); @@ -127,21 +129,21 @@ void serial_raw_putc(const char c)  	sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci));  } -void serial_putc(const char c) +static void sh_serial_putc(const char c)  {  	if (c == '\n')  		serial_raw_putc('\r');  	serial_raw_putc(c);  } -void serial_puts(const char *s) +static void sh_serial_puts(const char *s)  {  	char c;  	while ((c = *s++) != 0)  		serial_putc(c);  } -int serial_tstc(void) +static int sh_serial_tstc(void)  {  	return serial_rx_fifo_level() ? 1 : 0;  } @@ -167,7 +169,7 @@ int serial_getc_check(void)  	return status & (SCIF_DR | SCxSR_RDxF(&sh_sci));  } -int serial_getc(void) +static int sh_serial_getc(void)  {  	unsigned short status;  	char ch; @@ -187,3 +189,24 @@ int serial_getc(void)  		handle_error();  	return ch;  } + +static struct serial_device sh_serial_drv = { +	.name	= "sh_serial", +	.start	= sh_serial_init, +	.stop	= NULL, +	.setbrg	= sh_serial_setbrg, +	.putc	= sh_serial_putc, +	.puts	= sh_serial_puts, +	.getc	= sh_serial_getc, +	.tstc	= sh_serial_tstc, +}; + +void sh_serial_initialize(void) +{ +	serial_register(&sh_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &sh_serial_drv; +} diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c index 2bdb68ba4..9cc0b7f1d 100644 --- a/drivers/serial/serial_xuartlite.c +++ b/drivers/serial/serial_xuartlite.c @@ -96,39 +96,6 @@ static int uartlite_serial_init(const int port)  	return -1;  } -#if !defined(CONFIG_SERIAL_MULTI) -int serial_init(void) -{ -	return uartlite_serial_init(0); -} - -void serial_setbrg(void) -{ -	/* FIXME: what's this for? */ -} - -void serial_putc(const char c) -{ -	uartlite_serial_putc(c, 0); -} - -void serial_puts(const char *s) -{ -	uartlite_serial_puts(s, 0); -} - -int serial_getc(void) -{ -	return uartlite_serial_getc(0); -} - -int serial_tstc(void) -{ -	return uartlite_serial_tstc(0); -} -#endif - -#if defined(CONFIG_SERIAL_MULTI)  /* Multi serial device functions */  #define DECLARE_ESERIAL_FUNCTIONS(port) \  	int userial##port##_init(void) \ @@ -144,15 +111,16 @@ int serial_tstc(void)  				{ uartlite_serial_puts(s, port); }  /* Serial device descriptor */ -#define INIT_ESERIAL_STRUCTURE(port, name) {\ -	name,\ -	userial##port##_init,\ -	NULL,\ -	userial##port##_setbrg,\ -	userial##port##_getc,\ -	userial##port##_tstc,\ -	userial##port##_putc,\ -	userial##port##_puts, } +#define INIT_ESERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,			\ +	.start	= userial##port##_init,		\ +	.stop	= NULL,				\ +	.setbrg	= userial##port##_setbrg,	\ +	.getc	= userial##port##_getc,		\ +	.tstc	= userial##port##_tstc,		\ +	.putc	= userial##port##_putc,		\ +	.puts	= userial##port##_puts,		\ +}  DECLARE_ESERIAL_FUNCTIONS(0);  struct serial_device uartlite_serial0_device = @@ -180,4 +148,19 @@ __weak struct serial_device *default_serial_console(void)  	return NULL;  } -#endif /* CONFIG_SERIAL_MULTI */ + +void uartlite_serial_initialize(void) +{ +#ifdef XILINX_UARTLITE_BASEADDR +	serial_register(&uartlite_serial0_device); +#endif /* XILINX_UARTLITE_BASEADDR */ +#ifdef XILINX_UARTLITE_BASEADDR1 +	serial_register(&uartlite_serial1_device); +#endif /* XILINX_UARTLITE_BASEADDR1 */ +#ifdef XILINX_UARTLITE_BASEADDR2 +	serial_register(&uartlite_serial2_device); +#endif /* XILINX_UARTLITE_BASEADDR2 */ +#ifdef XILINX_UARTLITE_BASEADDR3 +	serial_register(&uartlite_serial3_device); +#endif /* XILINX_UARTLITE_BASEADDR3 */ +} diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c new file mode 100644 index 000000000..c09aa271b --- /dev/null +++ b/drivers/serial/serial_zynq.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved. + * + * 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> +#include <asm/io.h> +#include <linux/compiler.h> +#include <serial.h> + +#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */ +#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */ + +#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */ +#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */ +#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */ +#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */ + +#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */ + +/* Some clock/baud constants */ +#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */ +#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */ + +struct uart_zynq { +	u32 control; /* Control Register [8:0] */ +	u32 mode; /* Mode Register [10:0] */ +	u32 reserved1[4]; +	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */ +	u32 reserved2[4]; +	u32 channel_sts; /* Channel Status [11:0] */ +	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */ +	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */ +}; + +static struct uart_zynq *uart_zynq_ports[2] = { +#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0 +	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0, +#endif +#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1 +	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1, +#endif +}; + +struct uart_zynq_params { +	u32 baudrate; +	u32 clock; +}; + +static struct uart_zynq_params uart_zynq_ports_param[2] = { +#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) && defined(CONFIG_ZYNQ_SERIAL_CLOCK0) +	[0].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE0, +	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0, +#endif +#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) && defined(CONFIG_ZYNQ_SERIAL_CLOCK1) +	[1].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE1, +	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1, +#endif +}; + +/* Set up the baud rate in gd struct */ +static void uart_zynq_serial_setbrg(const int port) +{ +	/* Calculation results. */ +	unsigned int calc_bauderror, bdiv, bgen; +	unsigned long calc_baud = 0; +	unsigned long baud = uart_zynq_ports_param[port].baudrate; +	unsigned long clock = uart_zynq_ports_param[port].clock; +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	/*                master clock +	 * Baud rate = ------------------ +	 *              bgen * (bdiv + 1) +	 * +	 * Find acceptable values for baud generation. +	 */ +	for (bdiv = 4; bdiv < 255; bdiv++) { +		bgen = clock / (baud * (bdiv + 1)); +		if (bgen < 2 || bgen > 65535) +			continue; + +		calc_baud = clock / (bgen * (bdiv + 1)); + +		/* +		 * Use first calculated baudrate with +		 * an acceptable (<3%) error +		 */ +		if (baud > calc_baud) +			calc_bauderror = baud - calc_baud; +		else +			calc_bauderror = calc_baud - baud; +		if (((calc_bauderror * 100) / baud) < 3) +			break; +	} + +	writel(bdiv, ®s->baud_rate_divider); +	writel(bgen, ®s->baud_rate_gen); +} + +/* Initialize the UART, with...some settings. */ +static int uart_zynq_serial_init(const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	if (!regs) +		return -1; + +	/* RX/TX enabled & reset */ +	writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \ +					ZYNQ_UART_CR_RXRST, ®s->control); +	writel(ZYNQ_UART_MR_PARITY_NONE, ®s->mode); /* 8 bit, no parity */ +	uart_zynq_serial_setbrg(port); + +	return 0; +} + +static void uart_zynq_serial_putc(const char c, const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) +		WATCHDOG_RESET(); + +	if (c == '\n') { +		writel('\r', ®s->tx_rx_fifo); +		while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) +			WATCHDOG_RESET(); +	} +	writel(c, ®s->tx_rx_fifo); +} + +static void uart_zynq_serial_puts(const char *s, const int port) +{ +	while (*s) +		uart_zynq_serial_putc(*s++, port); +} + +static int uart_zynq_serial_tstc(const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	return (readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0; +} + +static int uart_zynq_serial_getc(const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	while (!uart_zynq_serial_tstc(port)) +		WATCHDOG_RESET(); +	return readl(®s->tx_rx_fifo); +} + +/* Multi serial device functions */ +#define DECLARE_PSSERIAL_FUNCTIONS(port) \ +	int uart_zynq##port##_init(void) \ +				{ return uart_zynq_serial_init(port); } \ +	void uart_zynq##port##_setbrg(void) \ +				{ return uart_zynq_serial_setbrg(port); } \ +	int uart_zynq##port##_getc(void) \ +				{ return uart_zynq_serial_getc(port); } \ +	int uart_zynq##port##_tstc(void) \ +				{ return uart_zynq_serial_tstc(port); } \ +	void uart_zynq##port##_putc(const char c) \ +				{ uart_zynq_serial_putc(c, port); } \ +	void uart_zynq##port##_puts(const char *s) \ +				{ uart_zynq_serial_puts(s, port); } + +/* Serial device descriptor */ +#define INIT_PSSERIAL_STRUCTURE(port, __name) {	\ +	  .name   = __name,			\ +	  .start  = uart_zynq##port##_init,	\ +	  .stop   = NULL,			\ +	  .setbrg = uart_zynq##port##_setbrg,	\ +	  .getc   = uart_zynq##port##_getc,	\ +	  .tstc   = uart_zynq##port##_tstc,	\ +	  .putc   = uart_zynq##port##_putc,	\ +	  .puts   = uart_zynq##port##_puts,	\ +} + +DECLARE_PSSERIAL_FUNCTIONS(0); +struct serial_device uart_zynq_serial0_device = +	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0"); +DECLARE_PSSERIAL_FUNCTIONS(1); +struct serial_device uart_zynq_serial1_device = +	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1"); + +__weak struct serial_device *default_serial_console(void) +{ +	if (uart_zynq_ports[0]) +		return &uart_zynq_serial0_device; +	if (uart_zynq_ports[1]) +		return &uart_zynq_serial1_device; + +	return NULL; +} + +void zynq_serial_initalize(void) +{ +#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0 +	serial_register(&uart_zynq_serial0_device); +#endif +#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1 +	serial_register(&uart_zynq_serial1_device); +#endif +}  |