[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/sdio.c b/boot/common/src/loader/drivers/sdio.c
new file mode 100644
index 0000000..03b4acc
--- /dev/null
+++ b/boot/common/src/loader/drivers/sdio.c
@@ -0,0 +1,544 @@
+/*******************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º sdio.c
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º 1.0
+* ×÷¡¡¡¡Õߣºcaidaofang
+* Íê³ÉÈÕÆÚ£º 
+*
+*
+*******************************************************************************/
+#include <common.h>
+#include <linux/byteorder/generic.h>
+#include <asm/io.h>
+#include <sdio.h>
+#include <image.h>
+
+
+#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
+
+uint32_t uboot_entry_point = 0;
+
+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)    = val;//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_4K(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_512K;    //256K
+    
+    while(1)
+    {
+        status = REG32(SDIO_SLAVE_INTSTATUS);
+
+        if((status &SDIO_STS_DMA1)!=0)
+        {
+
+            dma_addr += 0x1000;
+            /*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;
+                     
+        }
+        
+
+        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();
+
+
+    
+}
+
+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_4K(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;
+
+     printf("SDIO slave write \n");
+ 
+    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);
+    uboot_entry_point = ___htonl(header->ih_ep);
+
+  /*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: display the transfer times\n");
+    for( i=0; i<left_times+1; i++ )
+        printf(" + ");
+    printf("\n");
+
+  /*5.½ÓÊÕÆäÓàµÄÊý¾Ý */ 
+    for( i=0; i<left_times; i++ )
+    {
+        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();
+    printf("run into sdio_slave_process\n");
+/* 1. ½ÓÊÕuboot  */
+    ret = sdio_slave_read_bin();
+    if( ret != 0 )
+    {
+       printf("sdio_slave: read uboot error\n");
+       goto wait_error;
+    }
+    printf("sdio_slave: read uboot OK\n");
+
+
+    
+   ret = sdio_slave_write();
+   if(ret > 0)
+   {
+
+      printf("sdio_slave: write ack success\n"); 
+   }
+
+    
+
+    /*  r7 Ìø×ªÆô¶¯´úÂë */ 
+    writel(0xE59ff000, 0x100000);             
+    writel(uboot_entry_point, 0x100000 + 8);   
+
+    printf("Start the uboot....\n");
+
+    
+    writel(0xf, 0x130702c); 
+      
+    while(1);
+    
+wait_error:
+    printf("sdio_slave: error wait\n");
+    while(1);
+}
+