代码改变世界

SD卡 UBOOT环境

2013-03-27 16:54  至上  阅读(1603)  评论(0编辑  收藏  举报
static __inline__ void sdio_init( void )
{
        int resp;
        int temp;
        int no_resp;
        int resp_vld;
        int ccs;
    int i;

    __arch_putl(0x0,0x91004010);            /*stop clock*/                                          
        __arch_putl(0x80202000,0x9100402c);     /*updata clock*/                                        
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*wait updata clock*/
    __arch_putl(8,0x910040a0);            /*ahb 8  400k*/
        __arch_putl(128,0x91004008);            /*div0 16*/
        __arch_putl(0x0,0x9100400c);            /*clock 0*/
    __arch_putl(0x0,0x91004018);             /*ctype 1*/
        __arch_putl(0x80202000,0x9100402c);     /*updata clock*/
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*wait updata clock*/

    __arch_putl(0x1,0x91004010);            /*enable clock*/
        __arch_putl(0x80202000,0x9100402c);     /*updata clock*/
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*wait updata clock*/    

    printf("SDMMCInit cmd0\n");
    __arch_putl(0x0,0x91004028);/*cmd0*/
    __arch_putl(0x80008000,0x9100402c);
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
    do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
    }while(temp != 0x4);
    __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("resp_cmd0 = 0x%08x\n",__arch_getl(0x91004030));/*cuo wei*/

    printf("SDMMCInit cmd8\n");
    __arch_putl(0x1aa,0x91004028);  /*cmd8*/
    __arch_putl(0x80002148,0x9100402c);
    while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
     do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
    __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("resp_cmd8 = 0x%08x\n",__arch_getl(0x91004030));
    
    do{
    printf("SDMMCInit cmd55\n");
    __arch_putl(0x0,0x91004028); /*cmd55*/
    __arch_putl(0x80002177,0x9100402c);
    while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
     do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("resp_cmd55 = 0x%08x\n",__arch_getl(0x91004030));

    printf("SDMMCInit cmd41\n");
    __arch_putl(0x40300000,0x91004028);/*acmd41*/
    __arch_putl(0x80002069,0x9100402c);
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
    do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("resp_cmd41 = 0x%08x\n",__arch_getl(0x91004030));
    resp = __arch_getl(0x91004030);
      resp = resp & 0x80000000;
    }while(resp != 0x80000000);        


    printf("SDMMCInit cmd2\n");
    __arch_putl(0x0,0x91004028);/*cmd2*/
    __arch_putl(0x800021c2,0x9100402c);
    while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
    do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("resp_cmd2 = 0x%08x\n",__arch_getl(0x9100403c));
    printf("resp_cmd2 = 0x%08x\n",__arch_getl(0x91004038));
    printf("resp_cmd2 = 0x%08x\n",__arch_getl(0x91004034));
    printf("resp_cmd2 = 0x%08x\n",__arch_getl(0x91004030));
        
    printf("SDMMCInit cmd3\n");
    __arch_putl(0x0,0x91004028);/*cmd3*/
    __arch_putl(0x80002143,0x9100402c);
    while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
    do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
        resp = __arch_getl(0x91004030);
    printf("resp_cmd3 = 0x%08x\n",__arch_getl(0x91004030));
        gRCA = resp >> 16;

    printf("SDMMCInit cmd7\n");
        __arch_putl(gRCA<<16,0x91004028);/*cmd7*/
        __arch_putl(0x80002147,0x9100402c);
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
        do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        printf("resp_cmd7 = 0x%08x\n",__arch_getl(0x91004030));
        __arch_putl(__arch_getl(0x91004044),0x91004044);

    printf("stop clock to update to 50M\n");
        __arch_putl(0x0,0x91004010);            /*stop clock*/
        __arch_putl(0x80202000,0x9100402c);     /*updata clock*/
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*wait updata clock*/

        __arch_putl(0x1,0x910040a0);            /*ahb 1  50Mhz*/
        __arch_putl(0x2,0x91004008);            /*div0 1*/
        __arch_putl(0x0,0x9100400c);            /*clock 0*/
        __arch_putl(0x1,0x91004018);            /*bus 4*/
        __arch_putl(0x80202000,0x9100402c);     /*updata clock*/
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*wait updata clock*/

        __arch_putl(0x1,0x91004010);            /*enable clock*/
        __arch_putl(0x80202000,0x9100402c);     /*updata clock*/
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*wait updata clock*/
        printf("clock update over\n");


    printf("cmd 55\n");
    temp = gRCA<<16;
    temp = temp & 0xffff0000;
    __arch_putl(temp,0x91004028); /*cmd55*/
        __arch_putl(0x80000177,0x9100402c);
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
         do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
        printf("resp_cmd55 = 0x%08x\n",__arch_getl(0x91004030));

    printf("cmd 6\n");
    __arch_putl(0x2,0x91004028); /*cmd6 switch 4 bus*/
        __arch_putl(0x80002146,0x9100402c);
        while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);
         do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
        printf("resp_cmd6 = 0x%08x\n",__arch_getl(0x91004030));

    printf("SDMMCInit out\n");  
}

static inline void dma_transfer(void)
{
        printf("dma_transfer into\n");
        *(unsigned int *)0x30000000 = 0x80000018;  /*des0*/
        *(unsigned int *)0x30000004 = 0x3000;      /*des1*/
        *(unsigned int *)0x30000008 = 0x30001000;  /*des2*/

        *(unsigned int *)0x30000010 = 0x80000010;  /*des0*/
        *(unsigned int *)0x30000014 = 0x3000;      /*des1*/
        *(unsigned int *)0x30000018 = 0x30004000;  /*des2*/

    *(unsigned int *)0x30000020 = 0x80000010;  /*des0*/
        *(unsigned int *)0x30000024 = 0x3000;      /*des1*/
        *(unsigned int *)0x30000028 = 0x30007000;  /*des2*/
   
        *(unsigned int *)0x30000030 = 0x80000014;  /*des0*/
        *(unsigned int *)0x30000034 = 0x3000;      /*des1*/
        *(unsigned int *)0x30000038 = 0x3000a000;  /*des2*/

        *(unsigned int *)0x3000000c = 0x30000010;   /*des3*/
        *(unsigned int *)0x3000001c = 0x30000020;  /*des3*/
        *(unsigned int *)0x3000002c = 0x30000030;  /*des3*/
        *(unsigned int *)0x3000003c = 0;           /*des3*/

    __arch_putl(0x30000000,0x91004088); /*first dma struct address*/
        __arch_putl(0x82,0x91004080);               /*open dma*/
        printf("dma_transfer out\n");
}
static __inline__ void sd_init(void)
{
    int temp,resp,ready_for_data;
    printf("sd init\n");
        __arch_putl(0x22000037,0x91004000);     /*ctrl*/
        __arch_putl(0x20070008,0x9100404c);     /*fifo*/
        __arch_putl(0x3ffff,0x91004044);     /*RINTSTS*/

    sdio_init();
    do{
        __arch_putl(gRCA<<16,0x91004028);
            __arch_putl(0x8000014d,0x9100402c);
            do{
               temp = __arch_getl(0x91004044);
               temp = temp & 0x4;
              }while(temp != 0x4);
            temp = __arch_getl(0x91004044);
            __arch_putl(temp,0x91004044);
            resp = __arch_getl(0x91004030);
        resp = resp & 0x100;
        printf("resp_cmd13 = 0x%08x\n",resp);
    }while(resp !=0x100);
#if 1
    printf("cmd_16\n");
         __arch_putl(0x200,0x91004028);          
    __arch_putl(0x80002150,0x9100402c);     /*cmd 16*/
     while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*cmd done*/
     do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("resp_cmd16=0x%08x\n",__arch_getl(0x91004030));
#endif    
    __arch_putl(0x200,0x9100401c);          /*blksize*/
    __arch_putl(0xc000,0x91004020);         /*48k*/
    dma_transfer();
    printf("cmd_18\n");
         __arch_putl(0x0,0x91004028);           /*address 0*/
    __arch_putl(0x80002352,0x9100402c);     /*cmd 18*/
     while((__arch_getl(0x9100402c)&0x80000000)==0x80000000);/*cmd done*/
    do{
           temp = __arch_getl(0x91004044);
           temp = temp & 0x4;
        }while(temp != 0x4);
        __arch_putl(temp,0x91004044);
    printf("resp_cmd18=0x%08x\n",__arch_getl(0x91004030));
        printf("RINTSTS=0x%08x\n",__arch_getl(0x91004044));
    printf("cmd transfer over\n");
    do{                                                                                             
           temp = __arch_getl(0x91004044);                                                              
           temp = temp & 0x8;                                                                           
        }while(temp != 0x8);
        __arch_putl(__arch_getl(0x91004044),0x91004044);
    printf("sd data transfer over\n");


        printf("DATA=0x%08x\n",__arch_getl(0x91004100));
        printf("RINTSTS=0x%08x\n",__arch_getl(0x91004044));
        printf("IDSTS=0x%08x\n",__arch_getl(0x9100408c));
        printf("DMA=0x%08x\n",__arch_getl(0x91004094));
        printf("BUF=0x%08x\n",__arch_getl(0x91004098));
        printf("IDSTS=0x%08x\n",__arch_getl(0x9100408c));
        printf("BMOD=0x%08x\n",__arch_getl(0x91004080));
        printf("TBBCNT=0x%08x\n",__arch_getl(0x91004060));
        printf("0x30001000=0x%08x\n",*(unsigned int *)0x30001000);
        printf("0x30004000=0x%08x\n",*(unsigned int *)0x30004000);
        printf("0x30007000=0x%08x\n",*(unsigned int *)0x30007000);
        printf("0x3000a000=0x%08x\n",*(unsigned int *)0x3000a000);
}
  •  在UBOOT中,ahb总线分频失效,所以配置时钟要注意,400k和50M
  • 时钟不对的时候,会引起resp返回过慢,在命令中断产生时也读不到resp的值
  • 在调试的时候轮询比中断好用,轮询的时候可以查看相关寄存器的值,中断就不是那么方便了
  • sd卡初始化要注意顺序,一开始我认为直接上50M的时钟,就可以读取sd卡数据了,其实不是的。此时sd卡还不在传输状态,也不是4线模式。协议中说RCA是必须的,就是说cmd3是必须的。在发cmd3之前需要发acmd41,直到最高位置1.在cmd3之后需要cmd7切换到数据传输状态,然后改变时钟为50M,之后发acmd6切换为4线模式。然后就可以传输数据了。所以sd卡的初始化并不是每个cmd都是必须的,有些什么CSD CID等内容可以不读。
  • 如果cmd7 acmd6 cmd13 cmd18等resp不正常,这些命令都是在时钟改为50M之后发的,把时钟改低点就没问题了,不知道为什么。
  • 单个segment大小大于12K就不行了,dma本身有问题。
  • 对于DATA寄存器  应该是读一个数据,就少一个数据,所以测试的时候是不是不能随便读
  • 数据传输结束后,会发送cmd12,sd卡接受到命令后就停止发送数据,但这之间有一段延迟,致使fifo中有不需要的数据,所以fifo清零是必须的吧