[U-Boot] [PATCH 0/3] rockchip: Use the standard debug UART on rockchip

The RK3036 has only 8KB of RAM available for SPL. At present it uses its own debug UART code.
By allowing the ns16550 driver to provide a debug UART without providing a full serial driver, we can enable a UART with a very small overhead. This requires addition Kconfig options. The debug UART supports printhex8(), printascii() and a few other functions.
The root driver and uclass are pulled in by this series, but their size is very small. It would possible to drop these by disabling CONFIG_DM_SERIAL. However the ns16550 driver makes this hard, due to it supporting operation without driver model, and operating differently in this case.
Simon Glass (3): dm: serial: Allow the UART driver to be dropped from the image dm: ns16550: Allow the driver to be omitted if requested rockchip: Use the debug UART on rk3036
arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/rk3036-board-spl.c | 9 ++++- arch/arm/mach-rockchip/rk_early_print.c | 63 ------------------------------- configs/evb-rk3036_defconfig | 6 +++ drivers/serial/Kconfig | 20 ++++++++++ drivers/serial/ns16550.c | 2 + drivers/serial/serial-uclass.c | 2 + include/configs/rk3036_common.h | 2 + 8 files changed, 40 insertions(+), 65 deletions(-) delete mode 100644 arch/arm/mach-rockchip/rk_early_print.c

In very very space-constrained devices even the full UART driver is too large. In this case the debug UART can still be used in some cases.
Add options to enable the UART driver in SPL and U-Boot proper. Enable both options by default.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/serial/Kconfig | 20 ++++++++++++++++++++ drivers/serial/serial-uclass.c | 2 ++ 2 files changed, 22 insertions(+)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1fc287e..04541c9 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -15,6 +15,26 @@ config REQUIRE_SERIAL_CONSOLE during serial port initialization (default y). Set this to n on boards which have no debug serial port whatsoever.
+config SERIAL_PRESENT + bool "Provide a serial driver" + depends on DM_SERIAL + default y + help + In very space-constrained devices even the full UART driver is too + large. In this case the debug UART can still be used in some cases. + This option enables the full UART in U-Boot, so if is it disabled, + the full UART driver will be omitted, thus saving space. + +config SPL_SERIAL_PRESENT + bool "Provide a serial driver in SPL" + depends on DM_SERIAL + default y + help + In very space-constrained devices even the full UART driver is too + large. In this case the debug UART can still be used in some cases. + This option enables the full UART in SPL, so if is it disabled, + the full UART driver will be omitted, thus saving space. + config DM_SERIAL bool "Enable Driver Model for serial drivers" depends on DM diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 4bf9a5c..95c3b91 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -287,6 +287,7 @@ static int on_baudrate(const char *name, const char *value, enum env_op op, } U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT) static int serial_post_probe(struct udevice *dev) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -356,3 +357,4 @@ UCLASS_DRIVER(serial) = { .pre_remove = serial_pre_remove, .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), }; +#endif

Hi Simon,
On 2015年12月14日 12:36, Simon Glass wrote:
In very very space-constrained devices even the full UART driver is too large. In this case the debug UART can still be used in some cases.
Add options to enable the UART driver in SPL and U-Boot proper. Enable both options by default.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/serial/Kconfig | 20 ++++++++++++++++++++ drivers/serial/serial-uclass.c | 2 ++ 2 files changed, 22 insertions(+)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1fc287e..04541c9 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -15,6 +15,26 @@ config REQUIRE_SERIAL_CONSOLE during serial port initialization (default y). Set this to n on boards which have no debug serial port whatsoever.
+config SERIAL_PRESENT
- bool "Provide a serial driver"
- depends on DM_SERIAL
- default y
- help
In very space-constrained devices even the full UART driver is too
large. In this case the debug UART can still be used in some cases.
This option enables the full UART in U-Boot, so if is it disabled,
the full UART driver will be omitted, thus saving space.
+config SPL_SERIAL_PRESENT
- bool "Provide a serial driver in SPL"
- depends on DM_SERIAL
- default y
- help
In very space-constrained devices even the full UART driver is too
large. In this case the debug UART can still be used in some cases.
This option enables the full UART in SPL, so if is it disabled,
the full UART driver will be omitted, thus saving space.
- config DM_SERIAL bool "Enable Driver Model for serial drivers" depends on DM
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 4bf9a5c..95c3b91 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -287,6 +287,7 @@ static int on_baudrate(const char *name, const char *value, enum env_op op, } U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT) static int serial_post_probe(struct udevice *dev) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -356,3 +357,4 @@ UCLASS_DRIVER(serial) = { .pre_remove = serial_pre_remove, .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), }; +#endif
Reviewed-by: Thomas Chou thomas@wytron.com.tw

On 13 December 2015 at 21:36, Simon Glass sjg@chromium.org wrote:
In very very space-constrained devices even the full UART driver is too large. In this case the debug UART can still be used in some cases.
Add options to enable the UART driver in SPL and U-Boot proper. Enable both options by default.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/serial/Kconfig | 20 ++++++++++++++++++++ drivers/serial/serial-uclass.c | 2 ++ 2 files changed, 22 insertions(+)
[snip]
Due to a build warning, added an #ifdef around serial_stub_putc() for cm_t43, and:
Applied to u-boot-dm/next.

Allow the ns16550 debug UART to be used without the full driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/serial/ns16550.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 3fab3f1..2025423 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -440,6 +440,7 @@ static const struct udevice_id ns16550_serial_ids[] = { }; #endif
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT) U_BOOT_DRIVER(ns16550_serial) = { .name = "ns16550_serial", .id = UCLASS_SERIAL, @@ -453,4 +454,5 @@ U_BOOT_DRIVER(ns16550_serial) = { .ops = &ns16550_serial_ops, .flags = DM_FLAG_PRE_RELOC, }; +#endif #endif /* CONFIG_DM_SERIAL */

Hi Simon,
On 2015年12月14日 12:36, Simon Glass wrote:
Allow the ns16550 debug UART to be used without the full driver.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/serial/ns16550.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 3fab3f1..2025423 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -440,6 +440,7 @@ static const struct udevice_id ns16550_serial_ids[] = { }; #endif
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT) U_BOOT_DRIVER(ns16550_serial) = { .name = "ns16550_serial", .id = UCLASS_SERIAL, @@ -453,4 +454,5 @@ U_BOOT_DRIVER(ns16550_serial) = { .ops = &ns16550_serial_ops, .flags = DM_FLAG_PRE_RELOC, }; +#endif #endif /* CONFIG_DM_SERIAL */
Reviewed-by: Thomas Chou thomas@wytron.com.tw

Applied to u-boot-dm/next.

Rather than using a new debug UART implementation, use the standard one provided by U-Boot. Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/rk3036-board-spl.c | 9 ++++- arch/arm/mach-rockchip/rk_early_print.c | 63 ------------------------------- configs/evb-rk3036_defconfig | 6 +++ include/configs/rk3036_common.h | 2 + 5 files changed, 16 insertions(+), 65 deletions(-) delete mode 100644 arch/arm/mach-rockchip/rk_early_print.c
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b703c3c..1cc4a96 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -11,7 +11,6 @@ else obj-$(CONFIG_ROCKCHIP_RK3288) += board.o endif obj-y += rk_timer.o -obj-y += rk_early_print.o obj-$(CONFIG_$(SPL_)ROCKCHIP_COMMON) += common.o obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/ obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/ diff --git a/arch/arm/mach-rockchip/rk3036-board-spl.c b/arch/arm/mach-rockchip/rk3036-board-spl.c index 3a1491c..8015481 100644 --- a/arch/arm/mach-rockchip/rk3036-board-spl.c +++ b/arch/arm/mach-rockchip/rk3036-board-spl.c @@ -5,6 +5,7 @@ */
#include <common.h> +#include <debug_uart.h> #include <asm/io.h> #include <asm/arch/grf_rk3036.h> #include <asm/arch/hardware.h> @@ -34,7 +35,7 @@ void board_init_f(ulong dummy) GPIO1C2_MASK << GPIO1C2_SHIFT, GPIO1C3_UART2_SOUT << GPIO1C3_SHIFT | GPIO1C2_UART2_SIN << GPIO1C2_SHIFT); - rk_uart_init((void *)DEBUG_UART_BASE); + debug_uart_init(); #endif rockchip_timer_init(); sdram_init(); @@ -53,3 +54,9 @@ void board_init_r(gd_t *id, ulong dest_addr) while (1) ; } + +void hang(void) +{ + while (1) + ; +} diff --git a/arch/arm/mach-rockchip/rk_early_print.c b/arch/arm/mach-rockchip/rk_early_print.c deleted file mode 100644 index a1c14b0..0000000 --- a/arch/arm/mach-rockchip/rk_early_print.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * (C) Copyright 2015 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <asm/io.h> -#include <asm/arch/uart.h> -#include <common.h> - -static struct rk_uart *uart_ptr; - -static void uart_wrtie_byte(char byte) -{ - writel(byte, &uart_ptr->rbr); - while (!(readl(&uart_ptr->lsr) & 0x40)) - ; -} - -void print(char *s) -{ - while (*s) { - if (*s == '\n') - uart_wrtie_byte('\r'); - uart_wrtie_byte(*s); - s++; - } -} - -void print_hex(unsigned int n) -{ - int i; - int temp; - - uart_wrtie_byte('0'); - uart_wrtie_byte('x'); - - for (i = 8; i > 0; i--) { - temp = (n >> (i - 1) * 4) & 0x0f; - if (temp < 10) - uart_wrtie_byte((char)(temp + '0')); - else - uart_wrtie_byte((char)(temp - 10 + 'a')); - } - uart_wrtie_byte('\n'); - uart_wrtie_byte('\r'); -} - -/* - * TODO: since rk3036 only 4K sram to use in SPL, for saving space, - * we implement uart driver this way, we should convert this to use - * ns16550 driver in future, which support DEBUG_UART in the standard way - */ -void rk_uart_init(void *base) -{ - uart_ptr = (struct rk_uart *)base; - writel(0x83, &uart_ptr->lcr); - writel(0x0d, &uart_ptr->rbr); - writel(0x03, &uart_ptr->lcr); - - /* fifo enable, sfe is shadow register of FCR[0] */ - writel(0x01, &uart_ptr->sfe); -} diff --git a/configs/evb-rk3036_defconfig b/configs/evb-rk3036_defconfig index 2e915ff..c196bd6 100644 --- a/configs/evb-rk3036_defconfig +++ b/configs/evb-rk3036_defconfig @@ -24,3 +24,9 @@ CONFIG_DM_MMC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_CMD_DHRYSTONE=y CONFIG_ERRNO_STR=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_NS16550=y +CONFIG_DEBUG_UART_BASE=0x20068000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +# CONFIG_SPL_SERIAL_PRESENT is not set diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h index f753e68..d22ea74 100644 --- a/include/configs/rk3036_common.h +++ b/include/configs/rk3036_common.h @@ -24,6 +24,8 @@ #define CONFIG_SYS_TIMER_BASE 0x200440a0 /* TIMER5 */ #define CONFIG_SYS_TIMER_COUNTER (CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_SPL_SERIAL_SUPPORT + #define CONFIG_SYS_NS16550 #define CONFIG_SYS_NS16550_MEM32

Hi Simon,
On 2015年12月14日 12:37, Simon Glass wrote:
Rather than using a new debug UART implementation, use the standard one provided by U-Boot. Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/rk3036-board-spl.c | 9 ++++- arch/arm/mach-rockchip/rk_early_print.c | 63 ------------------------------- configs/evb-rk3036_defconfig | 6 +++ include/configs/rk3036_common.h | 2 + 5 files changed, 16 insertions(+), 65 deletions(-) delete mode 100644 arch/arm/mach-rockchip/rk_early_print.c
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b703c3c..1cc4a96 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -11,7 +11,6 @@ else obj-$(CONFIG_ROCKCHIP_RK3288) += board.o endif obj-y += rk_timer.o -obj-y += rk_early_print.o obj-$(CONFIG_$(SPL_)ROCKCHIP_COMMON) += common.o obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/ obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/ diff --git a/arch/arm/mach-rockchip/rk3036-board-spl.c b/arch/arm/mach-rockchip/rk3036-board-spl.c index 3a1491c..8015481 100644 --- a/arch/arm/mach-rockchip/rk3036-board-spl.c +++ b/arch/arm/mach-rockchip/rk3036-board-spl.c @@ -5,6 +5,7 @@ */
#include <common.h> +#include <debug_uart.h> #include <asm/io.h> #include <asm/arch/grf_rk3036.h> #include <asm/arch/hardware.h> @@ -34,7 +35,7 @@ void board_init_f(ulong dummy) GPIO1C2_MASK << GPIO1C2_SHIFT, GPIO1C3_UART2_SOUT << GPIO1C3_SHIFT | GPIO1C2_UART2_SIN << GPIO1C2_SHIFT);
- rk_uart_init((void *)DEBUG_UART_BASE);
- debug_uart_init(); #endif rockchip_timer_init(); sdram_init();
@@ -53,3 +54,9 @@ void board_init_r(gd_t *id, ulong dest_addr) while (1) ; }
+void hang(void) +{
- while (1)
;
+} diff --git a/arch/arm/mach-rockchip/rk_early_print.c b/arch/arm/mach-rockchip/rk_early_print.c deleted file mode 100644 index a1c14b0..0000000 --- a/arch/arm/mach-rockchip/rk_early_print.c +++ /dev/null @@ -1,63 +0,0 @@ -/*
- (C) Copyright 2015 Rockchip Electronics Co., Ltd
- SPDX-License-Identifier: GPL-2.0+
- */
-#include <asm/io.h> -#include <asm/arch/uart.h> -#include <common.h>
-static struct rk_uart *uart_ptr;
-static void uart_wrtie_byte(char byte) -{
- writel(byte, &uart_ptr->rbr);
- while (!(readl(&uart_ptr->lsr) & 0x40))
;
-}
-void print(char *s) -{
- while (*s) {
if (*s == '\n')
uart_wrtie_byte('\r');
uart_wrtie_byte(*s);
s++;
- }
-}
-void print_hex(unsigned int n) -{
- int i;
- int temp;
- uart_wrtie_byte('0');
- uart_wrtie_byte('x');
- for (i = 8; i > 0; i--) {
temp = (n >> (i - 1) * 4) & 0x0f;
if (temp < 10)
uart_wrtie_byte((char)(temp + '0'));
else
uart_wrtie_byte((char)(temp - 10 + 'a'));
- }
- uart_wrtie_byte('\n');
- uart_wrtie_byte('\r');
-}
-/*
- TODO: since rk3036 only 4K sram to use in SPL, for saving space,
- we implement uart driver this way, we should convert this to use
- ns16550 driver in future, which support DEBUG_UART in the standard way
- */
-void rk_uart_init(void *base) -{
- uart_ptr = (struct rk_uart *)base;
- writel(0x83, &uart_ptr->lcr);
- writel(0x0d, &uart_ptr->rbr);
- writel(0x03, &uart_ptr->lcr);
- /* fifo enable, sfe is shadow register of FCR[0] */
- writel(0x01, &uart_ptr->sfe);
-} diff --git a/configs/evb-rk3036_defconfig b/configs/evb-rk3036_defconfig index 2e915ff..c196bd6 100644 --- a/configs/evb-rk3036_defconfig +++ b/configs/evb-rk3036_defconfig @@ -24,3 +24,9 @@ CONFIG_DM_MMC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_CMD_DHRYSTONE=y CONFIG_ERRNO_STR=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_NS16550=y +CONFIG_DEBUG_UART_BASE=0x20068000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +# CONFIG_SPL_SERIAL_PRESENT is not set diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h index f753e68..d22ea74 100644 --- a/include/configs/rk3036_common.h +++ b/include/configs/rk3036_common.h @@ -24,6 +24,8 @@ #define CONFIG_SYS_TIMER_BASE 0x200440a0 /* TIMER5 */ #define CONFIG_SYS_TIMER_COUNTER (CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_SPL_SERIAL_SUPPORT
- #define CONFIG_SYS_NS16550 #define CONFIG_SYS_NS16550_MEM32
Reviewed-by: Thomas Chou thomas@wytron.com.tw

