[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/loader/drivers/denali.c b/boot/common/src/loader/drivers/denali.c
new file mode 100644
index 0000000..f4ddfd9
--- /dev/null
+++ b/boot/common/src/loader/drivers/denali.c
@@ -0,0 +1,496 @@
+/*
+ * (C) Copyright 2016 ZXIC Inc.
+ */
+   
+
+#include <common.h>
+#include <asm/arch/denali.h>
+#include <asm/io.h>
+#include <bbt.h>
+
+#include "flash.h"
+
+
+static struct nand_flash_device_para *nand_info = NULL;
+/* nand flash parameter config */
+static const struct nand_flash_device_para nand_flash_para[] = {
+	/* MT29F4G08ABBDAH4 for 7520V5 evb 512MB X 8 */
+	{0x2C, 0xAC, 0x90, 0, 4, 2048,11, 64, 17, 4096, 0x20000},
+    /* MT29F2G08ABBEA for 7520 evb 256MB X 8 */
+    {0x2C, 0xAA, 0x90, 0, 4, 2048,11, 64, 17, 2048, 0x20000},
+    
+    /* K9F2G08U0B for 7520 FPGA */
+    {0xEC, 0xDA, 0x10, 0, 4, 2048,11, 64, 17,2048, 0x20000},
+
+	/* JSFBA3YHABB for 7510 evb 256MB X 8  ---> DDR 128M*/
+	{0xAD, 0xAA, 0x90, 0, 8, 2048, 11, 128, 17,2048, 0x20000},
+
+	/* FM6BD2G1GA for 7510 evb 256MB X 8 ---> DDR 128M */
+	{0xC8, 0xAA, 0x90, 0, 4, 2048, 11, 64, 17, 2048, 0x20000},
+
+	/* H9TA4GG4GDMCPR for 7510 evb 512MB X 8 ---> DDR 512M */
+	{0xAD, 0xAC, 0x90, 0, 8, 2048, 11, 128, 17, 4096, 0x20000},
+
+	/* JSFCBX3Y7ABB for 7510 evb 512MB X 8 ---> DDR 256M */
+	{0x01, 0xAC, 0x90, 0, 8, 2048, 11, 128, 17, 4096, 0x20000},
+
+	/* FM6BD4G2GA for 7510 evb 512MB X 8 ---> DDR 256M*/
+	{0xC8, 0xAC, 0x90, 0, 4, 2048, 11, 64, 17, 4096, 0x20000},
+
+	/* NM1281KSLAXAJ for 7510 evb 256MB X 8  ---> DDR 128M*/
+	{0x98, 0xAA, 0x90, 0, 8, 2048, 11, 128, 17, 2048, 0x20000},
+
+	/* W71NW20GF3FW  for 7520 evb 256MB X 8 */	
+	{0xEF, 0xAA, 0x90, 0, 4, 2048,11, 64, 17, 2048, 0x20000},	
+	{0}
+};
+
+
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ static uint32_t wait_for_ready(uint32_t status_type)
+{
+    uint32_t status = 0;
+    while (!(readl(INTR_STATUS(0)) & status_type));
+    status = readl(INTR_STATUS(0));  
+    writew(0xffff, INTR_STATUS(0));
+	return status;
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+static void index_addr(uint32_t address, uint32_t data)
+{
+	writel(address, NAND_DATA);
+	writel(data, NAND_DATA_10);
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+static void index_addr_read_data(uint32_t address, uint32_t *pdata)
+{
+	writel(address, NAND_DATA);
+	*pdata = readl(NAND_DATA_10);
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+void nand_read_oob(uint8_t *buf, uint32_t offset, uint32_t len)
+{
+    uint32_t cmd, i, status_type; 
+    uint32_t *buf32 = NULL; 
+    uint32_t addr = offset >> (nand_info->page_size_shift);     //addr = bank0 | page
+    
+    /* 0. disable ECC */
+    writel(ECC_DISABLE__FLAG, ECC_ENABLE);
+
+	writel(0xffff, INTR_STATUS(0));
+
+    writel(TRANSFER_SPARE_REG__FLAG, TRANSFER_SPARE_REG);
+
+    /* setup page read request for SPARE_ACCESS read */
+	cmd = MODE_10 | addr;
+	index_addr((uint32_t)cmd, SPARE_ACCESS);
+
+	cmd = MODE_10 | addr;
+	index_addr((uint32_t)cmd, 0x2001);
+
+    /* page 33 of the NAND controller spec indicates we should not
+	    use the pipeline commands in Spare area only mode. So we
+		don't.
+	 */
+    cmd = MODE_01 | addr;
+    writel(cmd, NAND_DATA);
+
+    status_type = wait_for_ready(INTR_STATUS__LOAD_COMP | INTR_STATUS__TIME_OUT);
+	if (status_type & INTR_STATUS__TIME_OUT)
+		printf("[OT]\n");   /* OOB TIMEOUT */
+
+	/* 0. read oob data */
+    buf32 = (uint32_t *)buf;
+	for (i = 0; i < len / 4; i++)
+		*buf32++ = readl(NAND_DATA_10);
+
+	/* We set the device back to MAIN_ACCESS here as I observed
+	 * instability with the controller if you do a block erase
+	 * and the last transaction was a SPARE_ACCESS. Block erase
+	 * is reliable (according to the MTD test infrastructure)
+	 * if you are in MAIN_ACCESS.
+	 */
+	cmd = MODE_10 | addr;
+	index_addr((uint32_t)cmd, MAIN_ACCESS);
+    
+}
+
+
+void clear_intr(void)
+{
+	while(readl(INTR_STATUS(0)))
+	{
+		writew(0xffff, INTR_STATUS(0));
+		
+	}
+	writew(0xffff, INTR_STATUS(0));
+	
+	nsdelay(400000);//0.02s
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t read_page(uint32_t buf, uint32_t offset)
+{
+    uint32_t status = 0;
+	int32_t ecc_status = 0;
+    uint32_t page = offset >> (nand_info->page_size_shift);
+    uint32_t mode = MODE_10;         /* MODE_10 | BANK(denali->flash_bank) */
+
+    if((buf & 0x3) != 0)          /* DMAµØÖ·ÒªÇó4×Ö½Ú¶ÔÆë */
+    {
+        printf("[AE]\n"); /* [read_page]:ADDR ERROR */
+        return -1;      
+    }
+
+	ecc_status =readl(ECC_CORRECTION);
+
+	if(page < 64)
+	{
+		writel(0x8, ECC_CORRECTION);
+	}
+    
+    /* clear status */
+    writew(0xffff, INTR_STATUS(0));
+    
+	writel(TRANSFER_MAIN_REG__FLAG, TRANSFER_SPARE_REG);
+    
+    /* enable DMA */
+    writel(DMA_ENABLE__FLAG, DMA_ENABLE); 
+
+	/* setup transfer type and # of pages -FOR DMA */
+    index_addr(mode | page, 0x2001);    //mode10(0x08000000) | bank0(0) | page, 
+                                         //  0x2000 | DENALI_READ(0) | 1
+
+	/* set memory high address bits 23:8 -FOR DMA */
+    index_addr(mode | ((uint16_t)(buf >> 16) << 8), 0x2200);
+
+	/* set memory low address bits 23:8 -FOR DMA */
+    index_addr(mode | ((uint16_t)buf << 8), 0x2300);
+
+	/* interrupt when complete, burst len = 64 bytes -FOR DMA*/
+    index_addr( mode | 0x14000, 0x2400);     //zhouqi not interrupt 0X40
+
+    /* wait_for_ready */
+    status = wait_for_ready (INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__ECC_ERR);
+    if (status & INTR_STATUS__ECC_ERR )
+    {
+        printf("[EE]\n");     /* [read_page]: ECC ERROR */
+		/* 0. clear status */
+    	clear_intr();
+        return -1;        
+    }
+        
+
+    if (status & INTR_STATUS__TIME_OUT)
+    {
+        printf("TO\n");  /* [read_page]: TIME OUT */
+		/* clear status */
+    	clear_intr();
+        return -1;      
+    }
+
+	writel(ecc_status, ECC_CORRECTION);
+
+    /* disable DMA */
+    writel(DMA_DISABLE__FLAG, DMA_ENABLE);
+    
+    return 0;
+}
+
+
+/*******************************************************************************
+ * from: must page align
+   len:  must page align
+ */
+ /*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t nand_read(uint32_t from, uint32_t len, uint32_t to)
+{
+    uint32_t offset = from;
+    uint32_t left_to_read = len;
+    uint32_t p_to = to;
+    int32_t ret = 0;
+    int32_t page_size = (nand_info->page_size);
+
+    if((offset & (page_size - 1)) || (len & (page_size - 1)))
+    {
+        printf("param err.\n");
+        return -1;       
+    }
+
+    while(left_to_read > 0)
+    {       
+        ret = read_page(p_to, offset);
+		if(ret != 0)
+		{
+			return -1;
+		}
+        
+        left_to_read -= page_size;
+        offset += page_size;
+        p_to += page_size;          
+    }
+    return 0;
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t read_data(uint32_t from, uint32_t len, uint32_t to)
+{
+    uint32_t offset = from;
+    uint32_t left_to_read = len;
+    uint32_t p_to = to;
+    int32_t ret = 0;
+    int32_t block_size = (nand_info->block_size);
+            
+    while( left_to_read > 0 )
+    {
+        uint32_t block_offset = offset & (block_size - 1);
+		uint32_t read_length;
+
+        if( nand_block_isbad(offset) )
+        {
+            offset += block_size;
+            continue;
+        }
+            
+        if (left_to_read < (block_size - block_offset))
+			read_length = left_to_read;
+		else
+			read_length = block_size - block_offset;
+      
+        ret = nand_read(offset, read_length, p_to);
+		if(ret != 0)
+		{
+			return -1;
+		}
+
+        left_to_read -= read_length;
+        offset += read_length;
+        p_to += read_length;         
+    }
+    
+    return 0;
+}
+
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int32_t nand_read_id (void)
+{
+    uint32_t id[5];
+    uint32_t i = 0;
+	uint32_t addr = (uint32_t)MODE_11;      /*  | BANK(0) */
+    struct nand_flash_device_para *nand = &nand_flash_para[0];
+
+    index_addr(addr | 0, 0x90);
+	index_addr(addr | 1, 0);
+	for (i = 0; i < 5; i++) 
+    {
+		index_addr_read_data(addr | 2,	&id[i]);
+	}
+
+    i = 0;
+    while( nand->manuf_id != 0 )
+    {   
+        if( ((uint8_t)id[0] == nand->manuf_id) && 
+                ((uint8_t)id[1] == nand->device_id) &&
+                    ((uint8_t)id[2] == nand->res_id))
+        {
+            nand_info = nand;
+
+			writel(nand_info->bus_num, DEVICE_WIDTH);
+			writel(nand_info->page_size, DEVICE_MAIN_AREA_SIZE);
+			writel(nand_info->page_size, LOGICAL_PAGE_DATA_SIZE);
+			writel(nand_info->oob_size, DEVICE_SPARE_AREA_SIZE);
+			writel(nand_info->ecc_strength, ECC_CORRECTION);   
+            return 0;
+        };
+        nand++;
+        i++;
+    }
+    
+    return 1;   
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t nand_init (void)
+{
+    int32_t ret = 0;
+    writel(ECC_DISABLE__FLAG, ECC_ENABLE);      /*  ecc_enable */
+    writel(2, SPARE_AREA_SKIP_BYTES);
+
+    ret = nand_read_id();
+    if( ret != 0 )
+        return -1;
+
+	flash.flash_type = NAND_BOOT;
+	flash.manuf_id = nand_info->manuf_id;
+	flash.device_id = nand_info->device_id;
+	flash.page_size = nand_info->page_size;
+	flash.page_size_shift = nand_info->page_size_shift;
+	flash.oob_size = nand_info->oob_size;
+	flash.block_size = nand_info->block_size;
+	flash.block_size_shift = nand_info->block_size_shift;
+	flash.block_num = nand_info->block_num;
+	flash.read = read_data;
+	flash.read_oob = nand_read_oob;
+
+    return 0;
+    
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int board_flash_init(void)
+{
+	int ret = 0;
+	char boot_mode = 0;
+
+	boot_mode = get_boot_mode();
+	if(boot_mode != NAND_BOOT)
+	{
+		printf("not nand flash.\n");
+		return -1;
+	}
+	
+	writel(CFG_START_MODE_NAND, CFG_BOOT_MODE_START_MODE_FOR_UBOOT); 
+	ret = nand_init(); 
+	if(ret != 0)
+	{  
+		printf("nand init err.\n");
+		return -1;
+	}	
+	printf("nand init ok.\n");
+	
+	nand_creat_bbt();
+		
+	return 0;
+}
+
+