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清零是必须的吧