344 lines
9.4 KiB
C
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;
|
|
}
|