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