dm: serial: support always use uart debug mode

In this mode, uart debug is initialized depends on
configuration from pre-loader or CONFIG_UART_DEBUG_.

The serial is not care about dts "stdout-path" and
not register into console framework any more. It's
nice to use pre-loader serial and make serial easy
to configure.

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Change-Id: If4c68229d76b6f1710a35e3ef9a2a91cb306fa9c
This commit is contained in:
Joseph Chen 2020-09-27 16:47:48 +08:00
parent 93586e70e1
commit 034db99592
11 changed files with 278 additions and 46 deletions

View File

@ -84,9 +84,8 @@ ENTRY(_main)
/* set up gd here, outside any C code */ /* set up gd here, outside any C code */
mov r9, r0 mov r9, r0
bl board_init_f_init_reserve bl board_init_f_init_reserve
bl board_init_f_init_serial bl board_init_f_boot_flags
mov r0, #0
bl board_init_f bl board_init_f
#if ! defined(CONFIG_SPL_BUILD) #if ! defined(CONFIG_SPL_BUILD)

View File

@ -101,9 +101,8 @@ ENTRY(_main)
/* set up gd here, outside any C code */ /* set up gd here, outside any C code */
mov x18, x0 mov x18, x0
bl board_init_f_init_reserve bl board_init_f_init_reserve
bl board_init_f_init_serial bl board_init_f_boot_flags
mov x0, #0
bl board_init_f bl board_init_f
#if (defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_SKIP_RELOCATE)) || \ #if (defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_SKIP_RELOCATE)) || \

View File

@ -119,8 +119,8 @@ __weak void board_add_ram_info(int use_default)
static int init_baud_rate(void) static int init_baud_rate(void)
{ {
if (gd && gd->serial.using_pre_serial) if (gd && gd->serial.baudrate)
gd->baudrate = env_get_ulong("baudrate", 10, gd->serial.baudrate); gd->baudrate = gd->serial.baudrate;
else else
gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE); gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE);
@ -148,15 +148,22 @@ static int display_text_info(void)
return 0; return 0;
} }
#if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) static int announce_serial(void)
static int announce_pre_serial(void)
{ {
if (gd && gd->serial.using_pre_serial) if (gd && gd->serial.using_pre_serial)
printf("PreSerial: %d\n", gd->serial.id); printf("PreSerial: %d, ", gd->serial.id);
else
printf("Serial: ");
#ifdef CONFIG_DEBUG_UART_ALWAYS
printf("raw");
#else
printf("console");
#endif
printf(", 0x%lx\n", gd->serial.addr);
return 0; return 0;
} }
#endif
static int announce_dram_init(void) static int announce_dram_init(void)
{ {
@ -861,9 +868,8 @@ static const init_fnc_t init_sequence_f[] = {
#if defined(CONFIG_HARD_SPI) #if defined(CONFIG_HARD_SPI)
init_func_spi, init_func_spi,
#endif #endif
#if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) announce_serial,
announce_pre_serial,
#endif
announce_dram_init, announce_dram_init,
dram_init, /* configure available RAM banks */ dram_init, /* configure available RAM banks */
#ifdef CONFIG_POST #ifdef CONFIG_POST
@ -954,10 +960,6 @@ void board_init_f(ulong boot_flags)
gd->flags = boot_flags; gd->flags = boot_flags;
gd->have_console = 0; gd->have_console = 0;
#if defined(CONFIG_DISABLE_CONSOLE)
gd->flags |= GD_FLG_DISABLE_CONSOLE;
#endif
if (initcall_run_list(init_sequence_f)) if (initcall_run_list(init_sequence_f))
hang(); hang();

View File

@ -408,10 +408,8 @@ int fprintf(int file, const char *fmt, ...)
int getc(void) int getc(void)
{ {
#ifdef CONFIG_DISABLE_CONSOLE if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE)
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
return 0; return 0;
#endif
if (!gd->have_console) if (!gd->have_console)
return 0; return 0;
@ -436,10 +434,8 @@ int getc(void)
int tstc(void) int tstc(void)
{ {
#ifdef CONFIG_DISABLE_CONSOLE if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE)
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
return 0; return 0;
#endif
if (!gd->have_console) if (!gd->have_console)
return 0; return 0;
@ -460,10 +456,8 @@ int tstc(void)
void flushc(void) void flushc(void)
{ {
#ifdef CONFIG_DISABLE_CONSOLE if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE)
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
return; return;
#endif
if (gd->flags & GD_FLG_DEVINIT) if (gd->flags & GD_FLG_DEVINIT)
fclear(stdout); fclear(stdout);
@ -520,10 +514,8 @@ static inline void print_pre_console_buffer(int flushpoint) {}
void putc(const char c) void putc(const char c)
{ {
#ifdef CONFIG_DISABLE_CONSOLE
if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE) if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE)
return; return;
#endif
#ifdef CONFIG_DEBUG_UART #ifdef CONFIG_DEBUG_UART
/* if we don't have a console yet, use the debug UART */ /* if we don't have a console yet, use the debug UART */

View File

@ -130,10 +130,15 @@ void board_init_f_init_reserve(ulong base)
} }
/* /*
* Board-specific Platform code can init serial earlier if needed * Board-specific Platform code can init boot flags if needed
*/ */
__weak int board_init_f_init_serial(void) __weak int board_init_f_boot_flags(void)
{ {
gd->baudrate = CONFIG_BAUDRATE;
gd->serial.baudrate = CONFIG_BAUDRATE;
gd->serial.addr = CONFIG_DEBUG_UART_BASE;
gd->serial.using_pre_serial = 0;
return 0; return 0;
} }

View File

@ -346,6 +346,11 @@ config DEBUG_UART_SKIP_INIT
Select this if the UART you want to use for debug output is already Select this if the UART you want to use for debug output is already
initialized by the time U-Boot starts its execution. initialized by the time U-Boot starts its execution.
config DEBUG_UART_ALWAYS
bool "Always use debug UART mode"
help
Say y to always use debug UART, skip complicated console UART register.
config ALTERA_JTAG_UART config ALTERA_JTAG_UART
bool "Altera JTAG UART support" bool "Altera JTAG UART support"
depends on DM_SERIAL depends on DM_SERIAL

View File

@ -246,6 +246,12 @@ static inline void _debug_uart_init(void)
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
int baud_divisor; int baud_divisor;
if (gd && gd->flags & GD_FLG_DISABLE_CONSOLE)
return;
if (gd && gd->serial.using_pre_serial)
return;
/* /*
* We copy the code from above because it is already horribly messy. * We copy the code from above because it is already horribly messy.
* Trying to refactor to nicely remove the duplication doesn't seem * Trying to refactor to nicely remove the duplication doesn't seem
@ -266,13 +272,109 @@ static inline void _debug_uart_init(void)
static inline void _debug_uart_putc(int ch) static inline void _debug_uart_putc(int ch)
{ {
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; struct NS16550 *com_port;
if (gd && gd->flags & GD_FLG_DISABLE_CONSOLE)
return;
if (gd && gd->serial.addr)
com_port = (struct NS16550 *)gd->serial.addr;
else
com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
; ;
serial_dout(&com_port->thr, ch); serial_dout(&com_port->thr, ch);
} }
static inline int _debug_uart_getc(void)
{
struct NS16550 *com_port;
if (gd && gd->flags & GD_FLG_DISABLE_CONSOLE)
return 0;
if (gd && gd->serial.addr)
com_port = (struct NS16550 *)gd->serial.addr;
else
com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
while (!(serial_din(&com_port->lsr) & UART_LSR_DR))
;
return serial_din(&com_port->rbr);
}
static inline int _debug_uart_tstc(int input)
{
struct NS16550 *com_port;
if (gd && gd->flags & GD_FLG_DISABLE_CONSOLE)
return 0;
if (gd && gd->serial.addr)
com_port = (struct NS16550 *)gd->serial.addr;
else
com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
if (input)
return serial_din(&com_port->lsr) & UART_LSR_DR ? 1 : 0;
else
return serial_din(&com_port->lsr) & UART_LSR_THRE ? 0 : 1;
}
static inline int _debug_uart_clrc(void)
{
struct NS16550 *com_port;
if (gd && gd->flags & GD_FLG_DISABLE_CONSOLE)
return 0;
if (gd && gd->serial.addr)
com_port = (struct NS16550 *)gd->serial.addr;
else
com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
/*
* Wait fifo flush.
*
* UART_USR: bit2 trans_fifo_empty:
* 0 = Transmit FIFO is not empty
* 1 = Transmit FIFO is empty
*/
while (!(serial_din(&com_port->rbr + 0x1f) & 0x04))
;
return 0;
}
/* should use gd->baudrate, it can be updated by env callback: on_baudrate() */
static inline int _debug_uart_setbrg(void)
{
struct NS16550 *com_port;
int baud_divisor;
if (gd && gd->flags & GD_FLG_DISABLE_CONSOLE)
return 0;
if (gd && gd->serial.addr) {
com_port = (struct NS16550 *)gd->serial.addr;
baud_divisor = ns16550_calc_divisor(com_port,
CONFIG_DEBUG_UART_CLOCK, gd->baudrate);
} else {
com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
baud_divisor = ns16550_calc_divisor(com_port,
CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
}
serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
serial_dout(&com_port->dll, baud_divisor & 0xff);
serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
serial_dout(&com_port->lcr, UART_LCRVAL);
return 0;
}
DEBUG_UART_FUNCS DEBUG_UART_FUNCS
#endif #endif
@ -318,8 +420,15 @@ static int ns16550_serial_putc(struct udevice *dev, const char ch)
{ {
struct NS16550 *const com_port = dev_get_priv(dev); struct NS16550 *const com_port = dev_get_priv(dev);
if (!(serial_in(&com_port->lsr) & UART_LSR_THRE)) /*
return -EAGAIN; * Use fifo function.
*
* UART_USR: bit1 trans_fifo_not_full:
* 0 = Transmit FIFO is full;
* 1 = Transmit FIFO is not full;
*/
while (!(serial_in(&com_port->rbr + 0x1f) & 0x02))
;
serial_out(ch, &com_port->thr); serial_out(ch, &com_port->thr);
/* /*
@ -367,6 +476,23 @@ static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
return 0; return 0;
} }
static int ns16550_serial_clear(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
/*
* Wait fifo flush.
*
* UART_USR: bit2 trans_fifo_empty:
* 0 = Transmit FIFO is not empty
* 1 = Transmit FIFO is empty
*/
while (!(serial_in(&com_port->rbr + 0x1f) & 0x04))
;
return 0;
}
int ns16550_serial_probe(struct udevice *dev) int ns16550_serial_probe(struct udevice *dev)
{ {
struct NS16550 *const com_port = dev_get_priv(dev); struct NS16550 *const com_port = dev_get_priv(dev);
@ -442,7 +568,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
if (!IS_ERR_VALUE(err)) if (!IS_ERR_VALUE(err))
plat->clock = err; plat->clock = err;
} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) { } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
debug("ns16550 failed to get clock\n"); printf("ns16550 failed to get clock, err=%d\n", err);
return err; return err;
} }
@ -467,8 +593,10 @@ const struct dm_serial_ops ns16550_serial_ops = {
.pending = ns16550_serial_pending, .pending = ns16550_serial_pending,
.getc = ns16550_serial_getc, .getc = ns16550_serial_getc,
.setbrg = ns16550_serial_setbrg, .setbrg = ns16550_serial_setbrg,
.clear = ns16550_serial_clear,
}; };
#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
/* /*
* Please consider existing compatible strings before adding a new * Please consider existing compatible strings before adding a new
@ -491,8 +619,6 @@ static const struct udevice_id ns16550_serial_ids[] = {
}; };
#endif /* OF_CONTROL && !OF_PLATDATA */ #endif /* OF_CONTROL && !OF_PLATDATA */
#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
/* TODO(sjg@chromium.org): Integrate this into a macro like CONFIG_IS_ENABLED */ /* TODO(sjg@chromium.org): Integrate this into a macro like CONFIG_IS_ENABLED */
#if !defined(CONFIG_TPL_BUILD) || defined(CONFIG_TPL_DM_SERIAL) #if !defined(CONFIG_TPL_BUILD) || defined(CONFIG_TPL_DM_SERIAL)
U_BOOT_DRIVER(ns16550_serial) = { U_BOOT_DRIVER(ns16550_serial) = {

View File

@ -5,6 +5,7 @@
*/ */
#include <common.h> #include <common.h>
#include <debug_uart.h>
#include <dm.h> #include <dm.h>
#include <environment.h> #include <environment.h>
#include <errno.h> #include <errno.h>
@ -27,6 +28,7 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
#error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work" #error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work"
#endif #endif
#ifndef CONFIG_DEBUG_UART_ALWAYS
static int serial_check_stdout(const void *blob, struct udevice **devp) static int serial_check_stdout(const void *blob, struct udevice **devp)
{ {
int node; int node;
@ -134,6 +136,9 @@ int serial_init(void)
return 0; return 0;
} }
#else
int serial_init(void) { return 0; }
#endif
/* Called after relocation */ /* Called after relocation */
void serial_initialize(void) void serial_initialize(void)
@ -184,6 +189,14 @@ static int __serial_tstc(struct udevice *dev)
return 1; return 1;
} }
static void __serial_clear(struct udevice *dev)
{
struct dm_serial_ops *ops = serial_get_ops(dev);
if (ops->clear)
ops->clear(dev);
}
#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) #if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
static int _serial_tstc(struct udevice *dev) static int _serial_tstc(struct udevice *dev)
{ {
@ -226,42 +239,108 @@ void serial_putc(char ch)
{ {
if (gd->cur_serial_dev) if (gd->cur_serial_dev)
_serial_putc(gd->cur_serial_dev, ch); _serial_putc(gd->cur_serial_dev, ch);
else
printch(ch);
} }
void serial_puts(const char *str) void serial_puts(const char *str)
{ {
if (gd->cur_serial_dev) if (gd->cur_serial_dev)
_serial_puts(gd->cur_serial_dev, str); _serial_puts(gd->cur_serial_dev, str);
else
printascii(str);
} }
int serial_getc(void) int serial_getc(void)
{ {
if (!gd->cur_serial_dev) if (gd->cur_serial_dev)
return 0; return _serial_getc(gd->cur_serial_dev);
else
return _serial_getc(gd->cur_serial_dev); return debug_uart_getc();
} }
int serial_tstc(void) int serial_tstc(void)
{ {
if (!gd->cur_serial_dev) if (gd->cur_serial_dev)
return 0; return _serial_tstc(gd->cur_serial_dev);
else
return _serial_tstc(gd->cur_serial_dev); return debug_uart_tstc();
} }
void serial_setbrg(void) void serial_setbrg(void)
{ {
struct dm_serial_ops *ops; struct dm_serial_ops *ops;
if (!gd->cur_serial_dev) if (!gd->cur_serial_dev) {
debug_uart_setbrg();
return; return;
}
ops = serial_get_ops(gd->cur_serial_dev); ops = serial_get_ops(gd->cur_serial_dev);
if (ops->setbrg) if (ops->setbrg)
ops->setbrg(gd->cur_serial_dev, gd->baudrate); ops->setbrg(gd->cur_serial_dev, gd->baudrate);
} }
void serial_clear(void)
{
if (gd->cur_serial_dev)
__serial_clear(gd->cur_serial_dev);
else
debug_uart_clrc();
}
void serial_dev_putc(struct udevice *dev, char ch)
{
if (!dev)
return;
_serial_putc(dev, ch);
}
void serial_dev_puts(struct udevice *dev, const char *str)
{
if (!dev)
return;
_serial_puts(dev, str);
}
int serial_dev_getc(struct udevice *dev)
{
if (!dev)
return 0;
return _serial_getc(dev);
}
int serial_dev_tstc(struct udevice *dev)
{
if (!dev)
return 0;
return _serial_tstc(dev);
}
void serial_dev_setbrg(struct udevice *dev, int baudrate)
{
struct dm_serial_ops *ops;
if (!dev)
return;
ops = serial_get_ops(dev);
if (ops->setbrg)
ops->setbrg(dev, baudrate);
}
void serial_dev_clear(struct udevice *dev)
{
if (!dev)
return;
__serial_clear(dev);
}
void serial_stdio_init(void) void serial_stdio_init(void)
{ {
} }

View File

@ -33,6 +33,7 @@ struct pm_ctx {
struct pre_serial { struct pre_serial {
u32 using_pre_serial; u32 using_pre_serial;
u32 enable;
u32 id; u32 id;
u32 baudrate; u32 baudrate;
ulong addr; ulong addr;

View File

@ -149,7 +149,7 @@ void board_init_f_init_reserve(ulong base);
/* /*
* Board-specific Platform code can init serial earlier if needed * Board-specific Platform code can init serial earlier if needed
*/ */
__weak int board_init_f_init_serial(void); __weak int board_init_f_boot_flags(void);
/** /**
* arch_setup_gd() - Set up the global_data pointer * arch_setup_gd() - Set up the global_data pointer

View File

@ -76,6 +76,10 @@ static inline void board_debug_uart_init(void)
* @ch: Character to output * @ch: Character to output
*/ */
void printch(int ch); void printch(int ch);
int debug_uart_getc(void);
int debug_uart_tstc(void);
int debug_uart_clrc(void);
int debug_uart_setbrg(void);
/** /**
* printascii() - Output an ASCII string to the debug UART * printascii() - Output an ASCII string to the debug UART
@ -145,6 +149,26 @@ void printdec(uint value);
{ \ { \
_printch(ch); \ _printch(ch); \
} \ } \
\
int debug_uart_getc(void)\
{ \
return _debug_uart_getc(); \
} \
\
int debug_uart_tstc(void)\
{ \
return _debug_uart_tstc(true); \
} \
\
int debug_uart_clrc(void)\
{ \
return _debug_uart_clrc(); \
} \
\
int debug_uart_setbrg(void)\
{ \
return _debug_uart_setbrg(); \
} \
\ \
void printascii(const char *str) \ void printascii(const char *str) \
{ \ { \