All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Frysinger <vapier@gentoo.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 02/18] Blackfin: uart: add multiple serial support
Date: Tue, 28 Jun 2011 15:36:11 -0400	[thread overview]
Message-ID: <1309289787-7846-3-git-send-email-vapier@gentoo.org> (raw)
In-Reply-To: <1309289787-7846-1-git-send-email-vapier@gentoo.org>

This brings CONFIG_SERIAL_MULTI support to the Blackfin on-chip UARTs.
Ends up adding only ~512bytes per additional UART.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 arch/blackfin/cpu/initcode.c |   12 ++-
 arch/blackfin/cpu/serial.c   |  205 +++++++++++++++++++++++++++++++++---------
 arch/blackfin/cpu/serial.h   |   44 +++++++---
 arch/blackfin/lib/board.c    |    4 +
 common/serial.c              |    3 +
 include/serial.h             |    9 ++
 6 files changed, 222 insertions(+), 55 deletions(-)

diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c
index 750add0..61dc5ab 100644
--- a/arch/blackfin/cpu/initcode.c
+++ b/arch/blackfin/cpu/initcode.c
@@ -24,6 +24,8 @@
 __attribute__((always_inline))
 static inline void serial_init(void)
 {
+	uint32_t uart_base = UART_DLL;
+
 #ifdef __ADSPBF54x__
 # ifdef BFIN_BOOT_UART_USE_RTS
 #  define BFIN_UART_USE_RTS 1
@@ -65,13 +67,13 @@ static inline void serial_init(void)
 
 	if (BFIN_DEBUG_EARLY_SERIAL) {
 		int ucen = bfin_read16(&pUART->gctl) & UCEN;
-		serial_early_init();
+		serial_early_init(uart_base);
 
 		/* If the UART is off, that means we need to program
 		 * the baud rate ourselves initially.
 		 */
 		if (ucen != UCEN)
-			serial_early_set_baud(CONFIG_BAUDRATE);
+			serial_early_set_baud(uart_base, CONFIG_BAUDRATE);
 	}
 }
 
@@ -79,6 +81,8 @@ __attribute__((always_inline))
 static inline void serial_deinit(void)
 {
 #ifdef __ADSPBF54x__
+	uint32_t uart_base = UART_DLL;
+
 	if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
 		/* clear forced RTS rather than relying on auto RTS */
 		bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) & ~FCPOL);
@@ -89,6 +93,8 @@ static inline void serial_deinit(void)
 __attribute__((always_inline))
 static inline void serial_putc(char c)
 {
+	uint32_t uart_base = UART_DLL;
+
 	if (!BFIN_DEBUG_EARLY_SERIAL)
 		return;
 
@@ -519,7 +525,7 @@ update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB)
 		unsigned int quotient;
 		for (quotient = 0; dividend > 0; ++quotient)
 			dividend -= divisor;
-		serial_early_put_div(quotient - ANOMALY_05000230);
+		serial_early_put_div(UART_DLL, quotient - ANOMALY_05000230);
 		serial_putc('c');
 	}
 
diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c
index b15c945..0252220 100644
--- a/arch/blackfin/cpu/serial.c
+++ b/arch/blackfin/cpu/serial.c
@@ -39,6 +39,8 @@
 
 #include <common.h>
 #include <watchdog.h>
+#include <serial.h>
+#include <linux/compiler.h>
 #include <asm/blackfin.h>
 #include <asm/mach-common/bits/uart.h>
 
@@ -59,14 +61,14 @@ static size_t cache_count;
  * tally of all the status bits.
  */
 static uint16_t uart_lsr_save;
-static uint16_t uart_lsr_read(void)
+static uint16_t uart_lsr_read(uint32_t uart_base)
 {
 	uint16_t lsr = bfin_read16(&pUART->lsr);
 	uart_lsr_save |= (lsr & (OE|PE|FE|BI));
 	return lsr | uart_lsr_save;
 }
 /* Just do the clear for everyone since it can't hurt. */
