]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - arch/x86/cpu/tangier/sdram.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2017 Intel Corporation
10 #include <asm/global_data.h>
12 #include <linux/printk.h>
14 DECLARE_GLOBAL_DATA_PTR
;
17 * SFI tables are part of the first stage bootloader.
19 * U-Boot finds the System Table by searching 16-byte boundaries between
20 * physical address 0x000E0000 and 0x000FFFFF. U-Boot shall search this region
21 * starting at the low address and shall stop searching when the 1st valid SFI
22 * System Table is found.
24 #define SFI_BASE_ADDR 0x000E0000
25 #define SFI_LENGTH 0x00020000
26 #define SFI_TABLE_LENGTH 16
28 static int sfi_table_check(struct sfi_table_header
*sbh
)
31 char *pos
= (char *)sbh
;
34 if (sbh
->len
< SFI_TABLE_LENGTH
)
37 if (sbh
->len
> SFI_LENGTH
)
40 for (i
= 0; i
< sbh
->len
; i
++)
44 pr_err("sfi: Invalid checksum\n");
46 /* Checksum is OK if zero */
47 return chksum
? -EILSEQ
: 0;
50 static int sfi_table_is_type(struct sfi_table_header
*sbh
, const char *signature
)
52 return !strncmp(sbh
->sig
, signature
, SFI_SIGNATURE_SIZE
) &&
53 !sfi_table_check(sbh
);
56 static struct sfi_table_simple
*sfi_get_table_by_sig(unsigned long addr
,
57 const char *signature
)
59 struct sfi_table_simple
*sb
;
62 for (i
= 0; i
< SFI_LENGTH
; i
+= SFI_TABLE_LENGTH
) {
63 sb
= (struct sfi_table_simple
*)(addr
+ i
);
64 if (sfi_table_is_type(&sb
->header
, signature
))
71 static struct sfi_table_simple
*sfi_search_mmap(void)
73 struct sfi_table_header
*sbh
;
74 struct sfi_table_simple
*sb
;
79 sb
= sfi_get_table_by_sig(SFI_BASE_ADDR
, SFI_SIG_SYST
);
81 pr_err("sfi: failed to locate SYST table\n");
85 sys_entry_cnt
= (sb
->header
.len
- sizeof(*sbh
)) / 8;
87 /* Search through each SYST entry for MMAP table */
88 for (i
= 0; i
< sys_entry_cnt
; i
++) {
89 sbh
= (struct sfi_table_header
*)(unsigned long)sb
->pentry
[i
];
91 if (sfi_table_is_type(sbh
, SFI_SIG_MMAP
))
92 return (struct sfi_table_simple
*)sbh
;
95 pr_err("sfi: failed to locate SFI MMAP table\n");
99 #define sfi_for_each_mentry(i, sb, mentry) \
100 for (i = 0, mentry = (struct sfi_mem_entry *)sb->pentry; \
101 i < SFI_GET_NUM_ENTRIES(sb, struct sfi_mem_entry); \
104 static unsigned int sfi_setup_e820(unsigned int max_entries,
105 struct e820_entry
*entries
)
107 struct sfi_table_simple
*sb
;
108 struct sfi_mem_entry
*mentry
;
109 unsigned long long start
, end
, size
;
113 sb
= sfi_search_mmap();
117 sfi_for_each_mentry(i
, sb
, mentry
) {
118 start
= mentry
->phys_start
;
119 size
= mentry
->pages
<< 12;
125 /* translate SFI mmap type to E820 map type */
126 switch (mentry
->type
) {
130 case SFI_MEM_UNUSABLE
:
131 case SFI_RUNTIME_SERVICE_DATA
:
134 type
= E820_RESERVED
;
137 if (total
== E820MAX
)
139 entries
[total
].addr
= start
;
140 entries
[total
].size
= size
;
141 entries
[total
].type
= type
;
149 static int sfi_get_bank_size(void)
151 struct sfi_table_simple
*sb
;
152 struct sfi_mem_entry
*mentry
;
156 sb
= sfi_search_mmap();
160 sfi_for_each_mentry(i
, sb
, mentry
) {
161 if (mentry
->type
!= SFI_MEM_CONV
)
164 gd
->bd
->bi_dram
[bank
].start
= mentry
->phys_start
;
165 gd
->bd
->bi_dram
[bank
].size
= mentry
->pages
<< 12;
172 static phys_size_t
sfi_get_ram_size(void)
174 struct sfi_table_simple
*sb
;
175 struct sfi_mem_entry
*mentry
;
179 sb
= sfi_search_mmap();
183 sfi_for_each_mentry(i
, sb
, mentry
) {
184 if (mentry
->type
!= SFI_MEM_CONV
)
187 ram
+= mentry
->pages
<< 12;
190 debug("sfi: RAM size %llu\n", ram
);
194 unsigned int install_e820_map(unsigned int max_entries
,
195 struct e820_entry
*entries
)
197 return sfi_setup_e820(max_entries
, entries
);
201 * This function looks for the highest region of memory lower than 2GB which
202 * has enough space for U-Boot where U-Boot is aligned on a page boundary. It
203 * overrides the default implementation found elsewhere which simply picks the
204 * end of RAM, wherever that may be. The location of the stack, the relocation
205 * address, and how far U-Boot is moved by relocation are set in the global
208 phys_addr_t
board_get_usable_ram_top(phys_size_t total_size
)
210 struct sfi_table_simple
*sb
;
211 struct sfi_mem_entry
*mentry
;
215 sb
= sfi_search_mmap();
217 panic("No available memory found for relocation");
219 sfi_for_each_mentry(i
, sb
, mentry
) {
220 unsigned long long start
, end
;
222 if (mentry
->type
!= SFI_MEM_CONV
)
225 start
= mentry
->phys_start
;
226 end
= start
+ (mentry
->pages
<< 12);
228 /* Filter memory over 2GB. */
229 if (end
> 0x7fffffffULL
)
231 /* Skip this region if it's too small. */
232 if (end
- start
< total_size
)
235 /* Use this address if it's the largest so far. */
243 int dram_init_banksize(void)
251 gd
->ram_size
= sfi_get_ram_size();