// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019 MediaTek Inc. * Author: Sagy Shih */ #include #include #define MEM_TEST_SIZE 0x2000 #define PATTERN1 0x5A5A5A5A #define PATTERN2 0xA5A5A5A5 #if IS_ENABLED(CONFIG_SEC_FACTORY) int mtk_dramc_binning_test_sz(unsigned int len) #else int mtk_dramc_binning_test(void) #endif { unsigned char *mem8_base; unsigned short *mem16_base; unsigned int *mem32_base; unsigned int *mem_base; unsigned long mem_ptr; unsigned char pattern8; unsigned short pattern16; unsigned int i, j, size, pattern32; unsigned int value; #if !IS_ENABLED(CONFIG_SEC_FACTORY) unsigned int len = MEM_TEST_SIZE; #endif void *ptr; int ret = 1; ptr = vmalloc(len); if (!ptr) { ret = -24; goto fail; } mem8_base = (unsigned char *)ptr; mem16_base = (unsigned short *)ptr; mem32_base = (unsigned int *)ptr; mem_base = (unsigned int *)ptr; /* pr_info("Test DRAM start address 0x%lx\n", (unsigned long)ptr); */ pr_info("Test DRAM start address %p\n", ptr); pr_info("Test DRAM SIZE 0x%x\n", len); size = len >> 2; /* === test the tied bits (tied high) === */ for (i = 0; i < size; i++) mem32_base[i] = 0; for (i = 0; i < size; i++) { if (mem32_base[i] != 0) { /* return -1; */ ret = -1; goto fail; } else mem32_base[i] = 0xffffffff; } /* === test the tied bits (tied low) === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xffffffff) { /* return -2; */ ret = -2; goto fail; } else mem32_base[i] = 0x00; } /* === test pattern 1 (0x00~0xff) === */ pattern8 = 0x00; for (i = 0; i < len; i++) mem8_base[i] = pattern8++; pattern8 = 0x00; for (i = 0; i < len; i++) { if (mem8_base[i] != pattern8++) { /* return -3; */ ret = -3; goto fail; } } /* === test pattern 2 (0x00~0xff) === */ pattern8 = 0x00; for (i = j = 0; i < len; i += 2, j++) { if (mem8_base[i] == pattern8) mem16_base[j] = pattern8; if (mem16_base[j] != pattern8) { /* return -4; */ ret = -4; goto fail; } pattern8 += 2; } /* === test pattern 3 (0x00~0xffff) === */ pattern16 = 0x00; for (i = 0; i < (len >> 1); i++) mem16_base[i] = pattern16++; pattern16 = 0x00; for (i = 0; i < (len >> 1); i++) { if (mem16_base[i] != pattern16++) { /* return -5; */ ret = -5; goto fail; } } /* === test pattern 4 (0x00~0xffffffff) === */ pattern32 = 0x00; for (i = 0; i < (len >> 2); i++) mem32_base[i] = pattern32++; pattern32 = 0x00; for (i = 0; i < (len >> 2); i++) { if (mem32_base[i] != pattern32++) { /* return -6; */ ret = -6; goto fail; } } /* === Pattern 5: Filling memory range with 0x44332211 === */ for (i = 0; i < size; i++) mem32_base[i] = 0x44332211; /* === Read Check then Fill Memory with a5a5a5a5 Pattern === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0x44332211) { /* return -7; */ ret = -7; goto fail; } else { mem32_base[i] = 0xa5a5a5a5; } } /* === Read Check then Fill Memory with */ /* 00 Byte Pattern at offset 0h === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xa5a5a5a5) { /* return -8; */ ret = -8; goto fail; } else { mem8_base[i * 4] = 0x00; } } /* === Read Check then Fill Memory with */ /* 00 Byte Pattern at offset 2h === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xa5a5a500) { /* return -9; */ ret = -9; goto fail; } else { mem8_base[i * 4 + 2] = 0x00; } } /* === Read Check then Fill Memory with */ /* 00 Byte Pattern at offset 1h === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xa500a500) { /* return -10; */ ret = -10; goto fail; } else { mem8_base[i * 4 + 1] = 0x00; } } /* === Read Check then Fill Memory with */ /* 00 Byte Pattern at offset 3h === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xa5000000) { /* return -11; */ ret = -11; goto fail; } else { mem8_base[i * 4 + 3] = 0x00; } } /* === Read Check then Fill Memory with ffff */ /* Word Pattern at offset 1h == */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0x00000000) { /* return -12; */ ret = -12; goto fail; } else { mem16_base[i * 2 + 1] = 0xffff; } } /* === Read Check then Fill Memory with ffff */ /* Word Pattern at offset 0h == */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xffff0000) { /* return -13; */ ret = -13; goto fail; } else { mem16_base[i * 2] = 0xffff; } } /*=== Read Check === */ for (i = 0; i < size; i++) { if (mem32_base[i] != 0xffffffff) { /* return -14; */ ret = -14; goto fail; } } /************************************************ * Additional verification ************************************************/ /* === stage 1 => write 0 === */ for (i = 0; i < size; i++) mem_base[i] = PATTERN1; /* === stage 2 => read 0, write 0xF === */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN1) { /* return -15; */ ret = -15; goto fail; } mem_base[i] = PATTERN2; } /* === stage 3 => read 0xF, write 0 === */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN2) { /* return -16; */ ret = -16; goto fail; } mem_base[i] = PATTERN1; } /* === stage 4 => read 0, write 0xF === */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN1) { /* return -17; */ ret = -17; goto fail; } mem_base[i] = PATTERN2; } /* === stage 5 => read 0xF, write 0 === */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN2) { /* return -18; */ ret = -18; goto fail; } mem_base[i] = PATTERN1; } /* === stage 6 => read 0 === */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN1) { /* return -19; */ ret = -19; goto fail; } } /* === 1/2/4-byte combination test === */ mem_ptr = (unsigned long)mem_base; while (mem_ptr < ((unsigned long)mem_base + (size << 2))) { *((unsigned char *)mem_ptr) = 0x78; mem_ptr += 1; *((unsigned char *)mem_ptr) = 0x56; mem_ptr += 1; *((unsigned short *)mem_ptr) = 0x1234; mem_ptr += 2; *((unsigned int *)mem_ptr) = 0x12345678; mem_ptr += 4; *((unsigned short *)mem_ptr) = 0x5678; mem_ptr += 2; *((unsigned char *)mem_ptr) = 0x34; mem_ptr += 1; *((unsigned char *)mem_ptr) = 0x12; mem_ptr += 1; *((unsigned int *)mem_ptr) = 0x12345678; mem_ptr += 4; *((unsigned char *)mem_ptr) = 0x78; mem_ptr += 1; *((unsigned char *)mem_ptr) = 0x56; mem_ptr += 1; *((unsigned short *)mem_ptr) = 0x1234; mem_ptr += 2; *((unsigned int *)mem_ptr) = 0x12345678; mem_ptr += 4; *((unsigned short *)mem_ptr) = 0x5678; mem_ptr += 2; *((unsigned char *)mem_ptr) = 0x34; mem_ptr += 1; *((unsigned char *)mem_ptr) = 0x12; mem_ptr += 1; *((unsigned int *)mem_ptr) = 0x12345678; mem_ptr += 4; } for (i = 0; i < size; i++) { value = mem_base[i]; if (value != 0x12345678) { /* return -20; */ ret = -20; goto fail; } } /* === Verify pattern 1 (0x00~0xff) === */ pattern8 = 0x00; mem8_base[0] = pattern8; for (i = 0; i < size * 4; i++) { unsigned char waddr8, raddr8; waddr8 = i + 1; raddr8 = i; if (i < size * 4 - 1) mem8_base[waddr8] = pattern8 + 1; if (mem8_base[raddr8] != pattern8) { /* return -21; */ ret = -21; goto fail; } pattern8++; } /* === Verify pattern 2 (0x00~0xffff) === */ pattern16 = 0x00; mem16_base[0] = pattern16; for (i = 0; i < size * 2; i++) { if (i < size * 2 - 1) mem16_base[i + 1] = pattern16 + 1; if (mem16_base[i] != pattern16) { /* return -22; */ ret = -22; goto fail; } pattern16++; } /* === Verify pattern 3 (0x00~0xffffffff) === */ pattern32 = 0x00; mem32_base[0] = pattern32; for (i = 0; i < size; i++) { if (i < size - 1) mem32_base[i + 1] = pattern32 + 1; if (mem32_base[i] != pattern32) { /* return -23; */ ret = -23; goto fail; } pattern32++; } pr_info("complex R/W mem test pass\n"); fail: vfree(ptr); return ret; } #if IS_ENABLED(CONFIG_SEC_FACTORY) int mtk_dramc_binning_test(void) { return mtk_dramc_binning_test_sz(MEM_TEST_SIZE); } #endif