1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2019 Intel Corporation <www.intel.com> 4 */ 5 6#include <common.h> 7#include <init.h> 8#include <asm/global_data.h> 9#include <linux/sizes.h> 10#include <asm/e820.h> 11#include <asm/arch/slimbootloader.h> 12 13DECLARE_GLOBAL_DATA_PTR; 14 15/** 16 * This returns a data pointer of memory map info from the guid hob. 17 * 18 * @return: A data pointer of memory map info hob 19 */ 20static struct sbl_memory_map_info *get_memory_map_info(void) 21{ 22 struct sbl_memory_map_info *data; 23 const efi_guid_t guid = SBL_MEMORY_MAP_INFO_GUID; 24 25 if (!gd->arch.hob_list) 26 return NULL; 27 28 data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid); 29 if (!data) 30 panic("memory map info hob not found\n"); 31 if (!data->count) 32 panic("invalid number of memory map entries\n"); 33 34 return data; 35} 36 37#define for_each_if(condition) if (!(condition)) {} else 38 39#define for_each_memory_map_entry_reversed(iter, entries) \ 40 for (iter = entries->count - 1; iter >= 0; iter--) \ 41 for_each_if(entries->entry[iter].type == E820_RAM) 42 43/** 44 * This is to give usable memory region information for u-boot relocation. 45 * so search usable memory region lower than 4GB. 46 * The memory map entries from Slim Bootloader hob are already sorted. 47 * 48 * @total_size: The memory size that u-boot occupies 49 * Return: : The top available memory address lower than 4GB 50 */ 51phys_addr_t board_get_usable_ram_top(phys_size_t total_size) 52{ 53 struct sbl_memory_map_info *data; 54 int i; 55 u64 addr_start; 56 u64 addr_end; 57 ulong ram_top; 58 59 data = get_memory_map_info(); 60 61 /** 62 * sorted memory map entries from Slim Bootloader based on physical 63 * start memory address, from low to high. So do reversed search to 64 * get highest usable, suitable size, 4KB aligned available memory 65 * under 4GB. 66 */ 67 ram_top = 0; 68 for_each_memory_map_entry_reversed(i, data) { 69 addr_start = data->entry[i].addr; 70 addr_end = addr_start + data->entry[i].size; 71 72 if (addr_start > SZ_4G) 73 continue; 74 75 if (addr_end > SZ_4G) 76 addr_end = SZ_4G; 77 78 if (addr_end < total_size) 79 continue; 80 81 /* to relocate u-boot at 4K aligned memory */ 82 addr_end = rounddown(addr_end - total_size, SZ_4K); 83 if (addr_end >= addr_start) { 84 ram_top = (ulong)addr_end + total_size; 85 break; 86 } 87 } 88 89 if (!ram_top) 90 panic("failed to find available memory for relocation!"); 91 92 return ram_top; 93} 94 95/** 96 * The memory initialization has already been done in previous Slim Bootloader 97 * stage thru FSP-M. Instead, this sets the ram_size from the memory map info 98 * hob. 99 */ 100int dram_init(void) 101{ 102 struct sbl_memory_map_info *data; 103 int i; 104 u64 ram_size; 105 106 data = get_memory_map_info(); 107 108 /** 109 * sorted memory map entries from Slim Bootloader based on physical 110 * start memory address, from low to high. So do reversed search to 111 * simply get highest usable memory address as RAM size 112 */ 113 ram_size = 0; 114 for_each_memory_map_entry_reversed(i, data) { 115 /* simply use the highest usable memory address as RAM size */ 116 ram_size = data->entry[i].addr + data->entry[i].size; 117 break; 118 } 119 120 if (!ram_size) 121 panic("failed to detect memory size"); 122 123 gd->ram_size = ram_size; 124 return 0; 125} 126 127int dram_init_banksize(void) 128{ 129 if (!CONFIG_NR_DRAM_BANKS) 130 return 0; 131 132 /* simply use a single bank to have whole size for now */ 133 gd->bd->bi_dram[0].start = 0; 134 gd->bd->bi_dram[0].size = gd->ram_size; 135 return 0; 136} 137 138unsigned int install_e820_map(unsigned int max_entries, 139 struct e820_entry *entries) 140{ 141 struct sbl_memory_map_info *data; 142 unsigned int i; 143 144 data = get_memory_map_info(); 145 146 for (i = 0; i < data->count; i++) { 147 entries[i].addr = data->entry[i].addr; 148 entries[i].size = data->entry[i].size; 149 entries[i].type = data->entry[i].type; 150 } 151 152 return i; 153} 154