1// 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#ifdef CONFIG_RAM_ROCKCHIP_DEBUG
14void sdram_print_dram_type(unsigned char dramtype)
15{
16	switch (dramtype) {
17	case DDR3:
18		printascii("DDR3");
19		break;
20	case DDR4:
21		printascii("DDR4");
22		break;
23	case LPDDR2:
24		printascii("LPDDR2");
25		break;
26	case LPDDR3:
27		printascii("LPDDR3");
28		break;
29	case LPDDR4:
30		printascii("LPDDR4");
31		break;
32	default:
33		printascii("Unknown Device");
34		break;
35	}
36}
37
38void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
39			  struct sdram_base_params *base, u32 split)
40{
41	u64 cap;
42	u32 bg;
43
44	bg = (cap_info->dbw == 0) ? 2 : 1;
45
46	sdram_print_dram_type(base->dramtype);
47
48	printascii(", ");
49	printdec(base->ddr_freq);
50	printascii("MHz\n");
51
52	printascii("BW=");
53	printdec(8 << cap_info->bw);
54	printascii(" Col=");
55	printdec(cap_info->col);
56	printascii(" Bk=");
57	printdec(0x1 << cap_info->bk);
58	if (base->dramtype == DDR4) {
59		printascii(" BG=");
60		printdec(1 << bg);
61	}
62	printascii(" CS0 Row=");
63	printdec(cap_info->cs0_row);
64	if (cap_info->cs0_high16bit_row !=
65		cap_info->cs0_row) {
66		printascii("/");
67		printdec(cap_info->cs0_high16bit_row);
68	}
69	if (cap_info->rank > 1) {
70		printascii(" CS1 Row=");
71		printdec(cap_info->cs1_row);
72		if (cap_info->cs1_high16bit_row !=
73			cap_info->cs1_row) {
74			printascii("/");
75			printdec(cap_info->cs1_high16bit_row);
76		}
77	}
78	printascii(" CS=");
79	printdec(cap_info->rank);
80	printascii(" Die BW=");
81	printdec(8 << cap_info->dbw);
82
83	cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
84	if (cap_info->row_3_4)
85		cap = cap * 3 / 4;
86	else if (split)
87		cap = cap / 2 + (split << 24) / 2;
88
89	printascii(" Size=");
90	printdec(cap >> 20);
91	printascii("MB\n");
92}
93
94void sdram_print_stride(unsigned int stride)
95{
96	switch (stride) {
97	case 0xc:
98		printf("128B stride\n");
99		break;
100	case 5:
101	case 9:
102	case 0xd:
103	case 0x11:
104	case 0x19:
105		printf("256B stride\n");
106		break;
107	case 0xa:
108	case 0xe:
109	case 0x12:
110		printf("512B stride\n");
111		break;
112	case 0xf:
113		printf("4K stride\n");
114		break;
115	case 0x1f:
116		printf("32MB + 256B stride\n");
117		break;
118	default:
119		printf("no stride\n");
120	}
121}
122#else
123inline void sdram_print_dram_type(unsigned char dramtype)
124{
125}
126
127inline void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
128				 struct sdram_base_params *base, u32 split)
129{
130}
131
132inline void sdram_print_stride(unsigned int stride)
133{
134}
135#endif
136
137/*
138 * cs: 0:cs0
139 *	   1:cs1
140 *     else cs0+cs1
141 * note: it didn't consider about row_3_4
142 */
143u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
144{
145	u32 bg;
146	u64 cap[2];
147
148	if (dram_type == DDR4)
149		/* DDR4 8bit dram BG = 2(4bank groups),
150		 * 16bit dram BG = 1 (2 bank groups)
151		 */
152		bg = (cap_info->dbw == 0) ? 2 : 1;
153	else
154		bg = 0;
155	cap[0] = 1llu << (cap_info->bw + cap_info->col +
156		bg + cap_info->bk + cap_info->cs0_row);
157
158	if (cap_info->rank == 2)
159		cap[1] = 1llu << (cap_info->bw + cap_info->col +
160			bg + cap_info->bk + cap_info->cs1_row);
161	else
162		cap[1] = 0;
163
164	if (cs == 0)
165		return cap[0];
166	else if (cs == 1)
167		return cap[1];
168	else
169		return (cap[0] + cap[1]);
170}
171
172/* n: Unit bytes */
173void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
174{
175	int i;
176
177	for (i = 0; i < n / sizeof(u32); i++) {
178		writel(*src, dest);
179		src++;
180		dest++;
181	}
182}
183
184void sdram_org_config(struct sdram_cap_info *cap_info,
185		      struct sdram_base_params *base,
186		      u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
187{
188	*p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype);
189	*p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels);
190
191	*p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel);
192	*p_os_reg2 |= SYS_REG_ENC_CHINFO(channel);
193	*p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel);
194	*p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel);
195	*p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel);
196	*p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel);
197	*p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel);
198
199	SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
200	if (cap_info->cs1_row)
201		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2,
202				    *p_os_reg3, channel);
203	*p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel);
204	*p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
205}
206
207int sdram_detect_bw(struct sdram_cap_info *cap_info)
208{
209	return 0;
210}
211
212int sdram_detect_cs(struct sdram_cap_info *cap_info)
213{
214	return 0;
215}
216
217int sdram_detect_col(struct sdram_cap_info *cap_info,
218		     u32 coltmp)
219{
220	void __iomem *test_addr;
221	u32 col;
222	u32 bw = cap_info->bw;
223
224	for (col = coltmp; col >= 9; col -= 1) {
225		writel(0, CFG_SYS_SDRAM_BASE);
226		test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
227				(1ul << (col + bw - 1ul)));
228		writel(PATTERN, test_addr);
229		if ((readl(test_addr) == PATTERN) &&
230		    (readl(CFG_SYS_SDRAM_BASE) == 0))
231			break;
232	}
233	if (col == 8) {
234		printascii("col error\n");
235		return -1;
236	}
237
238	cap_info->col = col;
239
240	return 0;
241}
242
243int sdram_detect_bank(struct sdram_cap_info *cap_info,
244		      u32 coltmp, u32 bktmp)
245{
246	void __iomem *test_addr;
247	u32 bk;
248	u32 bw = cap_info->bw;
249
250	test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
251			(1ul << (coltmp + bktmp + bw - 1ul)));
252	writel(0, CFG_SYS_SDRAM_BASE);
253	writel(PATTERN, test_addr);
254	if ((readl(test_addr) == PATTERN) &&
255	    (readl(CFG_SYS_SDRAM_BASE) == 0))
256		bk = 3;
257	else
258		bk = 2;
259
260	cap_info->bk = bk;
261
262	return 0;
263}
264
265/* detect bg for ddr4 */
266int sdram_detect_bg(struct sdram_cap_info *cap_info,
267		    u32 coltmp)
268{
269	void __iomem *test_addr;
270	u32 dbw;
271	u32 bw = cap_info->bw;
272
273	test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
274			(1ul << (coltmp + bw + 1ul)));
275	writel(0, CFG_SYS_SDRAM_BASE);
276	writel(PATTERN, test_addr);
277	if ((readl(test_addr) == PATTERN) &&
278	    (readl(CFG_SYS_SDRAM_BASE) == 0))
279		dbw = 0;
280	else
281		dbw = 1;
282
283	cap_info->dbw = dbw;
284
285	return 0;
286}
287
288/* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
289int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type)
290{
291	u32 row, col, bk, bw, cs_cap, cs;
292	u32 die_bw_0 = 0, die_bw_1 = 0;
293
294	if (dram_type == DDR3 || dram_type == LPDDR4) {
295		cap_info->dbw = 1;
296	} else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
297		row = cap_info->cs0_row;
298		col = cap_info->col;
299		bk = cap_info->bk;
300		cs = cap_info->rank;
301		bw = cap_info->bw;
302		cs_cap = (1 << (row + col + bk + bw - 20));
303		if (bw == 2) {
304			if (cs_cap <= 0x2000000) /* 256Mb */
305				die_bw_0 = (col < 9) ? 2 : 1;
306			else if (cs_cap <= 0x10000000) /* 2Gb */
307				die_bw_0 = (col < 10) ? 2 : 1;
308			else if (cs_cap <= 0x40000000) /* 8Gb */
309				die_bw_0 = (col < 11) ? 2 : 1;
310			else
311				die_bw_0 = (col < 12) ? 2 : 1;
312			if (cs > 1) {
313				row = cap_info->cs1_row;
314				cs_cap = (1 << (row + col + bk + bw - 20));
315				if (cs_cap <= 0x2000000) /* 256Mb */
316					die_bw_0 = (col < 9) ? 2 : 1;
317				else if (cs_cap <= 0x10000000) /* 2Gb */
318					die_bw_0 = (col < 10) ? 2 : 1;
319				else if (cs_cap <= 0x40000000) /* 8Gb */
320					die_bw_0 = (col < 11) ? 2 : 1;
321				else
322					die_bw_0 = (col < 12) ? 2 : 1;
323			}
324		} else {
325			die_bw_1 = 1;
326			die_bw_0 = 1;
327		}
328		cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
329	}
330
331	return 0;
332}
333
334int sdram_detect_row(struct sdram_cap_info *cap_info,
335		     u32 coltmp, u32 bktmp, u32 rowtmp)
336{
337	u32 row;
338	u32 bw = cap_info->bw;
339	void __iomem *test_addr;
340
341	for (row = rowtmp; row > 12; row--) {
342		writel(0, CFG_SYS_SDRAM_BASE);
343		test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
344				(1ul << (row + bktmp + coltmp + bw - 1ul)));
345		writel(PATTERN, test_addr);
346		if ((readl(test_addr) == PATTERN) &&
347		    (readl(CFG_SYS_SDRAM_BASE) == 0))
348			break;
349	}
350	if (row == 12) {
351		printascii("row error");
352		return -1;
353	}
354
355	cap_info->cs0_row = row;
356
357	return 0;
358}
359
360int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
361			 u32 coltmp, u32 bktmp)
362{
363	u32 row_3_4;
364	u32 bw = cap_info->bw;
365	u32 row = cap_info->cs0_row;
366	void __iomem *test_addr, *test_addr1;
367
368	test_addr = CFG_SYS_SDRAM_BASE;
369	test_addr1 = (void __iomem *)(CFG_SYS_SDRAM_BASE +
370			(0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
371
372	writel(0, test_addr);
373	writel(PATTERN, test_addr1);
374	if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
375		row_3_4 = 0;
376	else
377		row_3_4 = 1;
378
379	cap_info->row_3_4 = row_3_4;
380
381	return 0;
382}
383
384int sdram_detect_high_row(struct sdram_cap_info *cap_info)
385{
386	cap_info->cs0_high16bit_row = cap_info->cs0_row;
387	cap_info->cs1_high16bit_row = cap_info->cs1_row;
388
389	return 0;
390}
391
392int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type)
393{
394	void __iomem *test_addr;
395	u32 row = 0, bktmp, coltmp, bw;
396	ulong cs0_cap;
397	u32 byte_mask;
398
399	if (cap_info->rank == 2) {
400		cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
401
402		if (dram_type == DDR4) {
403			if (cap_info->dbw == 0)
404				bktmp = cap_info->bk + 2;
405			else
406				bktmp = cap_info->bk + 1;
407		} else {
408			bktmp = cap_info->bk;
409		}
410		bw = cap_info->bw;
411		coltmp = cap_info->col;
412
413		/*
414		 * because px30 support axi split,min bandwidth
415		 * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
416		 * so we check low 16bit data when detect cs1 row.
417		 * if cs0 is 16bit/8bit, we check low 8bit data.
418		 */
419		if (bw == 2)
420			byte_mask = 0xFFFF;
421		else
422			byte_mask = 0xFF;
423
424		/* detect cs1 row */
425		for (row = cap_info->cs0_row; row > 12; row--) {
426			test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
427				    cs0_cap +
428				    (1ul << (row + bktmp + coltmp + bw - 1ul)));
429			writel(0, CFG_SYS_SDRAM_BASE + cs0_cap);
430			writel(PATTERN, test_addr);
431
432			if (((readl(test_addr) & byte_mask) ==
433			     (PATTERN & byte_mask)) &&
434			    ((readl(CFG_SYS_SDRAM_BASE + cs0_cap) &
435			      byte_mask) == 0)) {
436				break;
437			}
438		}
439	}
440
441	cap_info->cs1_row = row;
442
443	return 0;
444}
445