Commit 41538930 authored by Andre Przywara's avatar Andre Przywara
Browse files

allwinner: Find DTB in BL33 image



The initial PMIC setup for the Allwinner platform is quite board
specific, and used to be guarded by reading the .dtb stub *name* from the
SPL image in the legacy ATF port. This doesn't scale particularly well,
and requires constant maintainance.
Instead having the actual .dtb available would be much better, as the PMIC
setup requirements could be read from there directly.
The only available BL33 for Allwinner platforms so far is U-Boot, and
fortunately U-Boot comes with the full featured .dtb, appended to the
end of the U-Boot image.

Introduce some code that scans the beginning of the BL33 image to look
for the load address, which is followed by the image size. Adding those
two values together gives us the end of the image and thus the .dtb
address. Verify that this heuristic is valid by sanitising some values
and checking the DTB magic.

Print out the DTB address and the model name, if specified in the root
node.
Signed-off-by: default avatarAndre Przywara <andre.przywara@arm.com>
parent eae5fe79
...@@ -13,6 +13,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common \ ...@@ -13,6 +13,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common \
-I${AW_PLAT}/common/include \ -I${AW_PLAT}/common/include \
-I${AW_PLAT}/${PLAT}/include -I${AW_PLAT}/${PLAT}/include
include lib/libfdt/libfdt.mk
PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \
drivers/ti/uart/${ARCH}/16550_console.S \ drivers/ti/uart/${ARCH}/16550_console.S \
${XLAT_TABLES_LIB_SRCS} \ ${XLAT_TABLES_LIB_SRCS} \
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
/* How much memory to reserve as secure for BL32, if configured */ /* How much memory to reserve as secure for BL32, if configured */
#define SUNXI_DRAM_SEC_SIZE (32U << 20) #define SUNXI_DRAM_SEC_SIZE (32U << 20)
/* How much DRAM to map */ /* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */
#define SUNXI_DRAM_MAP_SIZE (64U << 20) #define SUNXI_DRAM_MAP_SIZE (64U << 20)
#define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_SHIFT 6
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <debug.h> #include <debug.h>
#include <generic_delay_timer.h> #include <generic_delay_timer.h>
#include <gicv2.h> #include <gicv2.h>
#include <libfdt.h>
#include <platform.h> #include <platform.h>
#include <platform_def.h> #include <platform_def.h>
#include <sunxi_def.h> #include <sunxi_def.h>
...@@ -28,6 +29,47 @@ static const gicv2_driver_data_t sunxi_gic_data = { ...@@ -28,6 +29,47 @@ static const gicv2_driver_data_t sunxi_gic_data = {
.gicc_base = SUNXI_GICC_BASE, .gicc_base = SUNXI_GICC_BASE,
}; };
/*
* Try to find a DTB loaded in memory by previous stages.
*
* At the moment we implement a heuristic to find the DTB attached to U-Boot:
* U-Boot appends its DTB to the end of the image. Assuming that BL33 is
* U-Boot, try to find the size of the U-Boot image to learn the DTB address.
* The generic ARMv8 U-Boot image contains the load address and its size
* as u64 variables at the beginning of the image. There might be padding
* or other headers before that data, so scan the first 2KB after the BL33
* entry point to find the load address, which should be followed by the
* size. Adding those together gives us the address of the DTB.
*/
static void *sunxi_find_dtb(void)
{
uint64_t *u_boot_base;
int i;
u_boot_base = (void *)(SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE);
for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
uint32_t *dtb_base;
if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET)
continue;
/* Does the suspected U-Boot size look anyhow reasonable? */
if (u_boot_base[i + 1] >= 256 * 1024 * 1024)
continue;
/* end of the image: base address + size */
dtb_base = (void *)((char *)u_boot_base + u_boot_base[i + 1]);
if (fdt_check_header(dtb_base) != 0)
continue;
return dtb_base;
}
return NULL;
}
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3) u_register_t arg2, u_register_t arg3)
{ {
...@@ -66,6 +108,7 @@ void bl31_platform_setup(void) ...@@ -66,6 +108,7 @@ void bl31_platform_setup(void)
{ {
const char *soc_name; const char *soc_name;
uint16_t soc_id = sunxi_read_soc_id(); uint16_t soc_id = sunxi_read_soc_id();
void *fdt;
switch (soc_id) { switch (soc_id) {
case SUNXI_SOC_A64: case SUNXI_SOC_A64:
...@@ -85,6 +128,18 @@ void bl31_platform_setup(void) ...@@ -85,6 +128,18 @@ void bl31_platform_setup(void)
generic_delay_timer_init(); generic_delay_timer_init();
fdt = sunxi_find_dtb();
if (fdt) {
const char *model;
int length;
model = fdt_getprop(fdt, 0, "model", &length);
NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt,
model ?: "unknown");
} else {
NOTICE("BL31: No DTB found.\n");
}
/* Configure the interrupt controller */ /* Configure the interrupt controller */
gicv2_driver_init(&sunxi_gic_data); gicv2_driver_init(&sunxi_gic_data);
gicv2_distif_init(); gicv2_distif_init();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment