xref: /rk3399_rockchip-uboot/cmd/ddr_tool/ddr_tool_common.c (revision 1d48cddb8501887a10ae59fdd0e3b156034585d1)
1f9a1c31dSWesley Yao // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2f9a1c31dSWesley Yao /*
3f9a1c31dSWesley Yao  * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
4f9a1c31dSWesley Yao  */
5f9a1c31dSWesley Yao 
6f9a1c31dSWesley Yao #include <common.h>
7f9a1c31dSWesley Yao #include <power/regulator.h>
8f9a1c31dSWesley Yao #include "ddr_tool_common.h"
9*1d48cddbSCanYang He #include <bidram.h>
10f9a1c31dSWesley Yao 
11*1d48cddbSCanYang He extern struct bidram plat_bidram;
12f9a1c31dSWesley Yao DECLARE_GLOBAL_DATA_PTR;
13f9a1c31dSWesley Yao 
14*1d48cddbSCanYang He struct bi_dram {
15*1d48cddbSCanYang He 	u64 start;
16*1d48cddbSCanYang He 	u64 size;
17*1d48cddbSCanYang He };
18*1d48cddbSCanYang He static struct bi_dram post_dram[CONFIG_NR_DRAM_BANKS];
19*1d48cddbSCanYang He 
write_buf_to_ddr(u32 * buf,u32 buf_len,ulong start_adr,ulong length)20f9a1c31dSWesley Yao void write_buf_to_ddr(u32 *buf, u32 buf_len, ulong start_adr, ulong length)
21f9a1c31dSWesley Yao {
22f9a1c31dSWesley Yao 	ulong *buful = (ulong *)buf;
23f9a1c31dSWesley Yao 	ulong *p = (ulong *)start_adr;
24f9a1c31dSWesley Yao 	u32 i, j;
25f9a1c31dSWesley Yao 
26f9a1c31dSWesley Yao 	buf_len = buf_len / sizeof(ulong) - 1;
27f9a1c31dSWesley Yao 
28f9a1c31dSWesley Yao 	for (i = 0, j = 0; i < length / sizeof(p[0]); i++) {
29f9a1c31dSWesley Yao 		p[i] = buful[j];
30f9a1c31dSWesley Yao 		j++;
31f9a1c31dSWesley Yao 		j &= buf_len;
32f9a1c31dSWesley Yao 	}
33f9a1c31dSWesley Yao }
34f9a1c31dSWesley Yao 
cmp_buf_data(u32 * buf,u32 buf_len,ulong start_adr,ulong length,u32 prt_en)35f9a1c31dSWesley Yao ulong cmp_buf_data(u32 *buf, u32 buf_len, ulong start_adr, ulong length,
36f9a1c31dSWesley Yao 		   u32 prt_en)
37f9a1c31dSWesley Yao {
38f9a1c31dSWesley Yao 	ulong *buful = (ulong *)buf;
39f9a1c31dSWesley Yao 	volatile unsigned long *p = (volatile unsigned long *)start_adr;
40f9a1c31dSWesley Yao 	u32 i, j;
41f9a1c31dSWesley Yao 	ulong reread = 0;
42f9a1c31dSWesley Yao 	ulong wr_val = 0;
43f9a1c31dSWesley Yao 	ulong val = 0;
44f9a1c31dSWesley Yao 	ulong err_adr = 0;
45f9a1c31dSWesley Yao 
46f9a1c31dSWesley Yao 	buf_len = buf_len / sizeof(ulong) - 1;
47f9a1c31dSWesley Yao 	err_adr = 0;
48f9a1c31dSWesley Yao 	for (i = 0, j = 0; i < length / sizeof(p[0]); i++) {
49f9a1c31dSWesley Yao 		val = p[i];
50f9a1c31dSWesley Yao 		if (val != buful[j]) {
51f9a1c31dSWesley Yao 			flush_dcache_range((ulong)&p[i],
52f9a1c31dSWesley Yao 					   (ulong)&p[i] + sizeof(u32));
53f9a1c31dSWesley Yao 			reread = p[i];
54f9a1c31dSWesley Yao 			err_adr = (ulong)&p[i];
55f9a1c31dSWesley Yao 			wr_val = buful[j];
56f9a1c31dSWesley Yao 			break;
57f9a1c31dSWesley Yao 		}
58f9a1c31dSWesley Yao 		j++;
59f9a1c31dSWesley Yao 		j &= buf_len;
60f9a1c31dSWesley Yao 	}
61f9a1c31dSWesley Yao 	if (err_adr && prt_en)
62f9a1c31dSWesley Yao 		printf("test fail:address:0x%lx,read:0x%lx,"
63f9a1c31dSWesley Yao 		       "reread:0x%lx,expect:0x%lx\n",
64f9a1c31dSWesley Yao 		       err_adr, val, reread, wr_val);
65f9a1c31dSWesley Yao 
66f9a1c31dSWesley Yao 	return err_adr;
67f9a1c31dSWesley Yao }
68f9a1c31dSWesley Yao 
print_memory(void * addr,ulong size)69f9a1c31dSWesley Yao void print_memory(void *addr, ulong size)
70f9a1c31dSWesley Yao {
71f9a1c31dSWesley Yao 	u32 *p = addr;
72f9a1c31dSWesley Yao 	u32 i;
73f9a1c31dSWesley Yao 
74f9a1c31dSWesley Yao 	for (i = 0; i < size / 4; i += 4) {
75f9a1c31dSWesley Yao 		printf("0x%08lx: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
76f9a1c31dSWesley Yao 		       (ulong)&p[i], p[i], p[i + 1], p[i + 2], p[i + 3]);
77f9a1c31dSWesley Yao 	}
78f9a1c31dSWesley Yao }
79f9a1c31dSWesley Yao 
80f9a1c31dSWesley Yao /* print available address for ddr testing in uboot */
get_print_available_addr(ulong * start_adr,ulong * length,int print_en)81f9a1c31dSWesley Yao void get_print_available_addr(ulong *start_adr, ulong *length, int print_en)
82f9a1c31dSWesley Yao {
83*1d48cddbSCanYang He 	u32 i, j, max_bank = 0;
84*1d48cddbSCanYang He 	u32 sp_bank = 0;
85f9a1c31dSWesley Yao 
86*1d48cddbSCanYang He 	/* find sp at which bank */
87f9a1c31dSWesley Yao 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
88f9a1c31dSWesley Yao 		if (gd->bd->bi_dram[i].start)
89*1d48cddbSCanYang He 			sp_bank = i;
90*1d48cddbSCanYang He 	}
91*1d48cddbSCanYang He 
92*1d48cddbSCanYang He 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
93*1d48cddbSCanYang He 		post_dram[i].start = 0;
94*1d48cddbSCanYang He 		post_dram[i].size = 0;
95*1d48cddbSCanYang He 	}
96*1d48cddbSCanYang He 
97*1d48cddbSCanYang He 	/* 0 - 4GB */
98*1d48cddbSCanYang He 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
99*1d48cddbSCanYang He 		if (!gd->bd->bi_dram[i].size)
100*1d48cddbSCanYang He 			break;
101*1d48cddbSCanYang He 		post_dram[i].start = gd->bd->bi_dram[i].start;
102*1d48cddbSCanYang He 		post_dram[i].size = gd->bd->bi_dram[i].size;
103*1d48cddbSCanYang He 	}
104*1d48cddbSCanYang He 
105*1d48cddbSCanYang He 	/* 4GB+ */
106*1d48cddbSCanYang He 	for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) {
107*1d48cddbSCanYang He 		if (!plat_bidram.size_u64[j])
108*1d48cddbSCanYang He 			break;
109*1d48cddbSCanYang He 		post_dram[i].start = plat_bidram.base_u64[j];
110*1d48cddbSCanYang He 		post_dram[i].size = plat_bidram.size_u64[j];
111*1d48cddbSCanYang He 		i++;
112*1d48cddbSCanYang He 	}
113*1d48cddbSCanYang He 
114*1d48cddbSCanYang He 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
115*1d48cddbSCanYang He 		if (post_dram[i].size)
116f9a1c31dSWesley Yao 			max_bank = i + 1;
117f9a1c31dSWesley Yao 		start_adr[i] = 0;
118f9a1c31dSWesley Yao 		length[i] = 0;
119f9a1c31dSWesley Yao 	}
120f9a1c31dSWesley Yao 
121f9a1c31dSWesley Yao 	for (i = 0; i < max_bank; i++) {
122*1d48cddbSCanYang He 		start_adr[i] = post_dram[i].start;
123*1d48cddbSCanYang He 		length[i] = post_dram[i].size;
1249bf9a700SWesley Yao #if defined(CONFIG_ROCKCHIP_RV1126)
1259bf9a700SWesley Yao 		/* On RV1126, writing data to 0x00600000 will cause a crash. */
1269bf9a700SWesley Yao 		if (start_adr[i] == 0 && length[i] > 0x00700000) {
1279bf9a700SWesley Yao 			start_adr[i] = 0x00700000;
1289bf9a700SWesley Yao 			length[i] -= 0x00700000;
1299bf9a700SWesley Yao 		}
1309bf9a700SWesley Yao #endif
131f9a1c31dSWesley Yao 	}
132f9a1c31dSWesley Yao 
133*1d48cddbSCanYang He 	length[sp_bank] = (gd->start_addr_sp - RESERVED_SP_SIZE -
134*1d48cddbSCanYang He 			start_adr[sp_bank]) & ~0xfff;
135f9a1c31dSWesley Yao 	if (print_en) {
136f9a1c31dSWesley Yao 		printf("available memory for test:\n");
137f9a1c31dSWesley Yao 		printf("	start		 end	length\n");
138f9a1c31dSWesley Yao 		for (i = 0; i < max_bank; i++)
139f9a1c31dSWesley Yao 			if (length[i])
140f9a1c31dSWesley Yao 				printf("	0x%08lx - 0x%08lx 0x%08lx\n",
141f9a1c31dSWesley Yao 				       start_adr[i], start_adr[i] + length[i],
142f9a1c31dSWesley Yao 				       length[i]);
143f9a1c31dSWesley Yao 	}
144f9a1c31dSWesley Yao }
145f9a1c31dSWesley Yao 
146f9a1c31dSWesley Yao /*
147f9a1c31dSWesley Yao  * judge if testing address is available
148f9a1c31dSWesley Yao  * arg[0]:start addr, arg[1]:length, return test banks number
149f9a1c31dSWesley Yao  */
judge_test_addr(ulong * arg,ulong * start_adr,ulong * length)150f9a1c31dSWesley Yao int judge_test_addr(ulong *arg, ulong *start_adr, ulong *length)
151f9a1c31dSWesley Yao {
152f9a1c31dSWesley Yao 	u32 i, max_bank = 0;
153f9a1c31dSWesley Yao 	u32 available = 0;
154f9a1c31dSWesley Yao 
155f9a1c31dSWesley Yao 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
156f9a1c31dSWesley Yao 		if (start_adr[i])
157f9a1c31dSWesley Yao 			max_bank = i + 1;
158f9a1c31dSWesley Yao 
159f9a1c31dSWesley Yao 	if (!arg[1])
160f9a1c31dSWesley Yao 		return max_bank;
161f9a1c31dSWesley Yao 
162f9a1c31dSWesley Yao 	for (i = 0; i < max_bank; i++)
163f9a1c31dSWesley Yao 		if (arg[0] >= start_adr[i] &&
164f9a1c31dSWesley Yao 		    arg[0] + arg[1] <= start_adr[i] + length[i])
165f9a1c31dSWesley Yao 			available |= 1;
166f9a1c31dSWesley Yao 	if (!available) {
167f9a1c31dSWesley Yao 		printf("Invalid test address\n");
168f9a1c31dSWesley Yao 	} else {
169f9a1c31dSWesley Yao 		start_adr[0] = arg[0];
170f9a1c31dSWesley Yao 		length[0] = arg[1];
171f9a1c31dSWesley Yao 		for (i = 1; i < max_bank; i++) {
172f9a1c31dSWesley Yao 			start_adr[i] = 0;
173f9a1c31dSWesley Yao 			length[i] = 0;
174f9a1c31dSWesley Yao 		}
175f9a1c31dSWesley Yao 	}
176f9a1c31dSWesley Yao 
177f9a1c31dSWesley Yao 	return available;
178f9a1c31dSWesley Yao }
179f9a1c31dSWesley Yao 
set_vdd_logic(u32 uv)180f9a1c31dSWesley Yao int set_vdd_logic(u32 uv)
181f9a1c31dSWesley Yao {
182f9a1c31dSWesley Yao 	struct udevice *dev;
183f9a1c31dSWesley Yao 	int ret;
184f9a1c31dSWesley Yao 
185f9a1c31dSWesley Yao 	ret = regulator_get_by_platname("vdd_logic", &dev);
186f9a1c31dSWesley Yao 	if (ret) {
187f9a1c31dSWesley Yao 		printf("Cannot set regulator name\n");
188f9a1c31dSWesley Yao 		return ret;
189f9a1c31dSWesley Yao 	}
190f9a1c31dSWesley Yao 
191f9a1c31dSWesley Yao 	/* Slowly raise to max CPU voltage to prevent overshoot */
192f9a1c31dSWesley Yao 	ret = regulator_set_value(dev, uv);
193f9a1c31dSWesley Yao 	udelay(100); /* Must wait for voltage to stabilize, 2mV/us */
194f9a1c31dSWesley Yao 	if (ret)
195f9a1c31dSWesley Yao 		printf("set vdd_logic fail\n");
196f9a1c31dSWesley Yao 	return ret;
197f9a1c31dSWesley Yao }
198f9a1c31dSWesley Yao 
199