public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] NS16550: buffer reads
@ 2011-10-15  0:03 Simon Glass
  2011-10-15 10:43 ` Albert ARIBAUD
  2011-10-17  4:56 ` [U-Boot] How to unsubscribe Sandeep Kumar
  0 siblings, 2 replies; 47+ messages in thread
From: Simon Glass @ 2011-10-15  0:03 UTC (permalink / raw)
  To: u-boot

From: Scott Wood <scottwood@freescale.com>

From: Scott Wood <scottwood@freescale.com>

This improves the performance of U-Boot when accepting rapid input,
such as pasting a sequence of commands.

Without this patch, on P4080DS I see a maximum of around 5 lines can
be pasted.  With this patch, it handles around 70 lines before lossage,
long enough for most things you'd paste.

With it enabled, on ppc it's an extra 396 bytes of image size, and 1056
bytes of BSS.

ARM note from Simon Glass <sjg@chromium.org> - ARM code size goes from
212 to 484 bytes (extra 272 bytes), BSS to 1056 bytes.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Changes in v2:
- Fix checkpatch warnings, the other one was already there

 README                   |    8 ++++
 drivers/serial/ns16550.c |   96 +++++++++++++++++++++++++++++++++++++++++++--
 drivers/serial/serial.c  |    5 +-
 include/ns16550.h        |    4 +-
 4 files changed, 104 insertions(+), 9 deletions(-)

diff --git a/README b/README
index 7e032a9..28d2e8a 100644
--- a/README
+++ b/README
@@ -2862,6 +2862,14 @@ use the "saveenv" command to store a valid environment.
 		space for already greatly restricted images, including but not
 		limited to NAND_SPL configurations.
 
+- CONFIG_NS16550_BUFFER_READS:
+		Instead of reading directly from the receive register
+		every time U-Boot is ready for another byte, keep a
+		buffer and fill it from the hardware fifo every time
+		U-Boot reads a character.  This helps U-Boot keep up with
+		a larger amount of rapid input, such as happens when
+		pasting text into the terminal.
+
 Low Level (hardware related) configuration options:
 ---------------------------------------------------
 
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 0174744..a012e5d 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -4,12 +4,15 @@
  * modified to use CONFIG_SYS_ISA_MEM and new defines
  */
 
+#include <common.h>
 #include <config.h>
 #include <ns16550.h>
 #include <watchdog.h>
 #include <linux/types.h>
 #include <asm/io.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define UART_LCRVAL UART_LCR_8N1		/* 8 data, 1 stop, no parity */
 #define UART_MCRVAL (UART_MCR_DTR | \
 		     UART_MCR_RTS)		/* RTS/DTR */
@@ -92,21 +95,104 @@ void NS16550_putc (NS16550_t com_port, char c)
 }
 
 #ifndef CONFIG_NS16550_MIN_FUNCTIONS
-char NS16550_getc (NS16550_t com_port)
+
+static char NS16550_raw_getc(NS16550_t regs)
 {
-	while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
+	while ((serial_in(&regs->lsr) & UART_LSR_DR) == 0) {
 #ifdef CONFIG_USB_TTY
 		extern void usbtty_poll(void);
 		usbtty_poll();
 #endif
 		WATCHDOG_RESET();
 	}
-	return serial_in(&com_port->rbr);
+	return serial_in(&regs->rbr);
+}
+
+static int NS16550_raw_tstc(NS16550_t regs)
+{
+	return ((serial_in(&regs->lsr) & UART_LSR_DR) != 0);
+}
+
+
+#ifdef CONFIG_NS16550_BUFFER_READS
+
+#define BUF_SIZE 256
+#define NUM_PORTS 4
+
+struct ns16550_priv {
+	char buf[BUF_SIZE];
+	unsigned int head, tail;
+};
+
+static struct ns16550_priv rxstate[NUM_PORTS];
+
+static void enqueue(unsigned int port, char ch)
+{
+	/* If queue is full, drop the character. */
+	if ((rxstate[port].head - rxstate[port].tail - 1) % BUF_SIZE == 0)
+		return;
+
+	rxstate[port].buf[rxstate[port].tail] = ch;
+	rxstate[port].tail = (rxstate[port].tail + 1) % BUF_SIZE;
+}
+
+static int dequeue(unsigned int port, char *ch)
+{
+	/* Empty queue? */
+	if (rxstate[port].head == rxstate[port].tail)
+		return 0;
+
+	*ch = rxstate[port].buf[rxstate[port].head];
+	rxstate[port].head = (rxstate[port].head + 1) % BUF_SIZE;
+	return 1;
+}
+
+static void fill_rx_buf(NS16550_t regs, unsigned int port)
+{
+	while ((serial_in(&regs->lsr) & UART_LSR_DR) != 0)
+		enqueue(port, serial_in(&regs->rbr));
+}
+
+char NS16550_getc(NS16550_t regs, unsigned int port)
+{
+	char ch;
+
+	if (port >= NUM_PORTS || !(gd->flags & GD_FLG_RELOC))
+		return NS16550_raw_getc(regs);
+
+	do  {
+#ifdef CONFIG_USB_TTY
+		extern void usbtty_poll(void);
+		usbtty_poll();
+#endif
+		fill_rx_buf(regs, port);
+		WATCHDOG_RESET();
+	} while (!dequeue(port, &ch));
+
+	return ch;
+}
+
+int NS16550_tstc(NS16550_t regs, unsigned int port)
+{
+	if (port >= NUM_PORTS || !(gd->flags & GD_FLG_RELOC))
+		return NS16550_raw_tstc(regs);
+
+	fill_rx_buf(regs, port);
+
+	return rxstate[port].head != rxstate[port].tail;
+}
+
+#else /* CONFIG_NS16550_BUFFER_READS */
+
+char NS16550_getc(NS16550_t regs, unsigned int port)
+{
+	return NS16550_raw_getc(regs);
 }
 
-int NS16550_tstc (NS16550_t com_port)
+int NS16550_tstc(NS16550_t regs, unsigned int port)
 {
-	return ((serial_in(&com_port->lsr) & UART_LSR_DR) != 0);
+	return NS16550_raw_tstc(regs);
 }
 
+#endif /* CONFIG_NS16550_BUFFER_READS */
 #endif /* CONFIG_NS16550_MIN_FUNCTIONS */
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index 0d56e78..cf9a1dd 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -93,6 +93,7 @@ static NS16550_t serial_ports[4] = {
 };
 
 #define PORT	serial_ports[port-1]
+#define PORTNR	(port-1)
 #if defined(CONFIG_CONS_INDEX)
 #define CONSOLE	(serial_ports[CONFIG_CONS_INDEX-1])
 #endif
@@ -219,13 +220,13 @@ _serial_puts (const char *s,const int port)
 int
 _serial_getc(const int port)
 {
-	return NS16550_getc(PORT);
+	return NS16550_getc(PORT, PORTNR);
 }
 
 int
 _serial_tstc(const int port)
 {
-	return NS16550_tstc(PORT);
+	return NS16550_tstc(PORT, PORTNR);
 }
 
 void
diff --git a/include/ns16550.h b/include/ns16550.h
index 51f1c17..60b0abc 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -164,6 +164,6 @@ typedef volatile struct NS16550 *NS16550_t;
 
 void	NS16550_init   (NS16550_t com_port, int baud_divisor);
 void	NS16550_putc   (NS16550_t com_port, char c);