-static void uart_lsr_clear(void)
+static void uart_lsr_clear(uint32_t uart_base)
 {
 	uart_lsr_save = 0;
 	bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1);
@@ -76,46 +78,17 @@ static void uart_lsr_clear(void)
  * bits get set/cleared, we don't really care since we don't read them
  * anyways (and thus anomaly 05000099 is irrelevant).
  */
-static uint16_t uart_lsr_read(void)
+static inline uint16_t uart_lsr_read(uint32_t uart_base)
 {
 	return bfin_read16(&pUART->lsr);
 }
-static void uart_lsr_clear(void)
+static void uart_lsr_clear(uint32_t uart_base)
 {
 	bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1);
 }
 #endif
 
-/* Symbol for our assembly to call. */
-void serial_set_baud(uint32_t baud)
-{
-	serial_early_set_baud(baud);
-}
-
-/* Symbol for common u-boot code to call.
- * Setup the baudrate (brg: baudrate generator).
- */
-void serial_setbrg(void)
-{
-	serial_set_baud(gd->baudrate);
-}
-
-/* Symbol for our assembly to call. */
-void serial_initialize(void)
-{
-	serial_early_init();
-}
-
-/* Symbol for common u-boot code to call. */
-int serial_init(void)
-{
-	serial_initialize();
-	serial_setbrg();
-	uart_lsr_clear();
-	return 0;
-}
-
-void serial_putc(const char c)
+static void uart_putc(uint32_t uart_base, const char c)
 {
 	/* send a \r for compatibility */
 	if (c == '\n')
@@ -124,7 +97,7 @@ void serial_putc(const char c)
 	WATCHDOG_RESET();
 
 	/* wait for the hardware fifo to clear up */
-	while (!(uart_lsr_read() & THRE))
+	while (!(uart_lsr_read(uart_base) & THRE))
 		continue;
 
 	/* queue the character for transmission */
@@ -134,18 +107,18 @@ void serial_putc(const char c)
 	WATCHDOG_RESET();
 }
 
-int serial_tstc(void)
+static int uart_tstc(uint32_t uart_base)
 {
 	WATCHDOG_RESET();
-	return (uart_lsr_read() & DR) ? 1 : 0;
+	return (uart_lsr_read(uart_base) & DR) ? 1 : 0;
 }
 
-int serial_getc(void)
+static int uart_getc(uint32_t uart_base)
 {
 	uint16_t uart_rbr_val;
 
 	/* wait for data ! */
-	while (!serial_tstc())
+	while (!uart_tstc(uart_base))
 		continue;
 
 	/* grab the new byte */
@@ -153,7 +126,7 @@ int serial_getc(void)
 
 #ifdef CONFIG_DEBUG_SERIAL
 	/* grab & clear the LSR */
-	uint16_t uart_lsr_val = uart_lsr_read();
+	uint16_t uart_lsr_val = uart_lsr_read(uart_base);
 
 	cached_lsr[cache_count] = uart_lsr_val;
 	cached_rbr[cache_count] = uart_rbr_val;
@@ -175,11 +148,159 @@ int serial_getc(void)
 		return -1;
 	}
 #endif
-	uart_lsr_clear();
+	uart_lsr_clear(uart_base);
 
 	return uart_rbr_val;
 }
 
