[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/nor.c b/boot/common/src/loader/drivers/nor.c
new file mode 100755
index 0000000..afccaf9
--- /dev/null
+++ b/boot/common/src/loader/drivers/nor.c
@@ -0,0 +1,417 @@
+/*
+ * Freescale QuadSPI driver.
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <sdio.h>
+#include <common.h>
+#include <asm/io.h>
+#include "nor.h"
+#include <image.h>
+#include <linux/byteorder/generic.h>
+#include <secure_verify.h>
+#include "config.h"
+#include "flash.h"
+
+
+/* Used when the "_ext_id" is two bytes at most */
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff,				\
+			((_ext_id) >> 8) & 0xff,			\
+			(_ext_id) & 0xff,				\
+			},						\
+		.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.flags = (_flags),
+
+
+spinor_cmd_t nor_cmd_table[]=
+{	
+	{CMD_RDFT, TX_DMA_DIS, RX_DMA_DIS, ADDR_TX_EN, ADDR_WIDTH_24, DATA_TX_DIS, DATA_RX_EN, DUMY_TX_EN, 1, 0, ADDR_MULTI_LINE_DIS, DATA_MULTI_LINE_DIS, TRANS_MOD_SINGLE, "read fast"},
+	{CMD_RDID, TX_DMA_DIS, RX_DMA_DIS, ADDR_TX_DIS, ADDR_WIDTH_24, DATA_TX_DIS, DATA_RX_EN, DUMY_TX_DIS, 0, 0, ADDR_MULTI_LINE_DIS, DATA_MULTI_LINE_DIS, TRANS_MOD_SINGLE, "read identification"},
+	{NULL}
+};
+
+#ifdef CONFIG_ZX297520V3_UFI_MINI_32K_NOR
+static const struct nor_info spi_nor_ids[] = {
+	/* GigaDevice */
+	{ "gd25q128", INFO(0xc86018, 0, 32 * 1024, 512, 0) },
+	/* winbond */	
+	{ "w25q128fw", INFO(0xef6018, 0, 32 * 1024, 512, 0) },
+	/* dosilicon */
+	{ "fm25m4aa", INFO(0xf84218, 0, 32 * 1024, 512, 0) },
+	/* fudanwei */
+	{ "fm25w128", INFO(0xA12818, 0, 32 * 1024, 512, 0) },
+	/* XMC */
+	{ "XM25QU64C", INFO(0x204117, 0, 32 * 1024, 256, 0) },
+	{ "XM25QU128", INFO(0x205018, 0, 32 * 1024, 512, 0) },
+	{ "XM25QU128C", INFO(0x204118, 0, 32 * 1024, 512, 0) },
+	/* DQ25Q128AL */
+	{ "DQ25Q128AL", INFO(0x546018, 0, 32 * 1024, 512, 0) },
+	/* dosilicon */
+	{ "DS25M4AB", INFO(0xE54218, 0, 32 * 1024, 512, 0) },
+	/* esmt(eon) */
+	{ "EN25SX128A", INFO(0x1C7818, 0, 32 * 1024, 512, 0) },
+	/* dosilicon */
+	{ "FM25M4AA", INFO(0xF84218, 0, 32 * 1024, 512, 0) },
+	{ },
+};
+#else
+static const struct nor_info spi_nor_ids[] = {
+	/* GigaDevice */
+	{ "gd25q128", INFO(0xc86018, 0, 64 * 1024, 256, 0) },
+	/* winbond */	
+	{ "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, 0) },
+	/* dosilicon */
+	{ "fm25m4aa", INFO(0xf84218, 0, 64 * 1024, 256, 0) },
+	/* fudanwei */
+	{ "fm25w128", INFO(0xA12818, 0, 64 * 1024, 256, 0) },
+	/* xmc */
+	{ "XM25QU128", INFO(0x205018, 0, 64 * 1024, 256, 0) },
+	{ "XM25QU128C", INFO(0x204118, 0, 64 * 1024, 256, 0) },
+	/* DQ25Q128AL */
+	{ "DQ25Q128AL", INFO(0x546018, 0, 64 * 1024, 256, 0) },
+	/* dosilicon */
+	{ "DS25M4AB", INFO(0xE54218, 0, 64 * 1024, 256, 0) },
+	/* esmt(eon) */
+	{ "EN25SX128A", INFO(0x1C7818, 0, 64 * 1024, 256, 0) },
+	/* dosilicon */
+	{ "FM25M4AA", INFO(0xF84218, 0, 64 * 1024, 256, 0) },
+	{ },
+};
+#endif
+
+
+struct nor_info *spi_nor_flash = NULL;
+
+
+ void spifc_enable(void)
+{
+   volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    
+    if(spifc->SFC_EN & FC_EN_BACK)
+    {
+		printf("spifc en err.\n");
+		return;
+	}   
+    spifc->SFC_EN |= (1 << FC_EN);  
+    spifc->SFC_CTRL0 |= (1 << FC_SCLK_PAUSE_EN);
+}
+
+ void spifc_disable(void)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    
+    if(!(spifc->SFC_EN & FC_EN_BACK))
+    {
+		printf("spifc dis err.\n");
+		return;
+	}     
+    spifc->SFC_EN &= (~(1 <<FC_EN));    
+}
+
+ void spifc_setup_cmd(spinor_cmd_t *cmd, uint32_t addr, uint32_t len)
+{   
+	volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+
+	/* clear dma config */
+	spifc->SFC_CTRL0 &= ~((1 << FC_RX_DMA_EN)|(1 << FC_TX_DMA_EN));
+	/* clear fifo */
+	spifc->SFC_CTRL0 |= (1 << FC_RXFIFO_CLR)|(1 << FC_TXFIFO_CLR);
+
+	/* clear interrupt register */
+	spifc->SFC_INT_SW_CLR = 0xFF;  
+	
+	/* dma + fifo config */
+	spifc->SFC_CTRL0 |= ((cmd->tx_dma_en << FC_TX_DMA_EN) 
+						  | (cmd->rx_dma_en << FC_RX_DMA_EN)
+						  | (1 << FC_RXFIFO_THRES)
+						  | (1 << FC_TXFIFO_THRES));
+
+	/* addr dumy data code config */
+    spifc->SFC_CTRL1 = 0;
+    spifc->SFC_CTRL1 = ((cmd->addr_tx_en << FC_ADDR_TX_EN) 
+						| (cmd->dumy_tx_en << FC_DUMMY_TX_EN) 
+                        | (cmd->data_rx_en << FC_READ_DAT_EN) 
+                        | (cmd->data_tx_en << FC_WRITE_DAT_EN));
+
+    spifc->SFC_CTRL2 = 0;
+    spifc->SFC_CTRL2 = ((cmd->dumy_byte_num << FC_DUMMY_BYTE_NUM) 
+            			| (cmd->dumy_bit_num << FC_DUMMY_BIT_NUM) 
+	            		| (cmd->addr_byte_num << FC_ADDR_BYTE_NUM)
+	            		| (cmd->addr_multi_line_en << FC_ADDR_MULTI_LINE_EN)
+	            		| (cmd->data_multi_line_en << FC_DAT_MULTI_LINE_EN)
+	            		| (cmd->trans_mod << FC_TRANS_MOD));
+
+    if(len)
+        spifc->SFC_BYTE_NUM = len - 1;
+    else
+        spifc->SFC_BYTE_NUM = 0; 
+	
+	spifc->SFC_ADDR = addr; 
+    spifc->SFC_INS = cmd->cmd;          
+}
+
+ int spifc_wait_cmd_end(void)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    uint32_t intr_status = 0;
+
+    while(!(spifc->SFC_INT_RAW & FC_INT_RAW_MASK));
+    
+    intr_status = spifc->SFC_INT_RAW;
+    spifc->SFC_INT_SW_CLR = intr_status;           /* ??? */   
+
+	if(intr_status & FC_INT_RAW_CMD_END)
+    {   
+        return 0;
+    }
+    else
+    {
+		printf("intr status err.\n");
+        return -1;
+    }   
+}
+
+uint32_t spifc_read_fifo(uint8_t *buf, uint32_t len)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    uint32_t *p = (uint32_t *)buf;
+    uint32_t cnt = 0;
+
+	int remainder_cnt = len % 4;
+
+	if(remainder_cnt != 0)
+	{
+		len = len + (4 - remainder_cnt);
+	}
+	else
+	{
+		remainder_cnt = 4;
+	}
+   
+    while(cnt < (len>>2))  
+    {
+        if(spifc->SFC_SW & (FC_RX_FIFO_CNT_MASK<<FC_RX_FIFO_CNT))//rx fifo not empty
+        {           
+            p[cnt++]= spifc->SFC_DATA;
+        }
+    }
+
+    return ((cnt<<2) - (4 - remainder_cnt));
+}
+
+ void spifc_start(void)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    
+    spifc->SFC_START |= FC_START;
+}
+
+spinor_cmd_t *cmd_seek(u8 opcode)
+{
+	int i;
+
+	for(i = 0; (&nor_cmd_table[i]) != NULL; i++)
+	{
+		if(opcode == nor_cmd_table[i].cmd)
+		{
+			return (&nor_cmd_table[i]);
+		}
+	}
+
+	return NULL;	
+}
+
+int nor_read_reg(u8 opcode, int len, u8 *buf)
+{
+	int ret = 0;
+	spinor_cmd_t *cmd = NULL;
+	
+	cmd = cmd_seek(opcode);
+	if(cmd == NULL)
+	{
+		printf("cmd_seek unkown cmd error.\n");
+		return -1;
+	}
+	
+	spifc_setup_cmd(cmd, 0x0, len);            
+    spifc_start();                          
+    ret = spifc_wait_cmd_end();             
+    if(ret != 0)
+    {
+		printf("spifc_wait_cmd_end error.\n");
+	   	return ret;
+    }
+
+	ret = spifc_read_fifo(buf, len);
+	if(ret < 0)
+	{
+		printf("spifc_read_fifo error.\n");
+	    return ret;
+	}
+
+	return 0;	
+}
+
+int nor_read_id(void)
+{
+	int	tmp;
+	u8	id[SPI_NOR_MAX_ID_LEN];
+	const struct nor_info	*info;
+
+	tmp = nor_read_reg(CMD_RDID, SPI_NOR_MAX_ID_LEN, id);
+	if(tmp < 0) 
+	{
+		printf("error reading JEDEC ID\n");
+		return tmp;
+	}
+
+	for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) 
+	{
+		info = &spi_nor_ids[tmp];
+		if(info->id_len) 
+		{
+			if(!memcmp(info->id, id, info->id_len))
+			{
+				spi_nor_flash = info;
+				return 0;
+			}
+		}
+	}
+	printf("unrecognized JEDEC id\n");
+	return -1;
+	
+}
+ 
+int spi_nor_read(uint32_t from, size_t len, u_char *buf)
+{
+	int ret;
+	spinor_cmd_t *cmd = NULL;
+
+	cmd = cmd_seek(CMD_RDFT);
+	if(cmd == NULL)
+	{
+		printf("cmd_seek unkown error.\n");
+		return -1;
+	}
+
+	spifc_setup_cmd(cmd, from, len);	            
+	spifc_start();
+	ret = spifc_read_fifo(buf, len);
+	if(ret < 0)
+	{
+		printf("spifc_read_fifo error.\n");
+		return ret;
+	}
+
+	ret = spifc_wait_cmd_end();             
+    if(ret != 0)
+    {
+		printf("spifc_wait_cmd_end error.\n");
+	   	return ret;
+    }
+	
+	return 0;
+}
+
+int nor_read(uint32_t from, uint32_t len, uint32_t to)
+{
+	int ret;
+	u32 page_offset, page_size, i;
+	struct nor_info *info = spi_nor_flash;
+	
+	page_offset = from & (info->page_size - 1);
+
+	/* do all the bytes fit onto one page? */
+	if (page_offset + len <= info->page_size) {
+		ret = spi_nor_read(from, len, (uint8_t *)to);
+	} else {
+		/* the size of data remaining on the first page */
+		page_size = info->page_size - page_offset;
+		ret = spi_nor_read(from, page_size, (uint8_t *)to);
+
+		/* read everything in nor->page_size chunks */
+		for (i = page_size; i < len; i += page_size) {
+			page_size = len - i;
+			if (page_size > info->page_size)
+				page_size = info->page_size;
+
+			ret = spi_nor_read(from + i, page_size, ((uint8_t *)to + i));
+		}
+	}
+
+	return ret;
+}
+
+
+
+int nor_init(void)
+{
+	int ret = 0;
+
+	spifc_disable(); //hsy ?
+	
+	spifc_enable();
+
+	ret = nor_read_id();
+	if(ret != 0)
+	{
+		return -1;
+	}
+	
+	flash.flash_type = NOR_BOOT;
+	flash.page_size = spi_nor_flash->page_size;
+	flash.read = nor_read;		
+	
+	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 != NOR_BOOT)
+	{
+		printf("not nor flash.\n");
+		return -1; 
+	}
+	
+	writel(CFG_START_MODE_NOR, CFG_BOOT_MODE_START_MODE_FOR_UBOOT); 
+	ret = nor_init();
+	if(ret != 0)
+	{
+		printf("nor init err.\n");
+		return -1;
+	}
+
+	printf("nor init ok.\n");
+
+	return 0;
+}
+
+
+