251 lines
5.0 KiB
C
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"
|
||
|
|
);
|