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