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