Commit | Line | Data |
---|---|---|
1fb17ea5 PA |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2019 Intel Corporation <www.intel.com> | |
4 | */ | |
5 | ||
6 | #include <common.h> | |
67c4e9f8 | 7 | #include <init.h> |
401d1c4f | 8 | #include <asm/global_data.h> |
1fb17ea5 PA |
9 | #include <linux/sizes.h> |
10 | #include <asm/e820.h> | |
11 | #include <asm/arch/slimbootloader.h> | |
12 | ||
13 | DECLARE_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 | */ | |
20 | static 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 | */ | |
51 | ulong board_get_usable_ram_top(ulong 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 | */ | |
100 | int 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 | ||
127 | int 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 | ||
138 | unsigned 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 | } |