aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2024-01-29 14:49:25 -0500
committerTom Rini <trini@konsulko.com>2024-01-29 14:49:25 -0500
commit073f4f10b9941c7b3cec7db41c82ac00b811eaba (patch)
treed738f7aac345d7c1cfdd9a5d22c7211156d202ce
parent7af90646df59dd7a4e0809c67ded6df835fd4808 (diff)
parentaaeb330cac116a1a41c97c8e7a8349b8aea914c2 (diff)
downloadu-boot-073f4f10b9941c7b3cec7db41c82ac00b811eaba.zip
u-boot-073f4f10b9941c7b3cec7db41c82ac00b811eaba.tar.gz
u-boot-073f4f10b9941c7b3cec7db41c82ac00b811eaba.tar.bz2
Merge patch series "Move framebuffer reservation for SPL to RAM end"
Devarsh Thakkar <devarsht@ti.com> says: Move video memory reservation for SPL at end of RAM so that it does not interefere with reservations for next stage so that the next stage need not have holes in between for passed regions and instead it can maintain continuity in reservations. Also catch the bloblist before starting reservations to avoid the same problem. While at it, also fill missing fields in video handoff struct before passing it to next stage. This is as per discussions at : For moving SPL framebuffer reservation at end of RAM: https://lore.kernel.org/all/CAPnjgZ3xSoe_G3yrqwuAvoiVjUfZ+YQgkOR0ZTVXGT9VK8TwJg@mail.gmail.com/ For filling missing video handoff fields : https://lore.kernel.org/all/CAPnjgZ1Hs0rNf0JDirp6YPsOQ5=QqQSP9g9qRwLoOASUV8a4cw@mail.gmail.com/
-rw-r--r--arch/arm/mach-k3/common.c17
-rw-r--r--board/ti/am62x/evm.c18
-rw-r--r--common/board_f.c41
-rw-r--r--common/spl/spl.c19
-rw-r--r--doc/develop/spl.rst37
-rw-r--r--drivers/video/video-uclass.c40
-rw-r--r--include/spl.h10
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