zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/boot/common/src/uboot/drivers/sdio/sdio.c b/boot/common/src/uboot/drivers/sdio/sdio.c
new file mode 100644
index 0000000..40244f2
--- /dev/null
+++ b/boot/common/src/uboot/drivers/sdio/sdio.c
@@ -0,0 +1,557 @@
+/*******************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º sdio.c
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º 1.0
+* ×÷¡¡¡¡Õߣºcaidaofang
+* Íê³ÉÈÕÆÚ£º
+*
+*
+*******************************************************************************/
+
+#include <common.h>
+#include <errno.h>
+#include <command.h>
+#include <malloc.h>
+#include <jffs2/load_kernel.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <load_image.h>
+#include <linux/byteorder/generic.h>
+#include <sdio.h>
+#include <image.h>
+#include <config.h>
+
+
+#define CFG_TEMP_ADDR   0x22000000
+
+#define CFG_SDIO_SLAVE_PACKAGE_LEN           0xD800     /* K  */
+#define CFG_SDIO_SLAVE_ALIGN_LEN           0x200     /* 512byte  */
+
+
+
+#define SYS_STD_CRM_BASE                   0x1307000
+#define DMA_BUFFER_SIZE_16K               (0x2<<1)
+
+#define DMA_BUFFER_SIZE_32K               (0x3<<1)
+#define DMA_BUFFER_SIZE_64K               (0x4<<1)
+
+#define DMA_BUFFER_SIZE_256K              (0x6<<1)
+#define DMA_BUFFER_SIZE_512K              (0x7<<1)
+#define SDIO_ERR                           -1
+#define SDIO_INPROGRESS                    -2
+
+static void usdelay(uint32_t delay)
+{
+    uint32_t i = 0;
+    for( ; i<delay*200; i++ );
+}
+
+static void sdio_clk_reset(void)
+{
+// enable sdio clk  16,17 hclk
+   REG32(SYS_STD_CRM_BASE+0x44) |= (0x3<<16);
+   usdelay(80);
+// release reset sdio clk 16 ahb clk
+   REG32(SYS_STD_CRM_BASE+0x48) |= (0x1<<16);
+   usdelay(80);
+}
+
+/*²ÉÓÃCPU¶ÁÈ¡FIFO£¬½ûÖ¹ÖжÏ*/
+static void sdio_initial_setup(void)
+{
+    u32 val = 0;
+  //  REG32(SDIO_SLAVE_IOREADY)          |= 0x3e;//ÅäÖÃ1-5bit
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0;  //mask sdio int
+    REG32(SDIO_SLAVE_INTSTATUS)         = 0xffffffff;//clear int
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0xffffffff; //enable status int
+
+    //REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0x33C0181B; //enable status int
+    REG32(SDIO_SLAVE_INTSIGNAL_EN)      = 0; //maskedÖжÏÐźÅ1£¬²»Éϱ¨¸øÖжϿØÖÆÆ÷
+    REG32(SDIO_SLAVE_INT_SIGNAL_EN2)    = 0; //maskedÖжÏÐźÅ2£¬²»Éϱ¨¸øÖжϿØÖÆÆ÷
+   // val = REG32(SDIO_SLAVE_SDIO_CCCR_CTRL);
+  /*  REG32(SDIO_SLAVE_SDIO_CCCR_CTRL)    = 0x3FF3E343;
+
+    REG32(0x1307080)= 0x7ffe0;
+
+    memset((u8*)0x20000000,0,1024*180);
+
+    val = REG32(SDIO_SLAVE_CARD_OCR);
+
+    REG32(SDIO_SLAVE_CARD_OCR) = val|0x01000000; */
+
+/*dma*/
+    /*dma1 address register config*/
+  //  REG32(SDIO_SLAVE_DMA1ADDR)          = CFG_SDIO_LOAD_BASE; //set dma address
+    /*adma/dma1 address register and buffer size is 0:not valid 1:valid,buffer size is 4K(default)*/
+   // REG32(SDIO_SLAVE_DMA1CTRL)         |=0x1|DMA_BUFFER_SIZE_256K;  //enable dma address
+    /*disable adma£¬enable dma ,sel one*/
+
+   /*REG32(SDIO_SLAVE_CTRL2)            &=(~0x4); */
+
+/*sdio slave config ready operate*/
+  //  REG32(SDIO_SLAVE_CTRL)             |=0x4; //ÅäÖõÚ2bit£¬±íʾ׼±¸²Ù×÷
+
+
+
+}
+
+int Sdio_Slave_Read_32K(const u32 load_addr,u32 len)
+{
+    u32 status =0 ;
+    int ret = 0;
+
+    u32 dma_addr = (u32)CFG_SDIO_LOAD_BASE;
+
+    REG32(SDIO_SLAVE_DMA1ADDR)  = CFG_SDIO_LOAD_BASE;  //CFG_SDIO_LOAD_BASE;
+    REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1|DMA_BUFFER_SIZE_32K;    //|DMA_BUFFER_SIZE_512K;    //256K
+
+    while(1)
+    {
+        status = REG32(SDIO_SLAVE_INTSTATUS);
+
+        if((status &SDIO_STS_DMA1)!=0)
+        {
+
+            dma_addr += 0x8000;
+            /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_DMA1);
+            /*2,clear*/
+
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_DMA1;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_DMA1;
+
+            REG32(SDIO_SLAVE_DMA1ADDR)  = dma_addr ;//CFG_SDIO_LOAD_BASE;
+            REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1|DMA_BUFFER_SIZE_32K;
+
+        }
+
+
+        if((status &SDIO_STS_TC)!=0)
+        {
+           // printf("SDIO xfer OK!\n");
+            break;
+        }
+
+        if((status &SDIO_STS_F_CRC_E)!=0)
+           {
+            printf("SDIO CRC Error!\n");
+
+           /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_CRC_E);
+            /*2,clear*/
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_CRC_E;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_CRC_E;
+
+            ret = SDIO_ERR;
+        }
+
+        if((status &SDIO_STS_F_A)!=0)
+           {
+
+            /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_A);
+            /*2,clear*/
+            //status = REG32(SDIO_SLAVE_INTSTATUS);
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_A;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_A;
+
+
+            printf("SDIO ABORT Xfer!\n");
+
+        }
+
+
+    }
+/*thansfer complete,write program done*/
+    REG32(SDIO_SLAVE_CTRL)     |= 0x1;
+/*clear int status*/
+    /*1,mask*/
+   // REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~(SDIO_STS_TC|SDIO_STS_WS|SDIO_STS_DMA1|SDIO_STS_F_A|SDIO_STS_F_CRC_E));
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0;
+    /*2,clear*/
+    status = REG32(SDIO_SLAVE_INTSTATUS);
+    REG32(SDIO_SLAVE_INTSTATUS) = status;
+    /*3,enalbe*/
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff;
+
+     /*thansfer complete,write program done*/
+   // REG32(SDIO_SLAVE_CTRL)     |= 0x1;
+
+   // REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0x33C0181B; //enable status int;
+    memcpy(load_addr,(u32)CFG_SDIO_LOAD_BASE,len);
+
+
+    return ret;
+}
+
+int Sdio_Slave_Write_Ack(void)
+{
+
+
+    u32 status = 0;
+    int ret = 0;
+
+   // u32 ack[2] = {0x11223344,0xAABBCCDD};
+
+    char *ack ="rxok";
+
+    memcpy((u32)CFG_SDIO_LOAD_BASE,ack,4);
+
+    printf("SDIO write ack\n");
+
+    REG32(SDIO_SLAVE_DMA1ADDR)  = CFG_SDIO_LOAD_BASE;
+    REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1;
+
+    while(1)
+    {
+        status = REG32(SDIO_SLAVE_INTSTATUS);
+
+
+        if((status &SDIO_STS_TC)!=0)
+        {
+           // printf("SDIO xfer OK!\n");
+            break;
+        }
+
+        if((status &SDIO_STS_F_CRC_E)!=0)
+           {
+            printf("SDIO CRC Error!\n");
+
+           /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_CRC_E);
+            /*2,clear*/
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_CRC_E;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_CRC_E;
+
+            ret = SDIO_ERR;
+        }
+
+        if((status &SDIO_STS_F_A)!=0)
+           {
+
+            /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_A);
+            /*2,clear*/
+            //status = REG32(SDIO_SLAVE_INTSTATUS);
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_A;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_A;
+
+
+            printf("SDIO ABORT Xfer!\n");
+
+        }
+
+
+    }
+/*thansfer complete,write program done*/
+   // REG32(SDIO_SLAVE_CTRL)     |= 0x1;
+/*clear int status*/
+    /*1,mask*/
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0;
+    /*2,clear*/
+    status = REG32(SDIO_SLAVE_INTSTATUS);
+    REG32(SDIO_SLAVE_INTSTATUS) = status;
+    /*3,enalbe*/
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff;
+
+    return ret;
+
+}
+
+static int sdio_slave_init(void)
+{
+
+    // SDIOÉèÖÃCPRMÄ£¿éµÄ´úÂë
+   // sdio_clk_reset();
+
+	// Initialize controller
+	sdio_initial_setup();
+
+	return 0;
+}
+
+static int slave_size = 0;
+
+/**************   success :return boot size  ***********/
+int sdio_slave_read(const u32 load_addr)
+{
+    u32 dwInt_status = 0;
+    u32 dwCurrent_Cmd = 0;
+    u32 cmdreg =0;
+    u32 argreg = 0;
+    u32 cmd = 0;
+    u32 blksize = 0;
+    u32 blkcnt = 0;
+    u32 boot_size = 0;
+
+    int ret = SDIO_INPROGRESS;
+
+    while(1)
+    {
+        // dwCurrent_CmdΪ53ʱ£¬½øÐÐÊý¾Ýдor¶Á²Ù×÷
+
+        dwCurrent_Cmd = ((REG32(SDIO_SLAVE_CMD)>>13) & 0x3F);
+
+        switch(dwCurrent_Cmd)
+        {
+		case SDIO_CMD53:
+            {
+
+            dwInt_status = REG32(SDIO_SLAVE_INTSTATUS);
+
+
+            if((dwInt_status & SDIO_STS_WS) == SDIO_STS_WS)
+            {
+                cmdreg = REG32(SDIO_SLAVE_CMD);
+                argreg = REG32(SDIO_SLAVE_ARGU);
+
+                blksize = (cmdreg >>1) &0xFFF;
+
+                blkcnt = argreg & 0x1FF;
+
+                if(!(argreg & 0x08000000))
+                {
+
+                   boot_size =blksize;
+                }
+                else
+                {
+                   boot_size =blkcnt * blksize;
+                }
+
+                slave_size = boot_size;
+
+
+               ret = Sdio_Slave_Read_32K(load_addr,boot_size);
+
+				if(!ret)
+					return boot_size;
+				else //if(ret == SDIO_ERR)
+					return SDIO_ERR;
+
+            }
+
+             break;
+           }
+		default:
+			break;
+        }
+
+    }
+
+    return boot_size;
+}
+
+int sdio_slave_write(void)
+{
+
+
+   u32 dwInt_status = 0;
+   u32 dwCurrent_Cmd = 0;
+   u32 cmdreg =0;
+   u32 argreg = 0;
+   u32 cmd = 0;
+   u32 blksize = 0;
+   u32 blkcnt = 0;
+   u32 boot_size = 0;
+
+   int ret = SDIO_INPROGRESS;
+
+
+    REG32(SDIO_SLAVE_FUN1CTRL) |= (0x4 & 0xFFFF);
+
+	while(1)
+	{
+        dwCurrent_Cmd = ((REG32(SDIO_SLAVE_CMD)>>13) & 0x3F);
+
+		switch(dwCurrent_Cmd)
+		{
+		case SDIO_CMD53:
+            {
+
+            dwInt_status = REG32(SDIO_SLAVE_INTSTATUS);
+
+
+            if((dwInt_status & SDIO_STS_RS) == SDIO_STS_RS)
+            {
+                cmdreg = REG32(SDIO_SLAVE_CMD);
+                argreg = REG32(SDIO_SLAVE_ARGU);
+
+                blksize = (cmdreg >>1) &0xFFF;
+
+                blkcnt = argreg & 0x1FF;
+
+                if(!(argreg & 0x08000000))
+                {
+
+                   boot_size =blksize;
+                }
+                else
+                {
+                   boot_size =blkcnt * blksize;
+                }
+
+
+               ret = Sdio_Slave_Write_Ack();
+
+				if(!ret)
+					return boot_size;
+				else //if(ret == SDIO_ERR)
+					return SDIO_ERR;
+
+            }
+
+             break;
+           }
+		default:
+			break;
+        }
+
+
+   }
+
+   return boot_size;
+
+}
+
+
+/*******************************************************************************
+ * Function:
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int sdio_slave_read_bin()
+{
+    int32_t len = 0;
+    uint32_t i =0;
+
+  /*1.µÚÒ»´Î½ÓÊÕ */
+    len = sdio_slave_read((u32)CFG_TEMP_ADDR);
+    if( len < 0 )
+    {
+        printf("sdio_slave: read first error\n");
+        goto sdio_error1;
+    }
+
+  /*2.»ñÈ¡°æ±¾ÐÅÏ¢ */
+    image_header_t *header = NULL;
+    header = (image_header_t *)CFG_TEMP_ADDR;
+    uint32_t header_size = sizeof(image_header_t);
+    uint32_t size = ___htonl(header->ih_size);
+    uint32_t load_addr = ___htonl(header->ih_load);
+    uint32_t entry_point = ___htonl(header->ih_ep);
+
+    printf("size = %d\n", (int)size);
+    printf("load_addr = 0x%0x\n", (unsigned int)load_addr);
+    printf("entry_point = 0x%0x\n", (unsigned int)entry_point);
+
+
+  /*3.¿½±´µÚÒ»´ÎÊý¾Ý */
+    memcpy(load_addr, CFG_TEMP_ADDR+sizeof(image_header_t), len);
+    load_addr = load_addr + len - header_size;
+
+  /*4.¼ÆËã´«Êä´ÎÊý */
+    /* Èç¹ûµÚÒ»´Î´«ÊäµÄ×Ö½Ú´óÓÚ»òµÈÓÚ°æ±¾µÄ´óС£¬Ôò´«ÊäÍê³ÉÖ±½Ó·µ»Ø */
+    if( (len > size) || (len == size) )
+    {
+        printf("sdio_slave: first finsh and return\n");
+        return 0;
+    }
+
+    uint32_t left_times = size/CFG_SDIO_SLAVE_PACKAGE_LEN;
+    uint32_t mod = size%CFG_SDIO_SLAVE_PACKAGE_LEN;
+    if( mod == 0 )
+    {
+        left_times--;
+    }
+
+    /* debug */
+    printf("sdio_slave: times = %d\n", (int)(left_times+1));
+
+
+
+  /*5.½ÓÊÕÆäÓàµÄÊý¾Ý */
+    for( i=0; i<(left_times); i++ )
+    {
+        //printf("sdio_slave: load_addr = 0x%0x\n",load_addr);
+        len = sdio_slave_read(load_addr);
+        if( len < 0 )
+        {
+            printf("sdio_slave: read others error\n");
+            goto sdio_error1;
+        }
+        load_addr += len;
+    }
+
+    return 0;
+ sdio_error1:
+    return -1;
+}
+
+/*******************************************************************************
+ * Function:
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+void sdio_slave_process(void)
+{
+    int ret = 0;
+
+    //sdio_slave_init();
+
+
+/* 1. ½ÓÊÕ  */
+    ret = sdio_slave_read_bin();
+    if( ret != 0 )
+    {
+       printf("sdio_slave: read big bin error\n");
+       goto wait_error;
+    }
+
+    ret = sdio_slave_write();
+    if(ret > 0)
+    {
+
+       printf("sdio_slave: write ack success\n");
+    }
+
+
+    printf("sdio_slave: read big bin OK\n");
+
+    while(1);
+
+wait_error:
+    printf("sdio_slave: error wait\n");
+    while(1);
+}
+