Patchwork [U-Boot,v1,1/3] blackfin: Enable early print via the generic serial API.

login
register
mail settings
Submitter Sonic Zhang
Date May 13, 2013, 4:20 a.m.
Message ID <1368418817-27670-1-git-send-email-sonic.adi@gmail.com>
Download mbox | patch
Permalink /patch/243263/
State Accepted, archived
Delegated to: Sonic Zhang
Headers show

Comments

Sonic Zhang - May 13, 2013, 4:20 a.m.
From: Sonic Zhang <sonic.zhang@analog.com>

Remove blackfin specific implementation of the generic serial API when
early print macro is defined.

In BFIN_BOOT_BYPASS mode, don't call generic serial_puts, because
early print in bypass mode is running before code binary is relocated
to the link address.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
 arch/blackfin/cpu/serial.c        |   71 ++++++++++++------------------------
 arch/blackfin/cpu/serial.h        |   10 +++---
 include/configs/bfin_adi_common.h |    3 --
 3 files changed, 29 insertions(+), 55 deletions(-)
Mike Frysinger - May 13, 2013, 4:42 a.m.
On Monday 13 May 2013 00:20:15 Sonic Zhang wrote:
> Remove blackfin specific implementation of the generic serial API when
> early print macro is defined.
> 
> In BFIN_BOOT_BYPASS mode, don't call generic serial_puts, because
> early print in bypass mode is running before code binary is relocated
> to the link address.

the link address of the function doesn't matter.  all Blackfin func calls are 
pcrel based, not absolute address calls.  i specifically crafted all of this 
early serial code so that this does work regardless of the address where the 
code happens to be executing.

what doesn't work is if you try to use the early serial console with 
CONFIG_SYS_BFIN_UART (which allows all the serial devices to be selected on 
the fly).  but the header file specifically handles that:
#ifndef CONFIG_DEBUG_EARLY_SERIAL
# define CONFIG_SYS_BFIN_UART
#endif

i guess the problem is that this commit is wrong:

commit 820edc18b5aefa8c82d420f6cba3e13b5631f9b8
Author: Sonic Zhang <sonic.zhang@analog.com>
Date:   Fri Nov 30 17:39:32 2012 +0800

    blackfin: Correct early serial mess output in BYPASS boot mode.

it shouldn't be messing with the addresses there
-mike
Sonic Zhang - May 13, 2013, 6:01 a.m.
Hi Mike,

On Mon, May 13, 2013 at 12:42 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Monday 13 May 2013 00:20:15 Sonic Zhang wrote:
>> Remove blackfin specific implementation of the generic serial API when
>> early print macro is defined.
>>
>> In BFIN_BOOT_BYPASS mode, don't call generic serial_puts, because
>> early print in bypass mode is running before code binary is relocated
>> to the link address.
>
> the link address of the function doesn't matter.  all Blackfin func calls are
> pcrel based, not absolute address calls.  i specifically crafted all of this
> early serial code so that this does work regardless of the address where the
> code happens to be executing.
>

When you developed the bfin serial driver, the generic serial API
serial_puts() is implemented in bfin serial driver directly. No such
link address issue.

void serial_putc(const char c)
 {
       uart_putc(UART_BASE, c);
 }

void serial_puts(const char *s)
 {
       while (*s)
               serial_putc(*s++);
 }

While in latest generic serial.c, serial_puts() calls uart_puts()
function in bfin serial via a pointer to the default serial_device
structure, which contains the link address in DRAM, other than a
relative jump.

void serial_puts(const char *s)
{
        get_current()->puts(s);
}

This has nothing to do with the patch " blackfin: Correct early serial
mess output in BYPASS boot mode.".

07f572c8 <_get_current>:
 7f572c8:       67 01           [--SP] = RETS;
 7f572ca:       58 a0           R0 = [P3 + 0x4];
 7f572cc:       a6 6f           SP += -0xc;             /* (-12) */
 7f572ce:       00 48           CC = !BITTST (R0, 0x0);         /* bit  0 */
 7f572d0:       08 18           IF CC JUMP 0x7f572e0 <_get_current+0x18>;
 7f572d2:       4a e1 f8 07     P2.H = 0x7f8;           /* (2040)
 P2=0x7f8e77c <_serial_devices> */
 7f572d6:       0a e1 80 e7     P2.L = 0xe780;          /* (-6272)
 P2=0x7f8e780 <_serial_current> */
 7f572da:       10 91           R0 = [P2];
 7f572dc:       00 0c           CC = R0 == 0x0;
 7f572de:       0b 14           IF !CC JUMP 0x7f572f4 <_get_current+0x2c> (BP);
> 7f572e0:       00 e3 02 02     CALL 0x7f576e4 <_default_serial_console>;
> 7f572e4:       00 0c           CC = R0 == 0x0;
 7f572e6:       07 14           IF !CC JUMP 0x7f572f4 <_get_current+0x2c> (BP);
 7f572e8:       40 e1 f7 07     R0.H = 0x7f7;           /* (2039)
 R0=0x7f7e764(133687140) */
 7f572ec:       00 e1 cc 03     R0.L = 0x3cc;           /* (972)
 R0=0x7f703cc(133628876) */
 7f572f0:       00 e3 8e 3e     CALL 0x7f5f00c <_panic>;
 7f572f4:       66 6c           SP += 0xc;              /* ( 12) */
 7f572f6:       27 01           RETS = [SP++];
 7f572f8:       10 00           RTS;
        ...

07f572fc <_serial_puts>:
 7f572fc:       78 05           [--SP] = (R7:7);
 7f572fe:       67 01           [--SP] = RETS;
 7f57300:       38 30           R7 = R0;
 7f57302:       a6 6f           SP += -0xc;             /* (-12) */
 7f57304:       ff e3 e2 ff     CALL 0x7f572c8 <_get_current>;
> 7f57308:       10 32           P2 = R0;
 7f5730a:       66 6c           SP += 0xc;              /* ( 12) */
 7f5730c:       27 01           RETS = [SP++];
 7f5730e:       07 30           R0 = R7;
 7f57310:       38 05           (R7:7) = [SP++];
 7f57312:       92 ae           P2 = [P2 + 0x28];
> 7f57314:       52 00           JUMP (P2);



Regards,

Sonic

> what doesn't work is if you try to use the early serial console with
> CONFIG_SYS_BFIN_UART (which allows all the serial devices to be selected on
> the fly).  but the header file specifically handles that:
> #ifndef CONFIG_DEBUG_EARLY_SERIAL
> # define CONFIG_SYS_BFIN_UART
> #endif
>
> i guess the problem is that this commit is wrong:
>
> commit 820edc18b5aefa8c82d420f6cba3e13b5631f9b8
> Author: Sonic Zhang <sonic.zhang@analog.com>
> Date:   Fri Nov 30 17:39:32 2012 +0800
>
>     blackfin: Correct early serial mess output in BYPASS boot mode.
>
> it shouldn't be messing with the addresses there
> -mike

Patch

diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c
index 36d2a5c..89290d6 100644
--- a/arch/blackfin/cpu/serial.c
+++ b/arch/blackfin/cpu/serial.c
@@ -197,13 +197,16 @@  static void uart_loop(uint32_t uart_base, int state)
 
 static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud)
 {
+#ifdef CONFIG_DEBUG_EARLY_SERIAL
+	serial_early_set_baud(uart_base, baud);
+#else
 	uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16)
 			- ANOMALY_05000230;
 
 	/* Program the divisor to get the baud rate we want */
 	serial_set_divisor(uart_base, divisor);
+#endif
 }
-#ifdef CONFIG_SYS_BFIN_UART
 
 static void uart_puts(uint32_t uart_base, const char *s)
 {
@@ -313,65 +316,39 @@  void bfin_serial_initialize(void)
 #endif
 }
 
