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
write_buf_to_ddr(u32 * buf,u32 buf_len,ulong start_adr,ulong length)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
cmp_buf_data(u32 * buf,u32 buf_len,ulong start_adr,ulong length,u32 prt_en)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
print_memory(void * addr,ulong size)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 */
get_print_available_addr(ulong * start_adr,ulong * length,int print_en)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 */
judge_test_addr(ulong * arg,ulong * start_adr,ulong * length)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
set_vdd_logic(u32 uv)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