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