+#ifdef CONFIG_SYS_BFIN_UART
+
+static void uart_puts(uint32_t uart_base, const char *s)
+{
+	while (*s)
+		uart_putc(uart_base, *s++);
+}
+
+#define DECL_BFIN_UART(n) \
+static int uart##n##_init(void) \
+{ \
+	const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \
+	peripheral_request_list(pins, "bfin-uart"); \
+	uart_init(MMR_UART(n)); \
+	serial_early_set_baud(MMR_UART(n), gd->baudrate); \
+	uart_lsr_clear(MMR_UART(n)); \
+	return 0; \
+} \
+\
+static int uart##n##_uninit(void) \
+{ \
+	return serial_early_uninit(MMR_UART(n)); \
+} \
+\
+static void uart##n##_setbrg(void) \
+{ \
+	serial_early_set_baud(MMR_UART(n), gd->baudrate); \
+} \
+\
+static int uart##n##_getc(void) \
+{ \
+	return uart_getc(MMR_UART(n)); \
+} \
+\
+static int uart##n##_tstc(void) \
+{ \
+	return uart_tstc(MMR_UART(n)); \
+} \
+\
+static void uart##n##_putc(const char c) \
+{ \
+	uart_putc(MMR_UART(n), c); \
+} \
+\
+static void uart##n##_puts(const char *s) \
+{ \
+	uart_puts(MMR_UART(n), s); \
+} \
+\
+struct serial_device bfin_serial##n##_device = { \
+	.name   = "bfin_uart"#n, \
+	.init   = uart##n##_init, \
+	.uninit = uart##n##_uninit, \
+	.setbrg = uart##n##_setbrg, \
+	.getc   = uart##n##_getc, \
+	.tstc   = uart##n##_tstc, \
+	.putc   = uart##n##_putc, \
+	.puts   = uart##n##_puts, \
+};
+
+#ifdef UART0_DLL
+DECL_BFIN_UART(0)
+#endif
+#ifdef UART1_DLL
+DECL_BFIN_UART(1)
+#endif
+#ifdef UART2_DLL
+DECL_BFIN_UART(2)
+#endif
+#ifdef UART3_DLL
+DECL_BFIN_UART(3)
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_UART_CONSOLE == 0
+	return &bfin_serial0_device;
+#elif CONFIG_UART_CONSOLE == 1
+	return &bfin_serial1_device;
+#elif CONFIG_UART_CONSOLE == 2
+	return &bfin_serial2_device;
+#elif CONFIG_UART_CONSOLE == 3
+	return &bfin_serial3_device;
+#endif
+}
+
+void serial_register_bfin_uart(void)
+{
+#ifdef UART0_DLL
+	serial_register(&bfin_serial0_device);
+#endif
+#ifdef UART1_DLL
+	serial_register(&bfin_serial1_device);
+#endif
+#ifdef UART2_DLL
+	serial_register(&bfin_serial2_device);
+#endif
+#ifdef UART3_DLL
+	serial_register(&bfin_serial3_device);
+#endif
+}
+
+#else
+
+/* Symbol for our assembly to call. */
+void serial_set_baud(uint32_t baud)
+{
+	serial_early_set_baud(UART_DLL, baud);
+}
+
+/* Symbol for common u-boot code to call.
+ * Setup the baudrate (brg: baudrate generator).
+ */
+void serial_setbrg(void)
+{
+	serial_set_baud(gd->baudrate);
+}
+
+/* Symbol for our assembly to call. */
+void serial_initialize(void)
+{
+	serial_early_init(UART_DLL);
+}
+
+/* Symbol for common u-boot code to call. */
+int serial_init(void)
+{
+	serial_initialize();
+	serial_setbrg();
+	uart_lsr_clear(UART_DLL);
+	return 0;
+}
+
+int serial_tstc(void)
+{
+	return uart_tstc(UART_DLL);
+}
+
+int serial_getc(void)
+{
+	return uart_getc(UART_DLL);
+}
+
+void serial_putc(const char c)
+{
+	uart_putc(UART_DLL, c);
+}
+
 void serial_puts(const char *s)
 {
 	while (*s)
@@ -187,3 +308,5 @@ void serial_puts(const char *s)
 }
 
 #endif
+
+#endif
diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h
index 7999a19..aa5c217 100644
--- a/arch/blackfin/cpu/serial.h
+++ b/arch/blackfin/cpu/serial.h
@@ -82,17 +82,19 @@ struct bfin_mmr_serial {
 
 #define __PASTE_UART(num, pfx, sfx) pfx##num##_##sfx
 #define _PASTE_UART(num, pfx, sfx) __PASTE_UART(num, pfx, sfx)
-#define MMR_UART(mmr) _PASTE_UART(CONFIG_UART_CONSOLE, UART, DLL)
-#define P_UART(pin) _PASTE_UART(CONFIG_UART_CONSOLE, P_UART, pin)
+#define MMR_UART(n) _PASTE_UART(n, UART, DLL)
+#define _P_UART(n, pin) _PASTE_UART(n, P_UART, pin)
+#define P_UART(pin) _P_UART(CONFIG_UART_CONSOLE, pin)
 
 #ifndef UART_DLL
-# define UART_DLL MMR_UART(DLL)
+# define UART_DLL MMR_UART(CONFIG_UART_CONSOLE)
 #else
+# define UART0_DLL UART_DLL
 # if CONFIG_UART_CONSOLE != 0
 #  error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
 # endif
 #endif
-#define pUART ((volatile struct bfin_mmr_serial *)UART_DLL)
+#define pUART ((volatile struct bfin_mmr_serial *)uart_base)
 
 #if BFIN_UART_HW_VER == 2
 # define ACCESS_LATCH()
@@ -168,11 +170,8 @@ static inline void serial_do_portmux(void)
 }
 
 __attribute__((always_inline))
-static inline void serial_early_init(void)
+static inline int uart_init(uint32_t uart_base)
 {
-	/* handle portmux crap on different Blackfins */
-	serial_do_portmux();
-
 	/* always enable UART -- avoids anomalies 05000309 and 05000350 */
 	bfin_write16(&pUART->gctl, UCEN);
 
@@ -180,10 +179,30 @@ static inline void serial_early_init(void)
 	bfin_write16(&pUART->lcr, WLS_8);
 
 	SSYNC();
+
+	return 0;
 }
 
 __attribute__((always_inline))