-char	NS16550_getc   (NS16550_t com_port);
-int	NS16550_tstc   (NS16550_t com_port);
+char NS16550_getc(NS16550_t regs, unsigned int port);
+int NS16550_tstc(NS16550_t regs, unsigned int port);
 void	NS16550_reinit (NS16550_t com_port, int baud_divisor);
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 47+ messages in thread
* [U-Boot] [PATCH v4 1/2] NS16550: trivial code clean for checkpatch
@ 2011-10-16  5:14 Simon Glass
  2011-10-16  5:14 ` [U-Boot] [PATCH v4 2/2] NS16550: buffer reads Simon Glass
  0 siblings, 1 reply; 47+ messages in thread
From: Simon Glass @ 2011-10-16  5:14 UTC (permalink / raw)
  To: u-boot

This removes most checkpatch warnings from the ns16550 driver and its
header.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/serial/ns16550.c |   37 ++++++++++++++++++++-----------------
 include/ns16550.h        |   16 ++++++++--------
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 0174744..056c25d 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -17,24 +17,24 @@
 		     UART_FCR_RXSR |	\
 		     UART_FCR_TXSR)		/* Clear & enable FIFOs */
 #ifdef CONFIG_SYS_NS16550_PORT_MAPPED
-#define serial_out(x,y)	outb(x,(ulong)y)
-#define serial_in(y)	inb((ulong)y)
+#define serial_out(x, y)	outb(x, (ulong)y)
+#define serial_in(y)		inb((ulong)y)
 #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0)
-#define serial_out(x,y) out_be32(y,x)
-#define serial_in(y) 	in_be32(y)
+#define serial_out(x, y)	out_be32(y, x)
+#define serial_in(y)		in_be32(y)
 #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0)
-#define serial_out(x,y) out_le32(y,x)
-#define serial_in(y) 	in_le32(y)
+#define serial_out(x, y)	out_le32(y, x)
+#define serial_in(y)		in_le32(y)
 #else
-#define serial_out(x,y) writeb(x,y)
-#define serial_in(y) 	readb(y)
+#define serial_out(x, y)	writeb(x, y)
+#define serial_in(y)		readb(y)
 #endif
 
 #ifndef CONFIG_SYS_NS16550_IER
 #define CONFIG_SYS_NS16550_IER  0x00
 #endif /* CONFIG_SYS_NS16550_IER */
 
-void NS16550_init (NS16550_t com_port, int baud_divisor)
+void NS16550_init(NS16550_t com_port, int baud_divisor)
 {
 	serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
 #if defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)
@@ -52,15 +52,17 @@ void NS16550_init (NS16550_t com_port, int baud_divisor)
 	serial_out(UART_LCRVAL, &com_port->lcr);
 #if defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)
 #if defined(CONFIG_APTIX)
-	serial_out(3, &com_port->mdr1);	/* /13 mode so Aptix 6MHz can hit 115200 */
+	/* /13 mode so Aptix 6MHz can hit 115200 */
+	serial_out(3, &com_port->mdr1);
 #else
-	serial_out(0, &com_port->mdr1);	/* /16 is proper to hit 115200 with 48MHz */
+	/* /16 is proper to hit 115200 with 48MHz */
+	serial_out(0, &com_port->mdr1);
 #endif
 #endif /* CONFIG_OMAP */
 }
 
 #ifndef CONFIG_NS16550_MIN_FUNCTIONS
-void NS16550_reinit (NS16550_t com_port, int baud_divisor)
+void NS16550_reinit(NS16550_t com_port, int baud_divisor)
 {
 	serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
 	serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
@@ -76,9 +78,10 @@ void NS16550_reinit (NS16550_t com_port, int baud_divisor)
 }
 #endif /* CONFIG_NS16550_MIN_FUNCTIONS */
 
-void NS16550_putc (NS16550_t com_port, char c)
+void NS16550_putc(NS16550_t com_port, char c)
 {
-	while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0);
+	while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0)
+		;
 	serial_out(c, &com_port->thr);
 
 	/*
@@ -92,7 +95,7 @@ void NS16550_putc (NS16550_t com_port, char c)
 }
 
 #ifndef CONFIG_NS16550_MIN_FUNCTIONS
-char NS16550_getc (NS16550_t com_port)
+char NS16550_getc(NS16550_t com_port)
 {
 	while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
 #ifdef CONFIG_USB_TTY
@@ -104,9 +107,9 @@ char NS16550_getc (NS16550_t com_port)
 	return serial_in(&com_port->rbr);
 }
 
-int NS16550_tstc (NS16550_t com_port)
+int NS16550_tstc(NS16550_t com_port)
 {
-	return ((serial_in(&com_port->lsr) & UART_LSR_DR) != 0);
+	return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0;
 }
 
 #endif /* CONFIG_NS16550_MIN_FUNCTIONS */
diff --git a/include/ns16550.h b/include/ns16550.h
index 51f1c17..e9d2eda 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -65,12 +65,12 @@ struct NS16550 {
 #define dll rbr
 #define dlm ier
 
-typedef volatile struct NS16550 *NS16550_t;
+typedef struct NS16550 *NS16550_t;
 
 /*
  * These are the definitions for the FIFO Control Register
  */
-#define UART_FCR_FIFO_EN 	0x01 /* Fifo enable */
+#define UART_FCR_FIFO_EN	0x01 /* Fifo enable */
 #define UART_FCR_CLEAR_RCVR	0x02 /* Clear the RCVR FIFO */
 #define UART_FCR_CLEAR_XMIT	0x04 /* Clear the XMIT FIFO */
 #define UART_FCR_DMA_SELECT	0x08 /* For DMA applications */
@@ -106,7 +106,7 @@ typedef volatile struct NS16550 *NS16550_t;
 #define UART_LCR_WLS_6	0x01		/* 6 bit character length */
 #define UART_LCR_WLS_7	0x02		/* 7 bit character length */
 #define UART_LCR_WLS_8	0x03		/* 8 bit character length */
-#define UART_LCR_STB	0x04		/* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define UART_LCR_STB	0x04		/* # stop Bits, off=1, on=1.5 or 2) */
 #define UART_LCR_PEN	0x08		/* Parity eneble */
 #define UART_LCR_EPS	0x10		/* Even Parity Select */
 #define UART_LCR_STKP	0x20		/* Stick Parity */
@@ -162,8 +162,8 @@ typedef volatile struct NS16550 *NS16550_t;
 /* useful defaults for LCR */
 #define UART_LCR_8N1	0x03
 
-void	NS16550_init   (NS16550_t com_port, int baud_divisor);
-void	NS16550_putc   (NS16550_t com_port, char c);
-char	NS16550_getc   (NS16550_t com_port);
-int	NS16550_tstc   (NS16550_t com_port);
-void	NS16550_reinit (NS16550_t com_port, int baud_divisor);
+void NS16550_init(NS16550_t com_port, int baud_divisor);
+void NS16550_putc(NS16550_t com_port, char c);
+char NS16550_getc(NS16550_t com_port);
+int NS16550_tstc(NS16550_t com_port);
+void NS16550_reinit(NS16550_t com_port, int baud_divisor);
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2011-10-26 19:19 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-15  0:03 [U-Boot] [PATCH v2] NS16550: buffer reads Simon Glass
2011-10-15 10:43 ` Albert ARIBAUD
2011-10-15 14:47   ` Simon Glass
2011-10-15 16:02     ` Wolfgang Denk
2011-10-15 16:12       ` Simon Glass
2011-10-15 16:21         ` Albert ARIBAUD
2011-10-15 16:50           ` Simon Glass
2011-10-15 17:45             ` Simon Glass
2011-10-15 19:14               ` Wolfgang Denk
2011-10-16  4:46                 ` Simon Glass
2011-10-16 19:52                   ` Wolfgang Denk
2011-10-16 21:02                     ` Simon Glass
2011-10-15 19:05             ` Wolfgang Denk
2011-10-15 19:00         ` Wolfgang Denk
2011-10-16  4:39           ` Simon Glass
2011-10-16 19:47             ` Wolfgang Denk
2011-10-16 20:43               ` Simon Glass
2011-10-16 21:00                 ` Wolfgang Denk
2011-10-17  4:56 ` [U-Boot] How to unsubscribe Sandeep Kumar
2011-10-17 15:40   ` Mike Frysinger
  -- strict thread matches above, loose matches on Subject: below --
