blob: ba3638e6acc64ae8c8446b441edf0f6bd25b2719 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Bin Meng2229c4c2015-05-07 21:34:08 +08002/*
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
Bin Meng2229c4c2015-05-07 21:34:08 +08004 */
5
Simon Glass6980b6b2019-11-14 12:57:45 -07006#include <init.h>
Simon Glass50706fd2025-03-15 14:25:47 +00007#include <spl.h>
Simon Glass3ba929a2020-10-30 21:38:53 -06008#include <asm/global_data.h>
Simon Glass50706fd2025-03-15 14:25:47 +00009#include <asm/mtrr.h>
Bin Meng2229c4c2015-05-07 21:34:08 +080010#include <asm/post.h>
11#include <asm/arch/qemu.h>
Simon Glassde1669f2023-07-30 21:02:04 -060012#include <linux/sizes.h>
Bin Meng2229c4c2015-05-07 21:34:08 +080013
14DECLARE_GLOBAL_DATA_PTR;
15
Bin Meng38502eb2019-08-29 02:53:04 -070016u32 qemu_get_low_memory_size(void)
Bin Meng2229c4c2015-05-07 21:34:08 +080017{
18 u32 ram;
19
20 outb(HIGH_RAM_ADDR, CMOS_ADDR_PORT);
21 ram = ((u32)inb(CMOS_DATA_PORT)) << 14;
22 outb(LOW_RAM_ADDR, CMOS_ADDR_PORT);
23 ram |= ((u32)inb(CMOS_DATA_PORT)) << 6;
24 ram += 16 * 1024;
25
Bin Meng38502eb2019-08-29 02:53:04 -070026 return ram * 1024;
27}
28
Bin Mengfc7f57f2019-08-29 02:53:05 -070029u64 qemu_get_high_memory_size(void)
30{
31 u64 ram;
32
33 outb(HIGH_HIGHRAM_ADDR, CMOS_ADDR_PORT);
34 ram = ((u64)inb(CMOS_DATA_PORT)) << 22;
35 outb(MID_HIGHRAM_ADDR, CMOS_ADDR_PORT);
36 ram |= ((u64)inb(CMOS_DATA_PORT)) << 14;
37 outb(LOW_HIGHRAM_ADDR, CMOS_ADDR_PORT);
38 ram |= ((u64)inb(CMOS_DATA_PORT)) << 6;
39
40 return ram * 1024;
41}
42
Bin Meng38502eb2019-08-29 02:53:04 -070043int dram_init(void)
44{
45 gd->ram_size = qemu_get_low_memory_size();
Bin Mengfc7f57f2019-08-29 02:53:05 -070046 gd->ram_size += qemu_get_high_memory_size();
Bin Meng2229c4c2015-05-07 21:34:08 +080047 post_code(POST_DRAM);
48
Simon Glass50706fd2025-03-15 14:25:47 +000049 if (xpl_phase() == PHASE_BOARD_F) {
50 u64 total = gd->ram_size;
51 int ret;
52
53 if (total > SZ_2G + SZ_1G)
54 total += SZ_1G;
55 ret = mtrr_add_request(MTRR_TYPE_WRBACK, 0, total);
56 if (ret != -ENOSYS) {
57 if (ret)
58 return log_msg_ret("mta", ret);
59 ret = mtrr_commit(false);
60 if (ret)
61 return log_msg_ret("mtc", ret);
62 }
63 }
64
Bin Meng2229c4c2015-05-07 21:34:08 +080065 return 0;
66}
67
Simon Glass2f949c32017-03-31 08:40:32 -060068int dram_init_banksize(void)
Bin Meng2229c4c2015-05-07 21:34:08 +080069{
Bin Mengfc7f57f2019-08-29 02:53:05 -070070 u64 high_mem_size;
71
Bin Meng2229c4c2015-05-07 21:34:08 +080072 gd->bd->bi_dram[0].start = 0;
Bin Mengfc7f57f2019-08-29 02:53:05 -070073 gd->bd->bi_dram[0].size = qemu_get_low_memory_size();
74
75 high_mem_size = qemu_get_high_memory_size();
76 if (high_mem_size) {
77 gd->bd->bi_dram[1].start = SZ_4G;
78 gd->bd->bi_dram[1].size = high_mem_size;
79 }
Simon Glass2f949c32017-03-31 08:40:32 -060080
81 return 0;
Bin Meng2229c4c2015-05-07 21:34:08 +080082}
83
84/*
85 * This function looks for the highest region of memory lower than 4GB which
86 * has enough space for U-Boot where U-Boot is aligned on a page boundary.
87 * It overrides the default implementation found elsewhere which simply
88 * picks the end of ram, wherever that may be. The location of the stack,
89 * the relocation address, and how far U-Boot is moved by relocation are
90 * set in the global data structure.
91 */
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +020092phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Bin Meng2229c4c2015-05-07 21:34:08 +080093{
Bin Mengfc7f57f2019-08-29 02:53:05 -070094 return qemu_get_low_memory_size();
Bin Meng2229c4c2015-05-07 21:34:08 +080095}