blob: 91951e4b8ccf113473466ed686049b3a9715202f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kever Yang5db9e672017-06-23 16:11:05 +08002/*
3 * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
Kever Yang5db9e672017-06-23 16:11:05 +08004 */
5
6#include <common.h>
7#include <dm.h>
Simon Glass6980b6b2019-11-14 12:57:45 -07008#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Kever Yang5db9e672017-06-23 16:11:05 +080010#include <ram.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Kever Yang5db9e672017-06-23 16:11:05 +080012#include <asm/io.h>
Kever Yange47db832019-11-15 11:04:33 +080013#include <asm/arch-rockchip/sdram.h>
Kever Yang5db9e672017-06-23 16:11:05 +080014#include <dm/uclass-internal.h>
15
16DECLARE_GLOBAL_DATA_PTR;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080017
18#define TRUST_PARAMETER_OFFSET (34 * 1024 * 1024)
19
20struct tos_parameter_t {
21 u32 version;
22 u32 checksum;
23 struct {
24 char name[8];
25 s64 phy_addr;
26 u32 size;
27 u32 flags;
28 } tee_mem;
29 struct {
30 char name[8];
31 s64 phy_addr;
32 u32 size;
33 u32 flags;
34 } drm_mem;
35 s64 reserve[8];
36};
37
38int dram_init_banksize(void)
39{
Tom Rinibb4dd962022-11-16 13:10:37 -050040 size_t top = min((unsigned long)(gd->ram_size + CFG_SYS_SDRAM_BASE),
Bin Meng98756b52021-01-31 20:35:58 +080041 (unsigned long)(gd->ram_top));
Kever Yangdfc8a7d2019-07-22 20:02:02 +080042
43#ifdef CONFIG_ARM64
44 /* Reserve 0x200000 for ATF bl31 */
45 gd->bd->bi_dram[0].start = 0x200000;
46 gd->bd->bi_dram[0].size = top - gd->bd->bi_dram[0].start;
47#else
Patrick Delaunaya7ca4802021-09-02 11:56:16 +020048#ifdef CONFIG_SPL_OPTEE_IMAGE
Kever Yangdfc8a7d2019-07-22 20:02:02 +080049 struct tos_parameter_t *tos_parameter;
50
Tom Rinibb4dd962022-11-16 13:10:37 -050051 tos_parameter = (struct tos_parameter_t *)(CFG_SYS_SDRAM_BASE +
Kever Yangdfc8a7d2019-07-22 20:02:02 +080052 TRUST_PARAMETER_OFFSET);
53
54 if (tos_parameter->tee_mem.flags == 1) {
Tom Rinibb4dd962022-11-16 13:10:37 -050055 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080056 gd->bd->bi_dram[0].size = tos_parameter->tee_mem.phy_addr
Tom Rinibb4dd962022-11-16 13:10:37 -050057 - CFG_SYS_SDRAM_BASE;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080058 gd->bd->bi_dram[1].start = tos_parameter->tee_mem.phy_addr +
59 tos_parameter->tee_mem.size;
Alex Beee3a34942020-07-15 01:03:31 +020060 gd->bd->bi_dram[1].size = top - gd->bd->bi_dram[1].start;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080061 } else {
Tom Rinibb4dd962022-11-16 13:10:37 -050062 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080063 gd->bd->bi_dram[0].size = 0x8400000;
64 /* Reserve 32M for OPTEE with TA */
Tom Rinibb4dd962022-11-16 13:10:37 -050065 gd->bd->bi_dram[1].start = CFG_SYS_SDRAM_BASE
Kever Yangdfc8a7d2019-07-22 20:02:02 +080066 + gd->bd->bi_dram[0].size + 0x2000000;
Alex Beee3a34942020-07-15 01:03:31 +020067 gd->bd->bi_dram[1].size = top - gd->bd->bi_dram[1].start;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080068 }
69#else
Tom Rinibb4dd962022-11-16 13:10:37 -050070 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
Kever Yangdfc8a7d2019-07-22 20:02:02 +080071 gd->bd->bi_dram[0].size = top - gd->bd->bi_dram[0].start;
72#endif
73#endif
74
75 return 0;
76}
77
Kever Yang5db9e672017-06-23 16:11:05 +080078size_t rockchip_sdram_size(phys_addr_t reg)
79{
Kever Yang117585a2019-11-15 11:04:35 +080080 u32 rank, cs0_col, bk, cs0_row, cs1_row, bw, row_3_4;
Kever Yang5db9e672017-06-23 16:11:05 +080081 size_t chipsize_mb = 0;
82 size_t size_mb = 0;
83 u32 ch;
Kever Yang117585a2019-11-15 11:04:35 +080084 u32 cs1_col = 0;
85 u32 bg = 0;
86 u32 dbw, dram_type;
Kever Yang4c0c6e42019-11-15 11:04:36 +080087 u32 sys_reg2 = readl(reg);
Kever Yang117585a2019-11-15 11:04:35 +080088 u32 sys_reg3 = readl(reg + 4);
Kever Yang4c0c6e42019-11-15 11:04:36 +080089 u32 ch_num = 1 + ((sys_reg2 >> SYS_REG_NUM_CH_SHIFT)
Kever Yang5db9e672017-06-23 16:11:05 +080090 & SYS_REG_NUM_CH_MASK);
Jonas Karlmanf570c252023-02-07 17:27:10 +000091 u32 version = (sys_reg3 >> SYS_REG_VERSION_SHIFT) &
92 SYS_REG_VERSION_MASK;
Kever Yang5db9e672017-06-23 16:11:05 +080093
Kever Yang4c0c6e42019-11-15 11:04:36 +080094 dram_type = (sys_reg2 >> SYS_REG_DDRTYPE_SHIFT) & SYS_REG_DDRTYPE_MASK;
Jonas Karlmanf570c252023-02-07 17:27:10 +000095 if (version >= 3)
96 dram_type |= ((sys_reg3 >> SYS_REG_EXTEND_DDRTYPE_SHIFT) &
97 SYS_REG_EXTEND_DDRTYPE_MASK) << 3;
Kever Yang4c0c6e42019-11-15 11:04:36 +080098 debug("%s %x %x\n", __func__, (u32)reg, sys_reg2);
Jonas Karlmanf570c252023-02-07 17:27:10 +000099 debug("%s %x %x\n", __func__, (u32)reg + 4, sys_reg3);
Kever Yang5db9e672017-06-23 16:11:05 +0800100 for (ch = 0; ch < ch_num; ch++) {
Kever Yang4c0c6e42019-11-15 11:04:36 +0800101 rank = 1 + (sys_reg2 >> SYS_REG_RANK_SHIFT(ch) &
Kever Yang5db9e672017-06-23 16:11:05 +0800102 SYS_REG_RANK_MASK);
Kever Yang4c0c6e42019-11-15 11:04:36 +0800103 cs0_col = 9 + (sys_reg2 >> SYS_REG_COL_SHIFT(ch) &
Kever Yang117585a2019-11-15 11:04:35 +0800104 SYS_REG_COL_MASK);
105 cs1_col = cs0_col;
Kever Yang4c0c6e42019-11-15 11:04:36 +0800106 bk = 3 - ((sys_reg2 >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
Jonas Karlmanf570c252023-02-07 17:27:10 +0000107 if (version >= 2) {
Kever Yang117585a2019-11-15 11:04:35 +0800108 cs1_col = 9 + (sys_reg3 >> SYS_REG_CS1_COL_SHIFT(ch) &
109 SYS_REG_CS1_COL_MASK);
110 if (((sys_reg3 >> SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) &
Kever Yang4c0c6e42019-11-15 11:04:36 +0800111 SYS_REG_EXTEND_CS0_ROW_MASK) << 2) + (sys_reg2 >>
Kever Yang117585a2019-11-15 11:04:35 +0800112 SYS_REG_CS0_ROW_SHIFT(ch) &
113 SYS_REG_CS0_ROW_MASK) == 7)
114 cs0_row = 12;
115 else
Kever Yang4c0c6e42019-11-15 11:04:36 +0800116 cs0_row = 13 + (sys_reg2 >>
Kever Yang117585a2019-11-15 11:04:35 +0800117 SYS_REG_CS0_ROW_SHIFT(ch) &
118 SYS_REG_CS0_ROW_MASK) +
119 ((sys_reg3 >>
120 SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) &
121 SYS_REG_EXTEND_CS0_ROW_MASK) << 2);
122 if (((sys_reg3 >> SYS_REG_EXTEND_CS1_ROW_SHIFT(ch) &
Kever Yang4c0c6e42019-11-15 11:04:36 +0800123 SYS_REG_EXTEND_CS1_ROW_MASK) << 2) + (sys_reg2 >>
Kever Yang117585a2019-11-15 11:04:35 +0800124 SYS_REG_CS1_ROW_SHIFT(ch) &
125 SYS_REG_CS1_ROW_MASK) == 7)
126 cs1_row = 12;
127 else
Kever Yang4c0c6e42019-11-15 11:04:36 +0800128 cs1_row = 13 + (sys_reg2 >>
Kever Yang117585a2019-11-15 11:04:35 +0800129 SYS_REG_CS1_ROW_SHIFT(ch) &
130 SYS_REG_CS1_ROW_MASK) +
131 ((sys_reg3 >>
132 SYS_REG_EXTEND_CS1_ROW_SHIFT(ch) &
133 SYS_REG_EXTEND_CS1_ROW_MASK) << 2);
134 } else {
Kever Yang4c0c6e42019-11-15 11:04:36 +0800135 cs0_row = 13 + (sys_reg2 >> SYS_REG_CS0_ROW_SHIFT(ch) &
Kever Yang5db9e672017-06-23 16:11:05 +0800136 SYS_REG_CS0_ROW_MASK);
Kever Yang4c0c6e42019-11-15 11:04:36 +0800137 cs1_row = 13 + (sys_reg2 >> SYS_REG_CS1_ROW_SHIFT(ch) &
Kever Yang5db9e672017-06-23 16:11:05 +0800138 SYS_REG_CS1_ROW_MASK);
Kever Yang117585a2019-11-15 11:04:35 +0800139 }
Kever Yang4c0c6e42019-11-15 11:04:36 +0800140 bw = (2 >> ((sys_reg2 >> SYS_REG_BW_SHIFT(ch)) &
Kever Yang5db9e672017-06-23 16:11:05 +0800141 SYS_REG_BW_MASK));
Kever Yang4c0c6e42019-11-15 11:04:36 +0800142 row_3_4 = sys_reg2 >> SYS_REG_ROW_3_4_SHIFT(ch) &
Kever Yang5db9e672017-06-23 16:11:05 +0800143 SYS_REG_ROW_3_4_MASK;
Kever Yang117585a2019-11-15 11:04:35 +0800144 if (dram_type == DDR4) {
Kever Yang4c0c6e42019-11-15 11:04:36 +0800145 dbw = (sys_reg2 >> SYS_REG_DBW_SHIFT(ch)) &
Kever Yang117585a2019-11-15 11:04:35 +0800146 SYS_REG_DBW_MASK;
147 bg = (dbw == 2) ? 2 : 1;
148 }
149 chipsize_mb = (1 << (cs0_row + cs0_col + bk + bg + bw - 20));
Kever Yang5db9e672017-06-23 16:11:05 +0800150
151 if (rank > 1)
Kever Yang117585a2019-11-15 11:04:35 +0800152 chipsize_mb += chipsize_mb >> ((cs0_row - cs1_row) +
153 (cs0_col - cs1_col));
Kever Yang5db9e672017-06-23 16:11:05 +0800154 if (row_3_4)
155 chipsize_mb = chipsize_mb * 3 / 4;
156 size_mb += chipsize_mb;
Kever Yang117585a2019-11-15 11:04:35 +0800157 if (rank > 1)
158 debug("rank %d cs0_col %d cs1_col %d bk %d cs0_row %d\
159 cs1_row %d bw %d row_3_4 %d\n",
160 rank, cs0_col, cs1_col, bk, cs0_row,
161 cs1_row, bw, row_3_4);
162 else
163 debug("rank %d cs0_col %d bk %d cs0_row %d\
164 bw %d row_3_4 %d\n",
165 rank, cs0_col, bk, cs0_row,
166 bw, row_3_4);
Kever Yang5db9e672017-06-23 16:11:05 +0800167 }
168
Kever Yange10e9062018-12-28 09:56:48 +0800169 /*
170 * This is workaround for issue we can't get correct size for 4GB ram
171 * in 32bit system and available before we really need ram space
172 * out of 4GB, eg.enable ARM LAPE(rk3288 supports 8GB ram).
173 * The size of 4GB is '0x1 00000000', and this value will be truncated
174 * to 0 in 32bit system, and system can not get correct ram size.
175 * Rockchip SoCs reserve a blob of space for peripheral near 4GB,
176 * and we are now setting SDRAM_MAX_SIZE as max available space for
177 * ram in 4GB, so we can use this directly to workaround the issue.
178 * TODO:
179 * 1. update correct value for SDRAM_MAX_SIZE as what dram
180 * controller sees.
181 * 2. update board_get_usable_ram_top() and dram_init_banksize()
182 * to reserve memory for peripheral space after previous update.
183 */
184 if (size_mb > (SDRAM_MAX_SIZE >> 20))
185 size_mb = (SDRAM_MAX_SIZE >> 20);
186
Kever Yang5db9e672017-06-23 16:11:05 +0800187 return (size_t)size_mb << 20;
188}
189
190int dram_init(void)
191{
192 struct ram_info ram;
193 struct udevice *dev;
194 int ret;
195
196 ret = uclass_get_device(UCLASS_RAM, 0, &dev);
197 if (ret) {
198 debug("DRAM init failed: %d\n", ret);
199 return ret;
200 }
201 ret = ram_get_info(dev, &ram);
202 if (ret) {
203 debug("Cannot get DRAM size: %d\n", ret);
204 return ret;
205 }
206 gd->ram_size = ram.size;
207 debug("SDRAM base=%lx, size=%lx\n",
208 (unsigned long)ram.base, (unsigned long)ram.size);
209
210 return 0;
211}
212
Pali Rohár4f4f5832022-09-09 17:32:40 +0200213phys_size_t board_get_usable_ram_top(phys_size_t total_size)
Kever Yang5db9e672017-06-23 16:11:05 +0800214{
Tom Rinibb4dd962022-11-16 13:10:37 -0500215 unsigned long top = CFG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE;
Kever Yang5db9e672017-06-23 16:11:05 +0800216
217 return (gd->ram_top > top) ? top : gd->ram_top;
218}