Files
BPI-CM9-Linux/aml-comp/uboot/bl33/v2019/cmd/amlogic/cmd_memtest.c
T

251 lines
5.0 KiB
C

// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <command.h>
#include <time.h>
#include <stdlib.h>
#include <common.h>
#include "memcpy_fast.h"
#ifdef CONFIG_ARMV8_MULTIENTRY
#include <asm/arch-meson/smp.h>
#endif
#include <linux/delay.h>
#include <vsprintf.h>
#define MAX_RAND_DATA 0x1000
#define SRC_BASE (void *)0x08000000
#define DST_BASE (void *)0x09002000
static unsigned int y = 1U;
static int start;
static unsigned long results[10];
static int sleeping;
static struct test_info {
void *src;
void *dst;
int size;
int id;
int type;
int cpu_nr;
void (*test_func1)(void *src, int size);
void (*test_func2)(void *dst, void *src, int size);
} tis[10];
static inline void clean_invd_dcache_addr(void *addr)
{
__asm__ __volatile__
("dc civac, %0\n"
"dsb sy\n"
:
: "r" (addr)
: "memory"
);
}
static void __attribute__((optimize("O0")))
test(int cpu, char *name, int type, void *func)
{
unsigned long t1, t2;
void *src, *dst;
int size;
unsigned long res;
struct test_info *ti = &tis[cpu];
unsigned long max = 0;
src = ti->src;
dst = ti->dst;
size = ti->size;
#define TEST_TIMES 5
for (int i = 0; i < TEST_TIMES; i++) {
clean_invd_dcache_addr(src);
clean_invd_dcache_addr(dst);
if (cpu == 0) {
for (int i = 0; i < 10; i++)
results[i] = 0;
start = 1;
}
if (cpu != 0)
while (start != 1)
;
if (type == 1) {
t1 = timer_get_us();
((void (*)(void *, int))func)(src, size);
t2 = timer_get_us();
} else {
t1 = timer_get_us();
((void (*)(void *, void *, int))func)(dst, src, size);
t2 = timer_get_us();
}
start = 0;
res = size / (t2 - t1);
//printf("time=%lu v=%lu\n", t1, res);
results[cpu] = res;
if (cpu == 0) {
unsigned long sum = 0;
mdelay(1); //等待slave 完成测试
for (int i = 0; i < 10; i++)
sum += results[i];
if (sum > max)
max = sum;
if (i == TEST_TIMES - 1)
printf("%-20s: sum = %lu\n", name, max);
}
}
}
static unsigned int _rand(unsigned int *seedp)
{
*seedp ^= (*seedp << 13);
*seedp ^= (*seedp >> 17);
*seedp ^= (*seedp << 5);
return *seedp;
}
static void random_number(uint32_t *src, int buf_size, uint32_t addr_mask)
{
for (int j = 0; j < buf_size; j++)
src[j] = _rand(&y) % addr_mask;
}
static void __attribute__((optimize("O0")))
test_randmem_access(char *start_addr, uint32_t rand_num[], int len)
{
uint64_t *paddr;
uint64_t data64 = 0x1122334455667788;
uint32_t offset;
int idx = 0;
for (int i = 0; i < len / 8; i++) {
offset = rand_num[idx++];
paddr = (uint64_t *)(start_addr + ((offset >> 3) << 3));
if (offset & 0x1)
// write
*paddr = data64 + offset;
else
// read
data64 = *paddr;
if (idx >= MAX_RAND_DATA - 1)
idx = 0;
}
}
static void vlsi_test(unsigned long argv)
{
int cpu = (int)argv;
while (1) {
test(cpu, "memcpy", 2, memcpy);
test(cpu, "memcpy_a", 2, memcpy_a);
test(cpu, "memcpy_n", 2, memcpy_n);
test(cpu, "memcpy_pld", 2, memcpy_pld);
test(cpu, "memcpy_pld_512", 2, memcpy_pld_512);
test(cpu, "memwrite", 2, test_memwrite);
test(cpu, "memread", 1, test_memread);
test(cpu, "memread_simple", 1, test_memread_simple);
test(cpu, "memcpy_arm", 2, memcpy_arm);
if (cpu > 0) {
sleeping = 1;
while (sleeping)
;
} else {
break;
}
}
}
static int do_aml_memtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
static uint32_t rand_data[MAX_RAND_DATA];
void *src[10], *dst[10];
int i;
int cpu_nr = 4;
int BUF_SIZE = 0x400000;
unsigned long t1, t2;
if (argc != 4 && argc != 5) {
printf("usage:\n\taml_memtest <cpu_nr> <src> <dst> [bufsize]\n");
printf("example:\n\taml_memtest 0 1000000 2002000 400000\n");
return 0;
}
/* bufsize: optional, default 4MB */
if (argc == 5)
BUF_SIZE = simple_strtol(argv[4], NULL, 16);
cpu_nr = simple_strtol(argv[1], NULL, 16);
src[0] = (void *)simple_strtol(argv[2], NULL, 16);
dst[0] = (void *)simple_strtol(argv[3], NULL, 16);
#ifndef CONFIG_ARMV8_MULTIENTRY
cpu_nr = 1;
#endif
printf("cpu_nr=%d\n", cpu_nr);
for (i = 0; i < cpu_nr; i++) {
src[i] = src[0] + i * (1 << 22);
dst[i] = dst[0] + i * (1 << 22);
tis[i].src = src[i];
tis[i].dst = dst[i];
tis[i].id = i;
tis[i].size = BUF_SIZE;
}
printf("src=%p dst=%p\n", src[0], dst[0]);
printf("########################sp######################\n");
vlsi_test(0);
random_number(rand_data, MAX_RAND_DATA, 0xfffff);
clean_invd_dcache_addr(rand_data);
clean_invd_dcache_addr((void *)src[0]);
t1 = timer_get_us();
test_randmem_access((void *)src[0], rand_data, 0x80000);
t2 = timer_get_us();
printf("%-20s: sum = %lu\n", "test_memrand_access", 0x80000 / (t2 - t1));
#ifdef CONFIG_ARMV8_MULTIENTRY
printf("########################mp######################\n");
for (int i = 1; i < cpu_nr; i++) {
if (sleeping)
sleeping = 0;
else //first time
run_smp_function(i, &vlsi_test, i);
}
vlsi_test(0);
#endif
return 0;
}
U_BOOT_CMD(
aml_memtest, 100, 0, do_aml_memtest,
"aml memory test",
"NULL\n"
" - memtest for bandwidth \\c abcd"
);