kernel_samsung_a34x-permissive/drivers/memory/mediatek/dramc_bin_old.c
2024-04-28 15:51:13 +02:00

383 lines
8 KiB
C

// 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