blob: 3f0e1d9a4256b33049407c7664ed5e98722159ba [file] [log] [blame]
Kever Yangb5497b52019-11-15 11:04:37 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
4 */
5
6#include <common.h>
7#include <debug_uart.h>
8#include <ram.h>
9#include <asm/io.h>
10#include <asm/arch-rockchip/sdram.h>
11#include <asm/arch-rockchip/sdram_common.h>
12
13/* n: Unit bytes */
14void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
15{
16 int i;
17
18 for (i = 0; i < n / sizeof(u32); i++) {
19 writel(*src, dest);
20 src++;
21 dest++;
22 }
23}
24
25void sdram_org_config(struct sdram_cap_info *cap_info,
26 struct sdram_base_params *base,
27 u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
28{
29 *p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype);
30 *p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels);
31
32 *p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel);
33 *p_os_reg2 |= SYS_REG_ENC_CHINFO(channel);
34 *p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel);
35 *p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel);
36 *p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel);
37 *p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel);
38 *p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel);
39
40 SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
41 if (cap_info->cs1_row)
42 SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2,
43 *p_os_reg3, channel);
44 *p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel);
45 *p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
46}
47
48int sdram_detect_bw(struct sdram_cap_info *cap_info)
49{
50 return 0;
51}
52
53int sdram_detect_cs(struct sdram_cap_info *cap_info)
54{
55 return 0;
56}
57
58int sdram_detect_col(struct sdram_cap_info *cap_info,
59 u32 coltmp)
60{
61 void __iomem *test_addr;
62 u32 col;
63 u32 bw = cap_info->bw;
64
65 for (col = coltmp; col >= 9; col -= 1) {
66 writel(0, CONFIG_SYS_SDRAM_BASE);
67 test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
68 (1ul << (col + bw - 1ul)));
69 writel(PATTERN, test_addr);
70 if ((readl(test_addr) == PATTERN) &&
71 (readl(CONFIG_SYS_SDRAM_BASE) == 0))
72 break;
73 }
74 if (col == 8) {
75 printascii("col error\n");
76 return -1;
77 }
78
79 cap_info->col = col;
80
81 return 0;
82}
83
84int sdram_detect_bank(struct sdram_cap_info *cap_info,
85 u32 coltmp, u32 bktmp)
86{
87 void __iomem *test_addr;
88 u32 bk;
89 u32 bw = cap_info->bw;
90
91 test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
92 (1ul << (coltmp + bktmp + bw - 1ul)));
93 writel(0, CONFIG_SYS_SDRAM_BASE);
94 writel(PATTERN, test_addr);
95 if ((readl(test_addr) == PATTERN) &&
96 (readl(CONFIG_SYS_SDRAM_BASE) == 0))
97 bk = 3;
98 else
99 bk = 2;
100
101 cap_info->bk = bk;
102
103 return 0;
104}
105
106/* detect bg for ddr4 */
107int sdram_detect_bg(struct sdram_cap_info *cap_info,
108 u32 coltmp)
109{
110 void __iomem *test_addr;
111 u32 dbw;
112 u32 bw = cap_info->bw;
113
114 test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
115 (1ul << (coltmp + bw + 1ul)));
116 writel(0, CONFIG_SYS_SDRAM_BASE);
117 writel(PATTERN, test_addr);
118 if ((readl(test_addr) == PATTERN) &&
119 (readl(CONFIG_SYS_SDRAM_BASE) == 0))
120 dbw = 0;
121 else
122 dbw = 1;
123
124 cap_info->dbw = dbw;
125
126 return 0;
127}
128
129/* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
130int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type)
131{
132 u32 row, col, bk, bw, cs_cap, cs;
133 u32 die_bw_0 = 0, die_bw_1 = 0;
134
135 if (dram_type == DDR3 || dram_type == LPDDR4) {
136 cap_info->dbw = 1;
137 } else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
138 row = cap_info->cs0_row;
139 col = cap_info->col;
140 bk = cap_info->bk;
141 cs = cap_info->rank;
142 bw = cap_info->bw;
143 cs_cap = (1 << (row + col + bk + bw - 20));
144 if (bw == 2) {
145 if (cs_cap <= 0x2000000) /* 256Mb */
146 die_bw_0 = (col < 9) ? 2 : 1;
147 else if (cs_cap <= 0x10000000) /* 2Gb */
148 die_bw_0 = (col < 10) ? 2 : 1;
149 else if (cs_cap <= 0x40000000) /* 8Gb */
150 die_bw_0 = (col < 11) ? 2 : 1;
151 else
152 die_bw_0 = (col < 12) ? 2 : 1;
153 if (cs > 1) {
154 row = cap_info->cs1_row;
155 cs_cap = (1 << (row + col + bk + bw - 20));
156 if (cs_cap <= 0x2000000) /* 256Mb */
157 die_bw_0 = (col < 9) ? 2 : 1;
158 else if (cs_cap <= 0x10000000) /* 2Gb */
159 die_bw_0 = (col < 10) ? 2 : 1;
160 else if (cs_cap <= 0x40000000) /* 8Gb */
161 die_bw_0 = (col < 11) ? 2 : 1;
162 else
163 die_bw_0 = (col < 12) ? 2 : 1;
164 }
165 } else {
166 die_bw_1 = 1;
167 die_bw_0 = 1;
168 }
169 cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
170 }
171
172 return 0;
173}
174
175int sdram_detect_row(struct sdram_cap_info *cap_info,
176 u32 coltmp, u32 bktmp, u32 rowtmp)
177{
178 u32 row;
179 u32 bw = cap_info->bw;
180 void __iomem *test_addr;
181
182 for (row = rowtmp; row > 12; row--) {
183 writel(0, CONFIG_SYS_SDRAM_BASE);
184 test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
185 (1ul << (row + bktmp + coltmp + bw - 1ul)));
186 writel(PATTERN, test_addr);
187 if ((readl(test_addr) == PATTERN) &&
188 (readl(CONFIG_SYS_SDRAM_BASE) == 0))
189 break;
190 }
191 if (row == 12) {
192 printascii("row error");
193 return -1;
194 }
195
196 cap_info->cs0_row = row;
197
198 return 0;
199}
200
201int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
202 u32 coltmp, u32 bktmp)
203{
204 u32 row_3_4;
205 u32 bw = cap_info->bw;
206 u32 row = cap_info->cs0_row;
207 void __iomem *test_addr, *test_addr1;
208
209 test_addr = CONFIG_SYS_SDRAM_BASE;
210 test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
211 (0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
212
213 writel(0, test_addr);
214 writel(PATTERN, test_addr1);
215 if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
216 row_3_4 = 0;
217 else
218 row_3_4 = 1;
219
220 cap_info->row_3_4 = row_3_4;
221
222 return 0;
223}
224
225int sdram_detect_high_row(struct sdram_cap_info *cap_info)
226{
227 cap_info->cs0_high16bit_row = cap_info->cs0_row;
228 cap_info->cs1_high16bit_row = cap_info->cs1_row;
229
230 return 0;
231}
232
233int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type)
234{
235 void __iomem *test_addr;
236 u32 row = 0, bktmp, coltmp, bw;
237 ulong cs0_cap;
238 u32 byte_mask;
239
240 if (cap_info->rank == 2) {
241 cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
242
243 if (dram_type == DDR4) {
244 if (cap_info->dbw == 0)
245 bktmp = cap_info->bk + 2;
246 else
247 bktmp = cap_info->bk + 1;
248 } else {
249 bktmp = cap_info->bk;
250 }
251 bw = cap_info->bw;
252 coltmp = cap_info->col;
253
254 /*
255 * because px30 support axi split,min bandwidth
256 * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
257 * so we check low 16bit data when detect cs1 row.
258 * if cs0 is 16bit/8bit, we check low 8bit data.
259 */
260 if (bw == 2)
261 byte_mask = 0xFFFF;
262 else
263 byte_mask = 0xFF;
264
265 /* detect cs1 row */
266 for (row = cap_info->cs0_row; row > 12; row--) {
267 test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
268 cs0_cap +
269 (1ul << (row + bktmp + coltmp + bw - 1ul)));
270 writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap);
271 writel(PATTERN, test_addr);
272
273 if (((readl(test_addr) & byte_mask) ==
274 (PATTERN & byte_mask)) &&
275 ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) &
276 byte_mask) == 0)) {
277 break;
278 }
279 }
280 }
281
282 cap_info->cs1_row = row;
283
284 return 0;
285}