Merge pull request #575 from antmicro/jboc/memtest
Move memtest from liblitedram to libbase
This commit is contained in:
commit
00d1118d41
|
@ -216,16 +216,6 @@ define_command(sdrwloff, sdrwloff, "Disable write leveling", LITEDRAM_CMDS);
|
||||||
define_command(sdrlevel, sdrlevel, "Perform read/write leveling", LITEDRAM_CMDS);
|
define_command(sdrlevel, sdrlevel, "Perform read/write leveling", LITEDRAM_CMDS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* Command "memtest"
|
|
||||||
*
|
|
||||||
* Run a memory test
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifdef CSR_SDRAM_BASE
|
|
||||||
define_command(memtest, memtest, "Run a memory test", LITEDRAM_CMDS);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command "spdread"
|
* Command "spdread"
|
||||||
*
|
*
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <memtest.h>
|
||||||
|
|
||||||
#include <generated/csr.h>
|
#include <generated/csr.h>
|
||||||
|
|
||||||
|
@ -137,3 +138,175 @@ static void mc(int nb_params, char **params)
|
||||||
}
|
}
|
||||||
|
|
||||||
define_command(mc, mc, "Copy address space", MEM_CMDS);
|
define_command(mc, mc, "Copy address space", MEM_CMDS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command "memtest"
|
||||||
|
*
|
||||||
|
* Run a memory test
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void memtest_handler(int nb_params, char **params)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
unsigned int *addr;
|
||||||
|
unsigned long maxsize = ~0uL;
|
||||||
|
|
||||||
|
if (nb_params < 1) {
|
||||||
|
printf("memtest <addr> [<maxsize>]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (unsigned int *)strtoul(params[0], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb_params >= 2) {
|
||||||
|
maxsize = strtoul(params[1], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect max size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memtest(addr, maxsize);
|
||||||
|
}
|
||||||
|
define_command(memtest, memtest_handler, "Run a memory test", MEM_CMDS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command "memspeed"
|
||||||
|
*
|
||||||
|
* Run a memory speed test
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void memspeed_handler(int nb_params, char **params)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
unsigned int *addr;
|
||||||
|
unsigned long size;
|
||||||
|
bool read_only = false;
|
||||||
|
|
||||||
|
if (nb_params < 1) {
|
||||||
|
printf("memspeed <addr> <size> [<readonly>]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (unsigned int *)strtoul(params[0], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = strtoul(params[1], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb_params >= 3) {
|
||||||
|
read_only = (bool) strtoul(params[2], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect readonly value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memspeed(addr, size, read_only);
|
||||||
|
}
|
||||||
|
define_command(memspeed, memspeed_handler, "Run a memory speed test", MEM_CMDS);
|
||||||
|
|
||||||
|
#ifdef CSR_DEBUG_PRINTER
|
||||||
|
/**
|
||||||
|
* Command "csrprint"
|
||||||
|
*
|
||||||
|
* Print CSR values
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void csrprint(int nb_params, char **params)
|
||||||
|
{
|
||||||
|
print_csrs();
|
||||||
|
}
|
||||||
|
define_command(csrprint, csrprint, "Print CSR values", MEM_CMDS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CSR_WB_SOFTCONTROL_BASE
|
||||||
|
static void wbr(int nb_params, char **params)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
unsigned int *addr;
|
||||||
|
unsigned int length;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (nb_params < 1) {
|
||||||
|
printf("mr <address> [length]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addr = (unsigned int *)strtoul(params[0], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (nb_params == 1) {
|
||||||
|
length = 4;
|
||||||
|
} else {
|
||||||
|
length = strtoul(params[1], &c, 0);
|
||||||
|
if(*c != 0) {
|
||||||
|
printf("\nIncorrect length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
wb_softcontrol_adr_write((unsigned long)(addr + i));
|
||||||
|
wb_softcontrol_read_write(1);
|
||||||
|
printf("0x%08x: 0x%08x\n", (unsigned long)(addr + i), wb_softcontrol_data_read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
define_command(wbr, wbr, "Read using softcontrol wishbone controller", MEM_CMDS);
|
||||||
|
|
||||||
|
static void wbw(int nb_params, char **params)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
unsigned int *addr;
|
||||||
|
unsigned int value;
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (nb_params < 2) {
|
||||||
|
printf("mw <address> <value> [count]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (unsigned int *)strtoul(params[0], &c, 0);
|
||||||
|
if (*c != 0) {
|
||||||
|
printf("Incorrect address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = strtoul(params[1], &c, 0);
|
||||||
|
if(*c != 0) {
|
||||||
|
printf("Incorrect value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb_params == 2) {
|
||||||
|
count = 1;
|
||||||
|
} else {
|
||||||
|
count = strtoul(params[2], &c, 0);
|
||||||
|
if(*c != 0) {
|
||||||
|
printf("Incorrect count");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wb_softcontrol_data_write(value);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
wb_softcontrol_adr_write((unsigned long)(addr + i));
|
||||||
|
wb_softcontrol_write_write(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
define_command(wbw, wbw, "Write using softcontrol wishbone controller", MEM_CMDS);
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef __MEMTEST_H
|
||||||
|
#define __MEMTEST_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
int memtest(unsigned int *addr, unsigned long maxsize);
|
||||||
|
void memspeed(unsigned int *addr, unsigned long size, bool read_only);
|
||||||
|
|
||||||
|
int memtest_addr(unsigned int *addr, unsigned long size, int random);
|
||||||
|
int memtest_data(unsigned int *addr, unsigned long size, int random);
|
||||||
|
int memtest_bus(unsigned int *addr, unsigned long size);
|
||||||
|
|
||||||
|
#endif /* __MEMTEST_H */
|
|
@ -17,7 +17,8 @@ OBJECTS = exception.o \
|
||||||
strcasecmp.o \
|
strcasecmp.o \
|
||||||
i2c.o \
|
i2c.o \
|
||||||
div64.o \
|
div64.o \
|
||||||
progress.o
|
progress.o \
|
||||||
|
memtest.o
|
||||||
|
|
||||||
all: crt0.o libbase.a libbase-nofloat.a
|
all: crt0.o libbase.a libbase-nofloat.a
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
#include "memtest.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <lfsr.h>
|
||||||
|
|
||||||
|
#include <system.h>
|
||||||
|
#include <generated/soc.h>
|
||||||
|
#include <generated/csr.h>
|
||||||
|
|
||||||
|
// #define MEMTEST_BUS_DEBUG
|
||||||
|
// #define MEMTEST_DATA_DEBUG
|
||||||
|
// #define MEMTEST_ADDR_DEBUG
|
||||||
|
|
||||||
|
#ifndef MEMTEST_BUS_SIZE
|
||||||
|
#define MEMTEST_BUS_SIZE (512)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MEMTEST_DATA_SIZE
|
||||||
|
#define MEMTEST_DATA_SIZE (2*1024*1024)
|
||||||
|
#endif
|
||||||
|
#define MEMTEST_DATA_RANDOM 1
|
||||||
|
|
||||||
|
#ifndef MEMTEST_ADDR_SIZE
|
||||||
|
#define MEMTEST_ADDR_SIZE (32*1024)
|
||||||
|
#endif
|
||||||
|
#define MEMTEST_ADDR_RANDOM 0
|
||||||
|
|
||||||
|
#define ONEZERO 0xAAAAAAAA
|
||||||
|
#define ZEROONE 0x55555555
|
||||||
|
|
||||||
|
static unsigned int seed_to_data_32(unsigned int seed, int random)
|
||||||
|
{
|
||||||
|
return random ? lfsr(32, seed) : seed + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short seed_to_data_16(unsigned short seed, int random)
|
||||||
|
{
|
||||||
|
return random ? lfsr(16, seed) : seed + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memtest_bus(unsigned int *addr, unsigned long size)
|
||||||
|
{
|
||||||
|
volatile unsigned int *array = addr;
|
||||||
|
int i, errors;
|
||||||
|
unsigned int rdata;
|
||||||
|
|
||||||
|
errors = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < size/4;i++) {
|
||||||
|
array[i] = ONEZERO;
|
||||||
|
}
|
||||||
|
flush_cpu_dcache();
|
||||||
|
#ifdef CONFIG_L2_SIZE
|
||||||
|
flush_l2_cache();
|
||||||
|
#endif
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
rdata = array[i];
|
||||||
|
if(rdata != ONEZERO) {
|
||||||
|
errors++;
|
||||||
|
#ifdef MEMTEST_BUS_DEBUG
|
||||||
|
printf("[bus: 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ONEZERO);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
array[i] = ZEROONE;
|
||||||
|
}
|
||||||
|
flush_cpu_dcache();
|
||||||
|
#ifdef CONFIG_L2_SIZE
|
||||||
|
flush_l2_cache();
|
||||||
|
#endif
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
rdata = array[i];
|
||||||
|
if(rdata != ZEROONE) {
|
||||||
|
errors++;
|
||||||
|
#ifdef MEMTEST_BUS_DEBUG
|
||||||
|
printf("[bus 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ZEROONE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memtest_data(unsigned int *addr, unsigned long size, int random)
|
||||||
|
{
|
||||||
|
volatile unsigned int *array = addr;
|
||||||
|
int i, errors;
|
||||||
|
unsigned int seed_32;
|
||||||
|
unsigned int rdata;
|
||||||
|
|
||||||
|
errors = 0;
|
||||||
|
seed_32 = 1;
|
||||||
|
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
seed_32 = seed_to_data_32(seed_32, random);
|
||||||
|
array[i] = seed_32;
|
||||||
|
}
|
||||||
|
|
||||||
|
seed_32 = 1;
|
||||||
|
flush_cpu_dcache();
|
||||||
|
#ifdef CONFIG_L2_SIZE
|
||||||
|
flush_l2_cache();
|
||||||
|
#endif
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
seed_32 = seed_to_data_32(seed_32, random);
|
||||||
|
rdata = array[i];
|
||||||
|
if(rdata != seed_32) {
|
||||||
|
errors++;
|
||||||
|
#ifdef MEMTEST_DATA_DEBUG
|
||||||
|
printf("[data 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, seed_32);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memtest_addr(unsigned int *addr, unsigned long size, int random)
|
||||||
|
{
|
||||||
|
volatile unsigned int *array = addr;
|
||||||
|
int i, errors;
|
||||||
|
unsigned short seed_16;
|
||||||
|
unsigned short rdata;
|
||||||
|
|
||||||
|
errors = 0;
|
||||||
|
seed_16 = 1;
|
||||||
|
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
seed_16 = seed_to_data_16(seed_16, random);
|
||||||
|
array[(unsigned int) seed_16] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
seed_16 = 1;
|
||||||
|
flush_cpu_dcache();
|
||||||
|
#ifdef CONFIG_L2_SIZE
|
||||||
|
flush_l2_cache();
|
||||||
|
#endif
|
||||||
|
for(i = 0; i < size/4; i++) {
|
||||||
|
seed_16 = seed_to_data_16(seed_16, random);
|
||||||
|
rdata = array[(unsigned int) seed_16];
|
||||||
|
if(rdata != i) {
|
||||||
|
errors++;
|
||||||
|
#ifdef MEMTEST_ADDR_DEBUG
|
||||||
|
printf("[addr 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, i);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memspeed(unsigned int *addr, unsigned long size, bool read_only)
|
||||||
|
{
|
||||||
|
volatile unsigned int *array = addr;
|
||||||
|
int i;
|
||||||
|
unsigned int start, end;
|
||||||
|
unsigned long write_speed = 0;
|
||||||
|
unsigned long read_speed;
|
||||||
|
__attribute__((unused)) unsigned long data;
|
||||||
|
const unsigned int sz = sizeof(unsigned long);
|
||||||
|
|
||||||
|
/* init timer */
|
||||||
|
timer0_en_write(0);
|
||||||
|
timer0_reload_write(0);
|
||||||
|
timer0_load_write(0xffffffff);
|
||||||
|
timer0_en_write(1);
|
||||||
|
|
||||||
|
/* write speed */
|
||||||
|
if (!read_only) {
|
||||||
|
timer0_update_value_write(1);
|
||||||
|
start = timer0_value_read();
|
||||||
|
for(i = 0; i < size/sz; i++) {
|
||||||
|
array[i] = i;
|
||||||
|
}
|
||||||
|
timer0_update_value_write(1);
|
||||||
|
end = timer0_value_read();
|
||||||
|
write_speed = (8*size*(CONFIG_CLOCK_FREQUENCY/1000000))/(start - end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* flush CPU and L2 caches */
|
||||||
|
flush_cpu_dcache();
|
||||||
|
#ifdef CONFIG_L2_SIZE
|
||||||
|
flush_l2_cache();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* read speed */
|
||||||
|
timer0_en_write(1);
|
||||||
|
timer0_update_value_write(1);
|
||||||
|
start = timer0_value_read();
|
||||||
|
for(i = 0; i < size/sz; i++) {
|
||||||
|
data = array[i];
|
||||||
|
}
|
||||||
|
timer0_update_value_write(1);
|
||||||
|
end = timer0_value_read();
|
||||||
|
read_speed = (8*size*(CONFIG_CLOCK_FREQUENCY/1000000))/(start - end);
|
||||||
|
|
||||||
|
printf("Memspeed Writes: %ldMbps Reads: %ldMbps\n", write_speed, read_speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int memtest(unsigned int *addr, unsigned long maxsize)
|
||||||
|
{
|
||||||
|
int bus_errors, data_errors, addr_errors;
|
||||||
|
unsigned long bus_size = MEMTEST_BUS_SIZE < maxsize ? MEMTEST_BUS_SIZE : maxsize;
|
||||||
|
unsigned long data_size = MEMTEST_DATA_SIZE < maxsize ? MEMTEST_DATA_SIZE : maxsize;
|
||||||
|
unsigned long addr_size = MEMTEST_ADDR_SIZE < maxsize ? MEMTEST_ADDR_SIZE : maxsize;
|
||||||
|
|
||||||
|
bus_errors = memtest_bus(addr, bus_size);
|
||||||
|
if(bus_errors != 0)
|
||||||
|
printf("Memtest bus failed: %d/%d errors\n", bus_errors, bus_size/4);
|
||||||
|
|
||||||
|
data_errors = memtest_data(addr, data_size, MEMTEST_DATA_RANDOM);
|
||||||
|
if(data_errors != 0)
|
||||||
|
printf("Memtest data failed: %d/%d errors\n", data_errors, data_size/4);
|
||||||
|
|
||||||
|
addr_errors = memtest_addr(addr, addr_size, MEMTEST_ADDR_RANDOM);
|
||||||
|
if(addr_errors != 0)
|
||||||
|
printf("Memtest addr failed: %d/%d errors\n", addr_errors, addr_size/4);
|
||||||
|
|
||||||
|
if(bus_errors + data_errors + addr_errors != 0)
|
||||||
|
return 0;
|
||||||
|
else {
|
||||||
|
printf("Memtest OK\n");
|
||||||
|
memspeed(addr, data_size, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <memtest.h>
|
||||||
|
#include <lfsr.h>
|
||||||
|
|
||||||
#ifdef CSR_SDRAM_BASE
|
#ifdef CSR_SDRAM_BASE
|
||||||
#include <generated/sdram_phy.h>
|
#include <generated/sdram_phy.h>
|
||||||
|
@ -20,12 +22,14 @@
|
||||||
#include <system.h>
|
#include <system.h>
|
||||||
|
|
||||||
#include "sdram.h"
|
#include "sdram.h"
|
||||||
#include "lfsr.h"
|
|
||||||
|
|
||||||
// FIXME(hack): If we don't have main ram, just target the sram instead.
|
// FIXME(hack): If we don't have main ram, just target the sram instead.
|
||||||
#ifndef MAIN_RAM_BASE
|
#ifndef MAIN_RAM_BASE
|
||||||
#define MAIN_RAM_BASE SRAM_BASE
|
#define MAIN_RAM_BASE SRAM_BASE
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MAIN_RAM_SIZE
|
||||||
|
#define MAIN_RAM_SIZE SRAM_SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
__attribute__((unused)) static void cdelay(int i)
|
__attribute__((unused)) static void cdelay(int i)
|
||||||
{
|
{
|
||||||
|
@ -725,227 +729,8 @@ static void read_level(int module)
|
||||||
|
|
||||||
#endif /* CSR_SDRAM_BASE */
|
#endif /* CSR_SDRAM_BASE */
|
||||||
|
|
||||||
static unsigned int seed_to_data_32(unsigned int seed, int random)
|
|
||||||
{
|
|
||||||
if (random)
|
|
||||||
return lfsr(32, seed);
|
|
||||||
else
|
|
||||||
return seed + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned short seed_to_data_16(unsigned short seed, int random)
|
|
||||||
{
|
|
||||||
if (random)
|
|
||||||
return lfsr(16, seed);
|
|
||||||
else
|
|
||||||
return seed + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ONEZERO 0xAAAAAAAA
|
|
||||||
#define ZEROONE 0x55555555
|
|
||||||
|
|
||||||
#ifndef MEMTEST_BUS_SIZE
|
|
||||||
#define MEMTEST_BUS_SIZE (512)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define MEMTEST_BUS_DEBUG
|
|
||||||
|
|
||||||
static int memtest_bus(void)
|
|
||||||
{
|
|
||||||
volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
|
|
||||||
int i, errors;
|
|
||||||
unsigned int rdata;
|
|
||||||
|
|
||||||
errors = 0;
|
|
||||||
|
|
||||||
for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
|
|
||||||
array[i] = ONEZERO;
|
|
||||||
}
|
|
||||||
flush_cpu_dcache();
|
|
||||||
#ifdef CONFIG_L2_SIZE
|
|
||||||
flush_l2_cache();
|
|
||||||
#endif
|
|
||||||
for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
|
|
||||||
rdata = array[i];
|
|
||||||
if(rdata != ONEZERO) {
|
|
||||||
errors++;
|
|
||||||
#ifdef MEMTEST_BUS_DEBUG
|
|
||||||
printf("[bus: 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ONEZERO);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
|
|
||||||
array[i] = ZEROONE;
|
|
||||||
}
|
|
||||||
flush_cpu_dcache();
|
|
||||||
#ifdef CONFIG_L2_SIZE
|
|
||||||
flush_l2_cache();
|
|
||||||
#endif
|
|
||||||
for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
|
|
||||||
rdata = array[i];
|
|
||||||
if(rdata != ZEROONE) {
|
|
||||||
errors++;
|
|
||||||
#ifdef MEMTEST_BUS_DEBUG
|
|
||||||
printf("[bus 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ZEROONE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MEMTEST_DATA_SIZE
|
|
||||||
#define MEMTEST_DATA_SIZE (2*1024*1024)
|
|
||||||
#endif
|
|
||||||
#define MEMTEST_DATA_RANDOM 1
|
|
||||||
|
|
||||||
//#define MEMTEST_DATA_DEBUG
|
|
||||||
|
|
||||||
static int memtest_data(void)
|
|
||||||
{
|
|
||||||
volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
|
|
||||||
int i, errors;
|
|
||||||
unsigned int seed_32;
|
|
||||||
unsigned int rdata;
|
|
||||||
|
|
||||||
errors = 0;
|
|
||||||
seed_32 = 1;
|
|
||||||
|
|
||||||
for(i=0;i<MEMTEST_DATA_SIZE/4;i++) {
|
|
||||||
seed_32 = seed_to_data_32(seed_32, MEMTEST_DATA_RANDOM);
|
|
||||||
array[i] = seed_32;
|
|
||||||
}
|
|
||||||
|
|
||||||
seed_32 = 1;
|
|
||||||
flush_cpu_dcache();
|
|
||||||
#ifdef CONFIG_L2_SIZE
|
|
||||||
flush_l2_cache();
|
|
||||||
#endif
|
|
||||||
for(i=0;i<MEMTEST_DATA_SIZE/4;i++) {
|
|
||||||
seed_32 = seed_to_data_32(seed_32, MEMTEST_DATA_RANDOM);
|
|
||||||
rdata = array[i];
|
|
||||||
if(rdata != seed_32) {
|
|
||||||
errors++;
|
|
||||||
#ifdef MEMTEST_DATA_DEBUG
|
|
||||||
printf("[data 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, seed_32);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
#ifndef MEMTEST_ADDR_SIZE
|
|
||||||
#define MEMTEST_ADDR_SIZE (32*1024)
|
|
||||||
#endif
|
|
||||||
#define MEMTEST_ADDR_RANDOM 0
|
|
||||||
|
|
||||||
//#define MEMTEST_ADDR_DEBUG
|
|
||||||
|
|
||||||
static int memtest_addr(void)
|
|
||||||
{
|
|
||||||
volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
|
|
||||||
int i, errors;
|
|
||||||
unsigned short seed_16;
|
|
||||||
unsigned short rdata;
|
|
||||||
|
|
||||||
errors = 0;
|
|
||||||
seed_16 = 1;
|
|
||||||
|
|
||||||
for(i=0;i<MEMTEST_ADDR_SIZE/4;i++) {
|
|
||||||
seed_16 = seed_to_data_16(seed_16, MEMTEST_ADDR_RANDOM);
|
|
||||||
array[(unsigned int) seed_16] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
seed_16 = 1;
|
|
||||||
flush_cpu_dcache();
|
|
||||||
#ifdef CONFIG_L2_SIZE
|
|
||||||
flush_l2_cache();
|
|
||||||
#endif
|
|
||||||
for(i=0;i<MEMTEST_ADDR_SIZE/4;i++) {
|
|
||||||
seed_16 = seed_to_data_16(seed_16, MEMTEST_ADDR_RANDOM);
|
|
||||||
rdata = array[(unsigned int) seed_16];
|
|
||||||
if(rdata != i) {
|
|
||||||
errors++;
|
|
||||||
#ifdef MEMTEST_ADDR_DEBUG
|
|
||||||
printf("[addr 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void memspeed(void)
|
|
||||||
{
|
|
||||||
volatile unsigned long *array = (unsigned long *)MAIN_RAM_BASE;
|
|
||||||
int i;
|
|
||||||
unsigned int start, end;
|
|
||||||
unsigned long write_speed;
|
|
||||||
unsigned long read_speed;
|
|
||||||
__attribute__((unused)) unsigned long data;
|
|
||||||
const unsigned int sz = sizeof(unsigned long);
|
|
||||||
|
|
||||||
/* init timer */
|
|
||||||
timer0_en_write(0);
|
|
||||||
timer0_reload_write(0);
|
|
||||||
timer0_load_write(0xffffffff);
|
|
||||||
timer0_en_write(1);
|
|
||||||
|
|
||||||
/* write speed */
|
|
||||||
timer0_update_value_write(1);
|
|
||||||
start = timer0_value_read();
|
|
||||||
for(i=0;i<MEMTEST_DATA_SIZE/sz;i++) {
|
|
||||||
array[i] = i;
|
|
||||||
}
|
|
||||||
timer0_update_value_write(1);
|
|
||||||
end = timer0_value_read();
|
|
||||||
write_speed = (8*MEMTEST_DATA_SIZE*(CONFIG_CLOCK_FREQUENCY/1000000))/(start - end);
|
|
||||||
|
|
||||||
/* flush CPU and L2 caches */
|
|
||||||
flush_cpu_dcache();
|
|
||||||
#ifdef CONFIG_L2_SIZE
|
|
||||||
flush_l2_cache();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* read speed */
|
|
||||||
timer0_en_write(1);
|
|
||||||
timer0_update_value_write(1);
|
|
||||||
start = timer0_value_read();
|
|
||||||
for(i=0;i<MEMTEST_DATA_SIZE/sz;i++) {
|
|
||||||
data = array[i];
|
|
||||||
}
|
|
||||||
timer0_update_value_write(1);
|
|
||||||
end = timer0_value_read();
|
|
||||||
read_speed = (8*MEMTEST_DATA_SIZE*(CONFIG_CLOCK_FREQUENCY/1000000))/(start - end);
|
|
||||||
|
|
||||||
printf("Memspeed Writes: %ldMbps Reads: %ldMbps\n", write_speed, read_speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
int memtest(void)
|
|
||||||
{
|
|
||||||
int bus_errors, data_errors, addr_errors;
|
|
||||||
|
|
||||||
bus_errors = memtest_bus();
|
|
||||||
if(bus_errors != 0)
|
|
||||||
printf("Memtest bus failed: %d/%d errors\n", bus_errors, 2*128);
|
|
||||||
|
|
||||||
data_errors = memtest_data();
|
|
||||||
if(data_errors != 0)
|
|
||||||
printf("Memtest data failed: %d/%d errors\n", data_errors, MEMTEST_DATA_SIZE/4);
|
|
||||||
|
|
||||||
addr_errors = memtest_addr();
|
|
||||||
if(addr_errors != 0)
|
|
||||||
printf("Memtest addr failed: %d/%d errors\n", addr_errors, MEMTEST_ADDR_SIZE/4);
|
|
||||||
|
|
||||||
if(bus_errors + data_errors + addr_errors != 0)
|
|
||||||
return 0;
|
|
||||||
else {
|
|
||||||
printf("Memtest OK\n");
|
|
||||||
memspeed();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CSR_SDRAM_BASE
|
#ifdef CSR_SDRAM_BASE
|
||||||
|
|
||||||
|
@ -1051,7 +836,7 @@ int sdrinit(void)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
sdrhw();
|
sdrhw();
|
||||||
if(!memtest()) {
|
if(!memtest((unsigned int *) MAIN_RAM_BASE, MAIN_RAM_SIZE)) {
|
||||||
#ifdef CSR_DDRCTRL_BASE
|
#ifdef CSR_DDRCTRL_BASE
|
||||||
ddrctrl_init_done_write(1);
|
ddrctrl_init_done_write(1);
|
||||||
ddrctrl_init_error_write(1);
|
ddrctrl_init_error_write(1);
|
||||||
|
|
|
@ -17,8 +17,6 @@ int write_level(void);
|
||||||
|
|
||||||
int sdrlevel(void);
|
int sdrlevel(void);
|
||||||
|
|
||||||
int memtest_silent(void);
|
|
||||||
int memtest(void);
|
|
||||||
int sdrinit(void);
|
int sdrinit(void);
|
||||||
|
|
||||||
#if defined(DDRPHY_CMD_DELAY) || defined(USDDRPHY_DEBUG)
|
#if defined(DDRPHY_CMD_DELAY) || defined(USDDRPHY_DEBUG)
|
||||||
|
|
Loading…
Reference in New Issue