diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index 954e17d8c3..29500e36ad 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -275,6 +275,47 @@ void enable_caches(void) dcache_enable(); } +/* + * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". + * This makes lmb_alloc_base() always alloc from tail of sdram. + * If we don't assign it, bi_dram[0] is used by default and it may cause + * lmb_alloc_base() fail when bi_dram[0] range is small. + */ +void board_lmb_reserve(struct lmb *lmb) +{ + u64 start, size; + char bootm_low[32]; + char bootm_mapsize[32]; + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + if (!gd->bd->bi_dram[i].size) + break; + } + + start = gd->bd->bi_dram[i - 1].start; + size = gd->bd->bi_dram[i - 1].size; + + /* + * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area, otherwise + * "Unable to handle kernel paging request at virtual address ...". + * If so, using low address region, i.e before tustos region(132MB). + */ +#ifndef ARM64 + if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_768M)) { + start = gd->bd->bi_dram[i - 2].start; + size = gd->bd->bi_dram[i - 2].size; + } + + if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_768M)) + size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_768M - start; +#endif + sprintf(bootm_low, "0x%llx", start); + sprintf(bootm_mapsize, "0x%llx", size); + env_set("bootm_low", bootm_low); + env_set("bootm_mapsize", bootm_mapsize); +} + #ifdef CONFIG_ROCKCHIP_PRELOADER_SERIAL int board_init_f_init_serial(void) { diff --git a/include/linux/sizes.h b/include/linux/sizes.h index ce3e8150c1..9f234b581d 100644 --- a/include/linux/sizes.h +++ b/include/linux/sizes.h @@ -40,6 +40,7 @@ #define SZ_128M 0x08000000 #define SZ_256M 0x10000000 #define SZ_512M 0x20000000 +#define SZ_768M 0x30000000 #define SZ_1G 0x40000000 #define SZ_2G 0x80000000