2011-10-16  5:14 [U-Boot] [PATCH v4 1/2] NS16550: trivial code clean for checkpatch Simon Glass
2011-10-16  5:14 ` [U-Boot] [PATCH v4 2/2] NS16550: buffer reads Simon Glass
2011-10-17 12:18   ` Wolfgang Denk
2011-10-17 16:40     ` Simon Glass
2011-10-22  8:44       ` Albert ARIBAUD
2011-10-22 22:15         ` Graeme Russ
2011-10-23  8:20           ` Wolfgang Denk
2011-10-23 11:50             ` Graeme Russ
2011-10-23 17:15               ` Wolfgang Denk
2011-10-23 20:17                 ` Graeme Russ
2011-10-23 21:22                   ` Wolfgang Denk
2011-10-23 21:32                     ` [U-Boot] [PATCH v2] " Graeme Russ
2011-10-23 22:18                       ` Wolfgang Denk
2011-10-23 23:30                         ` Graeme Russ
2011-10-24  4:47                           ` Simon Glass
2011-10-24 18:46                           ` Wolfgang Denk
2011-10-24 19:26                             ` Graeme Russ
2011-10-24 20:00                               ` Wolfgang Denk
2011-10-24 20:40                                 ` Graeme Russ
2011-10-24 21:59                                   ` Wolfgang Denk
2011-10-24 22:22                                     ` Graeme Russ
2011-10-24 23:31                                       ` J. William Campbell
2011-10-25  7:31                                       ` Wolfgang Denk
2011-10-25  8:34                                         ` Graeme Russ
2011-10-25 18:41                                           ` Wolfgang Denk
2011-10-25 22:37                                             ` Graeme Russ
2011-10-25 23:17                                               ` Simon Glass
     [not found]                                                 ` <CALButCK2XnZ=HR72VaXioCfxkMFgMh2JbXzSDq9TadgKFH52rQ@mail.gmail.com >
2011-10-25 23:37                                                 ` Graeme Russ
2011-10-25 23:48                                                   ` Simon Glass
2011-10-26  3:41                                                     ` Graeme Russ
2011-10-26  7:00                                                       ` Wolfgang Denk
2011-10-26  9:18                                                         ` Graeme Russ
2011-10-26 10:19                                                           ` Wolfgang Denk
2011-10-26 16:55                                                   ` Scott Wood
2011-10-26 18:17                                                     ` Wolfgang Denk
2011-10-26 18:50                                                       ` Scott Wood
2011-10-26 19:19                                                         ` Wolfgang Denk
2011-10-26  6:54                                               ` Wolfgang Denk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox