Merge git://git.denx.de/u-boot-dm

This commit is contained in:
Tom Rini 2016-01-21 11:49:49 -05:00
commit 6905f4d3c7
122 changed files with 7454 additions and 421 deletions

View file

@ -6,7 +6,13 @@
#
obj-y := reset.o
ifeq ($(CONFIG_TIMER),)
obj-y += timer.o
else
ifdef CONFIG_SPL_BUILD
obj-y += timer.o
endif
endif
obj-y += utils.o
ifneq ($(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)

View file

@ -93,7 +93,7 @@ dtb-$(CONFIG_TARGET_BEAGLE_X15) += am57xx-beagle-x15.dtb
dtb-$(CONFIG_TARGET_STV0991) += stv0991.dtb
dtb-$(CONFIG_LS102XA) += ls1021a-qds.dtb \
ls1021a-twr.dtb
ls1021a-twr-duart.dtb ls1021a-twr-lpuart.dtb
dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
fsl-ls2080a-rdb.dtb
dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds.dtb \

View file

@ -15,6 +15,7 @@
compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
chosen {
stdout-path = &uart0;
tick-timer = &timer2;
};
};

View file

@ -16,6 +16,7 @@
chosen {
stdout-path = &uart0;
tick-timer = &timer2;
};
cpus {

View file

@ -26,6 +26,7 @@
chosen {
stdout-path = &uart0;
tick-timer = &timer2;
};
vmmcsd_fixed: fixedregulator-sd {

View file

@ -26,6 +26,7 @@
chosen {
stdout-path = &uart0;
tick-timer = &timer2;
};
backlight {

View file

@ -16,6 +16,7 @@
chosen {
stdout-path = &uart1;
tick-timer = &timer2;
};
memory {

View file

@ -16,6 +16,7 @@
chosen {
stdout-path = &uart1;
tick-timer = &timer2;
};
memory {

View file

@ -0,0 +1,16 @@
/*
* Freescale ls1021a TWR board device tree source
*
* Copyright 2013-2015 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
#include "ls1021a-twr.dtsi"
/ {
chosen {
stdout-path = &uart0;
};
};

View file

@ -0,0 +1,16 @@
/*
* Freescale ls1021a TWR board device tree source
*
* Copyright 2013-2015 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
#include "ls1021a-twr.dtsi"
/ {
chosen {
stdout-path = &lpuart0;
};
};

View file

@ -1,12 +1,11 @@
/*
* Freescale ls1021a TWR board device tree source
* Freescale ls1021a TWR board common device tree source
*
* Copyright 2013-2015 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
#include "ls1021a.dtsi"
/ {
@ -19,6 +18,10 @@
spi0 = &qspi;
spi1 = &dspi1;
};
chosen {
stdout-path = &uart0;
};
};
&qspi {

View file

@ -218,7 +218,6 @@
compatible = "fsl,16550-FIFO64", "ns16550a";
reg = <0x21c0500 0x100>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <0>;
fifo-size = <15>;
status = "disabled";
};
@ -227,7 +226,6 @@
compatible = "fsl,16550-FIFO64", "ns16550a";
reg = <0x21c0600 0x100>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <0>;
fifo-size = <15>;
status = "disabled";
};
@ -236,7 +234,6 @@
compatible = "fsl,16550-FIFO64", "ns16550a";
reg = <0x21d0500 0x100>;
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <0>;
fifo-size = <15>;
status = "disabled";
};
@ -245,7 +242,6 @@
compatible = "fsl,16550-FIFO64", "ns16550a";
reg = <0x21d0600 0x100>;
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <0>;
fifo-size = <15>;
status = "disabled";
};

View file

@ -117,6 +117,7 @@
};
lcd {
u-boot,dm-pre-reloc;
compatible = "sandbox,lcd-sdl";
xres = <1366>;
yres = <768>;

View file

@ -195,6 +195,13 @@
vss-microvolts = <0>;
};
lcd {
u-boot,dm-pre-reloc;
compatible = "sandbox,lcd-sdl";
xres = <1366>;
yres = <768>;
};
leds {
compatible = "gpio-leds";

View file

@ -47,23 +47,6 @@ int dram_init(void)
return 0;
}
#ifdef CONFIG_BOARD_EARLY_INIT_F
int board_early_init_f(void)
{
#ifdef CONFIG_VIDEO_SANDBOX_SDL
int ret;
ret = sandbox_lcd_sdl_early_init();
if (ret) {
puts("Could not init sandbox LCD emulation\n");
return ret;
}
#endif
return 0;
}
#endif
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{

View file

@ -205,7 +205,9 @@ obj-$(CONFIG_I2C_EDID) += edid.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-y += splash.o
obj-$(CONFIG_SPLASH_SOURCE) += splash_source.o
ifndef CONFIG_DM_VIDEO
obj-$(CONFIG_LCD) += lcd.o lcd_console.o
endif
obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
obj-$(CONFIG_LYNXKDI) += lynxkdi.o

View file

@ -46,6 +46,7 @@
#include <spi.h>
#include <status_led.h>
#include <trace.h>
#include <video.h>
#include <watchdog.h>
#include <asm/errno.h>
#include <asm/io.h>
@ -437,19 +438,50 @@ static int reserve_mmu(void)
}
#endif
#ifdef CONFIG_LCD
#ifdef CONFIG_DM_VIDEO
static int reserve_video(void)
{
ulong addr;
int ret;
addr = gd->relocaddr;
ret = video_reserve(&addr);
if (ret)
return ret;
gd->relocaddr = addr;
return 0;
}
#else
# ifdef CONFIG_LCD
static int reserve_lcd(void)
{
#ifdef CONFIG_FB_ADDR
# ifdef CONFIG_FB_ADDR
gd->fb_base = CONFIG_FB_ADDR;
#else
# else
/* reserve memory for LCD display (always full pages) */
gd->relocaddr = lcd_setmem(gd->relocaddr);
gd->fb_base = gd->relocaddr;
#endif /* CONFIG_FB_ADDR */
# endif /* CONFIG_FB_ADDR */
return 0;
}
#endif /* CONFIG_LCD */
# endif /* CONFIG_LCD */
# if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
static int reserve_legacy_video(void)
{
/* reserve memory for video display (always full pages) */
gd->relocaddr = video_setmem(gd->relocaddr);
gd->fb_base = gd->relocaddr;
return 0;
}
# endif
#endif /* !CONFIG_DM_VIDEO */
static int reserve_trace(void)
{
@ -463,19 +495,6 @@ static int reserve_trace(void)
return 0;
}
#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
static int reserve_video(void)
{
/* reserve memory for video display (always full pages) */
gd->relocaddr = video_setmem(gd->relocaddr);
gd->fb_base = gd->relocaddr;
return 0;
}
#endif
static int reserve_uboot(void)
{
/*
@ -957,16 +976,20 @@ static init_fnc_t init_sequence_f[] = {
defined(CONFIG_ARM)
reserve_mmu,
#endif
#ifdef CONFIG_LCD
#ifdef CONFIG_DM_VIDEO
reserve_video,
#else
# ifdef CONFIG_LCD
reserve_lcd,
#endif
reserve_trace,
# endif
/* TODO: Why the dependency on CONFIG_8xx? */
#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
# if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
!defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K)
reserve_video,
#endif
reserve_legacy_video,
# endif
#endif /* CONFIG_DM_VIDEO */
reserve_trace,
#if !defined(CONFIG_BLACKFIN)
reserve_uboot,
#endif

View file

@ -10,11 +10,14 @@
*/
#include <common.h>
#include <dm.h>
#include <lcd.h>
#include <mapmem.h>
#include <bmp_layout.h>
#include <command.h>
#include <asm/byteorder.h>
#include <malloc.h>
#include <mapmem.h>
#include <splash.h>
#include <video.h>
@ -57,7 +60,8 @@ struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
/* align to 32-bit-aligned-address + 2 */
bmp = (struct bmp_image *)((((unsigned int)dst + 1) & ~3) + 2);
if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, (uchar *)addr, &len) != 0) {
if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0),
&len) != 0) {
free(dst);
return NULL;
}
@ -187,7 +191,7 @@ U_BOOT_CMD(
*/
static int bmp_info(ulong addr)
{
struct bmp_image *bmp = (struct bmp_image *)addr;
struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0);
void *bmp_alloc_addr = NULL;
unsigned long len;
@ -223,8 +227,11 @@ static int bmp_info(ulong addr)
*/
int bmp_display(ulong addr, int x, int y)
{
#ifdef CONFIG_DM_VIDEO
struct udevice *dev;
#endif
int ret;
struct bmp_image *bmp = (struct bmp_image *)addr;
struct bmp_image *bmp = map_sysmem(addr, 0);
void *bmp_alloc_addr = NULL;
unsigned long len;
@ -236,11 +243,27 @@ int bmp_display(ulong addr, int x, int y)
printf("There is no valid bmp file at the given address\n");
return 1;
}
addr = map_to_sysmem(bmp);
#if defined(CONFIG_LCD)
ret = lcd_display_bitmap((ulong)bmp, x, y);
#ifdef CONFIG_DM_VIDEO
ret = uclass_first_device(UCLASS_VIDEO, &dev);
if (!ret) {
if (!dev)
ret = -ENODEV;
if (!ret) {
bool align = false;
# ifdef CONFIG_SPLASH_SCREEN_ALIGN
align = true;
# endif /* CONFIG_SPLASH_SCREEN_ALIGN */
ret = video_bmp_display(dev, addr, x, y, align);
}
}
return ret ? CMD_RET_FAILURE : 0;
#elif defined(CONFIG_LCD)
ret = lcd_display_bitmap(addr, x, y);
#elif defined(CONFIG_VIDEO)
ret = video_display_bitmap((unsigned long)bmp, x, y);
ret = video_display_bitmap(addr, x, y);
#else
# error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
#endif

View file

@ -1809,7 +1809,8 @@ static int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc,
if (ret)
printf("Failure changing bus number (%d)\n", ret);
}
return ret;
return ret ? CMD_RET_FAILURE : 0;
}
#endif /* defined(CONFIG_SYS_I2C) */
@ -1852,7 +1853,8 @@ static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const
if (ret)
printf("Failure changing bus speed (%d)\n", ret);
}
return ret;
return ret ? CMD_RET_FAILURE : 0;
}
/**

View file

@ -131,18 +131,6 @@ static int fdt_fixup_stdout(void *fdt, int chosenoff)
OF_STDOUT_PATH, strlen(OF_STDOUT_PATH) + 1);
}
#elif defined(CONFIG_OF_STDOUT_VIA_ALIAS) && defined(CONFIG_CONS_INDEX)
static void fdt_fill_multisername(char *sername, size_t maxlen)
{
const char *outname = stdio_devices[stdout]->name;
if (strcmp(outname, "serial") > 0)
strncpy(sername, outname, maxlen);
/* eserial? */
if (strcmp(outname + 1, "serial") > 0)
strncpy(sername, outname + 1, maxlen);
}
static int fdt_fixup_stdout(void *fdt, int chosenoff)
{
int err;
@ -152,9 +140,7 @@ static int fdt_fixup_stdout(void *fdt, int chosenoff)
int len;
char tmp[256]; /* long enough */
fdt_fill_multisername(sername, sizeof(sername) - 1);
if (!sername[0])
sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1);
sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1);
aliasoff = fdt_path_offset(fdt, "/aliases");
if (aliasoff < 0) {

View file

@ -31,10 +31,6 @@
#endif
#endif
#ifdef CONFIG_SANDBOX
#include <asm/sdl.h>
#endif
#ifndef CONFIG_LCD_ALIGNMENT
#define CONFIG_LCD_ALIGNMENT PAGE_SIZE
#endif
@ -72,13 +68,6 @@ void lcd_sync(void)
if (lcd_flush_dcache)
flush_dcache_range((u32)lcd_base,
(u32)(lcd_base + lcd_get_size(&line_length)));
#elif defined(CONFIG_SANDBOX) && defined(CONFIG_VIDEO_SANDBOX_SDL)
static ulong last_sync;
if (get_timer(last_sync) > 10) {
sandbox_sdl_sync(lcd_base);
last_sync = get_timer(0);
}
#endif
}

View file

@ -281,12 +281,23 @@ int stdio_add_devices(void)
i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#endif
#endif
#ifdef CONFIG_LCD
#ifdef CONFIG_DM_VIDEO
struct udevice *vdev;
for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
vdev;
ret = uclass_next_device(&vdev))
;
if (ret)
printf("%s: Video device failed (ret=%d)\n", __func__, ret);
#else
# if defined(CONFIG_LCD)
drv_lcd_init ();
#endif
#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
# endif
# if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
drv_video_init ();
#endif
# endif
#endif /* CONFIG_DM_VIDEO */
#if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
drv_keyboard_init ();
#endif

View file

@ -65,7 +65,6 @@ static const unsigned char us_direction[256/8] = {
static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
static __u32 CBWTag;
#define USB_MAX_STOR_DEV 7
static int usb_max_devs; /* number of highest available usb device */
static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];

View file

@ -22,3 +22,5 @@ CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_DM_ETH=y
CONFIG_SYS_NS16550=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y

View file

@ -16,3 +16,5 @@ CONFIG_SPI_FLASH_WINBOND=y
CONFIG_DM_ETH=y
CONFIG_SYS_NS16550=y
CONFIG_RSA=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y

View file

@ -18,3 +18,5 @@ CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SYS_NS16550=y
CONFIG_TI_QSPI=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y

View file

@ -21,3 +21,5 @@ CONFIG_TI_QSPI=y
CONFIG_DM_SPI=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_BAR=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y

View file

@ -8,3 +8,4 @@ CONFIG_CMD_GPIO=y
CONFIG_DM=y
CONFIG_NAND_VF610_NFC=y
CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES=y
CONFIG_FSL_LPUART=y

View file

@ -11,3 +11,4 @@ CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_NAND_VF610_NFC=y
CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES=y
CONFIG_FSL_LPUART=y

View file

@ -22,3 +22,5 @@ CONFIG_SYS_NS16550=y
CONFIG_TI_QSPI=y
CONFIG_DM_SPI=y
CONFIG_DM_SPI_FLASH=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y

View file

@ -21,3 +21,5 @@ CONFIG_SYS_NS16550=y
CONFIG_TI_QSPI=y
CONFIG_DM_SPI=y
CONFIG_DM_SPI_FLASH=y
CONFIG_TIMER=y
CONFIG_OMAP_TIMER=y

View file

@ -4,3 +4,4 @@ CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,LPUART"
# CONFIG_CMD_SETEXPR is not set
CONFIG_NETDEVICES=y
CONFIG_E1000=y
CONFIG_FSL_LPUART=y

View file

@ -4,3 +4,4 @@ CONFIG_SYS_EXTRA_OPTIONS="LPUART"
# CONFIG_CMD_SETEXPR is not set
CONFIG_NETDEVICES=y
CONFIG_E1000=y
CONFIG_FSL_LPUART=y

View file

@ -1,6 +1,10 @@
CONFIG_ARM=y
CONFIG_TARGET_LS1021ATWR=y
CONFIG_DM_SERIAL=y
CONFIG_DEFAULT_DEVICE_TREE="ls1021a-twr-duart"
# CONFIG_CMD_SETEXPR is not set
CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_NETDEVICES=y
CONFIG_E1000=y
CONFIG_SYS_NS16550=y

View file

@ -1,6 +1,11 @@
CONFIG_ARM=y
CONFIG_TARGET_LS1021ATWR=y
CONFIG_DM_SERIAL=y
CONFIG_DEFAULT_DEVICE_TREE="ls1021a-twr-lpuart"
CONFIG_SYS_EXTRA_OPTIONS="LPUART"
# CONFIG_CMD_SETEXPR is not set
CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_NETDEVICES=y
CONFIG_E1000=y
CONFIG_FSL_LPUART=y

View file

@ -1,7 +1,7 @@
CONFIG_ARM=y
CONFIG_TARGET_LS1021ATWR=y
CONFIG_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="ls1021a-twr"
CONFIG_DEFAULT_DEVICE_TREE="ls1021a-twr-duart"
CONFIG_SYS_EXTRA_OPTIONS="QSPI_BOOT"
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_SETEXPR is not set

View file

@ -1,7 +1,7 @@
CONFIG_ARM=y
CONFIG_TARGET_LS1021ATWR=y
CONFIG_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="ls1021a-twr"
CONFIG_DEFAULT_DEVICE_TREE="ls1021a-twr-duart"
CONFIG_SPL=y
CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT_PBL,SPL_FSL_PBL,SD_BOOT,SD_BOOT_QSPI"
CONFIG_OF_CONTROL=y

View file

@ -3,3 +3,4 @@ CONFIG_TARGET_PCM052=y
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/phytec/pcm052/imximage.cfg,ENV_IS_IN_NAND"
CONFIG_NAND_VF610_NFC=y
CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
CONFIG_FSL_LPUART=y

View file

@ -1,6 +1,7 @@
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_PCI=y
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
CONFIG_DM_PCI_COMPAT=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_SIGNATURE=y
@ -51,7 +52,6 @@ CONFIG_SPI_FLASH_SST=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_DM_ETH=y
CONFIG_DM_PCI=y
CONFIG_DM_PCI_COMPAT=y
CONFIG_PCI_SANDBOX=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
@ -76,6 +76,9 @@ CONFIG_USB_EMUL=y
CONFIG_USB_STORAGE=y
CONFIG_USB_KEYBOARD=y
CONFIG_SYS_USB_EVENT_POLL=y
CONFIG_DM_VIDEO=y
CONFIG_VIDEO_ROTATION=y
CONFIG_VIDEO_SANDBOX_SDL=y
CONFIG_CMD_DHRYSTONE=y
CONFIG_TPM=y
CONFIG_LZ4=y

View file

@ -6,3 +6,4 @@ CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/vf610twr/imximage.cfg,ENV_I
CONFIG_NAND_VF610_NFC=y
CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
CONFIG_SPI_FLASH=y
CONFIG_FSL_LPUART=y

View file

@ -6,3 +6,4 @@ CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/vf610twr/imximage.cfg,ENV_I
CONFIG_NAND_VF610_NFC=y
CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
CONFIG_SPI_FLASH=y
CONFIG_FSL_LPUART=y

View file

@ -0,0 +1,43 @@
The chosen node
---------------
The chosen node does not represent a real device, but serves as a place
for passing data like which serial device to used to print the logs etc
stdout-path property
--------------------
Device trees may specify the device to be used for boot console output
with a stdout-path property under /chosen.
Example
-------
/ {
chosen {
stdout-path = "/serial@f00:115200";
};
serial@f00 {
compatible = "vendor,some-uart";
reg = <0xf00 0x10>;
};
};
tick-timer property
-------------------
In a system there are multiple timers, specify which timer to be used
as the tick-timer. Earlier it was hardcoded in the timer driver now
since device tree has all the timer nodes. Specify which timer to be
used as tick timer.
Example
-------
/ {
chosen {
tick-timer = "/timer2@f00";
};
timer2@f00 {
compatible = "vendor,some-timer";
reg = <0xf00 0x10>;
};
};

View file

@ -11,7 +11,6 @@ is time for maintainers to start converting over the remaining serial drivers:
opencores_yanu.c
serial_bfin.c
serial_imx.c
serial_lpuart.c
serial_max3100.c
serial_pxa.c
serial_s3c24x0.c

View file

@ -1,3 +1,5 @@
menu "Clock"
config CLK
bool "Enable clock driver support"
depends on DM
@ -17,3 +19,5 @@ config SPL_CLK
SPL, enable this option. It might provide a cleaner interface to
setting up clocks within SPL, and allows the same drivers to be
used as U-Boot proper.
endmenu

View file

@ -32,6 +32,16 @@ ulong clk_set_rate(struct udevice *dev, ulong rate)
return ops->set_rate(dev, rate);
}
int clk_enable(struct udevice *dev, int periph)
{
struct clk_ops *ops = clk_get_ops(dev);
if (!ops->enable)
return -ENOSYS;
return ops->enable(dev, periph);
}
ulong clk_get_periph_rate(struct udevice *dev, int periph)
{
struct clk_ops *ops = clk_get_ops(dev);

View file

@ -314,7 +314,7 @@ static ulong rk3036_clk_set_rate(struct udevice *dev, ulong rate)
return 0;
}
ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate)
static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate)
{
struct rk3036_clk_priv *priv = dev_get_priv(dev);
ulong new_rate;

View file

@ -508,7 +508,7 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint clk_general_rate,
return rockchip_spi_get_clk(cru, clk_general_rate, periph);
}
ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
{
struct rk3288_clk_priv *priv = dev_get_priv(dev);
ulong new_rate;

View file

@ -32,7 +32,7 @@ static ulong sandbox_clk_set_rate(struct udevice *dev, ulong rate)
return 0;
}
ulong sandbox_get_periph_rate(struct udevice *dev, int periph)
static ulong sandbox_get_periph_rate(struct udevice *dev, int periph)
{
struct sandbox_clk_priv *priv = dev_get_priv(dev);
@ -41,7 +41,8 @@ ulong sandbox_get_periph_rate(struct udevice *dev, int periph)
return priv->periph_rate[periph];
}
ulong sandbox_set_periph_rate(struct udevice *dev, int periph, ulong rate)
static ulong sandbox_set_periph_rate(struct udevice *dev, int periph,
ulong rate)
{
struct sandbox_clk_priv *priv = dev_get_priv(dev);
ulong old_rate;

View file

@ -135,6 +135,11 @@ int device_bind(struct udevice *parent, const struct driver *drv,
if (ret)
goto fail_child_post_bind;
}
if (uc->uc_drv->post_bind) {
ret = uc->uc_drv->post_bind(dev);
if (ret)
goto fail_uclass_post_bind;
}
if (parent)
dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
@ -145,6 +150,8 @@ int device_bind(struct udevice *parent, const struct driver *drv,
return 0;
fail_uclass_post_bind:
/* There is no child unbind() method, so no clean-up required */
fail_child_post_bind:
if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
if (drv->unbind && drv->unbind(dev)) {

View file

@ -278,6 +278,7 @@ static int uclass_find_device_by_of_offset(enum uclass_id id, int node,
return -ENODEV;
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
static int uclass_find_device_by_phandle(enum uclass_id id,
struct udevice *parent,
const char *name,
@ -308,6 +309,7 @@ static int uclass_find_device_by_phandle(enum uclass_id id,
return -ENODEV;
}
#endif
int uclass_get_device_tail(struct udevice *dev, int ret,
struct udevice **devp)
@ -374,6 +376,7 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node,
return uclass_get_device_tail(dev, ret, devp);
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
const char *name, struct udevice **devp)
{
@ -384,6 +387,7 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
ret = uclass_find_device_by_phandle(id, parent, name, &dev);
return uclass_get_device_tail(dev, ret, devp);
}
#endif
int uclass_first_device(enum uclass_id id, struct udevice **devp)
{
@ -426,11 +430,6 @@ int uclass_bind_device(struct udevice *dev)
goto err;
}
}
if (uc->uc_drv->post_bind) {
ret = uc->uc_drv->post_bind(dev);
if (ret)
goto err;
}
return 0;
err:

View file

@ -154,6 +154,7 @@ int dm_gpio_request(struct gpio_desc *desc, const char *label)
static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...)
{
#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF)
va_list args;
char buf[40];
@ -161,6 +162,9 @@ static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...)
vscnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
return dm_gpio_request(desc, buf);
#else
return dm_gpio_request(desc, fmt);
#endif
}
/**
@ -199,6 +203,7 @@ int gpio_request(unsigned gpio, const char *label)
*/
int gpio_requestf(unsigned gpio, const char *fmt, ...)
{
#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF)
va_list args;
char buf[40];
@ -206,6 +211,9 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...)
vscnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
return gpio_request(gpio, buf);
#else
return gpio_request(gpio, fmt);
#endif
}
int _dm_gpio_free(struct udevice *dev, uint offset)

View file

@ -1780,18 +1780,28 @@ static int mmc_probe(bd_t *bis)
#elif defined(CONFIG_DM_MMC)
static int mmc_probe(bd_t *bis)
{
int ret;
int ret, i;
struct uclass *uc;
struct udevice *m;
struct udevice *dev;
ret = uclass_get(UCLASS_MMC, &uc);
if (ret)
return ret;
uclass_foreach_dev(m, uc) {
ret = device_probe(m);
/*
* Try to add them in sequence order. Really with driver model we
* should allow holes, but the current MMC list does not allow that.
* So if we request 0, 1, 3 we will get 0, 1, 2.
*/
for (i = 0; ; i++) {
ret = uclass_get_device_by_seq(UCLASS_MMC, i, &dev);
if (ret == -ENODEV)
break;
}
uclass_foreach_dev(dev, uc) {
ret = device_probe(dev);
if (ret)
printf("%s - probe failed: %d\n", m->name, ret);
printf("%s - probe failed: %d\n", dev->name, ret);
}
return 0;

View file

@ -111,12 +111,16 @@ static int pinconfig_post_bind(struct udevice *dev)
{
const void *fdt = gd->fdt_blob;
int offset = dev->of_offset;
bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
const char *name;
int ret;
for (offset = fdt_first_subnode(fdt, offset);
offset > 0;
offset = fdt_next_subnode(fdt, offset)) {
if (pre_reloc_only &&
!fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
continue;
/*
* If this node has "compatible" property, this is not
* a pin configuration node, but a normal device. skip.

View file

@ -228,6 +228,12 @@ config ALTERA_UART
Select this to enable an UART for Altera devices. Please find
details on the "Embedded Peripherals IP User Guide" of Altera.
config FSL_LPUART
bool "Freescale LPUART support"
help
Select this to enable a Low Power UART for Freescale VF610 and
QorIQ Layerscape devices.
config SYS_NS16550
bool "NS16550 UART or compatible"
help

View file

@ -16,6 +16,7 @@
#include <lcd.h>
#include <os.h>
#include <serial.h>
#include <video.h>
#include <linux/compiler.h>
#include <asm/state.h>
@ -114,9 +115,7 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
return 0;
os_usleep(100);
#ifdef CONFIG_LCD
lcd_sync();
#endif
video_sync_all();
if (next_index == serial_buf_read)
return 1; /* buffer full */

View file

@ -5,6 +5,7 @@
*/
#include <common.h>
#include <dm.h>
#include <watchdog.h>
#include <asm/io.h>
#include <serial.h>
@ -12,15 +13,15 @@
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
#define US1_TDRE (1 << 7)
#define US1_RDRF (1 << 5)
#define US1_OR (1 << 3)
#define UC2_TE (1 << 3)
#define UC2_RE (1 << 2)
#define CFIFO_TXFLUSH (1 << 7)
#define CFIFO_RXFLUSH (1 << 6)
#define SFIFO_RXOF (1 << 2)
#define SFIFO_RXUF (1 << 0)
#define US1_TDRE (1 << 7)
#define US1_RDRF (1 << 5)
#define US1_OR (1 << 3)
#define UC2_TE (1 << 3)
#define UC2_RE (1 << 2)
#define CFIFO_TXFLUSH (1 << 7)
#define CFIFO_RXFLUSH (1 << 6)
#define SFIFO_RXOF (1 << 2)
#define SFIFO_RXUF (1 << 0)
#define STAT_LBKDIF (1 << 31)
#define STAT_RXEDGIF (1 << 30)
@ -34,7 +35,7 @@
#define STAT_MA1F (1 << 15)
#define STAT_MA2F (1 << 14)
#define STAT_FLAGS (STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \
STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
#define CTRL_TE (1 << 19)
#define CTRL_RE (1 << 18)
@ -49,23 +50,24 @@ DECLARE_GLOBAL_DATA_PTR;
struct lpuart_fsl *base = (struct lpuart_fsl *)LPUART_BASE;
struct lpuart_serial_platdata {
struct lpuart_fsl *reg;
};
#ifndef CONFIG_LPUART_32B_REG
static void lpuart_serial_setbrg(void)
static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate)
{
u32 clk = mxc_get_clock(MXC_UART_CLK);
u16 sbr;
if (!gd->baudrate)
gd->baudrate = CONFIG_BAUDRATE;
sbr = (u16)(clk / (16 * baudrate));
sbr = (u16)(clk / (16 * gd->baudrate));
/* place adjustment later - n/32 BRFA */
__raw_writeb(sbr >> 8, &base->ubdh);
__raw_writeb(sbr & 0xff, &base->ubdl);
}
static int lpuart_serial_getc(void)
static int _lpuart_serial_getc(struct lpuart_fsl *base)
{
while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
WATCHDOG_RESET();
@ -75,10 +77,10 @@ static int lpuart_serial_getc(void)
return __raw_readb(&base->ud);
}
static void lpuart_serial_putc(const char c)
static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c)
{
if (c == '\n')
serial_putc('\r');
_lpuart_serial_putc(base, '\r');
while (!(__raw_readb(&base->us1) & US1_TDRE))
WATCHDOG_RESET();
@ -86,10 +88,8 @@ static void lpuart_serial_putc(const char c)
__raw_writeb(c, &base->ud);
}
/*
* Test whether a character is in the RX buffer
*/
static int lpuart_serial_tstc(void)
/* Test whether a character is in the RX buffer */
static int _lpuart_serial_tstc(struct lpuart_fsl *base)
{
if (__raw_readb(&base->urcfifo) == 0)
return 0;
@ -101,7 +101,7 @@ static int lpuart_serial_tstc(void)
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*/
static int lpuart_serial_init(void)
static int _lpuart_serial_init(struct lpuart_fsl *base)
{
u8 ctrl;
@ -120,14 +120,39 @@ static int lpuart_serial_init(void)
__raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo);
/* provide data bits, parity, stop bit, etc */
serial_setbrg();
_lpuart_serial_setbrg(base, gd->baudrate);
__raw_writeb(UC2_RE | UC2_TE, &base->uc2);
return 0;
}
#ifndef CONFIG_DM_SERIAL
static void lpuart_serial_setbrg(void)
{
_lpuart_serial_setbrg(base, gd->baudrate);
}
static int lpuart_serial_getc(void)
{
return _lpuart_serial_getc(base);
}
static void lpuart_serial_putc(const char c)
{
_lpuart_serial_putc(base, c);
}
static int lpuart_serial_tstc(void)
{
return _lpuart_serial_tstc(base);
}
static int lpuart_serial_init(void)
{
return _lpuart_serial_init(base);
}
static struct serial_device lpuart_serial_drv = {
.name = "lpuart_serial",
.start = lpuart_serial_init,
@ -138,22 +163,67 @@ static struct serial_device lpuart_serial_drv = {
.getc = lpuart_serial_getc,
.tstc = lpuart_serial_tstc,
};
#else /* CONFIG_DM_SERIAL */
static int lpuart_serial_setbrg(struct udevice *dev, int baudrate)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
_lpuart_serial_setbrg(reg, baudrate);
return 0;
}
static int lpuart_serial_getc(struct udevice *dev)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
return _lpuart_serial_getc(reg);
}
static int lpuart_serial_putc(struct udevice *dev, const char c)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
_lpuart_serial_putc(reg, c);
return 0;
}
static int lpuart_serial_pending(struct udevice *dev, bool input)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
if (input)
return _lpuart_serial_tstc(reg);
else
return __raw_readb(&reg->us1) & US1_TDRE ? 0 : 1;
}
static int lpuart_serial_probe(struct udevice *dev)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
return _lpuart_serial_init(reg);
}
#endif /* CONFIG_DM_SERIAL */
#else
static void lpuart32_serial_setbrg(void)
static void _lpuart32_serial_setbrg(struct lpuart_fsl *base, int baudrate)
{
u32 clk = CONFIG_SYS_CLK_FREQ;
u32 sbr;
if (!gd->baudrate)
gd->baudrate = CONFIG_BAUDRATE;
sbr = (clk / (16 * baudrate));
sbr = (clk / (16 * gd->baudrate));
/* place adjustment later - n/32 BRFA */
out_be32(&base->baud, sbr);
}
static int lpuart32_serial_getc(void)
static int _lpuart32_serial_getc(struct lpuart_fsl *base)
{
u32 stat;
@ -165,10 +235,10 @@ static int lpuart32_serial_getc(void)
return in_be32(&base->data) & 0x3ff;
}
static void lpuart32_serial_putc(const char c)
static void _lpuart32_serial_putc(struct lpuart_fsl *base, const char c)
{
if (c == '\n')
serial_putc('\r');
_lpuart32_serial_putc(base, '\r');
while (!(in_be32(&base->stat) & STAT_TDRE))
WATCHDOG_RESET();
@ -176,10 +246,8 @@ static void lpuart32_serial_putc(const char c)
out_be32(&base->data, c);
}
/*
* Test whether a character is in the RX buffer
*/
static int lpuart32_serial_tstc(void)
/* Test whether a character is in the RX buffer */
static int _lpuart32_serial_tstc(struct lpuart_fsl *base)
{
if ((in_be32(&base->water) >> 24) == 0)
return 0;
@ -191,7 +259,7 @@ static int lpuart32_serial_tstc(void)
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*/
static int lpuart32_serial_init(void)
static int _lpuart32_serial_init(struct lpuart_fsl *base)
{
u8 ctrl;
@ -204,15 +272,41 @@ static int lpuart32_serial_init(void)
out_be32(&base->fifo, ~(FIFO_TXFE | FIFO_RXFE));
out_be32(&base->match, 0);
/* provide data bits, parity, stop bit, etc */
serial_setbrg();
/* provide data bits, parity, stop bit, etc */
_lpuart32_serial_setbrg(base, gd->baudrate);
out_be32(&base->ctrl, CTRL_RE | CTRL_TE);
return 0;
}
#ifndef CONFIG_DM_SERIAL
static void lpuart32_serial_setbrg(void)
{
_lpuart32_serial_setbrg(base, gd->baudrate);
}
static int lpuart32_serial_getc(void)
{
return _lpuart32_serial_getc(base);
}
static void lpuart32_serial_putc(const char c)
{
_lpuart32_serial_putc(base, c);
}
static int lpuart32_serial_tstc(void)
{
return _lpuart32_serial_tstc(base);
}
static int lpuart32_serial_init(void)
{
return _lpuart32_serial_init(base);
}
static struct serial_device lpuart32_serial_drv = {
.name = "lpuart32_serial",
.start = lpuart32_serial_init,
@ -223,8 +317,57 @@ static struct serial_device lpuart32_serial_drv = {
.getc = lpuart32_serial_getc,
.tstc = lpuart32_serial_tstc,
};
#else /* CONFIG_DM_SERIAL */
static int lpuart32_serial_setbrg(struct udevice *dev, int baudrate)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
_lpuart32_serial_setbrg(reg, baudrate);
return 0;
}
static int lpuart32_serial_getc(struct udevice *dev)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
return _lpuart32_serial_getc(reg);
}
static int lpuart32_serial_putc(struct udevice *dev, const char c)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
_lpuart32_serial_putc(reg, c);
return 0;
}
static int lpuart32_serial_pending(struct udevice *dev, bool input)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
if (input)
return _lpuart32_serial_tstc(reg);
else
return in_be32(&reg->stat) & STAT_TDRE ? 0 : 1;
}
static int lpuart32_serial_probe(struct udevice *dev)
{
struct lpuart_serial_platdata *plat = dev->platdata;
struct lpuart_fsl *reg = plat->reg;
return _lpuart32_serial_init(reg);
}
#endif /* CONFIG_DM_SERIAL */
#endif
#ifndef CONFIG_DM_SERIAL
void lpuart_serial_initialize(void)
{
#ifdef CONFIG_LPUART_32B_REG
@ -242,3 +385,66 @@ __weak struct serial_device *default_serial_console(void)
return &lpuart_serial_drv;
#endif
}
#else /* CONFIG_DM_SERIAL */
static int lpuart_serial_ofdata_to_platdata(struct udevice *dev)
{
struct lpuart_serial_platdata *plat = dev->platdata;
fdt_addr_t addr;
addr = dev_get_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
plat->reg = (struct lpuart_fsl *)addr;
return 0;
}
#ifndef CONFIG_LPUART_32B_REG
static const struct dm_serial_ops lpuart_serial_ops = {
.putc = lpuart_serial_putc,
.pending = lpuart_serial_pending,
.getc = lpuart_serial_getc,
.setbrg = lpuart_serial_setbrg,
};
static const struct udevice_id lpuart_serial_ids[] = {
{ .compatible = "fsl,vf610-lpuart" },
{ }
};
U_BOOT_DRIVER(serial_lpuart) = {
.name = "serial_lpuart",
.id = UCLASS_SERIAL,
.of_match = lpuart_serial_ids,
.ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
.probe = lpuart_serial_probe,
.ops = &lpuart_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};
#else /* CONFIG_LPUART_32B_REG */
static const struct dm_serial_ops lpuart32_serial_ops = {
.putc = lpuart32_serial_putc,
.pending = lpuart32_serial_pending,
.getc = lpuart32_serial_getc,
.setbrg = lpuart32_serial_setbrg,
};
static const struct udevice_id lpuart32_serial_ids[] = {
{ .compatible = "fsl,ls1021a-lpuart" },
{ }
};
U_BOOT_DRIVER(serial_lpuart32) = {
.name = "serial_lpuart32",
.id = UCLASS_SERIAL,
.of_match = lpuart32_serial_ids,
.ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
.probe = lpuart32_serial_probe,
.ops = &lpuart32_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};
#endif /* CONFIG_LPUART_32B_REG */
#endif /* CONFIG_DM_SERIAL */

View file

@ -30,4 +30,10 @@ config X86_TSC_TIMER
help
Select this to enable Time-Stamp Counter (TSC) timer for x86.
config OMAP_TIMER
bool "Omap timer support"
depends on TIMER
help
Select this to enable an timer for Omap devices.
endmenu

View file

@ -8,3 +8,4 @@ obj-$(CONFIG_TIMER) += timer-uclass.o
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o
obj-$(CONFIG_OMAP_TIMER) += omap-timer.o

108
drivers/timer/omap-timer.c Normal file
View file

@ -0,0 +1,108 @@
/*
* TI OMAP timer driver
*
* Copyright (C) 2015, Texas Instruments, Incorporated
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <timer.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
DECLARE_GLOBAL_DATA_PTR;
/* Timer register bits */
#define TCLR_START BIT(0) /* Start=1 */
#define TCLR_AUTO_RELOAD BIT(1) /* Auto reload */
#define TCLR_PRE_EN BIT(5) /* Pre-scaler enable */
#define TCLR_PTV_SHIFT (2) /* Pre-scaler shift value */
#define TIMER_CLOCK (V_SCLK / (2 << CONFIG_SYS_PTV))
struct omap_gptimer_regs {
unsigned int tidr; /* offset 0x00 */
unsigned char res1[12];
unsigned int tiocp_cfg; /* offset 0x10 */
unsigned char res2[12];
unsigned int tier; /* offset 0x20 */
unsigned int tistatr; /* offset 0x24 */
unsigned int tistat; /* offset 0x28 */
unsigned int tisr; /* offset 0x2c */
unsigned int tcicr; /* offset 0x30 */
unsigned int twer; /* offset 0x34 */
unsigned int tclr; /* offset 0x38 */
unsigned int tcrr; /* offset 0x3c */
unsigned int tldr; /* offset 0x40 */
unsigned int ttgr; /* offset 0x44 */
unsigned int twpc; /* offset 0x48 */
unsigned int tmar; /* offset 0x4c */
unsigned int tcar1; /* offset 0x50 */
unsigned int tscir; /* offset 0x54 */
unsigned int tcar2; /* offset 0x58 */
};
/* Omap Timer Priv */
struct omap_timer_priv {
struct omap_gptimer_regs *regs;
};
static int omap_timer_get_count(struct udevice *dev, u64 *count)
{
struct omap_timer_priv *priv = dev_get_priv(dev);
*count = readl(&priv->regs->tcrr);
return 0;
}
static int omap_timer_probe(struct udevice *dev)
{
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct omap_timer_priv *priv = dev_get_priv(dev);
uc_priv->clock_rate = TIMER_CLOCK;
/* start the counter ticking up, reload value on overflow */
writel(0, &priv->regs->tldr);
/* enable timer */
writel((CONFIG_SYS_PTV << 2) | TCLR_PRE_EN | TCLR_AUTO_RELOAD |
TCLR_START, &priv->regs->tclr);
return 0;
}
static int omap_timer_ofdata_to_platdata(struct udevice *dev)
{
struct omap_timer_priv *priv = dev_get_priv(dev);
priv->regs = (struct omap_gptimer_regs *)dev_get_addr(dev);
return 0;
}
static const struct timer_ops omap_timer_ops = {
.get_count = omap_timer_get_count,
};
static const struct udevice_id omap_timer_ids[] = {
{ .compatible = "ti,am335x-timer" },
{ .compatible = "ti,am4372-timer" },
{ .compatible = "ti,omap5430-timer" },
{}
};
U_BOOT_DRIVER(omap_timer) = {
.name = "omap_timer",
.id = UCLASS_TIMER,
.of_match = omap_timer_ids,
.ofdata_to_platdata = omap_timer_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct omap_timer_priv),
.probe = omap_timer_probe,
.ops = &omap_timer_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -27,6 +27,11 @@ static int sandbox_timer_get_count(struct udevice *dev, u64 *count)
static int sandbox_timer_probe(struct udevice *dev)
{
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
if (!uc_priv->clock_rate)
uc_priv->clock_rate = 1000000;
return 0;
}
@ -47,3 +52,8 @@ U_BOOT_DRIVER(sandbox_timer) = {
.ops = &sandbox_timer_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* This is here in case we don't have a device tree */
U_BOOT_DEVICE(sandbox_timer_non_fdt) = {
.name = "sandbox_timer",
};

View file

@ -6,6 +6,8 @@
#include <common.h>
#include <dm.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
#include <errno.h>
#include <timer.h>
@ -47,6 +49,16 @@ static int timer_pre_probe(struct udevice *dev)
return 0;
}
static int timer_post_probe(struct udevice *dev)
{
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
if (!uc_priv->clock_rate)
return -EINVAL;
return 0;
}
u64 timer_conv_64(u32 count)
{
/* increment tbh if tbl has rolled over */
@ -56,9 +68,53 @@ u64 timer_conv_64(u32 count)
return ((u64)gd->timebase_h << 32) | gd->timebase_l;
}
int notrace dm_timer_init(void)
{
const void *blob = gd->fdt_blob;
struct udevice *dev = NULL;
int node;
int ret;
if (gd->timer)
return 0;
/* Check for a chosen timer to be used for tick */
node = fdtdec_get_chosen_node(blob, "tick-timer");
if (node < 0) {
/* No chosen timer, trying first available timer */
ret = uclass_first_device(UCLASS_TIMER, &dev);
if (ret)
return ret;
if (!dev)
return -ENODEV;
} else {
if (uclass_get_device_by_of_offset(UCLASS_TIMER, node, &dev)) {
/*
* If the timer is not marked to be bound before
* relocation, bind it anyway.
*/
if (node > 0 &&
!lists_bind_fdt(gd->dm_root, blob, node, &dev)) {
ret = device_probe(dev);
if (ret)
return ret;
}
}
}
if (dev) {
gd->timer = dev;
return 0;
}
return -ENODEV;
}
UCLASS_DRIVER(timer) = {
.id = UCLASS_TIMER,
.name = "timer",
.pre_probe = timer_pre_probe,
.flags = DM_UC_FLAG_SEQ_ALIAS,
.post_probe = timer_post_probe,
.per_device_auto_alloc_size = sizeof(struct timer_dev_priv),
};

View file

@ -4,6 +4,59 @@
menu "Graphics support"
config DM_VIDEO
bool "Enable driver model support for LCD/video"
depends on DM
help
This enables driver model for LCD and video devices. These support
a bitmap display of various sizes and depths which can be drawn on
to display a command-line console or splash screen. Enabling this
option compiles in the video uclass and routes all LCD/video access
through this.
config VIDEO_BPP8
bool "Support 8-bit-per-pixel displays"
depends on DM_VIDEO
default y if DM_VIDEO
help
Support drawing text and bitmaps onto a 8-bit-per-pixel display.
Enabling this will include code to support this display. Without
this option, such displays will not be supported and console output
will be empty.
config VIDEO_BPP16
bool "Support 16-bit-per-pixel displays"
depends on DM_VIDEO
default y if DM_VIDEO
help
Support drawing text and bitmaps onto a 16-bit-per-pixel display.
Enabling this will include code to support this display. Without
this option, such displays will not be supported and console output
will be empty.
config VIDEO_BPP32
bool "Support 32-bit-per-pixel displays"
depends on DM_VIDEO
default y if DM_VIDEO
help
Support drawing text and bitmaps onto a 32-bit-per-pixel display.
Enabling this will include code to support this display. Without
this option, such displays will not be supported and console output
will be empty.
config VIDEO_ROTATION
bool "Support rotated displays"
depends on DM_VIDEO
help
Sometimes, for example if the display is mounted in portrait
mode or even if it's mounted landscape but rotated by 180degree,
we need to rotate our content of the display relative to the
framebuffer, so that user can read the messages which are
printed out. Enable this option to include a text driver which can
support this. The rotation is set by the 'rot' parameter in
struct video_priv: 0=unrotated, 1=90 degrees clockwise, 2=180
degrees, 3=270 degrees.
config VIDEO_VESA
bool "Enable VESA video driver support"
default n
@ -247,6 +300,15 @@ config DISPLAY_PORT
to drive LCD panels. This framework provides support for enabling
these displays where supported by the video hardware.
config VIDEO_SANDBOX_SDL
bool "Enable sandbox video console using SDL"
depends on SANDBOX
help
When using sandbox you can enable an emulated LCD display which
appears as an SDL (Simple DirectMedia Layer) window. This is a
console device and can display stdout output. Within U-Boot is is
a normal bitmap display and can display images as well as text.
config VIDEO_TEGRA124
bool "Enable video support on Tegra124"
help

View file

@ -7,6 +7,9 @@
ifdef CONFIG_DM
obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
obj-$(CONFIG_DM_VIDEO) += video_bmp.o
obj-$(CONFIG_VIDEO_ROTATION) += console_rotate.o
endif
obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2015 Google, Inc
* (C) Copyright 2001-2015
* DENX Software Engineering -- wd@denx.de
* Compulab Ltd - http://compulab.co.il/
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <video.h>
#include <video_console.h>
#include <video_font.h> /* Get font data, width and height */
static int console_normal_set_row(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
void *line;
int pixels = VIDEO_FONT_HEIGHT * vid_priv->line_length;
int i;
line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length;
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < pixels; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < pixels; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < pixels; i++)
*dst++ = clr;
break;
}
#endif
default:
return -ENOSYS;
}
return 0;
}
static int console_normal_move_rows(struct udevice *dev, uint rowdst,
uint rowsrc, uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
void *dst;
void *src;
dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * vid_priv->line_length;
src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * vid_priv->line_length;
memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
return 0;
}
static int console_normal_putc_xy(struct udevice *dev, uint x, uint y, char ch)
{
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
int i, row;
void *line = vid_priv->fb + y * vid_priv->line_length +
x * VNBYTES(vid_priv->bpix);
for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
*dst++ = (bits & 0x80) ? vid_priv->colour_fg
: vid_priv->colour_bg;
bits <<= 1;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
*dst++ = (bits & 0x80) ? vid_priv->colour_fg
: vid_priv->colour_bg;
bits <<= 1;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
*dst++ = (bits & 0x80) ? vid_priv->colour_fg
: vid_priv->colour_bg;
bits <<= 1;
}
break;
}
#endif
default:
return -ENOSYS;
}
line += vid_priv->line_length;
}
return 0;
}
struct vidconsole_ops console_normal_ops = {
.putc_xy = console_normal_putc_xy,
.move_rows = console_normal_move_rows,
.set_row = console_normal_set_row,
};
U_BOOT_DRIVER(vidconsole_normal) = {
.name = "vidconsole0",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_normal_ops,
};

View file

@ -0,0 +1,436 @@
/*
* Copyright (c) 2015 Google, Inc
* (C) Copyright 2015
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <video.h>
#include <video_console.h>
#include <video_font.h> /* Get font data, width and height */
static int console_set_row_1(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
int pbytes = VNBYTES(vid_priv->bpix);
void *line;
int i, j;
line = vid_priv->fb + vid_priv->line_length -
(row + 1) * VIDEO_FONT_HEIGHT * pbytes;
for (j = 0; j < vid_priv->ysize; j++) {
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
*dst++ = clr;
break;
}
#endif
default:
return -ENOSYS;
}
line += vid_priv->line_length;
}
return 0;
}
static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
void *dst;
void *src;
int pbytes = VNBYTES(vid_priv->bpix);
int j;
dst = vid_priv->fb + vid_priv->line_length -
(rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
src = vid_priv->fb + vid_priv->line_length -
(rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
for (j = 0; j < vid_priv->ysize; j++) {
memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
src += vid_priv->line_length;
dst += vid_priv->line_length;
}
return 0;
}
static int console_putc_xy_1(struct udevice *dev, uint x, uint y, char ch)
{
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
int pbytes = VNBYTES(vid_priv->bpix);
int i, col;
int mask = 0x80;
void *line = vid_priv->fb + (x + 1) * vid_priv->line_length -
(y + 1) * pbytes;
uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
: vid_priv->colour_bg;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
: vid_priv->colour_bg;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
: vid_priv->colour_bg;
}
break;
}
#endif
default:
return -ENOSYS;
}
line += vid_priv->line_length;
mask >>= 1;
}
return 0;
}
static int console_set_row_2(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
void *line;
int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
int i;
line = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
(row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < pixels; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < pixels; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < pixels; i++)
*dst++ = clr;
break;
}
#endif
default:
return -ENOSYS;
}
return 0;
}
static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
void *dst;
void *src;
void *end;
end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
vid_priv->line_length;
src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
vid_priv->line_length;
memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
return 0;
}
static int console_putc_xy_2(struct udevice *dev, uint x, uint y, char ch)
{
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
int i, row;
void *line;
line = vid_priv->fb + (vid_priv->ysize - y - 1) *
vid_priv->line_length +
(vid_priv->xsize - x - VIDEO_FONT_WIDTH - 1) *
VNBYTES(vid_priv->bpix);
for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
*dst-- = (bits & 0x80) ? vid_priv->colour_fg
: vid_priv->colour_bg;
bits <<= 1;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
*dst-- = (bits & 0x80) ? vid_priv->colour_fg
: vid_priv->colour_bg;
bits <<= 1;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
*dst-- = (bits & 0x80) ? vid_priv->colour_fg
: vid_priv->colour_bg;
bits <<= 1;
}
break;
}
#endif
default:
return -ENOSYS;
}
line -= vid_priv->line_length;
}
return 0;
}
static int console_set_row_3(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
int pbytes = VNBYTES(vid_priv->bpix);
void *line;
int i, j;
line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
for (j = 0; j < vid_priv->ysize; j++) {
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
*dst++ = clr;
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
*dst++ = clr;
break;
}
#endif
default:
return -ENOSYS;
}
line += vid_priv->line_length;
}
return 0;
}
static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
void *dst;
void *src;
int pbytes = VNBYTES(vid_priv->bpix);
int j;
dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
for (j = 0; j < vid_priv->ysize; j++) {
memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
src += vid_priv->line_length;
dst += vid_priv->line_length;
}
return 0;
}
static int console_putc_xy_3(struct udevice *dev, uint x, uint y, char ch)
{
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
int pbytes = VNBYTES(vid_priv->bpix);
int i, col;
int mask = 0x80;
void *line = vid_priv->fb + (vid_priv->ysize - x - 1) *
vid_priv->line_length + y * pbytes;
uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
switch (vid_priv->bpix) {
#ifdef CONFIG_VIDEO_BPP8
case VIDEO_BPP8: {
uint8_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
: vid_priv->colour_bg;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP16
case VIDEO_BPP16: {
uint16_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
: vid_priv->colour_bg;
}
break;
}
#endif
#ifdef CONFIG_VIDEO_BPP32
case VIDEO_BPP32: {
uint32_t *dst = line;
for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
: vid_priv->colour_bg;
}
break;
}
#endif
default:
return -ENOSYS;
}
line -= vid_priv->line_length;
mask >>= 1;
}
return 0;
}
static int console_probe_1_3(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
return 0;
}
struct vidconsole_ops console_ops_1 = {
.putc_xy = console_putc_xy_1,
.move_rows = console_move_rows_1,
.set_row = console_set_row_1,
};
struct vidconsole_ops console_ops_2 = {
.putc_xy = console_putc_xy_2,
.move_rows = console_move_rows_2,
.set_row = console_set_row_2,
};
struct vidconsole_ops console_ops_3 = {
.putc_xy = console_putc_xy_3,
.move_rows = console_move_rows_3,
.set_row = console_set_row_3,
};
U_BOOT_DRIVER(vidconsole_1) = {
.name = "vidconsole1",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_ops_1,
.probe = console_probe_1_3,
};
U_BOOT_DRIVER(vidconsole_2) = {
.name = "vidconsole2",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_ops_2,
};
U_BOOT_DRIVER(vidconsole_3) = {
.name = "vidconsole3",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_ops_3,
.probe = console_probe_1_3,
};

View file

@ -5,75 +5,67 @@
*/
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <lcd.h>
#include <malloc.h>
#include <video.h>
#include <asm/sdl.h>
#include <asm/u-boot-sandbox.h>
#include <dm/test.h>
DECLARE_GLOBAL_DATA_PTR;
enum {
/* Maximum LCD size we support */
/* Default LCD size we support */
LCD_MAX_WIDTH = 1366,
LCD_MAX_HEIGHT = 768,
LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */
};
vidinfo_t panel_info;
void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
static int sandbox_sdl_probe(struct udevice *dev)
{
}
struct sandbox_sdl_plat *plat = dev_get_platdata(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
int ret;
void lcd_ctrl_init(void *lcdbase)
{
/*
* Allocate memory to keep BMP color conversion map. This is required
* for 8 bit BMPs only (hence 256 colors). If malloc fails - keep
* going, it is not even clear if displyaing the bitmap will be
* required on the way up.
*/
panel_info.cmap = malloc(256 * NBITS(panel_info.vl_bpix) / 8);
}
void lcd_enable(void)
{
if (sandbox_sdl_init_display(panel_info.vl_col, panel_info.vl_row,
panel_info.vl_bpix))
ret = sandbox_sdl_init_display(plat->xres, plat->yres, plat->bpix);
if (ret) {
puts("LCD init failed\n");
return ret;
}
uc_priv->xsize = plat->xres;
uc_priv->ysize = plat->yres;
uc_priv->bpix = plat->bpix;
uc_priv->rot = plat->rot;
return 0;
}
int sandbox_lcd_sdl_early_init(void)
static int sandbox_sdl_bind(struct udevice *dev)
{
struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
struct sandbox_sdl_plat *plat = dev_get_platdata(dev);
const void *blob = gd->fdt_blob;
int xres = LCD_MAX_WIDTH, yres = LCD_MAX_HEIGHT;
int node;
int node = dev->of_offset;
int ret = 0;
/*
* The code in common/lcd.c does not cope with not being able to
* set up a frame buffer. It will just happily keep writing to
* invalid memory. So here we make sure that at least some buffer
* is available even if it actually won't be displayed.
*/
node = fdtdec_next_compatible(blob, 0, COMPAT_SANDBOX_LCD_SDL);
if (node >= 0) {
xres = fdtdec_get_int(blob, node, "xres", LCD_MAX_WIDTH);
yres = fdtdec_get_int(blob, node, "yres", LCD_MAX_HEIGHT);
if (xres < 0 || xres > LCD_MAX_WIDTH) {
xres = LCD_MAX_WIDTH;
ret = -EINVAL;
}
if (yres < 0 || yres > LCD_MAX_HEIGHT) {
yres = LCD_MAX_HEIGHT;
ret = -EINVAL;
}
}
panel_info.vl_col = xres;
panel_info.vl_row = yres;
panel_info.vl_bpix = LCD_COLOR16;
plat->xres = fdtdec_get_int(blob, node, "xres", LCD_MAX_WIDTH);
plat->yres = fdtdec_get_int(blob, node, "yres", LCD_MAX_HEIGHT);
plat->bpix = VIDEO_BPP16;
uc_plat->size = plat->xres * plat->yres * (1 << plat->bpix) / 8;
debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
return ret;
}
static const struct udevice_id sandbox_sdl_ids[] = {
{ .compatible = "sandbox,lcd-sdl" },
{ }
};
U_BOOT_DRIVER(sdl_sandbox) = {
.name = "sdl_sandbox",
.id = UCLASS_VIDEO,
.of_match = sandbox_sdl_ids,
.bind = sandbox_sdl_bind,
.probe = sandbox_sdl_probe,
.platdata_auto_alloc_size = sizeof(struct sandbox_sdl_plat),
};

View file

@ -0,0 +1,239 @@
/*
* Copyright (c) 2015 Google, Inc
* (C) Copyright 2001-2015
* DENX Software Engineering -- wd@denx.de
* Compulab Ltd - http://compulab.co.il/
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <video.h>
#include <video_console.h>
#include <video_font.h> /* Get font data, width and height */
/* By default we scroll by a single line */
#ifndef CONFIG_CONSOLE_SCROLL_LINES
#define CONFIG_CONSOLE_SCROLL_LINES 1
#endif
int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
if (!ops->putc_xy)
return -ENOSYS;
return ops->putc_xy(dev, x, y, ch);
}
int vidconsole_move_rows(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
if (!ops->move_rows)
return -ENOSYS;
return ops->move_rows(dev, rowdst, rowsrc, count);
}
int vidconsole_set_row(struct udevice *dev, uint row, int clr)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
if (!ops->set_row)
return -ENOSYS;
return ops->set_row(dev, row, clr);
}
/* Move backwards one space */
static void vidconsole_back(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
if (--priv->curr_col < 0) {
priv->curr_col = priv->cols - 1;
if (--priv->curr_row < 0)
priv->curr_row = 0;
}
vidconsole_putc_xy(dev, priv->curr_col * VIDEO_FONT_WIDTH,
priv->curr_row * VIDEO_FONT_HEIGHT, ' ');
}
/* Move to a newline, scrolling the display if necessary */
static void vidconsole_newline(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
const int rows = CONFIG_CONSOLE_SCROLL_LINES;
int i;
priv->curr_col = 0;
/* Check if we need to scroll the terminal */
if (++priv->curr_row >= priv->rows) {
vidconsole_move_rows(dev, 0, rows, priv->rows - rows);
for (i = 0; i < rows; i++)
vidconsole_set_row(dev, priv->rows - i - 1,
vid_priv->colour_bg);
priv->curr_row -= rows;
}
video_sync(dev->parent);
}
int vidconsole_put_char(struct udevice *dev, char ch)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
int ret;
switch (ch) {
case '\r':
priv->curr_col = 0;
break;
case '\n':
vidconsole_newline(dev);
break;
case '\t': /* Tab (8 chars alignment) */
priv->curr_col += 8;
priv->curr_col &= ~7;
if (priv->curr_col >= priv->cols)
vidconsole_newline(dev);
break;
case '\b':
vidconsole_back(dev);
break;
default:
/*
* Failure of this function normally indicates an unsupported
* colour depth. Check this and return an error to help with
* diagnosis.
*/
ret = vidconsole_putc_xy(dev,
priv->curr_col * VIDEO_FONT_WIDTH,
priv->curr_row * VIDEO_FONT_HEIGHT,
ch);
if (ret)
return ret;
if (++priv->curr_col >= priv->cols)
vidconsole_newline(dev);
break;
}
return 0;
}
static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
{
struct udevice *dev = sdev->priv;
vidconsole_put_char(dev, ch);
}
static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
{
struct udevice *dev = sdev->priv;
while (*s)
vidconsole_put_char(dev, *s++);
}
/* Set up the number of rows and colours (rotated drivers override this) */
static int vidconsole_pre_probe(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
return 0;
}
/* Register the device with stdio */
static int vidconsole_post_probe(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct stdio_dev *sdev = &priv->sdev;
int ret;
strlcpy(sdev->name, dev->name, sizeof(sdev->name));
sdev->flags = DEV_FLAGS_OUTPUT;
sdev->putc = vidconsole_putc;
sdev->puts = vidconsole_puts;
sdev->priv = dev;
ret = stdio_register(sdev);
if (ret)
return ret;
return 0;
}
UCLASS_DRIVER(vidconsole) = {
.id = UCLASS_VIDEO_CONSOLE,
.name = "vidconsole0",
.pre_probe = vidconsole_pre_probe,
.post_probe = vidconsole_post_probe,
.per_device_auto_alloc_size = sizeof(struct vidconsole_priv),
};
void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
priv->curr_col = min_t(short, col, priv->cols - 1);
priv->curr_row = min_t(short, row, priv->rows - 1);
}
static int do_video_setcursor(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
unsigned int col, row;
struct udevice *dev;
if (argc != 3)
return CMD_RET_USAGE;
uclass_first_device(UCLASS_VIDEO_CONSOLE, &dev);
if (!dev)
return CMD_RET_FAILURE;
col = simple_strtoul(argv[1], NULL, 10);
row = simple_strtoul(argv[2], NULL, 10);
vidconsole_position_cursor(dev, col, row);
return 0;
}
static int do_video_puts(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
struct udevice *dev;
const char *s;
if (argc != 2)
return CMD_RET_USAGE;
uclass_first_device(UCLASS_VIDEO_CONSOLE, &dev);
if (!dev)
return CMD_RET_FAILURE;
for (s = argv[1]; *s; s++)
vidconsole_put_char(dev, *s);
return 0;
}
U_BOOT_CMD(
setcurs, 3, 1, do_video_setcursor,
"set cursor position within screen",
" <col> <row> in character"
);
U_BOOT_CMD(
lcdputs, 2, 1, do_video_puts,
"print string on video framebuffer",
" <string>"
);

View file

@ -0,0 +1,249 @@
/*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <mapmem.h>
#include <stdio_dev.h>
#include <video.h>
#include <video_console.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
#ifdef CONFIG_SANDBOX
#include <asm/sdl.h>
#endif
/*
* Theory of operation:
*
* Before relocation each device is bound. The driver for each device must
* set the @align and @size values in struct video_uc_platdata. This
* information represents the requires size and alignment of the frame buffer
* for the device. The values can be an over-estimate but cannot be too
* small. The actual values will be suppled (in the same manner) by the bind()
* method after relocation.
*
* This information is then picked up by video_reserve() which works out how
* much memory is needed for all devices. This is allocated between
* gd->video_bottom and gd->video_top.
*
* After relocation the same process occurs. The driver supplies the same
* @size and @align information and this time video_post_bind() checks that
* the drivers does not overflow the allocated memory.
*
* The frame buffer address is actually set (to plat->base) in
* video_post_probe(). This function also clears the frame buffer and
* allocates a suitable text console device. This can then be used to write
* text to the video device.
*/
DECLARE_GLOBAL_DATA_PTR;
static ulong alloc_fb(struct udevice *dev, ulong *addrp)
{
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
ulong base, align, size;
align = plat->align ? plat->align : 1 << 20;
base = *addrp - plat->size;
base &= ~(align - 1);
plat->base = base;
size = *addrp - base;
*addrp = base;
return size;
}
int video_reserve(ulong *addrp)
{
struct udevice *dev;
ulong size;
gd->video_top = *addrp;
for (uclass_find_first_device(UCLASS_VIDEO, &dev);
dev;
uclass_find_next_device(&dev)) {
size = alloc_fb(dev, addrp);
debug("%s: Reserving %lx bytes at %lx for video device '%s'\n",
__func__, size, *addrp, dev->name);
}
gd->video_bottom = *addrp;
debug("Video frame buffers from %lx to %lx\n", gd->video_bottom,
gd->video_top);
return 0;
}
static int video_clear(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
if (priv->bpix == VIDEO_BPP32) {
u32 *ppix = priv->fb;
u32 *end = priv->fb + priv->fb_size;
while (ppix < end)
*ppix++ = priv->colour_bg;
} else {
memset(priv->fb, priv->colour_bg, priv->fb_size);
}
return 0;
}
/* Flush video activity to the caches */
void video_sync(struct udevice *vid)
{
/*
* flush_dcache_range() is declared in common.h but it seems that some
* architectures do not actually implement it. Is there a way to find
* out whether it exists? For now, ARM is safe.
*/
#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF)
struct video_priv *priv = dev_get_uclass_priv(vid);
if (priv->flush_dcache) {
flush_dcache_range((ulong)priv->fb,
(ulong)priv->fb + priv->fb_size);
}
#elif defined(CONFIG_VIDEO_SANDBOX_SDL)
struct video_priv *priv = dev_get_uclass_priv(vid);
static ulong last_sync;
if (get_timer(last_sync) > 10) {
sandbox_sdl_sync(priv->fb);
last_sync = get_timer(0);
}
#endif
}
void video_sync_all(void)
{
struct udevice *dev;
for (uclass_find_first_device(UCLASS_VIDEO, &dev);
dev;
uclass_find_next_device(&dev)) {
if (device_active(dev))
video_sync(dev);
}
}
int video_get_xsize(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
return priv->xsize;
}
int video_get_ysize(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
return priv->ysize;
}
/* Set up the colour map */
static int video_pre_probe(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
priv->cmap = calloc(256, sizeof(ushort));
if (!priv->cmap)
return -ENOMEM;
return 0;
}
static int video_pre_remove(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
free(priv->cmap);
return 0;
}
/* Set up the display ready for use */
static int video_post_probe(struct udevice *dev)
{
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
struct video_priv *priv = dev_get_uclass_priv(dev);
char name[30], drv[15], *str;
struct udevice *cons;
int ret;
/* Set up the line and display size */
priv->fb = map_sysmem(plat->base, plat->size);
priv->line_length = priv->xsize * VNBYTES(priv->bpix);
priv->fb_size = priv->line_length * priv->ysize;
/* Set up colours - we could in future support other colours */
#ifdef CONFIG_SYS_WHITE_ON_BLACK
priv->colour_fg = 0xffffff;
#else
priv->colour_bg = 0xffffff;
#endif
video_clear(dev);
/*
* Create a text console devices. For now we always do this, although
* it might be useful to support only bitmap drawing on the device
* for boards that don't need to display text.
*/
snprintf(name, sizeof(name), "%s.vidconsole", dev->name);
str = strdup(name);
if (!str)
return -ENOMEM;
snprintf(drv, sizeof(drv), "vidconsole%d", priv->rot);
ret = device_bind_driver(dev, drv, str, &cons);
if (ret) {
debug("%s: Cannot bind console driver\n", __func__);
return ret;
}
ret = device_probe(cons);
if (ret) {
debug("%s: Cannot probe console driver\n", __func__);
return ret;
}
return 0;
};
/* Post-relocation, allocate memory for the frame buffer */
static int video_post_bind(struct udevice *dev)
{
ulong addr = gd->video_top;
ulong size;
/* Before relocation there is nothing to do here */
if ((!gd->flags & GD_FLG_RELOC))
return 0;
size = alloc_fb(dev, &addr);
if (addr < gd->video_bottom) {
/* Device tree node may need the 'u-boot,dm-pre-reloc' tag */
printf("Video device '%s' cannot allocate frame buffer memory -ensure the device is set up before relocation\n",
dev->name);
return -ENOSPC;
}
debug("%s: Claiming %lx bytes at %lx for video device '%s'\n",
__func__, size, addr, dev->name);
gd->video_bottom = addr;
return 0;
}
UCLASS_DRIVER(video) = {
.id = UCLASS_VIDEO,
.name = "video",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.post_bind = video_post_bind,
.pre_probe = video_pre_probe,
.post_probe = video_post_probe,
.pre_remove = video_pre_remove,
.per_device_auto_alloc_size = sizeof(struct video_priv),
.per_device_platdata_auto_alloc_size = sizeof(struct video_uc_platdata),
};

353
drivers/video/video_bmp.c Normal file
View file

@ -0,0 +1,353 @@
/*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <bmp_layout.h>
#include <dm.h>
#include <mapmem.h>
#include <video.h>
#include <watchdog.h>
#include <asm/unaligned.h>
#ifdef CONFIG_VIDEO_BMP_RLE8
#define BMP_RLE8_ESCAPE 0
#define BMP_RLE8_EOL 0
#define BMP_RLE8_EOBMP 1
#define BMP_RLE8_DELTA 2
static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap,
int cnt)
{
while (cnt > 0) {
*(*fbp)++ = cmap[*bmap++];
cnt--;
}
}
static void draw_encoded_bitmap(ushort **fbp, ushort col, int cnt)
{
ushort *fb = *fbp;
while (cnt > 0) {
*fb++ = col;
cnt--;
}
*fbp = fb;
}
static void video_display_rle8_bitmap(struct udevice *dev,
struct bmp_image *bmp, ushort *cmap,
uchar *fb, int x_off, int y_off)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
uchar *bmap;
ulong width, height;
ulong cnt, runlen;
int x, y;
int decode = 1;
debug("%s\n", __func__);
width = get_unaligned_le32(&bmp->header.width);
height = get_unaligned_le32(&bmp->header.height);
bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
x = 0;
y = height - 1;
while (decode) {
if (bmap[0] == BMP_RLE8_ESCAPE) {
switch (bmap[1]) {
case BMP_RLE8_EOL:
/* end of line */
bmap += 2;
x = 0;
y--;
/* 16bpix, 2-byte per pixel, width should *2 */
fb -= (width * 2 + priv->line_length);
break;
case BMP_RLE8_EOBMP:
/* end of bitmap */
decode = 0;
break;
case BMP_RLE8_DELTA:
/* delta run */
x += bmap[2];
y -= bmap[3];
/* 16bpix, 2-byte per pixel, x should *2 */
fb = (uchar *)(priv->fb + (y + y_off - 1)
* priv->line_length + (x + x_off) * 2);
bmap += 4;
break;
default:
/* unencoded run */
runlen = bmap[1];
bmap += 2;
if (y < height) {
if (x < width) {
if (x + runlen > width)
cnt = width - x;
else
cnt = runlen;
draw_unencoded_bitmap(
(ushort **)&fb,
bmap, cmap, cnt);
}
x += runlen;
}
bmap += runlen;
if (runlen & 1)
bmap++;
}
} else {
/* encoded run */
if (y < height) {
runlen = bmap[0];
if (x < width) {
/* aggregate the same code */
while (bmap[0] == 0xff &&
bmap[2] != BMP_RLE8_ESCAPE &&
bmap[1] == bmap[3]) {
runlen += bmap[2];
bmap += 2;
}
if (x + runlen > width)
cnt = width - x;
else
cnt = runlen;
draw_encoded_bitmap((ushort **)&fb,
cmap[bmap[1]], cnt);
}
x += runlen;
}
bmap += 2;
}
}
}
#endif
__weak void fb_put_byte(uchar **fb, uchar **from)
{
*(*fb)++ = *(*from)++;
}
#if defined(CONFIG_BMP_16BPP)
__weak void fb_put_word(uchar **fb, uchar **from)
{
*(*fb)++ = *(*from)++;
*(*fb)++ = *(*from)++;
}
#endif /* CONFIG_BMP_16BPP */
#define BMP_ALIGN_CENTER 0x7fff
/**
* video_splash_align_axis() - Align a single coordinate
*
*- if a coordinate is 0x7fff then the image will be centred in
* that direction
*- if a coordinate is -ve then it will be offset to the
* left/top of the centre by that many pixels
*- if a coordinate is positive it will be used unchnaged.
*
* @axis: Input and output coordinate
* @panel_size: Size of panel in pixels for that axis
* @picture_size: Size of bitmap in pixels for that axis
*/
static void video_splash_align_axis(int *axis, unsigned long panel_size,
unsigned long picture_size)
{
unsigned long panel_picture_delta = panel_size - picture_size;
unsigned long axis_alignment;
if (*axis == BMP_ALIGN_CENTER)
axis_alignment = panel_picture_delta / 2;
else if (*axis < 0)
axis_alignment = panel_picture_delta + *axis + 1;
else
return;
*axis = max(0, (int)axis_alignment);
}
static void video_set_cmap(struct udevice *dev,
struct bmp_color_table_entry *cte, unsigned colours)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
int i;
ushort *cmap = priv->cmap;
debug("%s: colours=%d\n", __func__, colours);
for (i = 0; i < colours; ++i) {
*cmap = ((cte->red << 8) & 0xf800) |
((cte->green << 3) & 0x07e0) |
((cte->blue >> 3) & 0x001f);
cmap++;
cte++;
}
}
int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
bool align)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
ushort *cmap_base = NULL;
ushort i, j;
uchar *fb;
struct bmp_image *bmp = map_sysmem(bmp_image, 0);
uchar *bmap;
ushort padded_width;
unsigned long width, height, byte_width;
unsigned long pwidth = priv->xsize;
unsigned colours, bpix, bmp_bpix;
struct bmp_color_table_entry *palette;
int hdr_size;
if (!bmp || !(bmp->header.signature[0] == 'B' &&
bmp->header.signature[1] == 'M')) {
printf("Error: no valid bmp image at %lx\n", bmp_image);
return -EINVAL;
}
width = get_unaligned_le32(&bmp->header.width);
height = get_unaligned_le32(&bmp->header.height);
bmp_bpix = get_unaligned_le16(&bmp->header.bit_count);
hdr_size = get_unaligned_le16(&bmp->header.size);
debug("hdr_size=%d, bmp_bpix=%d\n", hdr_size, bmp_bpix);
palette = (void *)bmp + 14 + hdr_size;
colours = 1 << bmp_bpix;
bpix = VNBITS(priv->bpix);
if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) {
printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
bpix, bmp_bpix);
return -EINVAL;
}
/*
* We support displaying 8bpp BMPs on 16bpp LCDs
* and displaying 24bpp BMPs on 32bpp LCDs
* */
if (bpix != bmp_bpix &&
!(bmp_bpix == 8 && bpix == 16) &&
!(bmp_bpix == 24 && bpix == 32)) {
printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
bpix, get_unaligned_le16(&bmp->header.bit_count));
return -EPERM;
}
debug("Display-bmp: %d x %d with %d colours, display %d\n",
(int)width, (int)height, (int)colours, 1 << bpix);
if (bmp_bpix == 8)
video_set_cmap(dev, palette, colours);
padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width);
if (align) {
video_splash_align_axis(&x, priv->xsize, width);
video_splash_align_axis(&y, priv->ysize, height);
}
if ((x + width) > pwidth)
width = pwidth - x;
if ((y + height) > priv->ysize)
height = priv->ysize - y;
bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
fb = (uchar *)(priv->fb +
(y + height - 1) * priv->line_length + x * bpix / 8);
switch (bmp_bpix) {
case 1:
case 8: {
cmap_base = priv->cmap;
#ifdef CONFIG_VIDEO_BMP_RLE8
u32 compression = get_unaligned_le32(&bmp->header.compression);
debug("compressed %d %d\n", compression, BMP_BI_RLE8);
if (compression == BMP_BI_RLE8) {
if (bpix != 16) {
/* TODO implement render code for bpix != 16 */
printf("Error: only support 16 bpix");
return -EPROTONOSUPPORT;
}
video_display_rle8_bitmap(dev, bmp, cmap_base, fb, x,
y);
break;
}
#endif
if (bpix != 16)
byte_width = width;
else
byte_width = width * 2;
for (i = 0; i < height; ++i) {
WATCHDOG_RESET();
for (j = 0; j < width; j++) {
if (bpix != 16) {
fb_put_byte(&fb, &bmap);
} else {
*(uint16_t *)fb = cmap_base[*bmap];
bmap++;
fb += sizeof(uint16_t) / sizeof(*fb);
}
}
bmap += (padded_width - width);
fb -= byte_width + priv->line_length;
}
break;
}
#if defined(CONFIG_BMP_16BPP)
case 16:
for (i = 0; i < height; ++i) {
WATCHDOG_RESET();
for (j = 0; j < width; j++)
fb_put_word(&fb, &bmap);
bmap += (padded_width - width) * 2;
fb -= width * 2 + lcd_line_length;
}
break;
#endif /* CONFIG_BMP_16BPP */
#if defined(CONFIG_BMP_24BMP)
case 24:
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
*(fb++) = *(bmap++);
*(fb++) = *(bmap++);
*(fb++) = *(bmap++);
*(fb++) = 0;
}
fb -= lcd_line_length + width * (bpix / 8);
}
break;
#endif /* CONFIG_BMP_24BMP */
#if defined(CONFIG_BMP_32BPP)
case 32:
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
*(fb++) = *(bmap++);
*(fb++) = *(bmap++);
*(fb++) = *(bmap++);
*(fb++) = *(bmap++);
}
fb -= lcd_line_length + width * (bpix / 8);
}
break;
#endif /* CONFIG_BMP_32BPP */
default:
break;
};
video_sync(dev);
return 0;
}

View file

@ -122,6 +122,10 @@ typedef struct global_data {
struct membuff console_out; /* console output */
struct membuff console_in; /* console input */
#endif
#ifdef CONFIG_DM_VIDEO
ulong video_top; /* Top of video frame buffer area */
ulong video_bottom; /* Bottom of video frame buffer area */
#endif
} gd_t;
#endif

View file

@ -68,7 +68,10 @@
/* Configure for U-Boot environment */
#define BZ_NO_STDIO
#ifndef CONFIG_SANDBOX
#define BZ_NO_COMPRESS
#endif
/* End of configuration for U-Boot environment */
#ifdef __cplusplus

View file

@ -8,6 +8,10 @@
#ifndef _CLK_H_
#define _CLK_H_
#include <linux/types.h>
struct udevice;
int soc_clk_dump(void);
struct clk_ops {
@ -29,19 +33,28 @@ struct clk_ops {
ulong (*set_rate)(struct udevice *dev, ulong rate);
/**
* clk_set_periph_rate() - Set clock rate for a peripheral
*
* @dev: Device to adjust (UCLASS_CLK)
* @rate: New clock rate in Hz
* @return new clock rate in Hz, or -ve error code
*/
* enable() - Enable the clock for a peripheral
*
* @dev: clock provider
* @periph: Peripheral ID to enable
* @return zero on success, or -ve error code
*/
int (*enable)(struct udevice *dev, int periph);
/**
* get_periph_rate() - Get clock rate for a peripheral
*
* @dev: Device to check (UCLASS_CLK)
* @periph: Peripheral ID to check
* @return clock rate in Hz, or -ve error code
*/
ulong (*get_periph_rate)(struct udevice *dev, int periph);
/**
* clk_set_periph_rate() - Set current clock rate for a peripheral
* set_periph_rate() - Set current clock rate for a peripheral
*
* @dev: Device to update (UCLASS_CLK)
* @periph: Peripheral ID to cupdate
* @periph: Peripheral ID to update
* @return new clock rate in Hz, or -ve error code
*/
ulong (*set_periph_rate)(struct udevice *dev, int periph, ulong rate);
@ -58,7 +71,7 @@ struct clk_ops {
ulong clk_get_rate(struct udevice *dev);
/**
* set_rate() - Set current clock rate
* clk_set_rate() - Set current clock rate
*
* @dev: Device to adjust
* @rate: New clock rate in Hz
@ -66,6 +79,15 @@ ulong clk_get_rate(struct udevice *dev);
*/
ulong clk_set_rate(struct udevice *dev, ulong rate);
/**
* clk_enable() - Enable the clock for a peripheral
*
* @dev: clock provider
* @periph: Peripheral ID to enable
* @return zero on success, or -ve error code
*/
int clk_enable(struct udevice *dev, int periph);
/**
* clk_get_periph_rate() - Get current clock rate for a peripheral
*
@ -78,7 +100,7 @@ ulong clk_get_periph_rate(struct udevice *dev, int periph);
* clk_set_periph_rate() - Set current clock rate for a peripheral
*
* @dev: Device to update (UCLASS_CLK)
* @periph: Peripheral ID to cupdate
* @periph: Peripheral ID to update
* @return new clock rate in Hz, or -ve error code
*/
ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate);

View file

@ -357,6 +357,7 @@
*/
#ifdef CONFIG_SPL_BUILD
#undef CONFIG_DM_MMC
#undef CONFIG_TIMER
#endif
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_USBETH_SUPPORT)

View file

@ -144,6 +144,7 @@
#undef CONFIG_DM_MMC
#undef CONFIG_DM_SPI
#undef CONFIG_DM_SPI_FLASH
#undef CONFIG_TIMER
#endif
#ifndef CONFIG_SPL_BUILD

View file

@ -36,7 +36,6 @@
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_FSL_LPUART
#define LPUART_BASE UART0_BASE
/* Allow to overwrite serial and ethaddr */

View file

@ -371,7 +371,6 @@ unsigned long get_board_ddr_clk(void);
* Serial Port
*/
#ifdef CONFIG_LPUART
#define CONFIG_FSL_LPUART
#define CONFIG_LPUART_32B_REG
#else
#define CONFIG_CONS_INDEX 1

View file

@ -266,12 +266,13 @@
* Serial Port
*/
#ifdef CONFIG_LPUART
#define CONFIG_FSL_LPUART
#define CONFIG_LPUART_32B_REG
#else
#define CONFIG_CONS_INDEX 1
#define CONFIG_SYS_NS16550_SERIAL
#ifndef CONFIG_DM_SERIAL
#define CONFIG_SYS_NS16550_REG_SIZE 1
#endif
#define CONFIG_SYS_NS16550_CLK get_serial_clock()
#endif

View file

@ -27,7 +27,6 @@
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_FSL_LPUART
#define LPUART_BASE UART1_BASE
/* Allow to overwrite serial and ethaddr */

View file

@ -158,24 +158,23 @@
/* LCD and keyboard require SDL support */
#ifdef CONFIG_SANDBOX_SDL
#define CONFIG_LCD
#define CONFIG_VIDEO_SANDBOX_SDL
#define CONFIG_CMD_BMP
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_CONSOLE_MUX
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
#define LCD_BPP LCD_COLOR16
#define CONFIG_LCD_BMP_RLE8
#define CONFIG_VIDEO_BMP_RLE8
#define CONFIG_SPLASH_SCREEN_ALIGN
#define CONFIG_KEYBOARD
#define SANDBOX_SERIAL_SETTINGS "stdin=serial,cros-ec-keyb,usbkbd\0" \
"stdout=serial,lcd\0" \
"stderr=serial,lcd\0"
"stdout=serial,lcd.vidconsole\0" \
"stderr=serial,lcd.vidconsole\0"
#else
#define SANDBOX_SERIAL_SETTINGS "stdin=serial\0" \
"stdout=serial,lcd\0" \
"stderr=serial,lcd\0"
"stdout=serial,lcd.vidconsole\0" \
"stderr=serial,lcd.vidconsole\0"
#endif
#define SANDBOX_ETH_SETTINGS "ethaddr=00:00:11:22:33:44\0" \

View file

@ -164,6 +164,7 @@
*/
#ifdef CONFIG_SPL_BUILD
#undef CONFIG_DM_MMC
#undef CONFIG_TIMER
#endif
#endif /* __CONFIG_TI_OMAP5_COMMON_H */

View file

@ -34,7 +34,6 @@
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_FSL_LPUART
#define LPUART_BASE UART1_BASE
/* Allow to overwrite serial and ethaddr */

View file

@ -155,6 +155,14 @@ enum {
/* Declare a new driver model test */
#define DM_TEST(_name, _flags) UNIT_TEST(_name, _flags, dm_test)
/* This platform data is needed in tests, so declare it here */
struct sandbox_sdl_plat {
int xres;
int yres;
int bpix;
int rot;
};
/* Declare ping methods for the drivers */
int test_ping(struct udevice *dev, int pingval, int *pingret);
int testfdt_ping(struct udevice *dev, int pingval, int *pingret);

View file

@ -66,7 +66,9 @@ enum uclass_id {
UCLASS_USB, /* USB bus */
UCLASS_USB_DEV_GENERIC, /* USB generic device */
UCLASS_USB_HUB, /* USB hub */
UCLASS_VIDEO, /* Video or LCD device */
UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */
UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */
UCLASS_COUNT,
UCLASS_INVALID = -1,

View file

@ -151,7 +151,6 @@ enum fdt_compat_id {
COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */
COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */
COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */
COMPAT_SANDBOX_LCD_SDL, /* Sandbox LCD emulation with SDL */
COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */
COMPAT_INTEL_MICROCODE, /* Intel microcode update */
COMPAT_MEMORY_SPD, /* Memory SPD information */

View file

@ -18,6 +18,12 @@
#include <asm/byteorder.h>
#endif
int bmp_display(ulong addr, int x, int y);
struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
void **alloc_addr);
#ifndef CONFIG_DM_VIDEO
extern char lcd_is_enabled;
extern int lcd_line_length;
extern struct vidinfo panel_info;
@ -26,10 +32,6 @@ void lcd_ctrl_init(void *lcdbase);
void lcd_enable(void);
void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue);
struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
void **alloc_addr);
int bmp_display(ulong addr, int x, int y);
/**
* Set whether we need to flush the dcache when changing the LCD image. This
* defaults to off.
@ -209,4 +211,6 @@ void lcd_sync(void);
#define PAGE_SIZE 4096
#endif
#endif /* !CONFIG_DM_VIDEO */
#endif /* _LCD_H_ */

View file

@ -7,6 +7,15 @@
#ifndef _TIMER_H_
#define _TIMER_H_
/*
* dm_timer_init - initialize a timer for time keeping. On success
* initializes gd->timer so that lib/timer can use it for future
* referrence.
*
* @return - 0 on success or error number
*/
int dm_timer_init(void);
/*
* timer_conv_64 - convert 32-bit counter value to 64-bit
*

View file

@ -1,14 +1,167 @@
/*
** MPC823 Video Controller
** =======================
** (C) 2000 by Paolo Scaffardi (arsenio@tin.it)
** AIRVENT SAM s.p.a - RIMINI(ITALY)
**
*/
* Video uclass and legacy implementation
*
* Copyright (c) 2015 Google, Inc
*
* MPC823 Video Controller
* =======================
* (C) 2000 by Paolo Scaffardi (arsenio@tin.it)
* AIRVENT SAM s.p.a - RIMINI(ITALY)
*
*/
#ifndef _VIDEO_H_
#define _VIDEO_H_
#ifdef CONFIG_DM_VIDEO
#include <stdio_dev.h>
struct video_uc_platdata {
uint align;
uint size;
ulong base;
};
/*
* Bits per pixel selector. Each value n is such that the bits-per-pixel is
* 2 ^ n
*/
enum video_log2_bpp {
VIDEO_BPP1 = 0,
VIDEO_BPP2,
VIDEO_BPP4,
VIDEO_BPP8,
VIDEO_BPP16,
VIDEO_BPP32,
};
/*
* Convert enum video_log2_bpp to bytes and bits. Note we omit the outer
* brackets to allow multiplication by fractional pixels.
*/
#define VNBYTES(bpix) (1 << (bpix)) / 8
#define VNBITS(bpix) (1 << (bpix))
/**
* struct video_priv - Device information used by the video uclass
*
* @xsize: Number of pixel columns (e.g. 1366)
* @ysize: Number of pixels rows (e.g.. 768)
* @tor: Display rotation (0=none, 1=90 degrees clockwise, etc.)
* @bpix: Encoded bits per pixel
* @fb: Frame buffer
* @fb_size: Frame buffer size
* @line_length: Length of each frame buffer line, in bytes
* @colour_fg: Foreground colour (pixel value)
* @colour_bg: Background colour (pixel value)
* @flush_dcache: true to enable flushing of the data cache after
* the LCD is updated
* @cmap: Colour map for 8-bit-per-pixel displays
*/
struct video_priv {
/* Things set up by the driver: */
ushort xsize;
ushort ysize;
ushort rot;
enum video_log2_bpp bpix;
/*
* Things that are private to the uclass: don't use these in the
* driver
*/
void *fb;
int fb_size;
int line_length;
int colour_fg;
int colour_bg;
bool flush_dcache;
ushort *cmap;
};
/* Placeholder - there are no video operations at present */
struct video_ops {
};
#define video_get_ops(dev) ((struct video_ops *)(dev)->driver->ops)
/**
* video_reserve() - Reserve frame-buffer memory for video devices
*
* Note: This function is for internal use.
*
* This uses the uclass platdata's @size and @align members to figure out
* a size and position for each frame buffer as part of the pre-relocation
* process of determining the post-relocation memory layout.
*
* gd->video_top is set to the initial value of *@addrp and gd->video_bottom
* is set to the final value.
*
* @addrp: On entry, the top of available memory. On exit, the new top,
* after allocating the required memory.
* @return 0
*/
int video_reserve(ulong *addrp);
/**
* video_sync() - Sync a device's frame buffer with its hardware
*
* Some frame buffers are cached or have a secondary frame buffer. This
* function syncs these up so that the current contents of the U-Boot frame
* buffer are displayed to the user.
*
* @dev: Device to sync
*/
void video_sync(struct udevice *vid);
/**
* video_sync_all() - Sync all devices' frame buffers with there hardware
*
* This calls video_sync() on all active video devices.
*/
void video_sync_all(void);
/**
* video_bmp_display() - Display a BMP file
*
* @dev: Device to display the bitmap on
* @bmp_image: Address of bitmap image to display
* @x: X position in pixels from the left
* @y: Y position in pixels from the top
* @align: true to adjust the coordinates to centre the image. If false
* the coordinates are used as is. If true:
*
* - if a coordinate is 0x7fff then the image will be centred in
* that direction
* - if a coordinate is -ve then it will be offset to the
* left/top of the centre by that many pixels
* - if a coordinate is positive it will be used unchnaged.
* @return 0 if OK, -ve on error
*/
int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
bool align);
/**
* video_get_xsize() - Get the width of the display in pixels
*
* @dev: Device to check
* @return device frame buffer width in pixels
*/
int video_get_xsize(struct udevice *dev);
/**
* video_get_ysize() - Get the height of the display in pixels
*
* @dev: Device to check
* @return device frame buffer height in pixels
*/
int video_get_ysize(struct udevice *dev);
#endif /* CONFIG_DM_VIDEO */
#ifndef CONFIG_DM_VIDEO
/* Video functions */
struct stdio_dev;
@ -73,4 +226,7 @@ int kwh043st20_f01_spi_startup(unsigned int bus, unsigned int cs,
int lg4573_spi_startup(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode);
#endif
#endif /* CONFIG_DM_VIDEO */
#endif

136
include/video_console.h Normal file
View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __video_console_h
#define __video_console_h
/**
* struct vidconsole_priv - uclass-private data about a console device
*
* @sdev: stdio device, acting as an output sink
* @curr_col: Current text column (0=left)
* @curr_row: Current row (0=top)
* @rows: Number of text rows
* @cols: Number of text columns
*/
struct vidconsole_priv {
struct stdio_dev sdev;
int curr_col;
int curr_row;
int rows;
int cols;
};
/**
* struct vidconsole_ops - Video console operations
*
* These operations work on either an absolute console position (measured
* in pixels) or a text row number (measured in rows, where each row consists
* of an entire line of text - typically 16 pixels).
*/
struct vidconsole_ops {
/**
* putc_xy() - write a single character to a position
*
* @dev: Device to write to
* @x: Pixel X position (0=left-most pixel)
* @y: Pixel Y position (0=top-most pixel)
* @ch: Character to write
* @return 0 if OK, -ve on error
*/
int (*putc_xy)(struct udevice *dev, uint x, uint y, char ch);
/**
* move_rows() - Move text rows from one place to another
*
* @dev: Device to adjust
* @rowdst: Destination text row (0=top)
* @rowsrc: Source start text row
* @count: Number of text rows to move
* @return 0 if OK, -ve on error
*/
int (*move_rows)(struct udevice *dev, uint rowdst, uint rowsrc,
uint count);
/**
* set_row() - Set the colour of a text row
*
* Every pixel contained within the text row is adjusted
*
* @dev: Device to adjust
* @row: Text row to adjust (0=top)
* @clr: Raw colour (pixel value) to write to each pixel
* @return 0 if OK, -ve on error
*/
int (*set_row)(struct udevice *dev, uint row, int clr);
};
/* Get a pointer to the driver operations for a video console device */
#define vidconsole_get_ops(dev) ((struct vidconsole_ops *)(dev)->driver->ops)
/**
* vidconsole_putc_xy() - write a single character to a position
*
* @dev: Device to write to
* @x: Pixel X position (0=left-most pixel)
* @y: Pixel Y position (0=top-most pixel)
* @ch: Character to write
* @return 0 if OK, -ve on error
*/
int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch);
/**
* vidconsole_move_rows() - Move text rows from one place to another
*
* @dev: Device to adjust
* @rowdst: Destination text row (0=top)
* @rowsrc: Source start text row
* @count: Number of text rows to move
* @return 0 if OK, -ve on error
*/
int vidconsole_move_rows(struct udevice *dev, uint rowdst, uint rowsrc,
uint count);
/**
* vidconsole_set_row() - Set the colour of a text row
*
* Every pixel contained within the text row is adjusted
*
* @dev: Device to adjust
* @row: Text row to adjust (0=top)
* @clr: Raw colour (pixel value) to write to each pixel
* @return 0 if OK, -ve on error
*/
int vidconsole_set_row(struct udevice *dev, uint row, int clr);
/**
* vidconsole_put_char() - Output a character to the current console position
*
* Outputs a character to the console and advances the cursor. This function
* handles wrapping to new lines and scrolling the console. Special
* characters are handled also: \n, \r, \b and \t.
*
* The device always starts with the cursor at position 0,0 (top left). It
* can be adjusted manually using vidconsole_position_cursor().
*
* @dev: Device to adjust
* @ch: Character to write
* @return 0 if OK, -ve on error
*/
int vidconsole_put_char(struct udevice *dev, char ch);
/**
* vidconsole_position_cursor() - Move the text cursor
*
* @dev: Device to adjust
* @col: New cursor text column
* @row: New cursor text row
* @return 0 if OK, -ve on error
*/
void vidconsole_position_cursor(struct udevice *dev, unsigned col,
unsigned row);
#endif

View file

@ -4,3 +4,4 @@
obj-y += bzlib.o bzlib_crctable.o bzlib_decompress.o \
bzlib_randtable.o bzlib_huffman.o
obj-$(CONFIG_SANDBOX) += bzlib_compress.o bzlib_blocksort.o

1134
lib/bzip2/bzlib_blocksort.c Normal file

File diff suppressed because it is too large Load diff

714
lib/bzip2/bzlib_compress.c Normal file
View file

@ -0,0 +1,714 @@
/*-------------------------------------------------------------*/
/*--- Compression machinery (not incl block sorting) ---*/
/*--- compress.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
/* CHANGES
0.9.0 -- original version.
0.9.0a/b -- no changes in this file.
0.9.0c -- changed setting of nGroups in sendMTFValues()
so as to do a bit better on small files
*/
#include "bzlib_private.h"
/*---------------------------------------------------*/
/*--- Bit stream I/O ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
void BZ2_bsInitWrite ( EState* s )
{
s->bsLive = 0;
s->bsBuff = 0;
}
/*---------------------------------------------------*/
static
void bsFinishWrite ( EState* s )
{
while (s->bsLive > 0) {
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
s->numZ++;
s->bsBuff <<= 8;
s->bsLive -= 8;
}
}
/*---------------------------------------------------*/
#define bsNEEDW(nz) \
{ \
while (s->bsLive >= 8) { \
s->zbits[s->numZ] \
= (UChar)(s->bsBuff >> 24); \
s->numZ++; \
s->bsBuff <<= 8; \
s->bsLive -= 8; \
} \
}
/*---------------------------------------------------*/
static
__inline__
void bsW ( EState* s, Int32 n, UInt32 v )
{
bsNEEDW ( n );
s->bsBuff |= (v << (32 - s->bsLive - n));
s->bsLive += n;
}
/*---------------------------------------------------*/
static
void bsPutUInt32 ( EState* s, UInt32 u )
{
bsW ( s, 8, (u >> 24) & 0xffL );
bsW ( s, 8, (u >> 16) & 0xffL );
bsW ( s, 8, (u >> 8) & 0xffL );
bsW ( s, 8, u & 0xffL );
}
/*---------------------------------------------------*/
static
void bsPutUChar ( EState* s, UChar c )
{
bsW( s, 8, (UInt32)c );
}
/*---------------------------------------------------*/
/*--- The back end proper ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
static
void makeMaps_e ( EState* s )
{
Int32 i;
s->nInUse = 0;
for (i = 0; i < 256; i++)
if (s->inUse[i]) {
s->unseqToSeq[i] = s->nInUse;
s->nInUse++;
}
}
/*---------------------------------------------------*/
static
void generateMTFValues ( EState* s )
{
UChar yy[256];
Int32 i, j;
Int32 zPend;
Int32 wr;
Int32 EOB;
/*
After sorting (eg, here),
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
and
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
holds the original block data.
The first thing to do is generate the MTF values,
and put them in
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
Because there are strictly fewer or equal MTF values
than block values, ptr values in this area are overwritten
with MTF values only when they are no longer needed.
The final compressed bitstream is generated into the
area starting at
(UChar*) (&((UChar*)s->arr2)[s->nblock])
These storage aliases are set up in bzCompressInit(),
except for the last one, which is arranged in
compressBlock().
*/
UInt32* ptr = s->ptr;
UChar* block = s->block;
UInt16* mtfv = s->mtfv;
makeMaps_e ( s );
EOB = s->nInUse+1;
for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
wr = 0;
zPend = 0;
for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
for (i = 0; i < s->nblock; i++) {
UChar ll_i;
AssertD ( wr <= i, "generateMTFValues(1)" );
j = ptr[i]-1; if (j < 0) j += s->nblock;
ll_i = s->unseqToSeq[block[j]];
AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
if (yy[0] == ll_i) {
zPend++;
} else {
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB; wr++;
s->mtfFreq[BZ_RUNB]++;
} else {
mtfv[wr] = BZ_RUNA; wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2) break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
{
register UChar rtmp;
register UChar* ryy_j;
register UChar rll_i;
rtmp = yy[1];
yy[1] = yy[0];
ryy_j = &(yy[1]);
rll_i = ll_i;
while ( rll_i != rtmp ) {
register UChar rtmp2;
ryy_j++;
rtmp2 = rtmp;
rtmp = *ryy_j;
*ryy_j = rtmp2;
};
yy[0] = rtmp;
j = ryy_j - &(yy[0]);
mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
}
}
}
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB; wr++;
s->mtfFreq[BZ_RUNB]++;
} else {
mtfv[wr] = BZ_RUNA; wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2) break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
s->nMTF = wr;
}
/*---------------------------------------------------*/
#define BZ_LESSER_ICOST 0
#define BZ_GREATER_ICOST 15
static
void sendMTFValues ( EState* s )
{
Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
Int32 nGroups, nBytes;
/*--
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
is a global since the decoder also needs it.
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
are also globals only used in this proc.
Made global to keep stack frame size small.
--*/
UInt16 cost[BZ_N_GROUPS];
Int32 fave[BZ_N_GROUPS];
UInt16* mtfv = s->mtfv;
if (s->verbosity >= 3)
VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
"%d+2 syms in use\n",
s->nblock, s->nMTF, s->nInUse );
alphaSize = s->nInUse+2;
for (t = 0; t < BZ_N_GROUPS; t++)
for (v = 0; v < alphaSize; v++)
s->len[t][v] = BZ_GREATER_ICOST;
/*--- Decide how many coding tables to use ---*/
AssertH ( s->nMTF > 0, 3001 );
if (s->nMTF < 200) nGroups = 2; else
if (s->nMTF < 600) nGroups = 3; else
if (s->nMTF < 1200) nGroups = 4; else
if (s->nMTF < 2400) nGroups = 5; else
nGroups = 6;
/*--- Generate an initial set of coding tables ---*/
{
Int32 nPart, remF, tFreq, aFreq;
nPart = nGroups;
remF = s->nMTF;
gs = 0;
while (nPart > 0) {
tFreq = remF / nPart;
ge = gs-1;
aFreq = 0;
while (aFreq < tFreq && ge < alphaSize-1) {
ge++;
aFreq += s->mtfFreq[ge];
}
if (ge > gs
&& nPart != nGroups && nPart != 1
&& ((nGroups-nPart) % 2 == 1)) {
aFreq -= s->mtfFreq[ge];
ge--;
}
if (s->verbosity >= 3)
VPrintf5( " initial group %d, [%d .. %d], "
"has %d syms (%4.1f%%)\n",
nPart, gs, ge, aFreq,
(100.0 * (float)aFreq) / (float)(s->nMTF) );
for (v = 0; v < alphaSize; v++)
if (v >= gs && v <= ge)
s->len[nPart-1][v] = BZ_LESSER_ICOST; else
s->len[nPart-1][v] = BZ_GREATER_ICOST;
nPart--;
gs = ge+1;
remF -= aFreq;
}
}
/*---
Iterate up to BZ_N_ITERS times to improve the tables.
---*/
for (iter = 0; iter < BZ_N_ITERS; iter++) {
for (t = 0; t < nGroups; t++) fave[t] = 0;
for (t = 0; t < nGroups; t++)
for (v = 0; v < alphaSize; v++)
s->rfreq[t][v] = 0;
/*---
Set up an auxiliary length table which is used to fast-track
the common case (nGroups == 6).
---*/
if (nGroups == 6) {
for (v = 0; v < alphaSize; v++) {
s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
}
}
nSelectors = 0;
totc = 0;
gs = 0;
while (True) {
/*--- Set group start & end marks. --*/
if (gs >= s->nMTF) break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF) ge = s->nMTF-1;
/*--
Calculate the cost of this group as coded
by each of the coding tables.
--*/
for (t = 0; t < nGroups; t++) cost[t] = 0;
if (nGroups == 6 && 50 == ge-gs+1) {
/*--- fast track the common case ---*/
register UInt32 cost01, cost23, cost45;
register UInt16 icv;
cost01 = cost23 = cost45 = 0;
# define BZ_ITER(nn) \
icv = mtfv[gs+(nn)]; \
cost01 += s->len_pack[icv][0]; \
cost23 += s->len_pack[icv][1]; \
cost45 += s->len_pack[icv][2]; \
BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
# undef BZ_ITER
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
} else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++) {
UInt16 icv = mtfv[i];
for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
}
}
/*--
Find the coding table which is best for this group,
and record its identity in the selector table.
--*/
bc = 999999999; bt = -1;
for (t = 0; t < nGroups; t++)
if (cost[t] < bc) { bc = cost[t]; bt = t; };
totc += bc;
fave[bt]++;
s->selector[nSelectors] = bt;
nSelectors++;
/*--
Increment the symbol frequencies for the selected table.
--*/
if (nGroups == 6 && 50 == ge-gs+1) {
/*--- fast track the common case ---*/
# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
# undef BZ_ITUR
} else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++)
s->rfreq[bt][ mtfv[i] ]++;
}
gs = ge+1;
}
if (s->verbosity >= 3) {
VPrintf2 ( " pass %d: size is %d, grp uses are ",
iter+1, totc/8 );
for (t = 0; t < nGroups; t++)
VPrintf1 ( "%d ", fave[t] );
VPrintf0 ( "\n" );
}
/*--
Recompute the tables based on the accumulated frequencies.
--*/
/* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
comment in huffman.c for details. */
for (t = 0; t < nGroups; t++)
BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
alphaSize, 17 /*20*/ );
}
AssertH( nGroups < 8, 3002 );
AssertH( nSelectors < 32768 &&
nSelectors <= (2 + (900000 / BZ_G_SIZE)),
3003 );
/*--- Compute MTF values for the selectors. ---*/
{
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
for (i = 0; i < nGroups; i++) pos[i] = i;
for (i = 0; i < nSelectors; i++) {
ll_i = s->selector[i];
j = 0;
tmp = pos[j];
while ( ll_i != tmp ) {
j++;
tmp2 = tmp;
tmp = pos[j];
pos[j] = tmp2;
};
pos[0] = tmp;
s->selectorMtf[i] = j;
}
};
/*--- Assign actual codes for the tables. --*/
for (t = 0; t < nGroups; t++) {
minLen = 32;
maxLen = 0;
for (i = 0; i < alphaSize; i++) {
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
if (s->len[t][i] < minLen) minLen = s->len[t][i];
}
AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
AssertH ( !(minLen < 1), 3005 );
BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
minLen, maxLen, alphaSize );
}
/*--- Transmit the mapping table. ---*/
{
Bool inUse16[16];
for (i = 0; i < 16; i++) {
inUse16[i] = False;
for (j = 0; j < 16; j++)
if (s->inUse[i * 16 + j]) inUse16[i] = True;
}
nBytes = s->numZ;
for (i = 0; i < 16; i++)
if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
for (i = 0; i < 16; i++)
if (inUse16[i])
for (j = 0; j < 16; j++) {
if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
}
if (s->verbosity >= 3)
VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
}
/*--- Now the selectors. ---*/
nBytes = s->numZ;
bsW ( s, 3, nGroups );
bsW ( s, 15, nSelectors );
for (i = 0; i < nSelectors; i++) {
for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
bsW(s,1,0);
}
if (s->verbosity >= 3)
VPrintf1( "selectors %d, ", s->numZ-nBytes );
/*--- Now the coding tables. ---*/
nBytes = s->numZ;
for (t = 0; t < nGroups; t++) {
Int32 curr = s->len[t][0];
bsW ( s, 5, curr );
for (i = 0; i < alphaSize; i++) {
while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
bsW ( s, 1, 0 );
}
}
if (s->verbosity >= 3)
VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
/*--- And finally, the block data proper ---*/
nBytes = s->numZ;
selCtr = 0;
gs = 0;
while (True) {
if (gs >= s->nMTF) break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF) ge = s->nMTF-1;
AssertH ( s->selector[selCtr] < nGroups, 3006 );
if (nGroups == 6 && 50 == ge-gs+1) {
/*--- fast track the common case ---*/
UInt16 mtfv_i;
UChar* s_len_sel_selCtr
= &(s->len[s->selector[selCtr]][0]);
Int32* s_code_sel_selCtr
= &(s->code[s->selector[selCtr]][0]);
# define BZ_ITAH(nn) \
mtfv_i = mtfv[gs+(nn)]; \
bsW ( s, \
s_len_sel_selCtr[mtfv_i], \
s_code_sel_selCtr[mtfv_i] )
BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
# undef BZ_ITAH
} else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++) {
bsW ( s,
s->len [s->selector[selCtr]] [mtfv[i]],
s->code [s->selector[selCtr]] [mtfv[i]] );
}
}
gs = ge+1;
selCtr++;
}
AssertH( selCtr == nSelectors, 3007 );
if (s->verbosity >= 3)
VPrintf1( "codes %d\n", s->numZ-nBytes );
else /* squash compiler 'used but not set' warning */
nBytes = nBytes;
}
/*---------------------------------------------------*/
void BZ2_compressBlock ( EState* s, Bool is_last_block )
{
if (s->nblock > 0) {
BZ_FINALISE_CRC ( s->blockCRC );
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
s->combinedCRC ^= s->blockCRC;
if (s->blockNo > 1) s->numZ = 0;
if (s->verbosity >= 2)
VPrintf4( " block %d: crc = 0x%08x, "
"combined CRC = 0x%08x, size = %d\n",
s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
BZ2_blockSort ( s );
}
s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
/*-- If this is the first block, create the stream header. --*/
if (s->blockNo == 1) {
BZ2_bsInitWrite ( s );
bsPutUChar ( s, BZ_HDR_B );
bsPutUChar ( s, BZ_HDR_Z );
bsPutUChar ( s, BZ_HDR_h );
bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
}
if (s->nblock > 0) {
bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
/*-- Now the block's CRC, so it is in a known place. --*/
bsPutUInt32 ( s, s->blockCRC );
/*--
Now a single bit indicating (non-)randomisation.
As of version 0.9.5, we use a better sorting algorithm
which makes randomisation unnecessary. So always set
the randomised bit to 'no'. Of course, the decoder
still needs to be able to handle randomised blocks
so as to maintain backwards compatibility with
older versions of bzip2.
--*/
bsW(s,1,0);
bsW ( s, 24, s->origPtr );
generateMTFValues ( s );
sendMTFValues ( s );
}
/*-- If this is the last block, add the stream trailer. --*/
if (is_last_block) {
bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
bsPutUInt32 ( s, s->combinedCRC );
if (s->verbosity >= 2)
VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
bsFinishWrite ( s );
}
}
/*-------------------------------------------------------------*/
/*--- end compress.c ---*/
/*-------------------------------------------------------------*/

View file

@ -56,7 +56,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
COMPAT(INTEL_MICROCODE, "intel,microcode"),
COMPAT(MEMORY_SPD, "memory-spd"),

View file

@ -41,23 +41,6 @@ extern unsigned long __weak timer_read_counter(void);
#endif
#ifdef CONFIG_TIMER
static int notrace dm_timer_init(void)
{
struct udevice *dev;
int ret;
if (!gd->timer) {
ret = uclass_first_device(UCLASS_TIMER, &dev);
if (ret)
return ret;
if (!dev)
return -ENODEV;
gd->timer = dev;
}
return 0;
}
ulong notrace get_tbclk(void)
{
int ret;

View file

@ -82,13 +82,21 @@ int vprintf(const char *fmt, va_list va)
num = -(int)num;
out('-');
}
for (div = 1000000000; div; div /= 10)
div_out(&num, div);
if (!num) {
out_dgt(0);
} else {
for (div = 1000000000; div; div /= 10)
div_out(&num, div);
}
break;
case 'x':
num = va_arg(va, unsigned int);
for (div = 0x10000000; div; div /= 0x10)
div_out(&num, div);
if (!num) {
out_dgt(0);
} else {
for (div = 0x10000000; div; div /= 0x10)
div_out(&num, div);
}
break;
case 'c':
out((char)(va_arg(va, int)));
@ -108,8 +116,10 @@ int vprintf(const char *fmt, va_list va)
w--;
while (w-- > 0)
putc(lz ? '0' : ' ');
while ((ch = *p++))
putc(ch);
if (p) {
while ((ch = *p++))
putc(ch);
}
}
}

View file

@ -1,29 +0,0 @@
#!/bin/sh
# Test for U-Boot cli including command repeat
BASE="$(dirname $0)"
. $BASE/common.sh
run_test() {
./${OUTPUT_DIR}/u-boot <<END
setenv ctrlc_ignore y
md 0
reset
END
}
check_results() {
echo "Check results"
grep -q 00000100 ${tmp} || fail "Command did not repeat"
}
echo "Test CLI repeat"
echo
tmp="$(tempfile)"
build_uboot
run_test >${tmp}
check_results ${tmp}
rm ${tmp}
echo "Test passed"

View file

@ -7,9 +7,6 @@
#define DEBUG
#include <common.h>
#ifdef CONFIG_SANDBOX
#include <os.h>
#endif
static const char test_cmd[] = "setenv list 1\n setenv list ${list}2; "
"setenv list ${list}3\0"
@ -20,21 +17,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("%s: Testing commands\n", __func__);
run_command("env default -f -a", 0);
/* run a single command */
run_command("setenv single 1", 0);
assert(!strcmp("1", getenv("single")));
/* make sure that compound statements work */
#ifdef CONFIG_SYS_HUSH_PARSER
run_command("if test -n ${single} ; then setenv check 1; fi", 0);
assert(!strcmp("1", getenv("check")));
run_command("setenv check", 0);
#endif
/* commands separated by ; */
run_command_list("setenv list 1; setenv list ${list}1", -1, 0);
assert(!strcmp("11", getenv("list")));
/* commands separated by \n */
run_command_list("setenv list 1\n setenv list ${list}1", -1, 0);
assert(!strcmp("11", getenv("list")));
@ -43,11 +25,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
run_command_list("setenv list 1${list}\n", -1, 0);
assert(!strcmp("111", getenv("list")));
/* three commands in a row */
run_command_list("setenv list 1\n setenv list ${list}2; "
"setenv list ${list}3", -1, 0);
assert(!strcmp("123", getenv("list")));
/* a command string with \0 in it. Stuff after \0 should be ignored */
run_command("setenv list", 0);
run_command_list(test_cmd, sizeof(test_cmd), 0);
@ -66,13 +43,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
assert(run_command_list("false", -1, 0) == 1);
assert(run_command_list("echo", -1, 0) == 0);
run_command("setenv foo 'setenv monty 1; setenv python 2'", 0);
run_command("run foo", 0);
assert(getenv("monty") != NULL);
assert(!strcmp("1", getenv("monty")));
assert(getenv("python") != NULL);
assert(!strcmp("2", getenv("python")));
#ifdef CONFIG_SYS_HUSH_PARSER
run_command("setenv foo 'setenv black 1\nsetenv adder 2'", 0);
run_command("run foo", 0);
@ -80,112 +50,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
assert(!strcmp("1", getenv("black")));
assert(getenv("adder") != NULL);
assert(!strcmp("2", getenv("adder")));
/* Test the 'test' command */
#define HUSH_TEST(name, expr, expected_result) \
run_command("if test " expr " ; then " \
"setenv " #name "_" #expected_result " y; else " \
"setenv " #name "_" #expected_result " n; fi", 0); \
assert(!strcmp(#expected_result, getenv(#name "_" #expected_result))); \
setenv(#name "_" #expected_result, NULL);
/* Basic operators */
HUSH_TEST(streq, "aaa = aaa", y);
HUSH_TEST(streq, "aaa = bbb", n);
HUSH_TEST(strneq, "aaa != bbb", y);
HUSH_TEST(strneq, "aaa != aaa", n);
HUSH_TEST(strlt, "aaa < bbb", y);
HUSH_TEST(strlt, "bbb < aaa", n);
HUSH_TEST(strgt, "bbb > aaa", y);
HUSH_TEST(strgt, "aaa > bbb", n);
HUSH_TEST(eq, "123 -eq 123", y);
HUSH_TEST(eq, "123 -eq 456", n);
HUSH_TEST(ne, "123 -ne 456", y);
HUSH_TEST(ne, "123 -ne 123", n);
HUSH_TEST(lt, "123 -lt 456", y);
HUSH_TEST(lt_eq, "123 -lt 123", n);
HUSH_TEST(lt, "456 -lt 123", n);
HUSH_TEST(le, "123 -le 456", y);
HUSH_TEST(le_eq, "123 -le 123", y);
HUSH_TEST(le, "456 -le 123", n);
HUSH_TEST(gt, "456 -gt 123", y);
HUSH_TEST(gt_eq, "123 -gt 123", n);
HUSH_TEST(gt, "123 -gt 456", n);
HUSH_TEST(ge, "456 -ge 123", y);
HUSH_TEST(ge_eq, "123 -ge 123", y);
HUSH_TEST(ge, "123 -ge 456", n);
HUSH_TEST(z, "-z \"\"", y);
HUSH_TEST(z, "-z \"aaa\"", n);
HUSH_TEST(n, "-n \"aaa\"", y);
HUSH_TEST(n, "-n \"\"", n);
/* Inversion of simple tests */
HUSH_TEST(streq_inv, "! aaa = aaa", n);
HUSH_TEST(streq_inv, "! aaa = bbb", y);
HUSH_TEST(streq_inv_inv, "! ! aaa = aaa", y);
HUSH_TEST(streq_inv_inv, "! ! aaa = bbb", n);
/* Binary operators */
HUSH_TEST(or_0_0, "aaa != aaa -o bbb != bbb", n);
HUSH_TEST(or_0_1, "aaa != aaa -o bbb = bbb", y);
HUSH_TEST(or_1_0, "aaa = aaa -o bbb != bbb", y);
HUSH_TEST(or_1_1, "aaa = aaa -o bbb = bbb", y);
HUSH_TEST(and_0_0, "aaa != aaa -a bbb != bbb", n);
HUSH_TEST(and_0_1, "aaa != aaa -a bbb = bbb", n);
HUSH_TEST(and_1_0, "aaa = aaa -a bbb != bbb", n);
HUSH_TEST(and_1_1, "aaa = aaa -a bbb = bbb", y);
/* Inversion within binary operators */
HUSH_TEST(or_0_0_inv, "! aaa != aaa -o ! bbb != bbb", y);
HUSH_TEST(or_0_1_inv, "! aaa != aaa -o ! bbb = bbb", y);
HUSH_TEST(or_1_0_inv, "! aaa = aaa -o ! bbb != bbb", y);
HUSH_TEST(or_1_1_inv, "! aaa = aaa -o ! bbb = bbb", n);
HUSH_TEST(or_0_0_inv_inv, "! ! aaa != aaa -o ! ! bbb != bbb", n);
HUSH_TEST(or_0_1_inv_inv, "! ! aaa != aaa -o ! ! bbb = bbb", y);
HUSH_TEST(or_1_0_inv_inv, "! ! aaa = aaa -o ! ! bbb != bbb", y);
HUSH_TEST(or_1_1_inv_inv, "! ! aaa = aaa -o ! ! bbb = bbb", y);
setenv("ut_var_nonexistent", NULL);
setenv("ut_var_exists", "1");
HUSH_TEST(z_varexp_quoted, "-z \"$ut_var_nonexistent\"", y);
HUSH_TEST(z_varexp_quoted, "-z \"$ut_var_exists\"", n);
setenv("ut_var_exists", NULL);
run_command("setenv ut_var_space \" \"", 0);
assert(!strcmp(getenv("ut_var_space"), " "));
run_command("setenv ut_var_test $ut_var_space", 0);
assert(!getenv("ut_var_test"));
run_command("setenv ut_var_test \"$ut_var_space\"", 0);
assert(!strcmp(getenv("ut_var_test"), " "));
run_command("setenv ut_var_test \" 1${ut_var_space}${ut_var_space} 2 \"", 0);
assert(!strcmp(getenv("ut_var_test"), " 1 2 "));
setenv("ut_var_space", NULL);
setenv("ut_var_test", NULL);
#ifdef CONFIG_SANDBOX
/* File existence */
HUSH_TEST(e, "-e hostfs - creating_this_file_breaks_uboot_unit_test", n);
run_command("sb save hostfs - creating_this_file_breaks_uboot_unit_test 0 1", 0);
HUSH_TEST(e, "-e hostfs - creating_this_file_breaks_uboot_unit_test", y);
/* Perhaps this could be replaced by an "rm" shell command one day */
assert(!os_unlink("creating_this_file_breaks_uboot_unit_test"));
HUSH_TEST(e, "-e hostfs - creating_this_file_breaks_uboot_unit_test", n);
#endif
#endif
assert(run_command("", 0) == 0);

View file

@ -34,5 +34,6 @@ obj-$(CONFIG_DM_USB) += usb.o
obj-$(CONFIG_DM_PMIC) += pmic.o
obj-$(CONFIG_DM_REGULATOR) += regulator.o
obj-$(CONFIG_TIMER) += timer.o
obj-$(CONFIG_DM_VIDEO) += video.o
obj-$(CONFIG_ADC) += adc.o
endif

271
test/dm/video.c Normal file
View file

@ -0,0 +1,271 @@
/*
* Copyright (c) 2014 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <bzlib.h>
#include <dm.h>
#include <mapmem.h>
#include <os.h>
#include <video.h>
#include <video_console.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
#include <test/ut.h>
/*
* These tests use the standard sandbox frame buffer, the resolution of which
* is defined in the device tree. This only supports 16bpp so the tests only
* test that code path. It would be possible to adjust this fairly easily,
* by adjusting the bpix value in struct sandbox_sdl_plat. However the code
* in sandbox_sdl_sync() would also need to change to handle the different
* surface depth.
*/
DECLARE_GLOBAL_DATA_PTR;
/* Basic test of the video uclass */
static int dm_test_video_base(struct unit_test_state *uts)
{
struct video_priv *priv;
struct udevice *dev;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
ut_asserteq(1366, video_get_xsize(dev));
ut_asserteq(768, video_get_ysize(dev));
priv = dev_get_uclass_priv(dev);
ut_asserteq(priv->fb_size, 1366 * 768 * 2);
return 0;
}
DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/**
* compress_frame_buffer() - Compress the frame buffer and return its size
*
* We want to write tests which perform operations on the video console and
* check that the frame buffer ends up with the correct contents. But it is
* painful to store 'known good' images for comparison with the frame
* buffer. As an alternative, we can compress the frame buffer and check the
* size of the compressed data. This provides a pretty good level of
* certainty and the resulting tests need only check a single value.
*
* @dev: Video device
* @return compressed size of the frame buffer, or -ve on error
*/
static int compress_frame_buffer(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
uint destlen;
void *dest;
int ret;
destlen = priv->fb_size;
dest = malloc(priv->fb_size);
if (!dest)
return -ENOMEM;
ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
priv->fb, priv->fb_size,
3, 0, 0);
free(dest);
if (ret)
return ret;
return destlen;
}
/*
* Call this function at any point to halt and show the current display. Be
* sure to run the test with the -l flag.
*/
static void __maybe_unused see_output(void)
{
video_sync_all();
while (1);
}
/* Test text output works on the video console */
static int dm_test_video_text(struct unit_test_state *uts)
{
struct udevice *dev, *con;
int i;
#define WHITE 0xffff
#define SCROLL_LINES 100
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
ut_asserteq(46, compress_frame_buffer(dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_putc_xy(con, 0, 0, 'a');
ut_asserteq(79, compress_frame_buffer(dev));
vidconsole_putc_xy(con, 0, 0, ' ');
ut_asserteq(46, compress_frame_buffer(dev));
for (i = 0; i < 20; i++)
vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
ut_asserteq(273, compress_frame_buffer(dev));
vidconsole_set_row(con, 0, WHITE);
ut_asserteq(46, compress_frame_buffer(dev));
for (i = 0; i < 20; i++)
vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
ut_asserteq(273, compress_frame_buffer(dev));
return 0;
}
DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test handling of special characters in the console */
static int dm_test_video_chars(struct unit_test_state *uts)
{
struct udevice *dev, *con;
const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very modest \bman\n\t\tand Has much to\b\bto be modest about.";
const char *s;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
for (s = test_string; *s; s++)
vidconsole_put_char(con, *s);
ut_asserteq(466, compress_frame_buffer(dev));
return 0;
}
DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/**
* check_vidconsole_output() - Run a text console test
*
* @uts: Test state
* @rot: Console rotation (0, 90, 180, 270)
* @wrap_size: Expected size of compressed frame buffer for the wrap test
* @scroll_size: Same for the scroll test
* @return 0 on success
*/
static int check_vidconsole_output(struct unit_test_state *uts, int rot,
int wrap_size, int scroll_size)
{
struct udevice *dev, *con;
struct sandbox_sdl_plat *plat;
int i;
ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
ut_assert(!device_active(dev));
plat = dev_get_platdata(dev);
plat->rot = rot;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
ut_asserteq(46, compress_frame_buffer(dev));
/* Check display wrap */
for (i = 0; i < 120; i++)
vidconsole_put_char(con, 'A' + i % 50);
ut_asserteq(wrap_size, compress_frame_buffer(dev));
/* Check display scrolling */
for (i = 0; i < SCROLL_LINES; i++) {
vidconsole_put_char(con, 'A' + i % 50);
vidconsole_put_char(con, '\n');
}
ut_asserteq(scroll_size, compress_frame_buffer(dev));
/* If we scroll enough, the screen becomes blank again */
for (i = 0; i < SCROLL_LINES; i++)
vidconsole_put_char(con, '\n');
ut_asserteq(46, compress_frame_buffer(dev));
return 0;
}
/* Test text output through the console uclass */
static int dm_test_video_context(struct unit_test_state *uts)
{
return check_vidconsole_output(uts, 0, 788, 453);
}
DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test rotated text output through the console uclass */
static int dm_test_video_rotation1(struct unit_test_state *uts)
{
ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
return 0;
}
DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test rotated text output through the console uclass */
static int dm_test_video_rotation2(struct unit_test_state *uts)
{
ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
return 0;
}
DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test rotated text output through the console uclass */
static int dm_test_video_rotation3(struct unit_test_state *uts)
{
ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
return 0;
}
DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Read a file into memory and return a pointer to it */
static int read_file(struct unit_test_state *uts, const char *fname,
ulong *addrp)
{
int buf_size = 100000;
ulong addr = 0;
int size, fd;
char *buf;
buf = map_sysmem(addr, 0);
ut_assert(buf != NULL);
fd = os_open(fname, OS_O_RDONLY);
ut_assert(fd >= 0);
size = os_read(fd, buf, buf_size);
ut_assert(size >= 0);
ut_assert(size < buf_size);
os_close(fd);
*addrp = addr;
return 0;
}
/* Test drawing a bitmap file */
static int dm_test_video_bmp(struct unit_test_state *uts)
{
struct udevice *dev;
ulong addr;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
ut_asserteq(1368, compress_frame_buffer(dev));
return 0;
}
DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test drawing a compressed bitmap file */
static int dm_test_video_bmp_comp(struct unit_test_state *uts)
{
struct udevice *dev;
ulong addr;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
ut_asserteq(1368, compress_frame_buffer(dev));
return 0;
}
DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);

1
test/py/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.pyc

300
test/py/README.md Normal file
View file

@ -0,0 +1,300 @@
# U-Boot pytest suite
## Introduction
This tool aims to test U-Boot by executing U-Boot shell commands using the
console interface. A single top-level script exists to execute or attach to the
U-Boot console, run the entire script of tests against it, and summarize the
results. Advantages of this approach are:
- Testing is performed in the same way a user or script would interact with
U-Boot; there can be no disconnect.
- There is no need to write or embed test-related code into U-Boot itself.
It is asserted that writing test-related code in Python is simpler and more
flexible that writing it all in C.
- It is reasonably simple to interact with U-Boot in this way.
## Requirements
The test suite is implemented using pytest. Interaction with the U-Boot console
involves executing some binary and interacting with its stdin/stdout. You will
need to implement various "hook" scripts that are called by the test suite at
the appropriate time.
On Debian or Debian-like distributions, the following packages are required.
Similar package names should exist in other distributions.
| Package | Version tested (Ubuntu 14.04) |
| -------------- | ----------------------------- |
| python | 2.7.5-5ubuntu3 |
| python-pytest | 2.5.1-1 |
The test script supports either:
- Executing a sandbox port of U-Boot on the local machine as a sub-process,
and interacting with it over stdin/stdout.
- Executing an external "hook" scripts to flash a U-Boot binary onto a
physical board, attach to the board's console stream, and reset the board.
Further details are described later.
### Using `virtualenv` to provide requirements
Older distributions (e.g. Ubuntu 10.04) may not provide all the required
packages, or may provide versions that are too old to run the test suite. One
can use the Python `virtualenv` script to locally install more up-to-date
versions of the required packages without interfering with the OS installation.
For example:
```bash
$ cd /path/to/u-boot
$ sudo apt-get install python python-virtualenv
$ virtualenv venv
$ . ./venv/bin/activate
$ pip install pytest
```
## Testing sandbox
To run the testsuite on the sandbox port (U-Boot built as a native user-space
application), simply execute:
```
./test/py/test.py --bd sandbox --build
```
The `--bd` option tells the test suite which board type is being tested. This
lets the test suite know which features the board has, and hence exactly what
can be tested.
The `--build` option tells U-Boot to compile U-Boot. Alternatively, you may
omit this option and build U-Boot yourself, in whatever way you choose, before
running the test script.
The test script will attach to U-Boot, execute all valid tests for the board,
then print a summary of the test process. A complete log of the test session
will be written to `${build_dir}/test-log.html`. This is best viewed in a web
browser, but may be read directly as plain text, perhaps with the aid of the
`html2text` utility.
## Command-line options
- `--board-type`, `--bd`, `-B` set the type of the board to be tested. For
example, `sandbox` or `seaboard`.
- `--board-identity`, `--id` set the identity of the board to be tested.
This allows differentiation between multiple instances of the same type of
physical board that are attached to the same host machine. This parameter is
not interpreted by the test script in any way, but rather is simply passed
to the hook scripts described below, and may be used in any site-specific
way deemed necessary.
- `--build` indicates that the test script should compile U-Boot itself
before running the tests. If using this option, make sure that any
environment variables required by the build process are already set, such as
`$CROSS_COMPILE`.
- `--build-dir` sets the directory containing the compiled U-Boot binaries.
If omitted, this is `${source_dir}/build-${board_type}`.
- `--result-dir` sets the directory to write results, such as log files,
into. If omitted, the build directory is used.
- `--persistent-data-dir` sets the directory used to store persistent test
data. This is test data that may be re-used across test runs, such as file-
system images.
`pytest` also implements a number of its own command-line options. Please see
`pytest` documentation for complete details. Execute `py.test --version` for
a brief summary. Note that U-Boot's test.py script passes all command-line
arguments directly to `pytest` for processing.
## Testing real hardware
The tools and techniques used to interact with real hardware will vary
radically between different host and target systems, and the whims of the user.
For this reason, the test suite does not attempt to directly interact with real
hardware in any way. Rather, it executes a standardized set of "hook" scripts
via `$PATH`. These scripts implement certain actions on behalf of the test
suite. This keeps the test suite simple and isolated from system variances
unrelated to U-Boot features.
### Hook scripts
#### Environment variables
The following environment variables are set when running hook scripts:
- `UBOOT_BOARD_TYPE` the board type being tested.
- `UBOOT_BOARD_IDENTITY` the board identity being tested, or `na` if none was
specified.
- `UBOOT_SOURCE_DIR` the U-Boot source directory.
- `UBOOT_TEST_PY_DIR` the full path to `test/py/` in the source directory.
- `UBOOT_BUILD_DIR` the U-Boot build directory.
- `UBOOT_RESULT_DIR` the test result directory.
- `UBOOT_PERSISTENT_DATA_DIR` the test peristent data directory.
#### `u-boot-test-console`
This script provides access to the U-Boot console. The script's stdin/stdout
should be connected to the board's console. This process should continue to run
indefinitely, until killed. The test suite will run this script in parallel
with all other hooks.
This script may be implemented e.g. by exec()ing `cu`, `kermit`, `conmux`, etc.
If you are able to run U-Boot under a hardware simulator such as qemu, then
you would likely spawn that simulator from this script. However, note that
`u-boot-test-reset` may be called multiple times per test script run, and must
cause U-Boot to start execution from scratch each time. Hopefully your
simulator includes a virtual reset button! If not, you can launch the
simulator from `u-boot-test-reset` instead, while arranging for this console
process to always communicate with the current simulator instance.
#### `u-boot-test-flash`
Prior to running the test suite against a board, some arrangement must be made
so that the board executes the particular U-Boot binary to be tested. Often,
this involves writing the U-Boot binary to the board's flash ROM. The test
suite calls this hook script for that purpose.
This script should perform the entire flashing process synchronously; the
script should only exit once flashing is complete, and a board reset will
cause the newly flashed U-Boot binary to be executed.
It is conceivable that this script will do nothing. This might be useful in
the following cases:
- Some other process has already written the desired U-Boot binary into the
board's flash prior to running the test suite.
- The board allows U-Boot to be downloaded directly into RAM, and executed
from there. Use of this feature will reduce wear on the board's flash, so
may be preferable if available, and if cold boot testing of U-Boot is not
required. If this feature is used, the `u-boot-test-reset` script should
peform this download, since the board could conceivably be reset multiple
times in a single test run.
It is up to the user to determine if those situations exist, and to code this
hook script appropriately.
This script will typically be implemented by calling out to some SoC- or
board-specific vendor flashing utility.
#### `u-boot-test-reset`
Whenever the test suite needs to reset the target board, this script is
executed. This is guaranteed to happen at least once, prior to executing the
first test function. If any test fails, the test infra-structure will execute
this script again to restore U-Boot to an operational state before running the
next test function.
This script will likely be implemented by communicating with some form of
relay or electronic switch attached to the board's reset signal.
The semantics of this script require that when it is executed, U-Boot will
start running from scratch. If the U-Boot binary to be tested has been written
to flash, pulsing the board's reset signal is likely all this script need do.
However, in some scenarios, this script may perform other actions. For
example, it may call out to some SoC- or board-specific vendor utility in order
to download the U-Boot binary directly into RAM and execute it. This would
avoid the need for `u-boot-test-flash` to actually write U-Boot to flash, thus
saving wear on the flash chip(s).
### Board-type-specific configuration
Each board has a different configuration and behaviour. Many of these
differences can be automatically detected by parsing the `.config` file in the
build directory. However, some differences can't yet be handled automatically.
For each board, an optional Python module `u_boot_board_${board_type}` may exist
to provide board-specific information to the test script. Any global value
defined in these modules is available for use by any test function. The data
contained in these scripts must be purely derived from U-Boot source code.
Hence, these configuration files are part of the U-Boot source tree too.
### Execution environment configuration
Each user's hardware setup may enable testing different subsets of the features
implemented by a particular board's configuration of U-Boot. For example, a
U-Boot configuration may support USB device mode and USB Mass Storage, but this
can only be tested if a USB cable is connected between the board and the host
machine running the test script.
For each board, optional Python modules `u_boot_boardenv_${board_type}` and
`u_boot_boardenv_${board_type}_${board_identity}` may exist to provide
board-specific and board-identity-specific information to the test script. Any
global value defined in these modules is available for use by any test
function. The data contained in these is specific to a particular user's
hardware configuration. Hence, these configuration files are not part of the
U-Boot source tree, and should be installed outside of the source tree. Users
should set `$PYTHONPATH` prior to running the test script to allow these
modules to be loaded.
### Board module parameter usage
The test scripts rely on the following variables being defined by the board
module:
- None at present.
### U-Boot `.config` feature usage
The test scripts rely on various U-Boot `.config` features, either directly in
order to test those features, or indirectly in order to query information from
the running U-Boot instance in order to test other features.
One example is that testing of the `md` command requires knowledge of a RAM
address to use for the test. This data is parsed from the output of the
`bdinfo` command, and hence relies on CONFIG_CMD_BDI being enabled.
For a complete list of dependencies, please search the test scripts for
instances of:
- `buildconfig.get(...`
- `@pytest.mark.buildconfigspec(...`
### Complete invocation example
Assuming that you have installed the hook scripts into $HOME/ubtest/bin, and
any required environment configuration Python modules into $HOME/ubtest/py,
then you would likely invoke the test script as follows:
If U-Boot has already been built:
```bash
PATH=$HOME/ubtest/bin:$PATH \
PYTHONPATH=${HOME}/ubtest/py:${PYTHONPATH} \
./test/py/test.py --bd seaboard
```
If you want the test script to compile U-Boot for you too, then you likely
need to set `$CROSS_COMPILE` to allow this, and invoke the test script as
follow:
```bash
CROSS_COMPILE=arm-none-eabi- \
PATH=$HOME/ubtest/bin:$PATH \
PYTHONPATH=${HOME}/ubtest/py:${PYTHONPATH} \
./test/py/test.py --bd seaboard --build
```
## Writing tests
Please refer to the pytest documentation for details of writing pytest tests.
Details specific to the U-Boot test suite are described below.
A test fixture named `u_boot_console` should be used by each test function. This
provides the means to interact with the U-Boot console, and retrieve board and
environment configuration information.
The function `u_boot_console.run_command()` executes a shell command on the
U-Boot console, and returns all output from that command. This allows
validation or interpretation of the command output. This function validates
that certain strings are not seen on the U-Boot console. These include shell
error messages and the U-Boot sign-on message (in order to detect unexpected
board resets). See the source of `u_boot_console_base.py` for a complete list of
"bad" strings. Some test scenarios are expected to trigger these strings. Use
`u_boot_console.disable_check()` to temporarily disable checking for specific
strings. See `test_unknown_cmd.py` for an example.
Board- and board-environment configuration values may be accessed as sub-fields
of the `u_boot_console.config` object, for example
`u_boot_console.config.ram_base`.
Build configuration values (from `.config`) may be accessed via the dictionary
`u_boot_console.config.buildconfig`, with keys equal to the Kconfig variable
names.

Some files were not shown because too many files have changed in this diff Show more