blob: fbb33b246e5b5f395c6b7d5a8a32fc07a903f4b7 [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
6#include <common.h>
Simon Glass6980b6b2019-11-14 12:57:45 -07007#include <init.h>
Simon Glass3ba929a2020-10-30 21:38:53 -06008#include <asm/global_data.h>
Park, Aidendeffd422019-08-03 08:30:36 +00009#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
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010049 * Return: : The top available memory address lower than 4GB
Park, Aidendeffd422019-08-03 08:30:36 +000050 */
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +020051phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Park, Aidendeffd422019-08-03 08:30:36 +000052{
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}