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