#include #include #include #include #include #include "spi_flash.h" #ifdef CONFIG_SOC_LEOPARD #define DELAY_CHAIN_NUM 64 #else #define DELAY_CHAIN_NUM 16 #endif extern unsigned char spi_flash_set_delaytran(const struct device *dev, off_t offset, unsigned char delaytran); //static inline void test_setup_delaychain(struct spinor_info *sni, u8_t ns) //{ //struct acts_spi_reg *spi= (struct acts_spi_reg *)sni->spi.base; //spi->ctrl = (spi->ctrl & ~(0xF << 16)) | (ns << 16); //volatile int i = 100000; //while (i--); //} #define TEST_READ_WRITE #ifdef TEST_READ_WRITE #if defined(CONFIG_SPI_FLASH_GPIO_2CS) && (CONFIG_SPI_FLASH_GPIO_2CS == 1) extern unsigned int nor_cs0_size; static u32_t TEST_ADDR = 0x200000; static u32_t TEST_ADDR_END = 0x400000; #else #define TEST_ADDR 0x200000 #define TEST_ADDR_END 0x400000 #endif #define TEST_SIZE (1024*4) static u32_t nor_test_buf[TEST_SIZE/4]; static u32_t nor_test_start= 0x200000; __ramfunc int test_read_write_try(const struct device *dev, u8_t delay_chain) { int ret, i; struct spinor_info *sni = (struct spinor_info *)(dev)->data; spi_flash_set_delaytran(dev, TEST_ADDR, delay_chain); //sni->spi.delay_chain = delay_chain; if(nor_test_start < TEST_ADDR || nor_test_start >= TEST_ADDR_END) nor_test_start = TEST_ADDR; ret = flash_erase(dev, nor_test_start, TEST_SIZE); for(i = 0; i < TEST_SIZE/4; i++) nor_test_buf[i] = nor_test_start + i; ret = flash_write(dev, nor_test_start, nor_test_buf, TEST_SIZE); memset(nor_test_buf, 0 , TEST_SIZE); ret = flash_read(dev, nor_test_start, nor_test_buf, TEST_SIZE); if(ret){ //test_setup_delaychain(sni, CONFIG_SPI_FLASH_DELAY_CHAIN); printk("read write fail =0x%x\n", nor_test_start); return -1; } for(i = 0; i < TEST_SIZE/4; i++){ if( nor_test_buf[i] != nor_test_start + i){ //test_setup_delaychain(sni, CONFIG_SPI_FLASH_DELAY_CHAIN); printk("of=%x, read 0x%x != 0x%x\n",nor_test_start, nor_test_start + i, nor_test_buf[i]); nor_test_start += TEST_SIZE; return -1; } } nor_test_start += TEST_SIZE; return 0; } #endif __ramfunc u32_t test_delaychain_read_id(const struct device *dev, u8_t delay_chain) { u32_t nor_id, mid; struct spinor_info *sni = (struct spinor_info *)(dev)->data; //sni->spi.delay_chain = delay_chain; spi_flash_set_delaytran(dev, TEST_ADDR, delay_chain); /* configure delay chain */ //test_setup_delaychain(sni, sni->spi.delay_chain); //k_busy_wait(50); nor_id = p_spinor_api->read_chipid(sni) & 0xffffff; mid = nor_id & 0xff; if ((mid == 0xff) || (mid == 0x00)) return 0; return nor_id; } __ramfunc s32_t test_delaychain_try(const struct device *dev, u8_t *ret_delaychain, u32_t chipid_ref) { u32_t i, try_delaychain; bool match_flag = 0; //u32_t nor_id_value_check; u32_t local_irq_save; local_irq_save = irq_lock(); ret_delaychain[0] = 0; for (try_delaychain = 1; try_delaychain < DELAY_CHAIN_NUM; try_delaychain++) { match_flag = 1; printk("try_delaychain :%d\n", try_delaychain); soc_udelay(5000); #ifdef TEST_READ_WRITE for (i = 0; i < 2; i++) { if(test_read_write_try(dev, try_delaychain)){ match_flag = 0; break; } } #else for (i = 0; i < 64; i++) { nor_id_value_check = test_delaychain_read_id(dev, try_delaychain); if (nor_id_value_check != chipid_ref) { printk("read:0x%x @ %d\n", nor_id_value_check, try_delaychain); match_flag = 0; break; } } #endif ret_delaychain[try_delaychain] = match_flag; } //test_delaychain_read_id(dev, CONFIG_SPI_FLASH_DELAY_CHAIN); irq_unlock(local_irq_save); return 0; } __ramfunc u32_t nor_read_chipid(const struct device *dev) { u32_t nor_id; u32_t local_irq_save; struct spinor_info *sni = (struct spinor_info *)(dev)->data; local_irq_save = irq_lock(); nor_id = p_spinor_api->read_chipid(sni) & 0xffffff; irq_unlock(local_irq_save); return nor_id; } __ramfunc u8_t spinor_test_delaychain(const struct device *test_nor_dev) { u8_t ret_delaychain = 0; u8_t delaychain_flag[DELAY_CHAIN_NUM]; u8_t delaychain_total[DELAY_CHAIN_NUM]; u8_t start = 0, end, middle, i; u8_t expect_max_count_delay_chain = 0, max_count_delay_chain; //u32_t freq; u32_t chipid_ref; u8_t bak_delaytran; //struct device *test_nor_dev = device_get_binding(CONFIG_SPI_FLASH_NAME); struct spinor_info *sni = (struct spinor_info *)(test_nor_dev)->data; bak_delaytran = spi_flash_set_delaytran(test_nor_dev, TEST_ADDR, sni->spi.delay_chain); printk("spinor test delaychain start\n"); chipid_ref = nor_read_chipid(test_nor_dev); printk("delaytran=0x%x, chipid = 0x%x\n", bak_delaytran, chipid_ref); memset(delaychain_total, 0x0, DELAY_CHAIN_NUM); //for (freq = 6; freq <= 222; freq += 6) { expect_max_count_delay_chain++; // soc_freq_set_cpu_clk(0, freq); // printk("set cpu freq : %d\n", freq); if (test_delaychain_try(test_nor_dev, delaychain_flag, chipid_ref) == 0) { for (i = 0; i < DELAY_CHAIN_NUM; i++) delaychain_total[i] += delaychain_flag[i]; } else { printk("test_delaychain_try error!!\n"); goto delay_chain_exit; } //} spi_flash_set_delaytran(test_nor_dev, TEST_ADDR, bak_delaytran); //sni->spi.delay_chain = bak_delaytran; printk("delaychain_total : "); for (i = 0; i < DELAY_CHAIN_NUM; i++) printk("%d,", delaychain_total[i]); printk("\n"); max_count_delay_chain = 0; for (i = 0; i < DELAY_CHAIN_NUM; i++) { if (delaychain_total[i] > max_count_delay_chain) max_count_delay_chain = delaychain_total[i]; } for (i = 0; i < DELAY_CHAIN_NUM; i++) { if (delaychain_total[i] == max_count_delay_chain) { start = i; break; } } end = start; for (i = start + 1; i < DELAY_CHAIN_NUM; i++) { if (delaychain_total[i] != max_count_delay_chain) break; end = i; } if (max_count_delay_chain < expect_max_count_delay_chain) { printk("test delaychain max count is %d, less then expect %d!!\n", max_count_delay_chain, expect_max_count_delay_chain); goto delay_chain_exit; } if ((end - start + 1) < 3) { printk("test delaychain only %d ok!! too less!!\n", end - start + 1); goto delay_chain_exit; } middle = (start + end) / 2; printk("test delaychain pass, best delaychain is : %d\n\n", middle); ret_delaychain = middle; delay_chain_exit: return ret_delaychain; } /* leopard: vdd < 1000 spi clk 64MHZ else 93MHZ */ #define NUM_VDD_ITEM 4 const uint16_t g_vdd_volt[NUM_VDD_ITEM] = {1200, 1100, 1000, 950}; //const uint16_t g_vdd_volt[NUM_VDD_ITEM] = {1000, 950}; __ramfunc int nor_test_delaychain(const struct device *dev) { int i; uint16_t vdd; //printk_dma_switch(0); printk("-----nor_test_delaychain =0x%x----\n", sys_read32(SPI1_DELAYCHAIN)); sys_write32((sys_read32(SPI1_DELAYCHAIN)&(~0xf))|0x06, SPI1_DELAYCHAIN); soc_freq_set_cpu_clk(70,70); sys_write32(0, WD_CTL); #if 1 for(i = 0; i < NUM_VDD_ITEM; i++){ if(g_vdd_volt[i] == 950){ printk("set spi0/spi1 clk 0.95V\n"); sys_write32((sys_read32(SPI1_DELAYCHAIN)&(~0xf))|0x03, SPI1_DELAYCHAIN); clk_set_rate(CLOCK_ID_SPI1, MHZ(70) * 2); clk_set_rate(CLOCK_ID_SPI0, MHZ(64)); } soc_pmu_set_vdd_voltage(g_vdd_volt[i]); soc_udelay(1000); printk("-----%d vdd set %d mv, try delaytran----\n", i, g_vdd_volt[i]); printk("%d, vdd=%d mv, delaychain : %d\n", i, g_vdd_volt[i], spinor_test_delaychain(dev)); } #endif #if defined(CONFIG_SPI_FLASH_GPIO_2CS) && (CONFIG_SPI_FLASH_GPIO_2CS == 1) for(i = NUM_VDD_ITEM-1; i >= 0; i--){ vdd = g_vdd_volt[i]; soc_pmu_set_vdd_voltage(vdd); soc_udelay(1000); if(g_vdd_volt[i] == 1000){ printk("set spi0/spi1 clk 1.0V\n"); sys_write32((sys_read32(SPI1_DELAYCHAIN)&(~0xf))|0x06, SPI1_DELAYCHAIN); clk_set_rate(CLOCK_ID_SPI1, MHZ(140) * 2); clk_set_rate(CLOCK_ID_SPI0, MHZ(100)); } } printk("\n\n---------------try cs1 nor-----------------\n\n"); TEST_ADDR = 0x200000+nor_cs0_size; TEST_ADDR_END = 0x400000+nor_cs0_size; nor_test_start= TEST_ADDR; for(i = 0; i < NUM_VDD_ITEM; i++){ if(g_vdd_volt[i] == 950){ printk("set spi0/spi1 clk 0.95V\n"); sys_write32((sys_read32(SPI1_DELAYCHAIN)&(~0xf))|0x03, SPI1_DELAYCHAIN); clk_set_rate(CLOCK_ID_SPI1, MHZ(70) * 2); clk_set_rate(CLOCK_ID_SPI0, MHZ(64)); } soc_pmu_set_vdd_voltage(g_vdd_volt[i]); soc_udelay(1000); printk("--start cs1---%d vdd set %d mv, try delaytran----\n", i, g_vdd_volt[i]); printk("--end cs1 %d, vdd=%d mv, best delaychain : %d\n\n", i, g_vdd_volt[i], spinor_test_delaychain(dev)); } #endif printk("\n ----nor_test_delaychain-- finshed-----\n"); while(1); return 0; }