-static inline void serial_early_put_div(uint16_t divisor)
+static inline int serial_early_init(uint32_t uart_base)
+{
+	/* handle portmux crap on different Blackfins */
+	serial_do_portmux();
+
+	return uart_init(uart_base);
+}
+
+__attribute__((always_inline))
+static inline int serial_early_uninit(uint32_t uart_base)
+{
+	/* disable the UART by clearing UCEN */
+	bfin_write16(&pUART->gctl, 0);
+
+	return 0;
+}
+
+__attribute__((always_inline))
+static inline void serial_early_put_div(uint32_t uart_base, uint16_t divisor)
 {
 	/* Set DLAB in LCR to Access DLL and DLH */
 	ACCESS_LATCH();
@@ -202,6 +221,8 @@ static inline void serial_early_put_div(uint16_t divisor)
 __attribute__((always_inline))
 static inline uint16_t serial_early_get_div(void)
 {
+	uint32_t uart_base = UART_DLL;
+
 	/* Set DLAB in LCR to Access DLL and DLH */
 	ACCESS_LATCH();
 	SSYNC();
@@ -223,13 +244,14 @@ static inline uint16_t serial_early_get_div(void)
 #endif
 
 __attribute__((always_inline))
-static inline void serial_early_set_baud(uint32_t baud)
+static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
 {
 	/* Translate from baud into divisor in terms of SCLK.  The
 	 * weird multiplication is to make sure we over sample just
 	 * a little rather than under sample the incoming signals.
 	 */
-	serial_early_put_div((get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
+	serial_early_put_div(uart_base,
+		(get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
 }
 
 #ifndef BFIN_IN_INITCODE
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index 362b8c4..e00050c 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -12,6 +12,7 @@
 #include <common.h>
 #include <command.h>
 #include <stdio_dev.h>
+#include <serial.h>
 #include <environment.h>
 #include <malloc.h>
 #include <mmc.h>
@@ -265,6 +266,9 @@ void board_init_f(ulong bootflag)
 	init_baudrate();
 	serial_early_puts("Serial init\n");
 	serial_init();
+#ifdef CONFIG_SERIAL_MULTI
+	serial_initialize();
+#endif
 	serial_early_puts("Console init flash\n");
 	console_init_f();
 	serial_early_puts("End of early debugging\n");
diff --git a/common/serial.c b/common/serial.c
index 8ebf9a5..7a69fc1 100644
--- a/common/serial.c
+++ b/common/serial.c
@@ -173,6 +173,9 @@ void serial_initialize (void)
 	serial_register(&serial6_device);
 #endif
 #endif
+#if defined(CONFIG_SYS_BFIN_UART)
+	serial_register_bfin_uart();
+#endif
 	serial_assign (default_serial_console ()->name);
 }
 
diff --git a/include/serial.h b/include/serial.h
index f21d961..4aa1cdc 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -71,6 +71,15 @@ extern struct serial_device serial_ffuart_device;
 extern struct serial_device serial_btuart_device;
 extern struct serial_device serial_stuart_device;
 
+#if defined(CONFIG_SYS_BFIN_UART)
+extern void serial_register_bfin_uart(void);
+extern struct serial_device bfin_serial0_device;
+extern struct serial_device bfin_serial1_device;
+extern struct serial_device bfin_serial2_device;
+extern struct serial_device bfin_serial3_device;
+#endif
+
+extern void serial_register(struct serial_device *);
 extern void serial_initialize(void);
 extern void serial_stdio_init(void);
 extern int serial_assign(char * name);
-- 
1.7.5.3

  parent reply	other threads:[~2011-06-28 19:36 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-28 19:36 [U-Boot] [PATCH 00/18] Blackfin updates for v2011.09 Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 01/18] Blackfin: uart: move debug buffers into local bss Mike Frysinger
2011-06-28 19:36 ` Mike Frysinger [this message]
2011-06-28 19:36 ` [U-Boot] [PATCH 03/18] Blackfin: adi boards: enable multi serial support by default Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 04/18] Blackfin: dont reset SWRST on newer bf526 parts Mike Frysinger
2011-07-05  5:24   ` [U-Boot] [PATCH v2] " Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 05/18] Blackfin: add init.elf helper code Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 06/18] Blackfin: uart: fix printf warning Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 07/18] Blackfin: post: setup default CONFIG_SYS_POST_WORD_ADDR Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 08/18] Blackfin: gpio: optimize free path a little Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 09/18] Blackfin: sync MMR read/write helpers with Linux Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 10/18] Blackfin: cm-bf537e/cm-bf537u/tcm-bf537: update network settings Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 11/18] Blackfin: cm-bf537e/cm-bf537u/tcm-bf537: enable mmc_spi support Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 12/18] Blackfin: portmux: allow header to be included in assembly files Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 13/18] Blackfin: drop unused dma.h header from start code Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 14/18] Blackfin: adi boards: enable pretty flash progress output Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 15/18] Blackfin: split out async setup Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 16/18] Blackfin: serial: convert to bfin_{read, write} helpers Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 17/18] Blackfin: update anomaly lists to latest public info Mike Frysinger
2011-06-28 19:36 ` [U-Boot] [PATCH 18/18] Blackfin: adi boards: also set stderr to nc with helper Mike Frysinger
2011-06-29  2:50 ` [U-Boot] Pull request u-boot-blackfin.git Mike Frysinger
2011-06-29 21:23   ` Wolfgang Denk
2011-06-30 15:45     ` Mike Frysinger
2011-06-30 15:55       ` Wolfgang Denk
2011-06-29 21:23 ` [U-Boot] [PATCH 00/18] Blackfin updates for v2011.09 Wolfgang Denk
2011-06-30 17:23 ` Mike Frysinger
2011-07-05  5:25 ` [U-Boot] [PATCH 19/21] Blackfin: serial: move early debug strings into .rodata section Mike Frysinger
2011-07-05  5:25   ` [U-Boot] [PATCH 20/21] Blackfin: switch to common display_options() Mike Frysinger
2011-07-05  5:25   ` [U-Boot] [PATCH 21/21] Blackfin: jtag-console: fix timer usage Mike Frysinger
2011-07-12  6:21 ` [U-Boot] [PATCH 00/18] Blackfin updates for v2011.09 Mike Frysinger
2011-07-12  6:23 ` [U-Boot] Pull request u-boot-blackfin.git Mike Frysinger
2011-08-02 19:49   ` Wolfgang Denk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1309289787-7846-3-git-send-email-vapier@gentoo.org \
    --to=vapier@gentoo.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.