diff options
Diffstat (limited to 'drivers/serial')
32 files changed, 1543 insertions, 606 deletions
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 65d0f23..3c32f97 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 2980e4d..654b501 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 045f119..27550ed 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 943ef70..1303031 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 8ce3382..02429b5 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 d93b24b..00a7114 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 facadd2..9027781 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 e9645a0..cb545c4 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 f383011..49bccf3 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 aa378e1..423d26e6 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 a88e930..9ab8a28 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 1927c16..cb19401 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 b10bab7..5bbf3ae 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 +static struct serial_device *serial_devices; +static struct serial_device *serial_current; -#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 +static void serial_null(void) +{ +} -/* 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) - -/* 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,\ - eserial##port##_init,\ - NULL,\ - 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) +#define serial_initfunc(name) \ + void name(void) \ + __attribute__((weak, alias("serial_null"))); + +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); + +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; +} - /* 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_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(); + + 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) -{ - return _serial_getc(CONFIG_CONS_INDEX); -} -#endif -#if defined(CONFIG_SERIAL_MULTI) -static inline int -serial_tstc_dev(unsigned int dev_index) +int serial_getc(void) { - return _serial_tstc(dev_index); + return get_current()->getc(); } -#else -int -serial_tstc(void) + +int serial_tstc(void) { - return _serial_tstc(CONFIG_CONS_INDEX); + return get_current()->tstc(); } -#endif -#if defined(CONFIG_SERIAL_MULTI) -static inline void -serial_setbrg_dev(unsigned int dev_index) +void serial_putc(const char c) { - _serial_setbrg(dev_index); + get_current()->putc(c); } -#else -void -serial_setbrg(void) + +void serial_puts(const char *s) { - _serial_setbrg(CONFIG_CONS_INDEX); + get_current()->puts(s); } -#endif -#if defined(CONFIG_SERIAL_MULTI) - -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_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) { -#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 -} + unsigned char c; + int ret, saved_baud, b; + struct serial_device *saved_dev, *s; + bd_t *bd = gd->bd; + + /* Save current serial state */ + ret = 0; + saved_dev = serial_current; + saved_baud = bd->bi_baudrate; + + for (s = serial_devices; s; s = s->next) { + /* If this driver doesn't support loop back, skip it */ + if (!s->loop) + continue; + + /* 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(); + + /* 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(); -#endif /* CONFIG_SERIAL_MULTI */ + return ret; +} +#endif diff --git a/drivers/serial/serial_clps7111.c b/drivers/serial/serial_clps7111.c index a6aecad..65473e8 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 b9ca748..6c075b5 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 a9acd47..c8b3658 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 aacd1be..60e8007 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 4767489..6c96285 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 e3a60b6..fcab202 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 4abc271..3533cfc 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 af00b9c..b0612f5 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 d04790d..d30adc3 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 0000000..b5d1248 --- /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 d4c5137..7db7b65 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 a9976d7..ad39100 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 12bcdd3..4d214c3 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 95d0266..a4428e0 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 6819bb0..3c41242 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 5d18875..c6b34db 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 13919c6..1ddfc7d 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 2bdb68b..9cc0b7f 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 0000000..c09aa27 --- /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 +} |