Files
kunlun/dtest/ate_ddr_flash_test/ate_ddr_flash_test.c
2024-09-28 14:24:04 +08:00

344 lines
9.4 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics Ltd. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics Ltd and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "os_types.h"
#include "chip_reg_base.h"
#include "hw_reg_api.h"
#include "ate_main.h"
#include "iot_bitops.h"
#include "dbg_io.h"
#include "iot_io.h"
#include "clk.h"
#include "efuse.h"
#include "os_mem.h"
#include "iot_errno.h"
#include "sfc_rf.h"
#include "sfc.h"
#include "flash.h"
#include "gpio_mtx.h"
#include "apb.h"
#include "ahb.h"
#include "ddrc.h"
#include "efuse.h"
#include "efuse_mapping.h"
#define LOG_ENABLE 1
#if LOG_ENABLE
#define ATE_LOG(Format, ...) \
iot_printf(Format, ##__VA_ARGS__)
#else
#define ATE_LOG(Format, ...)
#endif
/* ate global structure */
ate_info_t *glb_ate_info = (ate_info_t *) 0xfff8000;
#define ATE_GLB_SET_RST(val) (glb_ate_info->result = val)
#define ATE_GLB_SET_FLAGS(val) (glb_ate_info->flags = val)
#define ATE_GLB_CNT_INCR() ({ \
while(1) { \
glb_ate_info->cnt = glb_ate_info->cnt + 1; \
ATE_LOG(""); \
}})
/* efuse info */
uint8_t mac_addr[6] = {0};
uint8_t version[2] = {0};
/* ddr bond test define */
#define DDR_MEM_START_ADDR (0)
#define DDR_MEM_ICACHE_ADDR (0x18000000)
#define DDR_MEM_DCACHE_ADDR (0x10000000)
#define DDR_MEM_TEST_STEP (1024*8) // uint is word, step size: 32KB
#define DDR_MEM_SIZE_32MB (8*1024*1024) // unit is word, total size: 32MB
#define DDR_MEM_SIZE_8MB (2*1024*1024) // unit is word, total size: 8MB
#define DDR_MEM_TEST_ADDR (DDR_MEM_ICACHE_ADDR + DDR_MEM_START_ADDR)
uint32_t test_pattern[] = {0x5a5a5a5a, 0xa5a5a5a5};
/* flash test define */
#define FLASH_TEST_OFFSET (0x0)
#define FLASH_VENDOR_ID_GD 0xc8
#define FLASH_VENDOR_ID_PUYA 0x85
#define FLASH_VENDOR_ID_ZBIT 0x5e
#define FLASH_VENDOR_ID_WINBOND 0xef
static uint8_t rdata[0x100] = {0};
static uint8_t wdata[0x100] = {0};
void efuse_mac_read()
{
uint32_t tmp;
uint8_t mac[6] = {0};
tmp = efuse_read(CFG_EFUSE_BITS32_2_ADDR);
mac[0] = REG_FIELD_GET(MAC_ADDR_B0, tmp);
tmp = efuse_read(CFG_EFUSE_BITS32_3_ADDR);
mac[1] = REG_FIELD_GET(MAC_ADDR_B1, tmp);
mac[2] = REG_FIELD_GET(MAC_ADDR_B2, tmp);
mac[3] = REG_FIELD_GET(MAC_ADDR_B3, tmp);
mac[4] = REG_FIELD_GET(MAC_ADDR_B4, tmp);
tmp = efuse_read(CFG_EFUSE_BITS32_4_ADDR);
mac[5] = REG_FIELD_GET(MAC_ADDR_B5, tmp);
ATE_LOG("[MAC_ID_TEST]efuse read MAC:%02X:%02X:%02X:%02X:%02X:%02X\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
os_mem_cpy(glb_ate_info->mac, mac, sizeof(mac));
}
uint8_t ate_ddr_bond_dtest(uint32_t mode)
{
ATE_GLB_SET_FLAGS(ATE_DDR_FAIL_BOND);
volatile uint32_t *src = (volatile uint32_t *) DDR_MEM_TEST_ADDR;
uint32_t test_size = 0;
if (mode == DEV_X16_MODE) {
test_size = DDR_MEM_SIZE_32MB;
} else {
test_size = DDR_MEM_SIZE_8MB;
}
/* write */
for(uint32_t i = 0; i < test_size; i+=DDR_MEM_TEST_STEP) {
*(src + i) = test_pattern[0];
*(src + i + 1) = test_pattern[1];
}
/* cache clear */
ahb_icache_flush((uint32_t)src, test_size);
/* read */
uint8_t err = 0;
uint32_t tmp0, tmp1;
for(uint32_t i = 0; i < test_size; i+=DDR_MEM_TEST_STEP) {
tmp0 = *(src + i);
tmp1 = *(src + i + 1);
if (tmp0 != test_pattern[0] || tmp1 != test_pattern[1]) {
ATE_LOG("[ATE]read error....addr-0x%08x: 0x%08x-[0x%08x 0x%08x]\n",
i*4, i, tmp0, tmp1);
glb_ate_info->result = ATE_TEST_FAIL;
err = 1;
}
}
if (err == 1) {
ATE_LOG("[ATE]ddr memory bond test failed\n");
return ERR_FAIL;
} else {
ATE_LOG("[ATE]ddr memory bond test pass\n");
return ERR_OK;
}
}
uint8_t ate_flash_bond_test(uint32_t mode)
{
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_BOND);
uint8_t flag = 0;
if (mode == DEV_X16_MODE) {
/* x16 bypass flash test */
flag = 2;
} else {
uint8_t data;
uint32_t flash_test_offset = 0;
uint32_t i = 0;
flash_test_offset += FLASH_TEST_OFFSET;
flash_init(0);
qspi_set_edge(0, 0, 7);
/* id test */
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_ID);
g_sfc_ctrl->get_dev_id(&data);
ATE_LOG("[FLASH_TEST]get id: %02x\n", data);
if (data != FLASH_VENDOR_ID_GD && data != FLASH_VENDOR_ID_PUYA\
&& data != FLASH_VENDOR_ID_ZBIT && data != FLASH_VENDOR_ID_WINBOND){
ATE_LOG("[FLASH_TEST]id is not match.\n");
flag = 1;
goto err;
}
/* init test */
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_INIT);
flash_init(1);
/* quad mode check */
uint8_t sts = 0;
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_QUAD);
if (flash_get_sts_reg(&sts, 1)) {
flag = 1;
goto err;
} else {
if ((sts & 0x2) != 0x2) {
flag = 1;
goto err;
}
}
/* erase test */
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_ERASE);
g_sfc_ctrl->erase_sector(flash_test_offset, MOD_SW_MODE_DIS);
qspi_set_edge(0, 0, 7);
for(i = 0; i < 0x100; i++) {
rdata[i] = 0xdd;
}
g_sfc_ctrl->read(rdata,flash_test_offset,sizeof(rdata), MOD_SFC_READ_SIG);
for (i = 0; i < 0x100; i++) {
if (rdata[i] != 0xff) {
flag = 1;
goto err;
}
}
qspi_set_edge(0, 0, 2);
/* program test */
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_PRGM);
g_sfc_ctrl->erase_sector(flash_test_offset, MOD_SW_MODE_DIS);
for(i = 0; i < 0x100; i++) {
wdata[i] = i;
rdata[i] = 0;
}
g_sfc_ctrl->write(wdata,flash_test_offset, sizeof(wdata),
MOD_SFC_PROG_QUAD, MOD_SW_MODE_DIS);
qspi_set_edge(0, 0, 7);
g_sfc_ctrl->read(rdata,flash_test_offset,sizeof(rdata), MOD_SFC_READ_SIG);
qspi_set_edge(0, 0, 2);
for(i = 0; i < 0x100; i++) {
if (wdata[i] != rdata[i]) {
flag = 1;
ATE_LOG("[ATE]flash read not match, index: %d, \
write:%02x, read: %02x\n", wdata[i], rdata[i]);
goto err;
}
}
/* read test */
ATE_GLB_SET_FLAGS(ATE_FLASH_FAIL_READ);
for(i = 0; i < 0x100; i++) {
rdata[i] = 0;
}
g_sfc_ctrl->read(rdata,flash_test_offset,sizeof(rdata), MOD_SFC_READ_QUAD_IO_FAST);
for(i = 0; i < 0x100; i++) {
if (wdata[i] != rdata[i]) {
flag = 1;
ATE_LOG("[ATE]flash read not match, index: %d, \
write:%02x, read: %02x\n", wdata[i], rdata[i]);
goto err;
}
}
}
err:
if (flag == 2) {
ATE_LOG("[ATE]flash test bypass.\n");
return ERR_OK;
} else if (flag == 1) {
ATE_LOG("[ATE]flash test failed.\n");
return ERR_FAIL;
} else {
ATE_LOG("[ATE]flash test pass.\n");
return ERR_OK;
}
}
/* initialize ate */
void ate_init(void)
{
/* init global info */
os_mem_set(glb_ate_info,0,sizeof(ate_info_t));
/* print software version */
ATE_LOG("[ATE]software version:%s\r\n", ATE_SW_VER);
os_mem_cpy(glb_ate_info->sw_version, ATE_SW_VER, sizeof(ATE_SW_VER));
/* print efuse mac address */
efuse_mac_read();
}
void ate_ddr_flash_entry()
{
uint8_t ret = ERR_FAIL;
ATE_GLB_SET_RST(ATE_TEST_FAIL);
//change CPU core to 150M.
ATE_GLB_SET_FLAGS(ATE_DDR_FAIL_FREQ);
clk_core_freq_set(CPU_FREQ_150M);
// disable cache
ahb_cache_disable();
ATE_GLB_SET_FLAGS(ATE_DDR_FAIL_INIT);
ddr_cache_init();
// enable ahb cache
ahb_cache_enable();
//ahb_cache_reset();
//enable dmc cache;
ahb_dmc_cache_enable();
//cache space init;
ahb_cache_fill_valid_space();
ATE_LOG("[ATE]ddr_training finish\n");
uint32_t mode;
uint32_t pkt_type = ahb_get_pkg_type();
if (pkt_type == AHB_PKG_AI) {
mode = DEV_X16_MODE;
} else {
mode = DEV_X8_MODE;
}
ATE_LOG("[ATE]ddr cache mode: %s, size: %d MB\n",
(mode?"X16":"X8"), (mode?32:8));
ret = ate_ddr_bond_dtest(mode);
if (ret) {
ATE_GLB_SET_RST(ATE_TEST_FAIL);
ATE_GLB_CNT_INCR();
}
ret = ate_flash_bond_test(mode);
if (ret) {
ATE_GLB_SET_RST(ATE_TEST_FAIL);
ATE_GLB_CNT_INCR();
}
ATE_GLB_SET_RST(ATE_TEST_OK);
ATE_GLB_SET_FLAGS(ATE_FLAG_OK);
}
/* main entry */
void ate_entry(void)
{
#if LOG_ENABLE
dbg_uart_init();
#endif
ATE_LOG("[ATE]start\n");
ate_init();
ate_ddr_flash_entry();
ATE_LOG("[ATE]end\n");
}
int main(void) {
ate_entry();
return 0;
}