Applied to u-boot-dm/next.

Hi Simon.
Thank you for updating this series patch, i have verified it in evb-rk3036 board, it worked.
On 14/12/15 12:36, Simon Glass wrote:
The RK3036 has only 8KB of RAM available for SPL. At present it uses its own debug UART code.
By allowing the ns16550 driver to provide a debug UART without providing a full serial driver, we can enable a UART with a very small overhead. This requires addition Kconfig options. The debug UART supports printhex8(), printascii() and a few other functions.
The root driver and uclass are pulled in by this series, but their size is very small. It would possible to drop these by disabling CONFIG_DM_SERIAL. However the ns16550 driver makes this hard, due to it supporting operation without driver model, and operating differently in this case.
Simon Glass (3): dm: serial: Allow the UART driver to be dropped from the image dm: ns16550: Allow the driver to be omitted if requested rockchip: Use the debug UART on rk3036
arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/rk3036-board-spl.c | 9 ++++- arch/arm/mach-rockchip/rk_early_print.c | 63 ------------------------------- configs/evb-rk3036_defconfig | 6 +++ drivers/serial/Kconfig | 20 ++++++++++ drivers/serial/ns16550.c | 2 + drivers/serial/serial-uclass.c | 2 + include/configs/rk3036_common.h | 2 + 8 files changed, 40 insertions(+), 65 deletions(-) delete mode 100644 arch/arm/mach-rockchip/rk_early_print.c

HI Lin,
On 13 December 2015 at 23:26, hl hl@rock-chips.com wrote:
Hi Simon.
Thank you for updating this series patch, i have verified it in
evb-rk3036 board, it worked.
Great, thanks!
On 14/12/15 12:36, Simon Glass wrote:
The RK3036 has only 8KB of RAM available for SPL. At present it uses its own debug UART code.
By allowing the ns16550 driver to provide a debug UART without providing a full serial driver, we can enable a UART with a very small overhead. This requires addition Kconfig options. The debug UART supports printhex8(), printascii() and a few other functions.
The root driver and uclass are pulled in by this series, but their size is very small. It would possible to drop these by disabling CONFIG_DM_SERIAL. However the ns16550 driver makes this hard, due to it supporting operation without driver model, and operating differently in this case.
Simon Glass (3): dm: serial: Allow the UART driver to be dropped from the image dm: ns16550: Allow the driver to be omitted if requested rockchip: Use the debug UART on rk3036
arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/rk3036-board-spl.c | 9 ++++- arch/arm/mach-rockchip/rk_early_print.c | 63
configs/evb-rk3036_defconfig | 6 +++ drivers/serial/Kconfig | 20 ++++++++++ drivers/serial/ns16550.c | 2 + drivers/serial/serial-uclass.c | 2 + include/configs/rk3036_common.h | 2 + 8 files changed, 40 insertions(+), 65 deletions(-) delete mode 100644 arch/arm/mach-rockchip/rk_early_print.c
-- Lin Huang
Regards, Simon
participants (3)
-
hl
-
Simon Glass
-
Thomas Chou