📄 sdhc.c
字号:
u32 temp; // Set_EMPC - Enable Master Power Control*/ // R/w F_No RAW stuff ADD stuff Data// rSDICARG=1<<31|0<<28|1<<27|0<<26|0x12<<9|0<<8|2<<0; temp = (u32)(1<<31|0<<28|1<<27|0<<26|0x12<<9|0<<8|2<<0); if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Set_EMPC : %x\n" , temp ); // IOE1 setting - Enable Function 1 in SDIO // R/w F_No RAW stuff ADD stuff Data temp = (u32)(1<<31|0<<28|1<<27|0<<26|0x2<<9|0<<8|2<<0); if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "IOE1 setting : %x\n" , temp ); // 4bit-width Setting. temp = (u32)(1<<31|0<<28|1<<27|0<<26|0x7<<9|0<<8|2<<0); if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "BUS width: %x\n" , temp ); Outp8( sCh->m_uBaseAddr+SDHC_HOST_CTRL, Inp8( sCh->m_uBaseAddr+SDHC_HOST_CTRL)& ~((1<<5)|(1<<1)) ); Outp8( sCh->m_uBaseAddr+SDHC_HOST_CTRL, Inp8( sCh->m_uBaseAddr+SDHC_HOST_CTRL)|(1<<1) ); // 4 bit bus mode. SDHC_SetHostCtrlSpeedMode( SDHC_NORMAL_SPEED, sCh ); // IO Block Size - Setting. - 0x800 -> 2048 /* I/0 block size for function 1 -LSB */ temp=(u32)(1<<31|0<<28|1<<27|0<<26|0x110<<9|0<<8|0x0<<0); if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Block Size LSB: %x\n" , temp ); temp=(u32)(1<<31|0<<28|1<<27|0<<26|0x110<<9|0<<8|0x2<<0); // youngbo.song - 0x8 if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Block Size MSB: %x\n" , temp ); // IO Block Size -- Setting -0x800 ->2048 temp=(u32)(1<<31|0<<28|0<<27|0<<26|0x10<<9|0<<8|0x0<<0); if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Block Size LSB: %x\n" , temp ); temp=(u32)(1<<31|0<<28|0<<27|0<<26|0x11<<9|0<<8|0x2<<0); // youngbo.song - 0x8 if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Block Size MSB: %x\n" , temp ); // Slave Interrupt Enable temp=(u32)(1<<31|0<<28|1<<27|0<<26|0x4<<9|0<<8|0x03<<0); //Set LSB if( !SDHC_IssueCommand52( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE, 0 ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Slave Interrupt Enable: %x\n" , temp ); // read Card Support Read Wait. temp=(u32)(0<<31|1<<28|1<<27|0<<26|8<<9|0<<8); if ( !SDHC_IssueCommand( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE ) ) { return FALSE; } temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Read Wait Bit------: %x\n" , temp ); return TRUE;}// Set SDIO Address for Channel IC.bool SDHC_setSDIOAddress( SDHC * sCh, u32 address ) { u32 temp; // set address mode temp=(u32)((1<<31)|(1<<28)|(1<<27)|(0<<26)|(0x1FF0C<<9)|(0<<8)|(address&0xff)<<0); if( !SDHC_IssueCommand( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Set address mode: %x\n" , temp ); temp=(u32)(1<<31|1<<28|1<<27|0<<26|(0x1FF0D<<9)|0<<8|((address>>8)&0xff)<<0); if( !SDHC_IssueCommand( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Set address mode: %x\n" , temp ); temp=(u32)(1<<31|1<<28|1<<27|0<<26|(0x1FF0E<<9)|0<<8|((address>>16)&0xff)<<0); if( !SDHC_IssueCommand( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Set address mode: %x\n" , temp ); temp=(u32)(1<<31|1<<28|1<<27|0<<26|(0x1FF0F<<9)|0<<8|((address>>24)&0xff)<<0); if( !SDHC_IssueCommand( sCh, 52, temp, SDHC_CMD_AC_TYPE, SDHC_RES_R5_TYPE ) ) return FALSE; temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); printf( "Set address mode: %x\n" , temp ); return TRUE;}// -------SDIO Test ----------------------------------------bool SDHC_newOCR(SDHC* sCh) { u32 temp; if ( sCh->m_eClockSource == SDHC_EXTCLK ) { SDHC_SetSdClock(0x40, sCh, SDHC_NORMAL_SPEED, 400000); // Under 400Khz. } else { SDHC_SetSdClock(0x80, sCh, SDHC_NORMAL_SPEED, 400000); // Under 400Khz. } Outp8( sCh->m_uBaseAddr+SDHC_TIMEOUT_CTRL, (Inp8(sCh->m_uBaseAddr+SDHC_TIMEOUT_CTRL)&(0xF<<4))|0xe); // Timeout setting. Outp8( sCh->m_uBaseAddr+SDHC_HOST_CTRL, Inp8( sCh->m_uBaseAddr+SDHC_HOST_CTRL ) & (~(0x1<<2)) ); // NORMAL Speed mode. SDHC_SetHostCtrlSpeedMode(SDHC_NORMAL_SPEED, sCh); SDHC_SetSdhcInterruptEnable(0xFF, 0xFF, sCh); // Place all cards in the idle state. if (!SDHC_IssueCommand( sCh, 0, 0, SDHC_CMD_BC_TYPE, SDHC_RES_NO_TYPE ) ) return FALSE; /* if ( !SDHC_IssueCommand( sCh, 5, 0, SDHC_CMD_AC_TYPE, SDHC_RES_R3_TYPE ) ) { return FALSE; } temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); sdDbg(( "Number of IO function : %d \n", (temp>>28)&0x7 )); sdDbg(( "Memory Presend : %d\n", (temp>>27)&0x1)); sdDbg(( "OCR: %x\n", temp )); */ // (Ocr:3.1V~3.3V) while ( 1 ) { if ( !SDHC_IssueCommand( sCh, 5, 0x380000, SDHC_CMD_AC_TYPE, SDHC_RES_R3_TYPE ) ) { // The current card is MMC card, then there's time out error, need to be cleared. SDHC_ClearErrInterruptStatus(sCh); return FALSE; // not sdio card. } else { temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); if ( temp & (u32)(1<<31) ) { sdDbg(( "Ready\n" )); break; } } } temp = Inp32( sCh->m_uBaseAddr+SDHC_RSP0 ); sdDbg(( "OCR: %x\n", temp )); sdDbg(( "Number of IO function : %d \n", (temp>>28)&0x7 )); sdDbg(( "Memory Presend : %d\n", (temp>>27)&0x1)); sCh->m_eCardType = SDHC_SDIO_CARD; sCh->m_eTransMode = SDHC_BYTE_MODE; // The current card is MMC card, then there's time out error, need to be cleared. SDHC_ClearErrInterruptStatus(sCh); if ( !( temp & (u32)(1<<31) ) ) { sdDbg(( "Not Ready\n" )); return FALSE; } sCh->m_uRca=0; if( !SDHC_IssueCommand( sCh, 3, sCh->m_uRca<<16, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ) ) { return FALSE; } sCh->m_uRca = (Inp32(sCh->m_uBaseAddr+SDHC_RSP0)>>16)&0xFFFF; sdDbg(("=> RCA=0x%x\n", sCh->m_uRca)); // card Selection if ( !SDHC_IssueCommand( sCh, 7, (u32)(sCh->m_uRca<<16), SDHC_CMD_AC_TYPE, SDHC_RES_R1B_TYPE ) ) return FALSE; // SDCLK Value Setting + Internal Clock Enable Outp16( sCh->m_uBaseAddr+SDHC_CLK_CTRL, (Inp16(sCh->m_uBaseAddr+SDHC_CLK_CTRL)&(~(0xff<<8)))|(sCh->m_uClockDivision<<8)|(1<<0) ); // Print SDIO Infomation. SDHC_printSDIOInfo( sCh ); return TRUE;}//////////// File Name : SDHC_SetSDOCR// File Description : Get SD OCR Register from SD Card.// Input : SDHC channel// Output : success or failure.bool SDHC_SetSDOCR(SDHC* sCh){ u32 i, OCR; // Place all cards in the idle state. if (!SDHC_IssueCommand( sCh, 0, 0, SDHC_CMD_BC_TYPE, SDHC_RES_NO_TYPE ) ) return FALSE; if ( SDHC_IssueCommand( sCh, 8, (0x1<<8)|(0xaa), SDHC_CMD_BCR_TYPE, SDHC_RES_R7_TYPE ) == TRUE ) { sdDbg( ( "CMD8 return TRUE\n" )); } // Normal SD has Command Response Error. SDHC_ClearErrInterruptStatus(sCh); for(i=0; i<500; i++) { // CMD55 (For ACMD) SDHC_IssueCommand( sCh, 55, 0, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ); // (Ocr:2.7V~3.6V) SDHC_IssueCommand( sCh, 41, 0x40ff8000, SDHC_CMD_BCR_TYPE, SDHC_RES_R3_TYPE ); if (Inp32(sCh->m_uBaseAddr+SDHC_RSP0)&(unsigned int)(0x1<<31)) { OCR = Inp32( sCh->m_uBaseAddr+SDHC_RSP0); //sdDbg(("\nrHM_RSPREG0=%x",rHM_RSPREG0)); if(OCR & (1<<7)) sdDbg(("Voltage range : 1.65V ~ 1.95V\n")); if(OCR & (1<<21)) sdDbg(("Voltage range: 2.7V ~ 3.4V\n")); else if(OCR & (1<<20)) sdDbg(("Voltage range: 2.7V ~ 3.3V\n")); else if(OCR & (1<<21)) sdDbg(("Voltage range: 2.7V ~ 3.4V\n")); else if(OCR & (1<<23)) sdDbg(("Voltage range: 2.7V ~ 3.6V\n")); if(OCR&(0x1<<30)) { sCh->m_eTransMode = SDHC_BLOCK_MODE; sdDbg(("High Capacity Card\n")); } else { sCh->m_eTransMode = SDHC_BYTE_MODE; sdDbg(("Byte mode\n")); } // Normal SD has Command Response Error. SDHC_ClearErrInterruptStatus(sCh); sCh->m_eCardType = SDHC_SD_CARD; return TRUE; } } // The current card is MMC card, then there's time out error, need to be cleared. SDHC_ClearErrInterruptStatus(sCh); return FALSE;}// Clock delay value for temporary.unsigned int sdhc_find_delay_tx;unsigned int sdhc_find_delay_rx;//////////// File Name : SDHC_SetSDOCR// File Description : Get SD OCR Register from SD Card.// Input : SDHC channel// Output : success or failure.void SDHC_SetSdClock(u32 uDivisor, SDHC* sCh, SDHC_SpeedMode speed, u32 workingFreq ){#if 0// No delay External Bus ONLY. if ( speed == SDHC_NORMAL_SPEED ) {// tx / rx Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, (1<<30)|(0x0<<15)|(0x0<<14)|(0x1<<8)|(sCh->m_eClockSource<<4) ); } else { Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, (1<<30)|(1<<15)|(1<<14)|(0x1<<8)|(sCh->m_eClockSource<<4) ); Outp32( sCh->m_uBaseAddr+SDHC_CONTROL3, ((sdhc_find_delay_tx&2)<<30) | ((sdhc_find_delay_tx&1)<<23) | ((sdhc_find_delay_rx&2)<<14) | ((sdhc_find_delay_rx&1)<<7) ); }#else // Host Controller sensitively react to feedback clock delay value. // There is need to SD/MMC card compliance test. if ( speed == SDHC_NORMAL_SPEED ) {// tx / rx Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, (0x0<<15)|(0x0<<14)|(0x1<<8)|(sCh->m_eClockSource<<4) ); Outp32( sCh->m_uBaseAddr+SDHC_CONTROL3, (1<<31) | (1<<23) | (0<<15) | (0<<7) ); } else { // Common High Speed Card Feedback clock delay setting. if ( workingFreq >= SDHC_CARD_DELAY_ON_CLOCK ) { Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, (1<<30)|(1<<15)|(1<<14)|(0x1<<8)|(sCh->m_eClockSource<<4) ); Outp32( sCh->m_uBaseAddr+SDHC_CONTROL3, (0<<31) | (0<<23) | (1<<15) | (1<<7) ); } else { // Turn off delay chain at 25~33Mhz.. // Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, (0<<15)|(0<<14)|(0x1<<8)|(sCh->m_eClockSource<<4) ); Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, (1<<30)|(0<<15)|(0<<14)|(0x1<<8)|(sCh->m_eClockSource<<4) ); Outp32( sCh->m_uBaseAddr+SDHC_CONTROL3, (1<<31) | (1<<23) | (0<<15) | (0<<7) ); } }#endif // SDCLK Value Setting + Internal Clock Enable Outp16( sCh->m_uBaseAddr+SDHC_CLK_CTRL, (Inp16(sCh->m_uBaseAddr+SDHC_CLK_CTRL)&(~(0xff<<8)))|(uDivisor<<8)|(1<<0) ); // CheckInternalClockStable while (!(Inp16( sCh->m_uBaseAddr+SDHC_CLK_CTRL )&0x2)); SDHC_SetSdClockOnOff( TRUE, sCh); sdDbg(("rHM_CONTROL2 = %x\n",Inp32( sCh->m_uBaseAddr+SDHC_CONTROL2 ))); sdDbg(("rHM_CLKCON = %x\n",Inp16( sCh->m_uBaseAddr+SDHC_CLK_CTRL )));}//////////// File Name : SDHC_CMD52_DMA_Handler// File Description : DMA Interrupt Handler Only for SDIO.// Input : NONE// Output : NONEvoid __irq SDHC_CMD52_DMA_Handler(void) { SDHC *sCh = SDHC_curr_card[SDHC_CHANNEL_0]; //1 You have to fit on your SDIO channel. int i;// SDHC_InterruptInspector( sCh ); if( ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_TRANSFERCOMPLETE_SIG_INT_EN ) && ( Inp16( sCh->m_uBaseAddr+SDHC_BLK_COUNT) == 0 ) ) { // sdDbg(("\nTransfer Complete\n")); // sdDbg(("T")); SDHC_INT_WAIT_CLEAR( sCh, 1, i);//SDHC_TRANSFERCOMPLETE_STS_INT_EN sCh->m_uRemainBlock=0; INTC_Disable(NUM_HSMMC1); } if ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_DMA_SIG_INT_EN ) { // sdDbg((" DMA buffer boundary is detected!\n")); // sdDbg(("B")); SDHC_INT_WAIT_CLEAR( sCh, 3, i); //SDHC_TRANSFERCOMPLETE_STS_INT_EN // SDHC_SetSystemAddressReg(sCh, Inp32(sCh->m_uBaseAddr+SDHC_SYS_ADDR) ); } if ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_CCS_INTERRUPT_STATUS_EN ) { SDHC_INT_WAIT_CLEAR( sCh, 9, i); //SDHC_CCS_INTERRUPT_STATUS_EN sCh->m_uCCSResponse=0;// sdDbg(("SDHC_CCS_INTERRUPT_STATUS_EN----------------\n"));// sdDbg(("C")); } INTC_ClearVectAddr();}//////////// File Name : SDHC_CMD53_RW// File Description : Data Read or Write Transaction Only for SDIO.// Input : ReadWrite : 0 - read / 1 - write.// uStBlock : start block address, uBlocks : data block size, uBufaddr : Source/Target Buffer Address, SDHC channel// Output : success or failurebool SDHC_CMD53_RW(u32 ReadWrite, u32 uStBlock, u16 uBlocks, u32 uBufAddr, SDHC* sCh) { u32 temp; if(sCh->m_eTransMode == SDHC_BYTE_MODE) uStBlock = uStBlock<<9; // uStBlock * 512; sCh->m_uRemainBlock = uBlocks; // number of blocks. sCh->m_uBufferPtr = (u32*)uBufAddr; // test Set Address. SDHC_setSDIOAddress(sCh, 0); INTC_SetVectAddr( sCh->m_ucIntChannelNum, SDHC_CMD52_DMA_Handler ); INTC_Enable( sCh->m_ucIntChannelNum ); Outp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT_ENABLE,// Inp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT_ENABLE)| SDHC_TRANSFERCOMPLETE_SIG_INT_EN| SDHC_BLOCKGAP_EVENT_SIG_INT_EN| SDHC_READWAIT_SIG_INT_EN| SDHC_COMMANDCOMPLETE_SIG_INT_EN ); Outp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_SIGNAL_ENABLE, SDHC_READWAIT_SIG_INT_EN| SDHC_BLOCKGAP_EVENT_SIG_INT_EN| SDHC_TRANSFERCOMPLETE_SIG_INT_EN); SDHC_SetSystemAddressReg(sCh, (u32)uBufAddr);// AHB System Address For Write SDHC_SetBlockSizeReg(sCh, 7, 512); // Maximum DMA Buffer Size, Block Size SDHC_SetBlockCountReg(sCh, uBlocks); // Block Numbers to Write SDHC_SetTransferModeReg( (uBlocks==1)?(0):(1), 1, 0, 1, 1, sCh ); Outp32(sCh->m_uBaseAddr+SDHC_CONTR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -