diff options
-rw-r--r-- | arch/arm/mach-k3/common.c | 17 | ||||
-rw-r--r-- | board/ti/am62x/evm.c | 18 | ||||
-rw-r--r-- | common/board_f.c | 41 | ||||
-rw-r--r-- | common/spl/spl.c | 19 | ||||
-rw-r--r-- | doc/develop/spl.rst | 37 | ||||
-rw-r--r-- | drivers/video/video-uclass.c | 40 | ||||
-rw-r--r-- | include/spl.h | 10 |
7 files changed, 142 insertions, 40 deletions
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index d5db805..f411366 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -525,19 +525,26 @@ void remove_fwl_configs(struct fwl_data *fwl_data, size_t fwl_data_size) void spl_enable_cache(void) { #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) - phys_addr_t ram_top = CFG_SYS_SDRAM_BASE; + gd->ram_top = CFG_SYS_SDRAM_BASE; + int ret = 0; dram_init(); /* reserve TLB table */ gd->arch.tlb_size = PGTABLE_SIZE; - ram_top += get_effective_memsize(); + gd->ram_top += get_effective_memsize(); /* keep ram_top in the 32-bit address space */ - if (ram_top >= 0x100000000) - ram_top = (phys_addr_t) 0x100000000; + if (gd->ram_top >= 0x100000000) + gd->ram_top = (phys_addr_t)0x100000000; - gd->arch.tlb_addr = ram_top - gd->arch.tlb_size; + gd->relocaddr = gd->ram_top; + + ret = spl_reserve_video_from_ram_top(); + if (ret) + panic("Failed to reserve framebuffer memory (%d)\n", ret); + + gd->arch.tlb_addr = gd->relocaddr - gd->arch.tlb_size; gd->arch.tlb_addr &= ~(0x10000 - 1); debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr, gd->arch.tlb_addr + gd->arch.tlb_size); diff --git a/board/ti/am62x/evm.c b/board/ti/am62x/evm.c index ad93908..88e0215 100644 --- a/board/ti/am62x/evm.c +++ b/board/ti/am62x/evm.c @@ -60,27 +60,9 @@ int dram_init_banksize(void) } #if defined(CONFIG_SPL_BUILD) -static int video_setup(void) -{ - if (CONFIG_IS_ENABLED(VIDEO)) { - ulong addr; - int ret; - - addr = gd->relocaddr; - ret = video_reserve(&addr); - if (ret) - return ret; - debug("Reserving %luk for video at: %08lx\n", - ((unsigned long)gd->relocaddr - addr) >> 10, addr); - gd->relocaddr = addr; - } - - return 0; -} void spl_board_init(void) { - video_setup(); enable_caches(); if (IS_ENABLED(CONFIG_SPL_SPLASH_SCREEN) && IS_ENABLED(CONFIG_SPL_BMP)) splash_display(); diff --git a/common/board_f.c b/common/board_f.c index d4d7d01..442b834 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -403,17 +403,47 @@ __weak int arch_reserve_mmu(void) return 0; } -static int reserve_video(void) +static int reserve_video_from_videoblob(void) { if (IS_ENABLED(CONFIG_SPL_VIDEO_HANDOFF) && spl_phase() > PHASE_SPL) { struct video_handoff *ho; + int ret = 0; ho = bloblist_find(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho)); if (!ho) - return log_msg_ret("blf", -ENOENT); - video_reserve_from_bloblist(ho); - gd->relocaddr = ho->fb; - } else if (CONFIG_IS_ENABLED(VIDEO)) { + return log_msg_ret("Missing video bloblist", -ENOENT); + + ret = video_reserve_from_bloblist(ho); + if (ret) + return log_msg_ret("Invalid Video handoff info", ret); + + /* Sanity check fb from blob is before current relocaddr */ + if (likely(gd->relocaddr > (unsigned long)ho->fb)) + gd->relocaddr = ho->fb; + } + + return 0; +} + +/* + * Check if any bloblist received specifying reserved areas from previous stage and adjust + * gd->relocaddr accordingly, so that we start reserving after pre-reserved areas + * from previous stage. + * + * NOTE: + * IT is recommended that all bloblists from previous stage are reserved from ram_top + * as next stage will simply start reserving further regions after them. + */ +static int setup_relocaddr_from_bloblist(void) +{ + reserve_video_from_videoblob(); + + return 0; +} + +static int reserve_video(void) +{ + if (CONFIG_IS_ENABLED(VIDEO)) { ulong addr; int ret; @@ -923,6 +953,7 @@ static const init_fnc_t init_sequence_f[] = { reserve_pram, #endif reserve_round_4k, + setup_relocaddr_from_bloblist, arch_reserve_mmu, reserve_video, reserve_trace, diff --git a/common/spl/spl.c b/common/spl/spl.c index 3ce5bfe..b65c439 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -42,6 +42,7 @@ #include <fdt_support.h> #include <bootcount.h> #include <wdt.h> +#include <video.h> DECLARE_GLOBAL_DATA_PTR; DECLARE_BINMAN_MAGIC_SYM; @@ -152,6 +153,24 @@ void spl_fixup_fdt(void *fdt_blob) #endif } +int spl_reserve_video_from_ram_top(void) +{ + if (CONFIG_IS_ENABLED(VIDEO)) { + ulong addr; + int ret; + + addr = gd->ram_top; + ret = video_reserve(&addr); + if (ret) + return ret; + debug("Reserving %luk for video at: %08lx\n", + ((unsigned long)gd->relocaddr - addr) >> 10, addr); + gd->relocaddr = addr; + } + + return 0; +} + ulong spl_get_image_pos(void) { if (!CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS)) diff --git a/doc/develop/spl.rst b/doc/develop/spl.rst index 76e87f0..0a3e572 100644 --- a/doc/develop/spl.rst +++ b/doc/develop/spl.rst @@ -65,6 +65,15 @@ CONFIG_SPL_NAND_LOAD (drivers/mtd/nand/raw/nand_spl_load.o) CONFIG_SPL_SPI_LOAD (drivers/mtd/spi/spi_spl_load.o) CONFIG_SPL_RAM_DEVICE (common/spl/spl.c) CONFIG_SPL_WATCHDOG (drivers/watchdog/libwatchdog.o) +CONFIG_SPL_SYSCON (drivers/core/syscon-uclass.o) +CONFIG_SPL_GZIP (lib/gzip.o) +CONFIG_SPL_VIDEO (drivers/video/video-uclass.o drivers/video/vidconsole-uclass.o) +CONFIG_SPL_SPLASH_SCREEN (common/splash.o) +CONFIG_SPL_SPLASH_SOURCE (common/splash_source.o) +CONFIG_SPL_GPIO (drivers/gpio) +CONFIG_SPL_DM_GPIO (drivers/gpio/gpio-uclass.o) +CONFIG_SPL_BMP (drivers/video/bmp.o) +CONFIG_SPL_BLOBLIST (common/bloblist.o) Adding SPL-specific code ------------------------ @@ -164,3 +173,31 @@ cflow will spit out a number of warnings as it does not parse the config files and picks functions based on #ifdef. Parsing the '.i' files instead introduces another set of headaches. These warnings are not usually important to understanding the flow, however. + + +Reserving memory in SPL +----------------------- + +If memory needs to be reserved in RAM during SPL stage with the requirement that +the SPL reserved memory remains preserved across further boot stages too +then it needs to be reserved mandatorily starting from end of RAM. This is to +ensure that further stages can simply skip this region before carrying out +further reservations or updating the relocation address. + +Also out of these regions which are to be preserved across further stages of +boot, video framebuffer memory region must be reserved first starting from +end of RAM for which helper function spl_reserve_video_from_ram_top is provided +which makes sure that video memory is placed at top of reservation area with +further reservations below it. + +The corresponding information of reservation for those regions can be passed to +further boot stages using a bloblist. For e.g. the information for +framebuffer area reserved by SPL can be passed onto U-boot using +BLOBLISTT_U_BOOT_VIDEO. + +The further boot stages need to parse each of the bloblist passed from SPL stage +starting from video bloblist and skip this whole SPL reserved memory area from +end of RAM as per the bloblists received, before carrying out further +reservations or updating the relocation address. For e.g, U-boot proper uses +function "setup_relocaddr_from_bloblist" to parse the bloblists passed from +previous stage and skip the memory reserved from previous stage accordingly. diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index f743ed7..3571e62 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -123,6 +123,9 @@ int video_reserve(ulong *addrp) struct udevice *dev; ulong size; + if (IS_ENABLED(CONFIG_SPL_VIDEO_HANDOFF) && spl_phase() == PHASE_BOARD_F) + return 0; + gd->video_top = *addrp; for (uclass_find_first_device(UCLASS_VIDEO, &dev); dev; @@ -141,16 +144,6 @@ int video_reserve(ulong *addrp) debug("Video frame buffers from %lx to %lx\n", gd->video_bottom, gd->video_top); - if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(VIDEO_HANDOFF)) { - struct video_handoff *ho; - - ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0); - if (!ho) - return log_msg_ret("blf", -ENOENT); - ho->fb = *addrp; - ho->size = size; - } - return 0; } @@ -208,11 +201,14 @@ int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, int video_reserve_from_bloblist(struct video_handoff *ho) { + if (!ho->fb || ho->size == 0) + return -ENOENT; + gd->video_bottom = ho->fb; gd->fb_base = ho->fb; gd->video_top = ho->fb + ho->size; - debug("Reserving %luk for video using blob at: %08x\n", - ((unsigned long)ho->size) >> 10, (u32)ho->fb); + debug("%s: Reserving %lx bytes at %08x as per bloblist received\n", + __func__, (unsigned long)ho->size, (u32)ho->fb); return 0; } @@ -546,6 +542,26 @@ static int video_post_probe(struct udevice *dev) priv->fb_size = priv->line_length * priv->ysize; + /* + * Set up video handoff fields for passing video blob to next stage + * NOTE: + * This assumes that reserved video memory only uses a single framebuffer + */ + if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(BLOBLIST)) { + struct video_handoff *ho; + + ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0); + if (!ho) + return log_msg_ret("blf", -ENOENT); + ho->fb = gd->video_bottom; + /* Fill aligned size here as calculated in video_reserve() */ + ho->size = gd->video_top - gd->video_bottom; + ho->xsize = priv->xsize; + ho->ysize = priv->ysize; + ho->line_length = priv->line_length; + ho->bpix = priv->bpix; + } + if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base) priv->copy_fb = map_sysmem(plat->copy_base, plat->size); diff --git a/include/spl.h b/include/spl.h index 0952188..043875f 100644 --- a/include/spl.h +++ b/include/spl.h @@ -889,6 +889,16 @@ int spl_usb_load(struct spl_image_info *spl_image, int spl_ymodem_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev); +/** + * spl_reserve_video_from_ram_top() - Reserve framebuffer memory from end of RAM + * + * This enforces framebuffer reservation at SPL stage from end of RAM so that + * next stage can directly skip this pre-reserved area before carrying out + * further reservations. The allocation address is stored in struct video_uc_plat. + * + * Return: 0 on success, otherwise error code + */ +int spl_reserve_video_from_ram_top(void); /** * spl_invoke_atf - boot using an ARM trusted firmware image |