From 1d3c266758570ea7d329746ae2d5b31fb12b9f61 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:16 +0530 Subject: spl: Enforce framebuffer reservation from end of RAM Add an API which enforces framebuffer reservation from end of RAM. This is done so that next stage can directly skip this region before carrying out further reservations. Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- common/spl/spl.c | 19 +++++++++++++++++++ include/spl.h | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/common/spl/spl.c b/common/spl/spl.c index 3ce5bfeec8b..b65c439e7aa 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -42,6 +42,7 @@ #include #include #include +#include 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/include/spl.h b/include/spl.h index 09521889014..043875f10f4 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 -- cgit v1.3.1 From ba20b2443c298a19ff70d66f71630c6d16c39c97 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:17 +0530 Subject: arm: mach-k3: common: Reserve video memory from end of the RAM Setup video memory before page table reservation using "spl_reserve_video_from_ram_top" which ensures framebuffer memory gets reserved from the end of RAM. This is done to enable the next stage to directly skip the pre-reserved area from previous stage right from the end of RAM without having to make any gaps/holes to accommodate those regions which was the case before as previous stage reserved region not from the end of RAM. Use gd->ram_top instead of local ram_top and update gd->reloc_addr after each reservation to ensure further regions are reserved properly. Signed-off-by: Devarsh Thakkar Reviewed-by: Nikhil M Jain --- arch/arm/mach-k3/common.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index fd400e7e3dd..42ceeb52967 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -524,19 +524,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); -- cgit v1.3.1 From 945053fd64ca1022f006ccd7f1518e52e34e30d8 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:18 +0530 Subject: board: ti: am62x: evm: Remove video_setup from spl_board_init Remove video_setup from evm_init sequence since video memory is getting called at an earlier place to make sure video memory is reserved at the end of RAM. Suggested-by: Simon Glass Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- board/ti/am62x/evm.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/board/ti/am62x/evm.c b/board/ti/am62x/evm.c index ad939088402..88e02155ee3 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(); -- cgit v1.3.1 From 4ef9c77248c95cd2bc63697084ae82f345e5c6e7 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:19 +0530 Subject: common/board_f: Catch bloblist before starting reservations Start reservations needed for init sequence only after catching bloblists from previous stage. This is to avoid catching bloblists in the middle causing gaps while u-boot is reserving. Adjust the relocaddr as per video hand-off information received from previous stage so that further reservations start only after regions reserved for previous stages Skip reservation for video memory if it was already filled by a bloblist. Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- common/board_f.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/common/board_f.c b/common/board_f.c index d4d7d01f8f6..acf802c9cb3 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -403,7 +403,7 @@ __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; @@ -412,8 +412,34 @@ static int reserve_video(void) if (!ho) return log_msg_ret("blf", -ENOENT); video_reserve_from_bloblist(ho); - gd->relocaddr = ho->fb; - } else if (CONFIG_IS_ENABLED(VIDEO)) { + + /* 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 +949,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, -- cgit v1.3.1 From eefe23c12775184b10068fd4f71c42db335ff3e6 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:20 +0530 Subject: video: Skip framebuffer reservation if already reserved Skip framebufer reservation if it was already reserved from previous stage and whose information was passed using a bloblist. Return error in case framebuffer information received from bloblist is invalid i.e NULL or empty. While at it, improve the debug message to make it more clear that address in discussion is of framebuffer and not bloblist and also match it with printing scheme followed in video_reserve function. Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- common/board_f.c | 8 ++++++-- drivers/video/video-uclass.c | 10 ++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/common/board_f.c b/common/board_f.c index acf802c9cb3..442b8349d08 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -407,11 +407,15 @@ 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); + 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)) diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index f743ed74c81..d620a29c253 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; @@ -208,11 +211,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; } -- cgit v1.3.1 From b30414f089d23942fe36a66a8de8c9c22fad91ba Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:21 +0530 Subject: video: Fill video handoff in video post probe Fill video handoff fields in video_post_probe as at this point we have full framebuffer-related information. Also fill all the fields available in video hand-off struct as those were missing earlier and U-boot framework expects them to be filled for some of the functionalities. While filling framebuffer size in video hand-off structure use the actual framebuffer region size as derived from gd->video_top and gd->video_bottom instead of directly using the size populated in video_uc_plat as it contains unaligned size. Reported-by: Simon Glass Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- drivers/video/video-uclass.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index d620a29c253..3571e62ba2d 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -144,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; } @@ -552,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); -- cgit v1.3.1 From b557e9f06e4082faf15df2cd40a2b1842a8888fe Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:22 +0530 Subject: doc: spl: Add info for missing Kconfigs Add info regarding splash screen, video, bloblist and GPIO related Kconfigs which were missing in the documentation. Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- doc/develop/spl.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/develop/spl.rst b/doc/develop/spl.rst index 76e87f07c72..814530d3486 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 ------------------------ -- cgit v1.3.1 From aaeb330cac116a1a41c97c8e7a8349b8aea914c2 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 5 Dec 2023 21:25:23 +0530 Subject: doc: spl: Add info regarding memory reservation Add details regarding scheme which need to be followed in SPL and further stages for those regions which need to be preserved across bootstages. Signed-off-by: Devarsh Thakkar Reviewed-by: Simon Glass --- doc/develop/spl.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/develop/spl.rst b/doc/develop/spl.rst index 814530d3486..0a3e572310a 100644 --- a/doc/develop/spl.rst +++ b/doc/develop/spl.rst @@ -173,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. -- cgit v1.3.1