c05564c4d8
Android 13
383 lines
8 KiB
C
Executable file
383 lines
8 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
* Author: Sagy Shih <sagy.shih@mediatek.com>
|
|
*/
|
|
|
|
#include <linux/printk.h>
|
|
#include <linux/vmalloc.h>
|
|
|
|
#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 |