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; | ||
|  | } |