serial: ns16550: support using pre-loader serial

- pass pre-loader serial configure by rk atags;
- it depends on serial aliases to find uart port;
- enabled by CONFIG_ROCKCHIP_USING_PRELOADER_SERIAL;

Change-Id: I6723cccc5e1f3dac77203b4cc19cdac631f5133b
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2018-10-09 19:45:00 +08:00 committed by Jianhong Chen
parent 701d3ebca8
commit 064eb49314
12 changed files with 138 additions and 2 deletions

View File

@ -84,6 +84,7 @@ ENTRY(_main)
/* set up gd here, outside any C code */
mov r9, r0
bl board_init_f_init_reserve
bl board_init_f_init_serial
mov r0, #0
bl board_init_f

View File

@ -83,6 +83,7 @@ ENTRY(_main)
/* set up gd here, outside any C code */
mov x18, x0
bl board_init_f_init_reserve
bl board_init_f_init_serial
mov x0, #0
bl board_init_f

View File

@ -519,6 +519,13 @@ config ROCKCHIP_PRELOADER_ATAGS
tos, U-Boot, etc. It delivers boot and configure information, shared with pre-loaders
and finally ends with U-Boot.
config ROCKCHIP_PRELOADER_SERIAL
bool "Rockchip pre-loader serial"
default y if ROCKCHIP_PRELOADER_ATAGS
help
This enable U-Boot using pre-loader atags serial configure to initialize console.
It denpends on serial aliases to find pre-loader serial number.
config GICV2
bool "ARM GICv2"

View File

@ -16,6 +16,7 @@
#include <asm/arch/clock.h>
#include <asm/arch/periph.h>
#include <asm/arch/boot_mode.h>
#include <asm/arch/rk_atags.h>
#ifdef CONFIG_DM_CHARGE_DISPLAY
#include <power/charge_display.h>
#endif
@ -274,6 +275,27 @@ void enable_caches(void)
dcache_enable();
}
#ifdef CONFIG_ROCKCHIP_PRELOADER_SERIAL
int board_init_f_init_serial(void)
{
struct tag *t = atags_get_tag(ATAG_SERIAL);
if (t) {
gd->serial.using_pre_serial = t->u.serial.enable;
gd->serial.addr = t->u.serial.addr;
gd->serial.baudrate = t->u.serial.baudrate;
gd->serial.id = t->u.serial.id;
debug("%s: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n",
__func__, gd->serial.using_pre_serial,
gd->serial.addr, gd->serial.baudrate,
gd->serial.id);
}
return 0;
}
#endif
#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
#include <fdt_support.h>
#include <usb.h>

View File

