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