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