// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #include #include #include #include #include "memcpy_fast.h" #ifdef CONFIG_ARMV8_MULTIENTRY #include #endif #include #include #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 [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" );