@ -117,7 +117,11 @@ __weak void board_add_ram_info(int use_default)
static int init_baud_rate(void)
{
gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE);
if (gd && gd->serial.using_pre_serial)
gd->baudrate = env_get_ulong("baudrate", 10, gd->serial.baudrate);
else
gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE);
return 0;
}
@ -142,6 +146,16 @@ static int display_text_info(void)
return 0;
}
#if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL)
static int announce_pre_serial(void)
{
if (gd && gd->serial.using_pre_serial)
printf("PreSerial: %d\n", gd->serial.id);
return 0;
}
#endif
static int announce_dram_init(void)
{
puts("DRAM: ");
@ -803,6 +817,9 @@ static const init_fnc_t init_sequence_f[] = {
#endif
#if defined(CONFIG_HARD_SPI)
init_func_spi,
#endif
#if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL)
announce_pre_serial,
#endif
announce_dram_init,
dram_init, /* configure available RAM banks */

View File

@ -172,7 +172,22 @@ static int initr_reloc_global_data(void)
static int initr_serial(void)
{
/*
* 1. Serial has been initialized in board_f.c => serial_init(), there is
* no special reason to init it again;
*
* 2. Pre-serial works depending on aliases to get pre-serial phandle when
* parse dtb. If CONFIG_USING_KERNEL_DTB is enabled, there are both kernel
* dtb and U-Boot dtb aliases added into aliases_lookup, these nodes have
* same names but different phanles(U-Boot nodes has high prior), this may
* lead a wrong aliases node finding if try to get a node after kenrel dtb
* unflattened, i.e. using U-Boot phandle to get kernel dtb node!!
*
* Notice: of_alias_dump() is provided to dump all aliases node.
*/
#ifndef CONFIG_USING_KERNEL_DTB
serial_initialize();
#endif
return 0;
}

View File

@ -129,6 +129,14 @@ void board_init_f_init_reserve(ulong base)
#endif
}
/*
* Board-specific Platform code can init serial earlier if needed
*/
__weak int board_init_f_init_serial(void)
{
return 0;
}
/*
* Board-specific Platform code can reimplement show_boot_progress () if needed
*/

View File

@ -804,5 +804,17 @@ struct device_node *of_alias_dump(void)
struct device_node *of_get_stdout(void)
{
struct device_node *np;
if (gd && gd->serial.using_pre_serial) {
np = of_alias_get_dev("serial", gd->serial.id);
if (!np)
printf("Can't find alias serial%d\n", gd->serial.id);
else
debug("Find alias serial: %s\n", np->full_name);
of_stdout = np;
}
return of_stdout;
}

View File

@ -254,6 +254,13 @@ static inline void _debug_uart_init(void)
*/
baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
if (gd && gd->serial.using_pre_serial) {
com_port = (struct NS16550 *)gd->serial.addr;
baud_divisor = ns16550_calc_divisor(com_port,
CONFIG_DEBUG_UART_CLOCK, gd->serial.baudrate);
}
serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
serial_dout(&com_port->mcr, UART_MCRVAL);
serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
@ -268,6 +275,9 @@ static inline void _debug_uart_putc(int ch)
{
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
if (gd && gd->serial.using_pre_serial)
com_port = (struct NS16550 *)gd->serial.addr;
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
;
serial_dout(&com_port->thr, ch);
@ -288,6 +298,13 @@ static inline void _debug_uart_init(void)
baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
if (gd && gd->serial.using_pre_serial) {
com_port = (struct NS16550 *)gd->serial.addr;
baud_divisor = ns16550_calc_divisor(com_port,
CONFIG_DEBUG_UART_CLOCK, gd->serial.baudrate);
}
serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
serial_dout(&com_port->mdr1, 0x7);
serial_dout(&com_port->mcr, UART_MCRVAL);
@ -304,6 +321,9 @@ static inline void _debug_uart_putc(int ch)
{
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
if (gd && gd->serial.using_pre_serial)
com_port = (struct NS16550 *)gd->serial.addr;
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
;
serial_dout(&com_port->thr, ch);
@ -456,6 +476,10 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
plat->base = addr;
#else
if (gd && gd->serial.using_pre_serial)
addr = gd->serial.addr;
plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE);
#endif

View File

@ -54,6 +54,23 @@ static int serial_check_stdout(const void *blob, struct udevice **devp)
}
if (node < 0)
node = fdt_path_offset(blob, "console");
if (gd && gd->serial.using_pre_serial) {
const char *serial_path;
char serial[12];
snprintf(serial, 12, "serial%d", gd->serial.id);
serial_path = fdt_get_alias(blob, serial);
if (serial_path) {
debug("Find alias %s, path: %s\n", serial, serial_path);
node = fdt_path_offset(blob, serial_path);
if (node < 0)
printf("Can't find %s by path\n", serial);
} else {
printf("Can't find alias %s\n", serial);
}
}
if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp))
return 0;

View File

@ -31,6 +31,13 @@ struct pm_ctx {
unsigned long suspend_regs[15];
};
struct pre_serial {
u32 using_pre_serial;
u32 id;
u32 baudrate;
ulong addr;
};
typedef struct global_data {
bd_t *bd;
unsigned long flags;
@ -126,7 +133,7 @@ typedef struct global_data {
#ifdef CONFIG_BOOTSTAGE_PRINTF_TIMESTAMP
int new_line;
#endif
struct pre_serial serial;
#ifdef CONFIG_LOG
int log_drop_count; /* Number of dropped log messages */
int default_log_level; /* For devices with no filters */

View File

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