-#else
-
-/* Symbol for our assembly to call. */
-void serial_set_baud(uint32_t baud)
-{
-	serial_early_set_baud(UART_BASE, baud);
-}
-
-/* Symbol for common u-boot code to call.
- * Setup the baudrate (brg: baudrate generator).
- */
-void serial_setbrg(void)
+#ifdef CONFIG_DEBUG_EARLY_SERIAL
+inline void uart_early_putc(uint32_t uart_base, const char c)
 {
-	serial_set_baud(gd->baudrate);
-}
-
-/* Symbol for our assembly to call. */
-void serial_initialize(void)
-{
-	serial_early_init(UART_BASE);
-}
-
-/* Symbol for common u-boot code to call. */
-int serial_init(void)
-{
-	serial_initialize();
-	serial_setbrg();
-	uart_lsr_clear(UART_BASE);
-	return 0;
-}
+	/* send a \r for compatibility */
+	if (c == '\n')
+		uart_early_putc(uart_base, '\r');
 
-int serial_tstc(void)
-{
-	return uart_tstc(UART_BASE);
-}
+	/* wait for the hardware fifo to clear up */
+	while (!(_lsr_read(pUART) & THRE))
+		continue;
 
-int serial_getc(void)
-{
-	return uart_getc(UART_BASE);
+	/* queue the character for transmission */
+	bfin_write(&pUART->thr, c);
+	SSYNC();
 }
 
-void serial_putc(const char c)
+void uart_early_puts(const char *s)
 {
-	uart_putc(UART_BASE, c);
+	while (*s)
+		uart_early_putc(UART_BASE, *s++);
 }
 
-void serial_puts(const char *s)
+/* Symbol for our assembly to call. */
+void _serial_early_set_baud(uint32_t baud)
 {
-	while (*s)
-		serial_putc(*s++);
+	serial_early_set_baud(UART_BASE, baud);
 }
 
-LOOP(
-void serial_loop(int state)
+/* Symbol for our assembly to call. */
+void _serial_early_init(void)
 {
-	uart_loop(UART_BASE, state);
+	serial_early_init(UART_BASE);
 }
-)
-
 #endif
 
 #endif
diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h
index d67fd81..87a337d 100644
--- a/arch/blackfin/cpu/serial.h
+++ b/arch/blackfin/cpu/serial.h
@@ -78,16 +78,16 @@  static inline void serial_early_puts(const char *s)
 #else
 
 .macro serial_early_init
-#if defined(CONFIG_DEBUG_EARLY_SERIAL) && defined(BFIN_BOOT_BYPASS)
-	call _serial_initialize;
+#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM)
+	call __serial_early_init;
 #endif
 .endm
 
 .macro serial_early_set_baud
-#if defined(CONFIG_DEBUG_EARLY_SERIAL) && defined(BFIN_BOOT_BYPASS)
+#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM)
 	R0.L = LO(CONFIG_BAUDRATE);
 	R0.H = HI(CONFIG_BAUDRATE);
-	call _serial_set_baud;
+	call __serial_early_set_baud;
 #endif
 .endm
 
@@ -121,7 +121,7 @@  static inline void serial_early_puts(const char *s)
 	R0.L = 7b; \
 	R0.H = 7b; \
 	update_serial_early_string_addr \
-	call _serial_puts;
+	call _uart_early_puts;
 #else
 # define serial_early_puts(str)
 #endif
diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h
index d3ae3a7..c986ba3 100644
--- a/include/configs/bfin_adi_common.h
+++ b/include/configs/bfin_adi_common.h
@@ -111,9 +111,6 @@ 
 #ifndef CONFIG_BAUDRATE
 # define CONFIG_BAUDRATE	57600
 #endif
-#ifndef CONFIG_DEBUG_EARLY_SERIAL
-# define CONFIG_SYS_BFIN_UART
-#endif
 
 /*
  * Debug Settings