aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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