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