[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/zx_mmc.c b/boot/common/src/loader/drivers/zx_mmc.c
new file mode 100644
index 0000000..057b6e9
--- /dev/null
+++ b/boot/common/src/loader/drivers/zx_mmc.c
@@ -0,0 +1,256 @@
+/*
+ * (C) Copyright 2003
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <common.h>
+#include "zx_mmc.h"
+#include "type.h"
+#include <asm/io.h>
+#include <image.h>
+#include <linux/byteorder/generic.h>
+
+
+u32 mmc_rca;
+static u32 ocr_avail = 0;
+static u32 block_addr = 0;
+
+#define MMC_BLOCK_SIZE 512
+
+static u32 emmc_cmd(u32 cmd, u32 arg,
+	void *resp, u32 flags)
+{
+	u32 *response = resp;
+	u32 i,response_words = 0;
+	u32 status,err_status = ZXMCI_STS_RE | ZXMCI_STS_RCRC | ZXMCI_STS_RTO;
+	u32 cmdreg;
+
+	/*Clear all raw interrupt status*/
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_RINTSTS) = 0xffffffff;
+
+	cmdreg = cmd & ZXMCI_CMD_INDEX_MASK;
+	cmdreg |= flags | ZXMCI_CMD_START;
+
+	cmdreg |= (0x1 << 29);
+	
+	if(flags & ZXMCI_CMD_RSPLEN)
+	{
+		response_words = 4;
+	}
+	else if(flags & ZXMCI_CMD_RSPEXP)
+	{
+		response_words = 1;
+	}
+
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_CMDARG) = arg;
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_CMD)    = cmdreg;
+
+/*check command done*/	
+	do {
+		status = REG32(SYS_EMMC_REGS_BASE+ZXMCI_RINTSTS);
+        
+	} while (!(status & ZXMCI_STS_CD)); 
+/*check error*/
+    if(status & err_status)
+    {
+        printf("send cmd error\n");
+        return 1;
+    }
+
+	for(i = 0;i < response_words;i++)
+	{
+		response[i] = REG32(SYS_EMMC_REGS_BASE+ZXMCI_RESP0 + i*4);
+	}
+	
+	return 0;
+}
+
+s32 zx_mmc_read(u32 src, u8 * dst, u32 size)
+{
+	u32 ret, i = 0,j = 0;
+	u32 resp;
+	u32 data;
+	u32 wordcount;
+	u32 *p = (u32 *)dst;
+	u32 status;
+	u32 start_addr;
+	u32 fifo_cnt;
+
+	if (size == 0)
+		return -1;
+
+	while((REG32(SYS_EMMC_REGS_BASE+ZXMCI_STATUS) & ZXMCI_STA_DATBUSY) != 0)
+	{
+		i++;
+        mmcdelay((80));
+		if(i>200)
+			break;
+	}
+
+
+	start_addr = src;
+
+
+	data = REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL);
+	data |=(1<<1) ;
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL) = data;
+
+    i = 0;
+    do
+    {
+		i++;
+        mmcdelay((80));
+        if(i>100)
+        {
+            printf("fifo reset failure");
+            break;
+        }
+	}while(REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL) & 2);
+
+
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_BYTCNT) = size;
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_BLKSIZ) = MMC_DEFAULT_BLKLEN;
+	
+	if (size > MMC_DEFAULT_BLKLEN)
+	{
+		ret = emmc_cmd(MMC_CMD_READ_MULTIPLE_BLOCK,start_addr, &resp,(R1 | CF_DATA));
+		if (ret)
+		{
+			return -MMC_CMD_READ_MULTIPLE_BLOCK;
+		}
+	}
+	else
+	{
+		ret = emmc_cmd(MMC_CMD_READ_SINGLE_BLOCK,start_addr, &resp,(R1 | CF_DATA));
+		if (ret)
+		{
+			return -MMC_CMD_READ_SINGLE_BLOCK;
+		}
+	}
+
+	wordcount = 0;
+	do {
+		
+		status = REG32(SYS_EMMC_REGS_BASE+ZXMCI_STATUS);	
+		fifo_cnt =(status >> 17) & 0x1fff;
+		for(j = 0;j < fifo_cnt;j++)
+		{
+			data = REG32(SYS_EMMC_REGS_BASE+ZXMCI_FIFO);
+			*p++ = data;
+			wordcount++;
+		}
+			
+	} while(wordcount < (size/4));
+		
+	return 0;
+    
+}
+
+static u32 mmc_bread(u32 dev_num, u32 blknr, u32 blkcnt, void *dst)
+{
+	u32 src = 0;
+	s32 ret;
+
+	if (block_addr == 0)
+	{
+		src = blknr * MMC_BLOCK_SIZE;
+	}
+	else
+	{
+		src = blknr;
+	}
+	
+	ret = zx_mmc_read(src, (u8 *) dst, blkcnt * MMC_BLOCK_SIZE);
+	if (ret < 0)
+	{
+		printf("mmc read error\n");
+		return 1;
+	}
+		
+	return blkcnt;
+}
+
+
+ void mmcdelay(unsigned long us)
+ {
+	volatile int i = 0; /* approximate */
+	for(i=0;i<5000;i++)
+	{
+        ;
+	}
+ }
+
+int mmc_read( u32 src, u32 length, void *dst)
+{
+    u32 blkcnt = 0;
+	u32 start_blk = 0;
+	int ret = 0;
+    
+    if(length%MMC_DEFAULT_BLKLEN)
+	    blkcnt = (length/MMC_DEFAULT_BLKLEN)+1;
+	else
+		blkcnt = (length/MMC_DEFAULT_BLKLEN);
+
+	start_blk = src/MMC_DEFAULT_BLKLEN;
+    block_addr = 1;
+
+	printf("entry mmc_bread\n");
+	ret = mmc_bread(0, start_blk, blkcnt, (void *)dst);
+
+	if(ret == blkcnt )
+		return 0;
+	else
+		return -1;
+
+}
+
+uint32_t page_align(uint32_t offset)
+{
+    uint32_t page_size = 2048;
+    if( offset & (page_size - 1) )
+    {
+        offset &= (~(page_size - 1));
+        offset += page_size;
+    }
+    return offset;
+}
+
+/*******************************************************************************
+ * Function:     nand_init
+ * Description: mmc init
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t mmc_init (void)
+{
+    return 0;
+    
+}
+
+