diff --git a/arch/arm/include/asm/arch-rockchip/param.h b/arch/arm/include/asm/arch-rockchip/param.h index 66ba2ac22e..5cd8538e1b 100644 --- a/arch/arm/include/asm/arch-rockchip/param.h +++ b/arch/arm/include/asm/arch-rockchip/param.h @@ -7,28 +7,28 @@ #ifndef __ROCKCHIP_PARAM_H_ #define __ROCKCHIP_PARAM_H_ -#include +#include /** * param_parse_atf_mem() - Parse atf memory region * - * @return sysmem_property structure which contains base and size info. + * @return memblock structure which contains base and size info. */ -struct sysmem_property param_parse_atf_mem(void); +struct memblock param_parse_atf_mem(void); /** * param_parse_atf_mem() - Parse op-tee memory region * - * @return sysmem_property structure which contains base and size info. + * @return memblock structure which contains base and size info. */ -struct sysmem_property param_parse_optee_mem(void); +struct memblock param_parse_optee_mem(void); /** * param_parse_atf_mem() - Parse platform common reserved memory region * - * @return sysmem_property structure which contains base and size info. + * @return memblock structure which contains base and size info. */ -struct sysmem_property param_parse_common_resv_mem(void); +struct memblock param_parse_common_resv_mem(void); /** * param_parse_bootdev() - Parse boot device info. diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 33618ae6ca..00132884a3 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -24,6 +24,7 @@ obj-y += boot_mode.o obj-y += board.o obj-y += chip_info.o obj-y += iomem.o +obj-y += memblk.o obj-$(CONFIG_ROCKCHIP_CRC) += rockchip_crc.o obj-$(CONFIG_ROCKCHIP_SMCCC) += rockchip_smccc.o diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index 573956c118..fe18ace42c 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -442,34 +442,6 @@ void board_lmb_reserve(struct lmb *lmb) } #endif -#ifdef CONFIG_SYSMEM -int board_sysmem_reserve(struct sysmem *sysmem) -{ - struct sysmem_property prop; - int ret; - - /* ATF */ - prop = param_parse_atf_mem(); - ret = sysmem_reserve(prop.name, prop.base, prop.size); - if (ret) - return ret; - - /* PSTORE/ATAGS/SHM */ - prop = param_parse_common_resv_mem(); - ret = sysmem_reserve(prop.name, prop.base, prop.size); - if (ret) - return ret; - - /* OP-TEE */ - prop = param_parse_optee_mem(); - ret = sysmem_reserve(prop.name, prop.base, prop.size); - if (ret) - return ret; - - return 0; -} -#endif - #if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \ defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS) int board_init_f_init_serial(void) diff --git a/arch/arm/mach-rockchip/memblk.c b/arch/arm/mach-rockchip/memblk.c new file mode 100644 index 0000000000..7d288ab080 --- /dev/null +++ b/arch/arm/mach-rockchip/memblk.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd + */ + +#include +#include + +const static struct memblk_attr plat_mem_attr[MEMBLK_ID_MAX] = { + [MEMBLK_ID_DEMO] = { + .name = "DEMO", + .flags = M_ATTR_NONE, + }, + [MEMBLK_ID_ATF] = { + .name = "ATF", + .flags = M_ATTR_NONE, + }, + [MEMBLK_ID_OPTEE] = { + .name = "OP-TEE", + .flags = M_ATTR_NONE, + }, + [MEMBLK_ID_SHM] = { + .name = "SHM", + .flags = M_ATTR_NONE, + }, + [MEMBLK_ID_UBOOT] = { + .name = "U-Boot", + .flags = M_ATTR_OVERLAP, + }, + [MEMBLK_ID_FASTBOOT] = { + .name = "FASTBOOT", + .flags = M_ATTR_OVERLAP, + }, + [MEMBLK_ID_STACK] = { + .name = "STACK", + .flags = M_ATTR_HOFC | M_ATTR_OVERLAP, + }, + [MEMBLK_ID_FDT] = { + .name = "FDT", + .flags = M_ATTR_OFC, + }, + [MEMBLK_ID_FDT_DTBO] = { + .name = "FDT_DTBO", + .flags = M_ATTR_OFC, + }, + [MEMBLK_ID_FDT_AOSP] = { + .name = "FDT_AOSP", + .flags = M_ATTR_OFC, + }, + [MEMBLK_ID_RAMDISK] = { + .name = "RAMDISK", + .alias[0] = "BOOT", + .alias[1] = "RECOVERY", + .flags = M_ATTR_OFC, + }, + [MEMBLK_ID_KERNEL] = { + .name = "KERNEL", + .flags = M_ATTR_OFC, + }, + [MEMBLK_ID_ANDROID] = { + .name = "ANDROID", + .flags = M_ATTR_OFC, + }, +}; + +const struct memblk_attr *mem_attr = plat_mem_attr; diff --git a/arch/arm/mach-rockchip/param.c b/arch/arm/mach-rockchip/param.c index c5c28d4955..3e1bdca38e 100644 --- a/arch/arm/mach-rockchip/param.c +++ b/arch/arm/mach-rockchip/param.c @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include #include @@ -47,13 +49,12 @@ static uint16_t trust_checksum(const uint8_t *buf, uint16_t len) return checksum; } -struct sysmem_property param_parse_atf_mem(void) +struct memblock param_parse_atf_mem(void) { - struct sysmem_property prop; + struct memblock mem; - prop.name = "ATF"; - prop.base = 0; - prop.size = 0; + mem.base = 0; + mem.size = 0; #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS struct tag *t = NULL; @@ -66,41 +67,40 @@ struct sysmem_property param_parse_atf_mem(void) */ t = atags_get_tag(ATAG_ATF_MEM); if (t && t->u.atf_mem.size) { - prop.base = t->u.atf_mem.phy_addr; - prop.size = t->u.atf_mem.size; + mem.base = t->u.atf_mem.phy_addr; + mem.size = t->u.atf_mem.size; /* Sanity */ - if (prop.base + prop.size > SDRAM_OFFSET(SZ_1M)) { + if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) { printf("%s: ATF reserved region is not within 0-1MB " "offset(0x%08llx-0x%08llx)!\n", - __func__, (u64)prop.base, (u64)prop.base + prop.size); - return prop; + __func__, (u64)mem.base, (u64)mem.base + mem.size); + return mem; } } #endif /* Legacy */ - if (!prop.size) { + if (!mem.size) { if (IS_ENABLED(CONFIG_ARM64) || IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) { - prop.base = SDRAM_OFFSET(0); - prop.size = SZ_1M; + mem.base = SDRAM_OFFSET(0); + mem.size = SZ_1M; } } - debug("ATF: 0x%llx - 0x%llx\n", (u64)prop.base, (u64)prop.base + prop.size); + debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); - return prop; + return mem; } -struct sysmem_property param_parse_optee_mem(void) +struct memblock param_parse_optee_mem(void) { struct tos_param_t *tos_parameter; - struct sysmem_property prop; + struct memblock mem; u32 checksum; - prop.name = "OP-TEE"; - prop.base = 0; - prop.size = 0; + mem.base = 0; + mem.size = 0; #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS struct tag *t = NULL; @@ -113,13 +113,13 @@ struct sysmem_property param_parse_optee_mem(void) */ t = atags_get_tag(ATAG_TOS_MEM); if (t && (t->u.tos_mem.tee_mem.flags == 1)) { - prop.base = t->u.tos_mem.tee_mem.phy_addr; - prop.size = t->u.tos_mem.tee_mem.size; + mem.base = t->u.tos_mem.tee_mem.phy_addr; + mem.size = t->u.tos_mem.tee_mem.size; } #endif /* Legacy */ - if (!prop.size) { + if (!mem.size) { tos_parameter = (struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET)); checksum = @@ -127,28 +127,27 @@ struct sysmem_property param_parse_optee_mem(void) sizeof(struct tos_param_t) - 8); if ((checksum == tos_parameter->checksum) && (tos_parameter->tee_mem.flags == 1)) { - prop.base = tos_parameter->tee_mem.phy_addr; - prop.size = tos_parameter->tee_mem.size; + mem.base = tos_parameter->tee_mem.phy_addr; + mem.size = tos_parameter->tee_mem.size; } } - if (prop.size) + if (mem.size) gd->flags |= GD_FLG_BL32_ENABLED; - debug("TOS: 0x%llx - 0x%llx\n", (u64)prop.base, (u64)prop.base + prop.size); + debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); - return prop; + return mem; } -struct sysmem_property param_parse_common_resv_mem(void) +struct memblock param_parse_common_resv_mem(void) { - struct sysmem_property prop; + struct memblock mem; - prop.name = "PSTORE/ATAGS/SHM"; - prop.base = SDRAM_OFFSET(SZ_1M); - prop.size = SZ_1M; + mem.base = SDRAM_OFFSET(SZ_1M); + mem.size = SZ_1M; - return prop; + return mem; } int param_parse_bootdev(char **devtype, char **devnum) diff --git a/arch/arm/mach-rockchip/resource_img.c b/arch/arm/mach-rockchip/resource_img.c index fced26ff81..d2742fbad7 100755 --- a/arch/arm/mach-rockchip/resource_img.c +++ b/arch/arm/mach-rockchip/resource_img.c @@ -664,7 +664,7 @@ int rockchip_read_dtb_file(void *fdt_addr) if (size < 0) return size; - if (!sysmem_alloc_base("fdt", (phys_addr_t)fdt_addr, + if (!sysmem_alloc_base(MEMBLK_ID_FDT, (phys_addr_t)fdt_addr, ALIGN(size, RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD)) return -ENOMEM; diff --git a/arch/arm/mach-rockchip/sdram_common.c b/arch/arm/mach-rockchip/sdram_common.c index b0e1e4cf6e..1ed20cbbfe 100644 --- a/arch/arm/mach-rockchip/sdram_common.c +++ b/arch/arm/mach-rockchip/sdram_common.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -23,7 +24,7 @@ DECLARE_GLOBAL_DATA_PTR; #define NOT_INITIAL -1 static int __dram_init_banksize(int resv_tee) { - struct sysmem_property prop; + struct memblock prop; size_t top = min((unsigned long)(gd->ram_size + CONFIG_SYS_SDRAM_BASE), gd->ram_top); u64 start[CONFIG_NR_DRAM_BANKS], size[CONFIG_NR_DRAM_BANKS]; diff --git a/cmd/fastboot.c b/cmd/fastboot.c index bb2f416b78..c9ef71da45 100644 --- a/cmd/fastboot.c +++ b/cmd/fastboot.c @@ -65,7 +65,7 @@ static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) goto exit; } - if (!sysmem_alloc_base("fastboot", + if (!sysmem_alloc_base(MEMBLK_ID_FASTBOOT, CONFIG_FASTBOOT_BUF_ADDR, CONFIG_FASTBOOT_BUF_SIZE)) { printf("The fastboot memory space is unusable!\n"); diff --git a/common/android_bootloader.c b/common/android_bootloader.c index a5f59dc64f..2b0a5864e4 100644 --- a/common/android_bootloader.c +++ b/common/android_bootloader.c @@ -332,8 +332,6 @@ int android_bootloader_boot_kernel(unsigned long kernel_address) printf("Booting kernel at %s with fdt at %s...\n\n\n", kernel_addr_r, fdt_addr); - sysmem_dump_check(); - do_bootm(NULL, 0, 4, bootm_args); return -1; @@ -813,7 +811,7 @@ int android_fdt_overlay_apply(void *fdt_addr) if (sysmem_free((phys_addr_t)fdt_addr)) goto out; - if (!sysmem_alloc_base("fdt(dtbo)", + if (!sysmem_alloc_base(MEMBLK_ID_FDT_DTBO, (phys_addr_t)fdt_addr, fdt_size + CONFIG_SYS_FDT_PAD)) goto out; diff --git a/common/boot_rkimg.c b/common/boot_rkimg.c index ca8c2a42d3..9c2aedf03d 100644 --- a/common/boot_rkimg.c +++ b/common/boot_rkimg.c @@ -88,12 +88,10 @@ static void boot_lmb_init(bootm_headers_t *images) * return the image size on success, and a * negative value on error. */ -static int read_rockchip_image(struct blk_desc *dev_desc, - disk_partition_t *part_info, - void *dst) +int read_rockchip_image(struct blk_desc *dev_desc, + disk_partition_t *part_info, void *dst) { struct rockchip_image *img; - const char *name; int header_len = 8; int cnt; int ret; @@ -101,14 +99,6 @@ static int read_rockchip_image(struct blk_desc *dev_desc, u32 crc32; #endif - if (!strcmp((char *)part_info->name, "kernel")) - name = "kernel"; - else if (!strcmp((char *)part_info->name, "boot") || - !strcmp((char *)part_info->name, "recovery")) - name = "ramdisk"; - else - name = NULL; - img = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE); if (!img) { printf("out of memory\n"); @@ -133,7 +123,9 @@ static int read_rockchip_image(struct blk_desc *dev_desc, * total size = image size + 8 bytes header + 4 bytes crc32 */ cnt = DIV_ROUND_UP(img->size + 8 + 4, RK_BLK_SIZE); - if (!sysmem_alloc_base(name, (phys_addr_t)dst, cnt * dev_desc->blksz)) { + if (!sysmem_alloc_base_by_name((const char *)part_info->name, + (phys_addr_t)dst, + cnt * dev_desc->blksz)) { ret = -ENXIO; goto err; } @@ -524,7 +516,6 @@ int boot_rockchip_image(struct blk_desc *dev_desc, disk_partition_t *boot_part) printf("ramdisk @ 0x%08lx (0x%08x)\n", ramdisk_addr_r, ramdisk_size); fdt_ramdisk_skip_relocation(); - sysmem_dump_check(); #if defined(CONFIG_ARM64) char cmdbuf[64]; diff --git a/common/image-android.c b/common/image-android.c index f37123efaa..64374b10e4 100644 --- a/common/image-android.c +++ b/common/image-android.c @@ -290,7 +290,7 @@ static int android_image_load_separate(struct blk_desc *dev_desc, size = hdr->kernel_size + hdr->page_size; blk_start = part->start; blk_cnt = DIV_ROUND_UP(size, dev_desc->blksz); - if (!sysmem_alloc_base("kernel", + if (!sysmem_alloc_base(MEMBLK_ID_KERNEL, (phys_addr_t)android_load_address, blk_cnt * dev_desc->blksz)) return -ENXIO; @@ -311,7 +311,7 @@ static int android_image_load_separate(struct blk_desc *dev_desc, size = hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size); blk_start = part->start + DIV_ROUND_UP(size, dev_desc->blksz); blk_cnt = DIV_ROUND_UP(hdr->ramdisk_size, dev_desc->blksz); - if (!sysmem_alloc_base("ramdisk", + if (!sysmem_alloc_base(MEMBLK_ID_RAMDISK, ramdisk_addr_r, blk_cnt * dev_desc->blksz)) return -ENXIO; @@ -347,7 +347,7 @@ static int android_image_load_separate(struct blk_desc *dev_desc, ALIGN(hdr->ramdisk_size, hdr->page_size); blk_start = part->start + DIV_ROUND_UP(size, dev_desc->blksz); blk_cnt = DIV_ROUND_UP(hdr->second_size, dev_desc->blksz); - if (!sysmem_alloc_base("fdt(AOSP)", + if (!sysmem_alloc_base(MEMBLK_ID_FDT_AOSP, fdt_addr_r, blk_cnt * dev_desc->blksz + CONFIG_SYS_FDT_PAD)) @@ -456,7 +456,7 @@ long android_image_load(struct blk_desc *dev_desc, } else #endif { - if (!sysmem_alloc_base("android", + if (!sysmem_alloc_base(MEMBLK_ID_ANDROID, (phys_addr_t)buf, blk_cnt * part_info->blksz)) return -ENXIO; diff --git a/common/image-fdt.c b/common/image-fdt.c index c903d51443..6cabd2eeff 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -143,7 +143,6 @@ int boot_fdt_add_sysmem_rsv_regions(void *fdt_blob) static int rsv_done; char resvname[32]; const void *prop; - int ret; if (fdt_check_header(fdt_blob) != 0 || rsv_done) return -EINVAL; @@ -157,9 +156,8 @@ int boot_fdt_add_sysmem_rsv_regions(void *fdt_blob) debug(" sysmem: reserving fdt memory region: addr=%llx size=%llx\n", (unsigned long long)addr, (unsigned long long)size); sprintf(resvname, "fdt-memory-reserved%d", i); - ret = sysmem_reserve(resvname, addr, size); - if (ret) - return ret; + if (!sysmem_fdt_reserve_alloc_base(resvname, addr, size)) + return -ENOMEM; } rsv_offset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory"); @@ -181,10 +179,9 @@ int boot_fdt_add_sysmem_rsv_regions(void *fdt_blob) debug(" sysmem: 'reserved-memory' %s: addr=%llx size=%llx\n", fdt_get_name(fdt_blob, offset, NULL), (unsigned long long)rsv_addr, (unsigned long long)rsv_size); - ret = sysmem_reserve(fdt_get_name(fdt_blob, offset, NULL), - rsv_addr, rsv_size); - if (ret) - return ret; + if (!sysmem_fdt_reserve_alloc_base(fdt_get_name(fdt_blob, offset, NULL), + rsv_addr, rsv_size)) + return -ENOMEM; } return 0; diff --git a/include/boot_rkimg.h b/include/boot_rkimg.h index e88375159f..795ad62901 100644 --- a/include/boot_rkimg.h +++ b/include/boot_rkimg.h @@ -29,6 +29,9 @@ enum _boot_mode { int rockchip_get_boot_mode(void); int boot_rockchip_image(struct blk_desc *dev, disk_partition_t *boot_part); +int read_rockchip_image(struct blk_desc *dev_desc, + disk_partition_t *part_info, void *dst); + struct blk_desc *rockchip_get_bootdev(void); /* diff --git a/include/image.h b/include/image.h index 8daffcceee..11c65292ba 100644 --- a/include/image.h +++ b/include/image.h @@ -693,6 +693,8 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob); #ifdef CONFIG_SYSMEM int boot_fdt_add_sysmem_rsv_regions(void *fdt_blob); +#else +static inline int boot_fdt_add_sysmem_rsv_regions(void *fdt_blob) { return 0; } #endif int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size); diff --git a/include/sysmem.h b/include/sysmem.h index 58de824968..0a5d807f82 100644 --- a/include/sysmem.h +++ b/include/sysmem.h @@ -6,12 +6,7 @@ #ifndef _SYSMEM_H #define _SYSMEM_H -#include - -#define MAX_SYSMEM_REGIONS 64 - -#undef MAX_LMB_REGIONS -#define MAX_LMB_REGIONS MAX_SYSMEM_REGIONS +#include /* * CONFIG_SYS_FDT_PAD default value is sync with bootm framework in: @@ -21,21 +16,22 @@ #define CONFIG_SYS_FDT_PAD 0x3000 #endif -struct sysmem_property { - const char *name; - phys_addr_t base; - phys_size_t size; - struct list_head node; -}; - struct sysmem { struct lmb lmb; struct list_head allocated_head; - struct list_head reserved_head; ulong allocated_cnt; - bool has_init; + bool has_initf; + bool has_initr; }; +#ifdef CONFIG_SYSMEM +/** + * sysmem_has_init() - Is sysmem initialized + * + * @return true or false + */ +bool sysmem_has_init(void); + /** * sysmem_init() - Sysmem initialization * @@ -44,73 +40,60 @@ struct sysmem { int sysmem_init(void); /** - * sysmem_add() - Add sysmem region - * - * @base: region base address - * @size: region size + * sysmem_initr() - Sysmem initialization after relocation * * @return 0 on success, otherwise error */ -int sysmem_add(phys_addr_t base, phys_size_t size); - -/** - * sysmem_reserve() - Reserve sysmem region - * - * @name: region name - * @base: region base address - * @size: region size - * - * @return 0 on success, otherwise error - */ -int sysmem_reserve(const char *name, phys_addr_t base, phys_size_t size); +int sysmem_initr(void); /** * sysmem_alloc() - Alloc sysmem region at anywhere * - * @name: region name + * @id: memblk id * @size: region size * * @return NULL on error, otherwise the allocated region address ptr */ -void *sysmem_alloc(const char *name, phys_size_t size); - -/** - * sysmem_alloc_align() - Alloc sysmem region at anywhere with addr align down - * - * @name: region name - * @size: region size - * @align: region base address align (down) - * - * @return NULL on error, otherwise the allocated region address ptr - */ -void *sysmem_alloc_align(const char *name, phys_size_t size, ulong align); +void *sysmem_alloc(enum memblk_id id, phys_size_t size); /** * sysmem_alloc_base() - Alloc sysmem region at the expect addr * - * @name: region name + * @id: memblk id * @base: region base * @size: region size * * @return NULL on error, otherwise the allocated region address ptr */ -void *sysmem_alloc_base(const char *name, phys_addr_t base, phys_size_t size); +void *sysmem_alloc_base(enum memblk_id id, phys_addr_t base, phys_size_t size); /** - * sysmem_alloc_align_base() - Alloc sysmem region at the expect addr with align down + * sysmem_alloc_base_by_name() - Alloc sysmem region at the expect addr by name * - * @name: region name + * @name: memblk name * @base: region base * @size: region size - * @align: region base address align (down) * * @return NULL on error, otherwise the allocated region address ptr */ -void *sysmem_alloc_align_base(const char *name, phys_addr_t base, - phys_size_t size, ulong align); +void *sysmem_alloc_base_by_name(const char *name, + phys_addr_t base, phys_size_t size); /** - * sysmem_free() - Free sysmem region + * sysmem_fdt_reserve_alloc_base() - Alloc sysmem region at the expect addr by name, + * called only for reserve memory from fdt. + * + * @name: memblk name + * @base: region base + * @size: region size + * + * @return NULL on error, otherwise the allocated region address ptr + */ +void *sysmem_fdt_reserve_alloc_base(const char *name, + phys_addr_t base, phys_size_t size); + +/** + * sysmem_free() - Free allocated sysmem region * * @base: region base * @@ -119,22 +102,10 @@ void *sysmem_alloc_align_base(const char *name, phys_addr_t base, int sysmem_free(phys_addr_t base); /** - * sysmem_check() - Check sysmem regions - * - * @return 0 on okay, otherwise something wrong - */ -int sysmem_check(void); - -/** - * sysmem_dump_all() - Dump all sysmem stat + * sysmem_dump() - Dump all sysmem region state and check overflow */ void sysmem_dump(void); -/** - * sysmem_dump_check() - Dump all sysmem stat and check overflow - */ -int sysmem_dump_check(void); - /** * board_sysmem_reserve() - Weak function for board to implement * @@ -143,14 +114,29 @@ int sysmem_dump_check(void); * @return 0 on success, otherwise error */ int board_sysmem_reserve(struct sysmem *sysmem); - -/** - * arch_sysmem_reserve() - Weak function for arch to implement - * - * @sysmem: global sysmem point, ignored - * - * @return 0 on success, otherwise error - */ -int arch_sysmem_reserve(struct sysmem *sysmem); - +#else +static inline bool sysmem_has_init(void) { return false; } +static inline int sysmem_init(void) { return 0; } +static inline int sysmem_initr(void) { return 0; } +static inline int sysmem_free(phys_addr_t base) { return 0; } +static inline void sysmem_dump(void) {} +__weak int board_sysmem_reserve(struct sysmem *sysmem) { return 0; } +static inline void *sysmem_alloc_base(enum memblk_id id, + phys_addr_t base, phys_size_t size) +{ + return (void *)base; +} +static inline void *sysmem_alloc_base_by_name(const char *name, + phys_addr_t base, + phys_size_t size) +{ + return (void *)base; +} +static inline void *sysmem_fdt_reserve_alloc_base(const char *name, + phys_addr_t base, + phys_size_t size) +{ + return (void *)base; +} +#endif /* CONFIG_SYSMEM */ #endif /* _SYSMEM_H */ diff --git a/lib/sysmem.c b/lib/sysmem.c index 2549de95f2..b050177af1 100644 --- a/lib/sysmem.c +++ b/lib/sysmem.c @@ -15,45 +15,38 @@ DECLARE_GLOBAL_DATA_PTR; #define SYSMEM_ALLOC_ANYWHERE 0 #define SYSMEM_ALLOC_NO_ALIGN 1 -#ifndef CONFIG_SYS_STACK_SIZE -#define CONFIG_SYS_STACK_SIZE SZ_2M -#endif - -#define SIZE_MB(len) ((len) >> 20) -#define SIZE_KB(len) (((len) % (1 << 20)) >> 10) - #define SYSMEM_I(fmt, args...) printf("Sysmem: "fmt, ##args) #define SYSMEM_W(fmt, args...) printf("Sysmem Warn: "fmt, ##args) #define SYSMEM_E(fmt, args...) printf("Sysmem Error: "fmt, ##args) #define SYSMEM_D(fmt, args...) debug("Sysmem Debug: "fmt, ##args) -static struct sysmem plat_sysmem; /* Global for platform */ - -struct sysmem_check { +struct memcheck { uint32_t magic; }; -static int sysmem_has_init(void) -{ - if (!plat_sysmem.has_init) { - SYSMEM_E("Framework is not initialized\n"); - return 0; - } +/* Global for platform, must in data section */ +struct sysmem plat_sysmem __section(".data") = { + .has_initf = false, + .has_initr = false, +}; - return 1; +bool sysmem_has_init(void) +{ + return gd->flags & GD_FLG_RELOC ? + plat_sysmem.has_initr : plat_sysmem.has_initf; } void sysmem_dump(void) { -#ifdef DEBUG struct sysmem *sysmem = &plat_sysmem; struct lmb *lmb = &sysmem->lmb; - struct sysmem_property *prop; - struct sysmem_check *check; + struct memblock *mem; + struct memcheck *check; struct list_head *node; ulong memory_size = 0; ulong reserved_size = 0; ulong allocated_size = 0; + bool overflow = false; ulong i; if (!sysmem_has_init()) @@ -62,12 +55,13 @@ void sysmem_dump(void) printf("\nsysmem_dump_all:\n"); /* Memory pool */ - printf(" ------------------------------------------------------\n"); + printf(" --------------------------------------------------------------------\n"); for (i = 0; i < lmb->memory.cnt; i++) { memory_size += lmb->memory.region[i].size; - printf(" memory.rgn[%ld].base = 0x%08lx\n", i, - (ulong)lmb->memory.region[i].base); - printf(" .size = 0x%08lx\n", + printf(" memory.rgn[%ld].addr = 0x%08lx - 0x%08lx (size: 0x%08lx)\n", i, + (ulong)lmb->memory.region[i].base, + (ulong)lmb->memory.region[i].base + + (ulong)lmb->memory.region[i].size, (ulong)lmb->memory.region[i].size); } printf("\n memory.total = 0x%08lx (%ld MiB. %ld KiB)\n", @@ -75,54 +69,48 @@ void sysmem_dump(void) SIZE_MB((ulong)memory_size), SIZE_KB((ulong)memory_size)); - /* Reserved */ - i = 0; - printf(" ------------------------------------------------------\n"); - list_for_each(node, &sysmem->reserved_head) { - prop = list_entry(node, struct sysmem_property, node); - reserved_size += prop->size; - printf(" reserved.rgn[%ld].name = \"%s\"\n", i, prop->name); - printf(" .base = 0x%08lx\n", - (ulong)prop->base); - printf(" .size = 0x%08lx\n", - (ulong)prop->size); - i++; - } - printf("\n reserved.total = 0x%08lx (%ld MiB. %ld KiB)\n", - (ulong)reserved_size, - SIZE_MB((ulong)reserved_size), - SIZE_KB((ulong)reserved_size)); - /* Allocated */ i = 0; - printf(" ------------------------------------------------------\n"); + printf(" --------------------------------------------------------------------\n"); list_for_each(node, &sysmem->allocated_head) { - prop = list_entry(node, struct sysmem_property, node); - allocated_size += prop->size; - check = (struct sysmem_check *) - (prop->base + prop->size - sizeof(*check)); - printf(" allocated.rgn[%ld].name = \"%s\"%s\n", - i, prop->name, - check->magic != SYSMEM_MAGIC ? " (Overflow)" : ""); - printf(" .base = 0x%08lx\n", - (ulong)prop->base); - printf(" .size = 0x%08lx\n", - (ulong)prop->size); + mem = list_entry(node, struct memblock, node); + allocated_size += mem->size; + if (mem->attr.flags & M_ATTR_OFC) { + check = (struct memcheck *) + (mem->base + mem->size - sizeof(*check)); + overflow = (check->magic != SYSMEM_MAGIC); + } else if (mem->attr.flags & M_ATTR_HOFC) { + check = (struct memcheck *) + (mem->base - sizeof(*check)); + overflow = (check->magic != SYSMEM_MAGIC); + } else { + overflow = false; + } + + printf(" allocated.rgn[%ld].name = \"%s\" %s\n", + i, mem->attr.name, overflow ? " " : ""); + printf(" .addr = 0x%08lx - 0x%08lx (size: 0x%08lx)\n", + (ulong)mem->base, (ulong)(mem->base + mem->size), + (ulong)mem->size); i++; } + + printf("\n malloc_r: %d MiB, malloc_f: %d KiB\n", + SIZE_MB(CONFIG_SYS_MALLOC_LEN), SIZE_KB(CONFIG_SYS_MALLOC_F_LEN)); printf("\n allocated.total = 0x%08lx (%ld MiB. %ld KiB)\n", (ulong)allocated_size, SIZE_MB((ulong)allocated_size), SIZE_KB((ulong)allocated_size)); /* LMB core reserved */ - printf(" ------------------------------------------------------\n"); + printf(" --------------------------------------------------------------------\n"); reserved_size = 0; for (i = 0; i < lmb->reserved.cnt; i++) { reserved_size += lmb->reserved.region[i].size; - printf(" LMB.reserved[%ld].base = 0x%08lx\n", i, - (ulong)lmb->reserved.region[i].base); - printf(" .size = 0x%08lx\n", + printf(" LMB.reserved[%ld].addr = 0x%08lx - 0x%08lx (size: 0x%08lx)\n", i, + (ulong)lmb->reserved.region[i].base, + (ulong)lmb->reserved.region[i].base + + (ulong)lmb->reserved.region[i].size, (ulong)lmb->reserved.region[i].size); } @@ -130,167 +118,159 @@ void sysmem_dump(void) (ulong)reserved_size, SIZE_MB((ulong)reserved_size), SIZE_KB((ulong)reserved_size)); - printf(" ------------------------------------------------------\n\n"); -#endif + printf(" --------------------------------------------------------------------\n\n"); } -int sysmem_check(void) -{ - struct sysmem *sysmem = &plat_sysmem; - struct sysmem_property *prop; - struct sysmem_check *check; - struct list_head *node; - int ret = 0; - - if (!sysmem_has_init()) - return -ENOSYS; - - /* Check allocated */ - list_for_each(node, &sysmem->allocated_head) { - prop = list_entry(node, struct sysmem_property, node); - check = (struct sysmem_check *) - (prop->base + prop->size - sizeof(*check)); - if (check->magic != SYSMEM_MAGIC) { - ret = -EOVERFLOW; - SYSMEM_E("\"%s\" (base=0x%08lx, size=0x%lx) is Overflow!\n", - prop->name, (ulong)prop->base, (ulong)prop->size); - } - } - - /* Check stack */ - check = (struct sysmem_check *)(gd->start_addr_sp - CONFIG_SYS_STACK_SIZE); - if (check->magic != SYSMEM_MAGIC) { - ret = -EOVERFLOW; - SYSMEM_E("Runtime stack is Overflow!\n"); - } - - return ret; -} - -int sysmem_dump_check(void) -{ - sysmem_dump(); - - return sysmem_check(); -} - -static int sysmem_is_overlap(phys_addr_t base1, phys_size_t size1, - phys_addr_t base2, phys_size_t size2) +static inline int sysmem_is_overlap(phys_addr_t base1, phys_size_t size1, + phys_addr_t base2, phys_size_t size2) { return ((base1 < (base2 + size2)) && (base2 < (base1 + size1))); } -int sysmem_add(phys_addr_t base, phys_size_t size) +static int sysmem_add(phys_addr_t base, phys_size_t size) { struct sysmem *sysmem = &plat_sysmem; int ret; - if (!sysmem_has_init()) - return -ENOSYS; + if (!size) + return -EINVAL; ret = lmb_add(&sysmem->lmb, base, size); if (ret < 0) - SYSMEM_E("Failed to add sysmem at 0x%lx for 0x%lx size\n", + SYSMEM_E("Failed to add sysmem at 0x%08lx for 0x%08lx size\n", (ulong)base, (ulong)size); return (ret >= 0) ? 0 : ret; } -int sysmem_reserve(const char *name, phys_addr_t base, phys_size_t size) +static const char *sysmem_alias2name(const char *name, int *id) { - struct sysmem *sysmem = &plat_sysmem; - struct sysmem_property *prop; - struct list_head *node; - int ret = 0; + const char *alias; + int n, i, j; + int match = 0; - if (!sysmem_has_init()) - return -ENOSYS; + for (i = 0; i < MEMBLK_ID_MAX; i++) { + /* Pirmary name */ + if (mem_attr[i].name && !strcasecmp(mem_attr[i].name, name)) { + match = 1; + goto finish; + } - if (!name) { - SYSMEM_E("NULL name for reserved sysmem\n"); - return -EINVAL; - } + /* Alias name */ + alias = mem_attr[i].alias[0]; + if (!alias) + continue; - /* Check overlap */ - list_for_each(node, &sysmem->reserved_head) { - prop = list_entry(node, struct sysmem_property, node); - if (!strcmp(prop->name, name)) { - SYSMEM_E("Failed to double reserve for existence \"%s\"\n", name); - return -EEXIST; - } else if (sysmem_is_overlap(prop->base, prop->size, base, size)) { - SYSMEM_D("\"%s\" (base=0x%08lx, size=0x%lx) reserve is " - "overlap with existence \"%s\" (base=0x%08lx, size=0x%lx)\n", - name, (ulong)base, (ulong)size, prop->name, - (ulong)prop->base, (ulong)prop->size); + n = ARRAY_SIZE(mem_attr[i].alias); + for (j = 0; j < n; j++, alias++) { + if (alias && !strcasecmp(alias, name)) { + match = 1; + goto finish; + } } } - ret = lmb_reserve(&sysmem->lmb, base, size); - if (ret >= 0) { - prop = malloc(sizeof(*prop)); - if (!prop) { - SYSMEM_E("No memory for \"%s\" reserve sysmem\n", name); - return -ENOMEM; - } - - prop->name = name; - prop->base = base; - prop->size = size; - list_add_tail(&prop->node, &sysmem->reserved_head); - } else { - SYSMEM_E("Failed to reserve \"%s\" at 0x%lx\n", name, (ulong)base); - return -EINVAL; +finish: + if (match) { + *id = i; + return mem_attr[i].name; } - return 0; + return name; } -void *sysmem_alloc_align_base(const char *name, - phys_addr_t base, - phys_size_t size, - ulong align) +static void *sysmem_alloc_align_base(enum memblk_id id, + const char *mem_name, + phys_addr_t base, + phys_size_t size, + ulong align) { struct sysmem *sysmem = &plat_sysmem; - struct sysmem_property *prop; - struct sysmem_check *check; + struct memblk_attr attr; + struct memblock *mem; + struct memcheck *check; struct list_head *node; + const char *name; phys_addr_t paddr; phys_addr_t alloc_base; phys_size_t alloc_size; + bool req_overlap = false; if (!sysmem_has_init()) return NULL; - if (!name) { - SYSMEM_E("NULL name for alloc sysmem\n"); + if (id == MEMBLK_ID_BY_NAME || id == MEMBLK_ID_FDT_RESV) { + if (!mem_name) { + SYSMEM_E("NULL name for alloc sysmem\n"); + return NULL; + } else if (id == MEMBLK_ID_FDT_RESV) { + req_overlap = true; + if (base >= gd->ram_top) + return (void *)base; + } + name = sysmem_alias2name(mem_name, (int *)&id); + attr = mem_attr[id]; + } else if (id > MEMBLK_ID_UNK && id < MEMBLK_ID_MAX) { + attr = mem_attr[id]; + name = attr.name; + } else { + SYSMEM_E("Unsupport memblk id %d for alloc sysmem\n", id); + return NULL; + } + + if (!size) { + SYSMEM_E("\"%s\" size is 0 for alloc sysmem\n", name); return NULL; } if (!IS_ALIGNED(base, 4)) { - SYSMEM_E("\"%s\" base=0x%08lx is not 4-byte aligned\n", name, (ulong)base); + SYSMEM_E("\"%s\" base=0x%08lx is not 4-byte aligned\n", + name, (ulong)base); return NULL; } /* Must be 4-byte aligned */ size = ALIGN(size, 4); + SYSMEM_D("Enter alloc: \"%s\" 0x%08lx - 0x%08lx\n", + name, (ulong)base, (ulong)(base + size)); + /* Already allocated ? */ list_for_each(node, &sysmem->allocated_head) { - prop = list_entry(node, struct sysmem_property, node); - if (!strcmp(prop->name, name)) { + mem = list_entry(node, struct memblock, node); + SYSMEM_D("Has allcated: %s, 0x%08lx - 0x%08lx\n", + mem->attr.name, (ulong)mem->base, + (ulong)(mem->base + mem->size)); + if (!strcmp(mem->attr.name, name)) { SYSMEM_E("Failed to double alloc for existence \"%s\"\n", name); return NULL; - } else if (sysmem_is_overlap(prop->base, prop->size, base, size)) { - SYSMEM_E("\"%s\" (base=0x%08lx, size=0x%lx) alloc is " - "overlap with existence \"%s\" (base=0x%08lx, size=0x%lx)\n", - name, (ulong)base, (ulong)size, - prop->name, (ulong)prop->base, - (ulong)prop->size); + } else if (sysmem_is_overlap(mem->base, mem->size, base, size)) { + if (req_overlap && mem->attr.flags & M_ATTR_OVERLAP) { + if (lmb_reserve(&sysmem->lmb, base, size)) + SYSMEM_E("Failed to overlap alloc \"%s\" " + "at 0x%08lx - 0x%08lx\n", + name, (ulong)base, + (ulong)(base + size)); + return (void *)base; + } + + SYSMEM_E("\"%s\" (0x%08lx - 0x%08lx) alloc is " + "overlap with existence \"%s\" (0x%08lx - " + "0x%08lx)\n", + name, (ulong)base, (ulong)(base + size), + mem->attr.name, (ulong)mem->base, + (ulong)(mem->base + mem->size)); return NULL; } } - alloc_size = size + sizeof(*check); + /* Add overflow check magic ? */ + if (attr.flags & M_ATTR_OFC) + alloc_size = size + sizeof(*check); + else + alloc_size = size; + + /* Alloc anywhere ? */ if (base == SYSMEM_ALLOC_ANYWHERE) alloc_base = base; else @@ -298,127 +278,170 @@ void *sysmem_alloc_align_base(const char *name, paddr = lmb_alloc_base(&sysmem->lmb, alloc_size, align, alloc_base); if (paddr) { - if ((paddr == base) || (base == SYSMEM_ALLOC_ANYWHERE)) { - prop = malloc(sizeof(*prop)); - if (!prop) { + if ((paddr == base) || (base == SYSMEM_ALLOC_ANYWHERE)) { + mem = malloc(sizeof(*mem)); + if (!mem) { SYSMEM_E("No memory for \"%s\" alloc sysmem\n", name); return NULL; } - prop->name = name; - prop->base = paddr; - prop->size = alloc_size; + mem->base = paddr; + mem->size = alloc_size; + mem->attr = attr; sysmem->allocated_cnt++; + list_add_tail(&mem->node, &sysmem->allocated_head); - check = (struct sysmem_check *)(paddr + size); - check->magic = SYSMEM_MAGIC; - - list_add_tail(&prop->node, &sysmem->allocated_head); + if (mem->attr.flags & M_ATTR_OFC) { + check = (struct memcheck *)(paddr + size); + check->magic = SYSMEM_MAGIC; + } else if (mem->attr.flags & M_ATTR_HOFC) { + check = (struct memcheck *)(paddr - sizeof(*check)); + check->magic = SYSMEM_MAGIC; + } } else { - SYSMEM_E("Failed to alloc \"%s\" at expect 0x%lx but " - "alloc at 0x%lx\n", - name, (ulong)base, (ulong)paddr); + SYSMEM_E("Failed to alloc \"%s\" expect at 0x%08lx - 0x%08lx " + "but at 0x%08lx - x%08lx\n", + name, (ulong)base, (ulong)(base + size), + (ulong)paddr, (ulong)(paddr + size)); + if (lmb_free(&sysmem->lmb, paddr, alloc_size)) + SYSMEM_E("Failed to free \"%s\"\n", name); + return NULL; } } else { - SYSMEM_E("Failed to alloc \"%s\" at 0x%lx\n", name, (ulong)base); + SYSMEM_E("Failed to alloc \"%s\" at 0x%08lx - 0x%08lx\n", + name, (ulong)base, (ulong)(base + size)); } - SYSMEM_D("Alloc: \"%s\", paddr=0x%lx, size=0x%lx, align=0x%x, anywhere=%d\n", + SYSMEM_D("Exit alloc: \"%s\", paddr=0x%08lx, size=0x%08lx, align=0x%x, anywhere=%d\n", name, (ulong)paddr, (ulong)size, (u32)align, !base); return (void *)paddr; } -void *sysmem_alloc_align(const char *name, phys_size_t size, ulong align) +void *sysmem_alloc_base(enum memblk_id id, phys_addr_t base, phys_size_t size) { - return sysmem_alloc_align_base(name, - SYSMEM_ALLOC_ANYWHERE, - size, - align); + void *paddr; + + paddr = sysmem_alloc_align_base(id, + NULL, + base, + size, + SYSMEM_ALLOC_NO_ALIGN); + if (!paddr) + sysmem_dump(); + + return paddr; } -void *sysmem_alloc_base(const char *name, phys_addr_t base, phys_size_t size) +void *sysmem_alloc_base_by_name(const char *name, + phys_addr_t base, phys_size_t size) { - return sysmem_alloc_align_base(name, - base, - size, - SYSMEM_ALLOC_NO_ALIGN); + void *paddr; + + paddr = sysmem_alloc_align_base(MEMBLK_ID_BY_NAME, + name, + base, + size, + SYSMEM_ALLOC_NO_ALIGN); + if (!paddr) + sysmem_dump(); + + return paddr; } -void *sysmem_alloc(const char *name, phys_size_t size) +void *sysmem_fdt_reserve_alloc_base(const char *name, + phys_addr_t base, phys_size_t size) { - return sysmem_alloc_align_base(name, - SYSMEM_ALLOC_ANYWHERE, - size, - SYSMEM_ALLOC_NO_ALIGN); + void *paddr; + + paddr = sysmem_alloc_align_base(MEMBLK_ID_FDT_RESV, + name, + base, + size, + SYSMEM_ALLOC_NO_ALIGN); + if (!paddr) + sysmem_dump(); + + return paddr; } int sysmem_free(phys_addr_t base) { struct sysmem *sysmem = &plat_sysmem; - struct sysmem_property *prop; + struct memblock *mem; struct list_head *node; - int found = 0; - int ret; + int ret, found = 0; if (!sysmem_has_init()) return -ENOSYS; /* Find existence */ list_for_each(node, &sysmem->allocated_head) { - prop = list_entry(node, struct sysmem_property, node); - if (prop->base == base) { + mem = list_entry(node, struct memblock, node); + if (mem->base == base) { found = 1; break; } } if (!found) { - SYSMEM_E("Failed to free no allocated sysmem at 0x%lx\n", (ulong)base); + SYSMEM_E("Failed to free no allocated sysmem at 0x%08lx\n", + (ulong)base); return -EINVAL; } - ret = lmb_free(&sysmem->lmb, prop->base, prop->size); + ret = lmb_free(&sysmem->lmb, mem->base, mem->size); if (ret >= 0) { - SYSMEM_D("Free: \"%s\", paddr=0x%lx, size=0x%lx\n", - prop->name, (ulong)prop->base, (ulong)prop->size); + SYSMEM_D("Free: \"%s\" 0x%08lx - 0x%08lx\n", + mem->attr.name, (ulong)mem->base, + (ulong)(mem->base + mem->size)); sysmem->allocated_cnt--; - list_del(&prop->node); - free(prop); + list_del(&mem->node); + free(mem); } else { - SYSMEM_E("Failed to free \"%s\" at 0x%lx\n", prop->name, (ulong)base); + SYSMEM_E("Failed to free \"%s\" at 0x%08lx\n", + mem->attr.name, (ulong)base); } return (ret >= 0) ? 0 : ret; } +int sysmem_initr(void) +{ + return sysmem_init(); +} + int sysmem_init(void) { struct sysmem *sysmem = &plat_sysmem; - struct sysmem_check *check; phys_addr_t mem_start; phys_size_t mem_size; int ret; - SYSMEM_I("init\n"); - lmb_init(&sysmem->lmb); INIT_LIST_HEAD(&sysmem->allocated_head); - INIT_LIST_HEAD(&sysmem->reserved_head); sysmem->allocated_cnt = 0; - sysmem->has_init = true; + if (gd->flags & GD_FLG_RELOC) { + sysmem->has_initr = true; + } else { + SYSMEM_I("init\n"); + sysmem->has_initf = true; + } /* Add all available system memory */ #ifdef CONFIG_NR_DRAM_BANKS int i; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + if (!gd->bd->bi_dram[i].size) + continue; + ret = sysmem_add(gd->bd->bi_dram[i].start, gd->bd->bi_dram[i].size); if (ret) { SYSMEM_E("Failed to add sysmem from bi_dram[%d]\n", i); - return ret; + goto fail; } } #else @@ -427,39 +450,44 @@ int sysmem_init(void) ret = sysmem_add(mem_start, mem_size); if (ret) { SYSMEM_E("Failed to add sysmem from bootm_low/size\n"); - return ret; + goto fail; } #endif - - /* Reserved for arch */ - ret = arch_sysmem_reserve(sysmem); - if (ret) { - SYSMEM_E("Failed to reserve sysmem for arch\n"); - return ret; - } - /* Reserved for board */ ret = board_sysmem_reserve(sysmem); if (ret) { SYSMEM_E("Failed to reserve sysmem for board\n"); - return ret; + goto fail; } - /* Reserved for U-boot framework 'reserve_xxx()' */ - mem_start = gd->start_addr_sp - CONFIG_SYS_STACK_SIZE; + /* Reserved for U-boot framework: 'reserve_xxx()' */ + mem_start = gd->start_addr_sp; mem_size = gd->ram_top - mem_start; - check = (struct sysmem_check *)mem_start; - check->magic = SYSMEM_MAGIC; - - ret = sysmem_reserve("U-Boot", mem_start, mem_size); - if (ret) { + if (!sysmem_alloc_base(MEMBLK_ID_UBOOT, mem_start, mem_size)) { SYSMEM_E("Failed to reserve sysmem for U-Boot framework\n"); - return ret; + ret = -ENOMEM; + goto fail; } - sysmem_dump(); + /* Reserved for U-Boot stack */ + mem_start = gd->start_addr_sp - CONFIG_SYS_STACK_SIZE; + mem_size = CONFIG_SYS_STACK_SIZE; + if (!sysmem_alloc_base(MEMBLK_ID_STACK, mem_start, mem_size)) { + SYSMEM_E("Failed to reserve sysmem for stack\n"); + ret = -ENOMEM; + goto fail; + } return 0; + +fail: + if (ret && !(gd->flags & GD_FLG_RELOC)) { + sysmem_dump(); + SYSMEM_W("Maybe malloc size %d MiB is too large?\n\n", + SIZE_MB(CONFIG_SYS_MALLOC_LEN)); + } + + return ret; } __weak int board_sysmem_reserve(struct sysmem *sysmem) @@ -468,8 +496,15 @@ __weak int board_sysmem_reserve(struct sysmem *sysmem) return 0; } -__weak int arch_sysmem_reserve(struct sysmem *sysmem) +static int do_dump_sysmem(cmd_tbl_t *cmdtp, int flag, + int argc, char *const argv[]) { - /* please define platform specific arch_sysmem_reserve() */ + sysmem_dump(); return 0; } + +U_BOOT_CMD( + dump_sysmem, 1, 1, do_dump_sysmem, + "Dump sysmem layout", + "" +);