blob: 75ca5273625cd8fab5ebd3dfd165e08b475f0b7d [file] [log] [blame]
Park, Aidendeffd422019-08-03 08:30:36 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Intel Corporation <www.intel.com>
4 */
5
Simon Glass6980b6b2019-11-14 12:57:45 -07006#include <init.h>
Simon Glass3ba929a2020-10-30 21:38:53 -06007#include <asm/global_data.h>
Park, Aidendeffd422019-08-03 08:30:36 +00008#include <linux/sizes.h>
9#include <asm/e820.h>
10#include <asm/arch/slimbootloader.h>
11
12DECLARE_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 */
19static 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
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010048 * Return: : The top available memory address lower than 4GB
Park, Aidendeffd422019-08-03 08:30:36 +000049 */
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +020050phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Park, Aidendeffd422019-08-03 08:30:36 +000051{
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 */
99int 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
126int 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
137unsigned 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}