18e366508SSimon Glass /* 28e366508SSimon Glass * Copyright (c) 2015 Google, Inc 38e366508SSimon Glass * Written by Simon Glass <sjg@chromium.org> 48e366508SSimon Glass * 58e366508SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 68e366508SSimon Glass */ 78e366508SSimon Glass 88e366508SSimon Glass #include <common.h> 98e366508SSimon Glass #include <debug_uart.h> 108e366508SSimon Glass #include <efi.h> 118e366508SSimon Glass #include <errno.h> 128e366508SSimon Glass #include <linux/err.h> 138e366508SSimon Glass #include <linux/types.h> 148e366508SSimon Glass 158e366508SSimon Glass DECLARE_GLOBAL_DATA_PTR; 168e366508SSimon Glass 178e366508SSimon Glass /* 188e366508SSimon Glass * This function looks for the highest region of memory lower than 4GB which 198e366508SSimon Glass * has enough space for U-Boot where U-Boot is aligned on a page boundary. 208e366508SSimon Glass * It overrides the default implementation found elsewhere which simply 218e366508SSimon Glass * picks the end of ram, wherever that may be. The location of the stack, 228e366508SSimon Glass * the relocation address, and how far U-Boot is moved by relocation are 238e366508SSimon Glass * set in the global data structure. 248e366508SSimon Glass */ 258e366508SSimon Glass ulong board_get_usable_ram_top(ulong total_size) 268e366508SSimon Glass { 278e366508SSimon Glass struct efi_mem_desc *desc, *end; 288e366508SSimon Glass struct efi_entry_memmap *map; 298e366508SSimon Glass int ret, size; 308e366508SSimon Glass uintptr_t dest_addr = 0; 318e366508SSimon Glass struct efi_mem_desc *largest = NULL; 328e366508SSimon Glass 338e366508SSimon Glass /* 348e366508SSimon Glass * Find largest area of memory below 4GB. We could 358e366508SSimon Glass * call efi_build_mem_table() for a more accurate picture since it 368e366508SSimon Glass * merges areas together where possible. But that function uses more 378e366508SSimon Glass * pre-relocation memory, and it's not critical that we find the 388e366508SSimon Glass * absolute largest region. 398e366508SSimon Glass */ 408e366508SSimon Glass ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 418e366508SSimon Glass if (ret) { 428e366508SSimon Glass /* We should have stopped in dram_init(), something is wrong */ 438e366508SSimon Glass debug("%s: Missing memory map\n", __func__); 448e366508SSimon Glass goto err; 458e366508SSimon Glass } 468e366508SSimon Glass 478e366508SSimon Glass end = (struct efi_mem_desc *)((ulong)map + size); 488e366508SSimon Glass desc = map->desc; 498e366508SSimon Glass for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) { 508e366508SSimon Glass if (desc->type != EFI_CONVENTIONAL_MEMORY || 518e366508SSimon Glass desc->physical_start >= 1ULL << 32) 528e366508SSimon Glass continue; 538e366508SSimon Glass if (!largest || desc->num_pages > largest->num_pages) 548e366508SSimon Glass largest = desc; 558e366508SSimon Glass } 568e366508SSimon Glass 578e366508SSimon Glass /* If no suitable area was found, return an error. */ 588e366508SSimon Glass assert(largest); 598e366508SSimon Glass if (!largest || (largest->num_pages << EFI_PAGE_SHIFT) < (2 << 20)) 608e366508SSimon Glass goto err; 618e366508SSimon Glass 628e366508SSimon Glass dest_addr = largest->physical_start + (largest->num_pages << 638e366508SSimon Glass EFI_PAGE_SHIFT); 648e366508SSimon Glass 658e366508SSimon Glass return (ulong)dest_addr; 668e366508SSimon Glass err: 678e366508SSimon Glass panic("No available memory found for relocation"); 688e366508SSimon Glass return 0; 698e366508SSimon Glass } 708e366508SSimon Glass 718e366508SSimon Glass int dram_init(void) 728e366508SSimon Glass { 738e366508SSimon Glass struct efi_mem_desc *desc, *end; 748e366508SSimon Glass struct efi_entry_memmap *map; 758e366508SSimon Glass int size, ret; 768e366508SSimon Glass 778e366508SSimon Glass ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 788e366508SSimon Glass if (ret) { 798e366508SSimon Glass printf("Cannot find EFI memory map tables, ret=%d\n", ret); 808e366508SSimon Glass 818e366508SSimon Glass return -ENODEV; 828e366508SSimon Glass } 838e366508SSimon Glass 848e366508SSimon Glass end = (struct efi_mem_desc *)((ulong)map + size); 858e366508SSimon Glass gd->ram_size = 0; 868e366508SSimon Glass desc = map->desc; 878e366508SSimon Glass for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) { 888e366508SSimon Glass if (desc->type < EFI_MMAP_IO) 898e366508SSimon Glass gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT; 908e366508SSimon Glass } 918e366508SSimon Glass 928e366508SSimon Glass return 0; 938e366508SSimon Glass } 948e366508SSimon Glass 958e366508SSimon Glass void dram_init_banksize(void) 968e366508SSimon Glass { 978e366508SSimon Glass struct efi_mem_desc *desc, *end; 988e366508SSimon Glass struct efi_entry_memmap *map; 998e366508SSimon Glass int ret, size; 1008e366508SSimon Glass int num_banks; 1018e366508SSimon Glass 1028e366508SSimon Glass ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 1038e366508SSimon Glass if (ret) { 1048e366508SSimon Glass /* We should have stopped in dram_init(), something is wrong */ 1058e366508SSimon Glass debug("%s: Missing memory map\n", __func__); 1068e366508SSimon Glass return; 1078e366508SSimon Glass } 1088e366508SSimon Glass end = (struct efi_mem_desc *)((ulong)map + size); 1098e366508SSimon Glass desc = map->desc; 1108e366508SSimon Glass for (num_banks = 0; 1118e366508SSimon Glass desc < end && num_banks < CONFIG_NR_DRAM_BANKS; 1128e366508SSimon Glass desc = efi_get_next_mem_desc(map, desc)) { 1138e366508SSimon Glass /* 1148e366508SSimon Glass * We only use conventional memory below 4GB, and ignore 1158e366508SSimon Glass * anything less than 1MB. 1168e366508SSimon Glass */ 1178e366508SSimon Glass if (desc->type != EFI_CONVENTIONAL_MEMORY || 1188e366508SSimon Glass desc->physical_start >= 1ULL << 32 || 1198e366508SSimon Glass (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20) 1208e366508SSimon Glass continue; 1218e366508SSimon Glass gd->bd->bi_dram[num_banks].start = desc->physical_start; 1228e366508SSimon Glass gd->bd->bi_dram[num_banks].size = desc->num_pages << 1238e366508SSimon Glass EFI_PAGE_SHIFT; 1248e366508SSimon Glass num_banks++; 1258e366508SSimon Glass } 1268e366508SSimon Glass } 1278e366508SSimon Glass 128*76d1d02fSSimon Glass int checkcpu(void) 129*76d1d02fSSimon Glass { 130*76d1d02fSSimon Glass return 0; 131*76d1d02fSSimon Glass } 132*76d1d02fSSimon Glass 1338e366508SSimon Glass int print_cpuinfo(void) 1348e366508SSimon Glass { 1358e366508SSimon Glass return default_print_cpuinfo(); 1368e366508SSimon Glass } 1378e366508SSimon Glass 1388e366508SSimon Glass /* Find any available tables and copy them to a safe place */ 1398e366508SSimon Glass int reserve_arch(void) 1408e366508SSimon Glass { 1418e366508SSimon Glass struct efi_info_hdr *hdr; 1428e366508SSimon Glass 1438e366508SSimon Glass debug("table=%lx\n", gd->arch.table); 1448e366508SSimon Glass if (!gd->arch.table) 1458e366508SSimon Glass return 0; 1468e366508SSimon Glass 1478e366508SSimon Glass hdr = (struct efi_info_hdr *)gd->arch.table; 1488e366508SSimon Glass 1498e366508SSimon Glass gd->start_addr_sp -= hdr->total_size; 1508e366508SSimon Glass memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size); 1518e366508SSimon Glass debug("Stashing EFI table at %lx to %lx, size %x\n", 1528e366508SSimon Glass gd->arch.table, gd->start_addr_sp, hdr->total_size); 1538e366508SSimon Glass gd->arch.table = gd->start_addr_sp; 1548e366508SSimon Glass 1558e366508SSimon Glass return 0; 1568e366508SSimon Glass } 157