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