xref: /rk3399_rockchip-uboot/cmd/ddr_tool/ddr_tool_common.c (revision f9a1c31d51021ad79fb5d72e074600eeeeee80f8)
1*f9a1c31dSWesley Yao // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2*f9a1c31dSWesley Yao /*
3*f9a1c31dSWesley Yao  * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
4*f9a1c31dSWesley Yao  */
5*f9a1c31dSWesley Yao 
6*f9a1c31dSWesley Yao #include <common.h>
7*f9a1c31dSWesley Yao #include <power/regulator.h>
8*f9a1c31dSWesley Yao #include "ddr_tool_common.h"
9*f9a1c31dSWesley Yao 
10*f9a1c31dSWesley Yao DECLARE_GLOBAL_DATA_PTR;
11*f9a1c31dSWesley Yao 
12*f9a1c31dSWesley Yao void write_buf_to_ddr(u32 *buf, u32 buf_len, ulong start_adr, ulong length)
13*f9a1c31dSWesley Yao {
14*f9a1c31dSWesley Yao 	ulong *buful = (ulong *)buf;
15*f9a1c31dSWesley Yao 	ulong *p = (ulong *)start_adr;
16*f9a1c31dSWesley Yao 	u32 i, j;
17*f9a1c31dSWesley Yao 
18*f9a1c31dSWesley Yao 	buf_len = buf_len / sizeof(ulong) - 1;
19*f9a1c31dSWesley Yao 
20*f9a1c31dSWesley Yao 	for (i = 0, j = 0; i < length / sizeof(p[0]); i++) {
21*f9a1c31dSWesley Yao 		p[i] = buful[j];
22*f9a1c31dSWesley Yao 		j++;
23*f9a1c31dSWesley Yao 		j &= buf_len;
24*f9a1c31dSWesley Yao 	}
25*f9a1c31dSWesley Yao }
26*f9a1c31dSWesley Yao 
27*f9a1c31dSWesley Yao ulong cmp_buf_data(u32 *buf, u32 buf_len, ulong start_adr, ulong length,
28*f9a1c31dSWesley Yao 		   u32 prt_en)
29*f9a1c31dSWesley Yao {
30*f9a1c31dSWesley Yao 	ulong *buful = (ulong *)buf;
31*f9a1c31dSWesley Yao 	volatile unsigned long *p = (volatile unsigned long *)start_adr;
32*f9a1c31dSWesley Yao 	u32 i, j;
33*f9a1c31dSWesley Yao 	ulong reread = 0;
34*f9a1c31dSWesley Yao 	ulong wr_val = 0;
35*f9a1c31dSWesley Yao 	ulong val = 0;
36*f9a1c31dSWesley Yao 	ulong err_adr = 0;
37*f9a1c31dSWesley Yao 
38*f9a1c31dSWesley Yao 	buf_len = buf_len / sizeof(ulong) - 1;
39*f9a1c31dSWesley Yao 	err_adr = 0;
40*f9a1c31dSWesley Yao 	for (i = 0, j = 0; i < length / sizeof(p[0]); i++) {
41*f9a1c31dSWesley Yao 		val = p[i];
42*f9a1c31dSWesley Yao 		if (val != buful[j]) {
43*f9a1c31dSWesley Yao 			flush_dcache_range((ulong)&p[i],
44*f9a1c31dSWesley Yao 					   (ulong)&p[i] + sizeof(u32));
45*f9a1c31dSWesley Yao 			reread = p[i];
46*f9a1c31dSWesley Yao 			err_adr = (ulong)&p[i];
47*f9a1c31dSWesley Yao 			wr_val = buful[j];
48*f9a1c31dSWesley Yao 			break;
49*f9a1c31dSWesley Yao 		}
50*f9a1c31dSWesley Yao 		j++;
51*f9a1c31dSWesley Yao 		j &= buf_len;
52*f9a1c31dSWesley Yao 	}
53*f9a1c31dSWesley Yao 	if (err_adr && prt_en)
54*f9a1c31dSWesley Yao 		printf("test fail:address:0x%lx,read:0x%lx,"
55*f9a1c31dSWesley Yao 		       "reread:0x%lx,expect:0x%lx\n",
56*f9a1c31dSWesley Yao 		       err_adr, val, reread, wr_val);
57*f9a1c31dSWesley Yao 
58*f9a1c31dSWesley Yao 	return err_adr;
59*f9a1c31dSWesley Yao }
60*f9a1c31dSWesley Yao 
61*f9a1c31dSWesley Yao void print_memory(void *addr, ulong size)
62*f9a1c31dSWesley Yao {
63*f9a1c31dSWesley Yao 	u32 *p = addr;
64*f9a1c31dSWesley Yao 	u32 i;
65*f9a1c31dSWesley Yao 
66*f9a1c31dSWesley Yao 	for (i = 0; i < size / 4; i += 4) {
67*f9a1c31dSWesley Yao 		printf("0x%08lx: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
68*f9a1c31dSWesley Yao 		       (ulong)&p[i], p[i], p[i + 1], p[i + 2], p[i + 3]);
69*f9a1c31dSWesley Yao 	}
70*f9a1c31dSWesley Yao }
71*f9a1c31dSWesley Yao 
72*f9a1c31dSWesley Yao /* print available address for ddr testing in uboot */
73*f9a1c31dSWesley Yao void get_print_available_addr(ulong *start_adr, ulong *length, int print_en)
74*f9a1c31dSWesley Yao {
75*f9a1c31dSWesley Yao 	u32 i, max_bank = 0;
76*f9a1c31dSWesley Yao 
77*f9a1c31dSWesley Yao 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
78*f9a1c31dSWesley Yao 		if (gd->bd->bi_dram[i].start)
79*f9a1c31dSWesley Yao 			max_bank = i + 1;
80*f9a1c31dSWesley Yao 		start_adr[i] = 0;
81*f9a1c31dSWesley Yao 		length[i] = 0;
82*f9a1c31dSWesley Yao 	}
83*f9a1c31dSWesley Yao 
84*f9a1c31dSWesley Yao 	for (i = 0; i < max_bank; i++) {
85*f9a1c31dSWesley Yao 		start_adr[i] = gd->bd->bi_dram[i].start;
86*f9a1c31dSWesley Yao 		length[i] = gd->bd->bi_dram[i].size;
87*f9a1c31dSWesley Yao 	}
88*f9a1c31dSWesley Yao 
89*f9a1c31dSWesley Yao 	length[max_bank - 1] = (gd->start_addr_sp - RESERVED_SP_SIZE -
90*f9a1c31dSWesley Yao 			start_adr[max_bank - 1]) & ~0xfff;
91*f9a1c31dSWesley Yao 	if (print_en) {
92*f9a1c31dSWesley Yao 		printf("available memory for test:\n");
93*f9a1c31dSWesley Yao 		printf("	start		 end	length\n");
94*f9a1c31dSWesley Yao 		for (i = 0; i < max_bank; i++)
95*f9a1c31dSWesley Yao 			if (length[i])
96*f9a1c31dSWesley Yao 				printf("	0x%08lx - 0x%08lx 0x%08lx\n",
97*f9a1c31dSWesley Yao 				       start_adr[i], start_adr[i] + length[i],
98*f9a1c31dSWesley Yao 				       length[i]);
99*f9a1c31dSWesley Yao 	}
100*f9a1c31dSWesley Yao }
101*f9a1c31dSWesley Yao 
102*f9a1c31dSWesley Yao /*
103*f9a1c31dSWesley Yao  * judge if testing address is available
104*f9a1c31dSWesley Yao  * arg[0]:start addr, arg[1]:length, return test banks number
105*f9a1c31dSWesley Yao  */
106*f9a1c31dSWesley Yao int judge_test_addr(ulong *arg, ulong *start_adr, ulong *length)
107*f9a1c31dSWesley Yao {
108*f9a1c31dSWesley Yao 	u32 i, max_bank = 0;
109*f9a1c31dSWesley Yao 	u32 available = 0;
110*f9a1c31dSWesley Yao 
111*f9a1c31dSWesley Yao 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
112*f9a1c31dSWesley Yao 		if (start_adr[i])
113*f9a1c31dSWesley Yao 			max_bank = i + 1;
114*f9a1c31dSWesley Yao 
115*f9a1c31dSWesley Yao 	if (!arg[1])
116*f9a1c31dSWesley Yao 		return max_bank;
117*f9a1c31dSWesley Yao 
118*f9a1c31dSWesley Yao 	for (i = 0; i < max_bank; i++)
119*f9a1c31dSWesley Yao 		if (arg[0] >= start_adr[i] &&
120*f9a1c31dSWesley Yao 		    arg[0] + arg[1] <= start_adr[i] + length[i])
121*f9a1c31dSWesley Yao 			available |= 1;
122*f9a1c31dSWesley Yao 	if (!available) {
123*f9a1c31dSWesley Yao 		printf("Invalid test address\n");
124*f9a1c31dSWesley Yao 	} else {
125*f9a1c31dSWesley Yao 		start_adr[0] = arg[0];
126*f9a1c31dSWesley Yao 		length[0] = arg[1];
127*f9a1c31dSWesley Yao 		for (i = 1; i < max_bank; i++) {
128*f9a1c31dSWesley Yao 			start_adr[i] = 0;
129*f9a1c31dSWesley Yao 			length[i] = 0;
130*f9a1c31dSWesley Yao 		}
131*f9a1c31dSWesley Yao 	}
132*f9a1c31dSWesley Yao 
133*f9a1c31dSWesley Yao 	return available;
134*f9a1c31dSWesley Yao }
135*f9a1c31dSWesley Yao 
136*f9a1c31dSWesley Yao int set_vdd_logic(u32 uv)
137*f9a1c31dSWesley Yao {
138*f9a1c31dSWesley Yao 	struct udevice *dev;
139*f9a1c31dSWesley Yao 	int ret;
140*f9a1c31dSWesley Yao 
141*f9a1c31dSWesley Yao 	ret = regulator_get_by_platname("vdd_logic", &dev);
142*f9a1c31dSWesley Yao 	if (ret) {
143*f9a1c31dSWesley Yao 		printf("Cannot set regulator name\n");
144*f9a1c31dSWesley Yao 		return ret;
145*f9a1c31dSWesley Yao 	}
146*f9a1c31dSWesley Yao 
147*f9a1c31dSWesley Yao 	/* Slowly raise to max CPU voltage to prevent overshoot */
148*f9a1c31dSWesley Yao 	ret = regulator_set_value(dev, uv);
149*f9a1c31dSWesley Yao 	udelay(100); /* Must wait for voltage to stabilize, 2mV/us */
150*f9a1c31dSWesley Yao 	if (ret)
151*f9a1c31dSWesley Yao 		printf("set vdd_logic fail\n");
152*f9a1c31dSWesley Yao 	return ret;
153*f9a1c31dSWesley Yao }
154*f9a1c31dSWesley Yao 
155