📄 sdhc.c
字号:
} else { // CMD18: Multi-Read if( !SDHC_IssueCommand( sCh, 18, uStBlock, SDHC_CMD_ADTC_TYPE, SDHC_RES_R1_TYPE )) { return FALSE; } } if ( sCh->m_eOpMode == SDHC_POLLING_MODE ) { while( sCh->m_uRemainBlock != 0 ) { SDHC_ReadOneBlock( sCh, 0 ); } } else if ( sCh->m_eOpMode == SDHC_INTERRUPT_MODE ) { Outp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_SIGNAL_ENABLE, Inp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_SIGNAL_ENABLE)|SDHC_BUFFER_READREADY_SIG_INT_EN ); INTC_Enable( sCh->m_ucIntChannelNum ); while(sCh->m_uRemainBlock != 0 ); } else if ( sCh->m_eOpMode == SDHC_DMA_MODE ) { while(sCh->m_uRemainBlock != 0 ); } // wait for Transfer Complete if ( sCh->m_eOpMode != SDHC_DMA_MODE ) { // When DMA mode, clear at DMA Done handler. SDHC_INT_WAIT_CLEAR( sCh, 1, i ); } return TRUE; // block_cnt * 512}//////////// File Name : SDHC_EraseBlocks// File Description : Erase Block test - erase block size depend on card specification.// Input : SDHC channel, startblock, end-block// Output : Success or Failurebool SDHC_EraseBlocks( SDHC* sCh, u32 startBlock, u32 endBlock ) { u32 endAddress; if(sCh->m_eCardType == SDHC_SD_CARD) { SDHC_IssueCommand( sCh, 32, startBlock, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ); SDHC_IssueCommand( sCh, 33, endBlock, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ); } else if(sCh->m_eCardType == SDHC_MMC_CARD) { SDHC_IssueCommand( sCh, 35, startBlock, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ); SDHC_IssueCommand( sCh, 36, endAddress, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ); } SDHC_IssueCommand( sCh, 38, 0, SDHC_CMD_AC_TYPE, SDHC_RES_R1B_TYPE ); return TRUE;}//////////// File Name : SDHC_IsErrorOccured// File Description : Get error source data. // Input : SDHC channel// Output : Success or Failurebool SDHC_IsErrorOccured(SDHC* sCh){ u16 usStatus; usStatus = Inp16( sCh->m_uBaseAddr+SDHC_ERROR_INT_STAT ); if (usStatus!= 0) { sdDbg((" SDHC_ERROR_INT_STAT = 0x%x.\n", usStatus)); return TRUE; } else return FALSE;}//////////// File Name : SDHC_WaitForCard2TransferState// File Description : Get error source data. // Input : SDHC channel// Output : Success or Failurebool SDHC_WaitForCard2TransferState(SDHC* sCh) { u32 uStatus; // do until programming status. do { if ( !SDHC_IssueCommand( sCh, 13, sCh->m_uRca<<16, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE) ) { return FALSE; } uStatus = (Inp32( sCh->m_uBaseAddr+SDHC_RSP0)>>9) & 0xf; } while(uStatus==7); return (uStatus==4) ? TRUE : FALSE;}//////////// File Name : SDHC_ResetController// File Description : Reset SDHC Controller.// Input : SDHC channel// Output : NONE.void SDHC_ResetController(SDHC* sCh) { Outp8( sCh->m_uBaseAddr+SDHC_SOFTWARE_RESET, 0x3);}//////////// File Name : SDHC_IssueCommand// File Description : This function issue sd/mmc command.// Input : SDHC, command Index, Argument, Command Type, Response Type// Output : Command Result.bool SDHC_IssueCommand( SDHC* sCh, u16 uCmd, u32 uArg, SDHC_CommandType cType, SDHC_ResponseType rType ) { u16 sfrData; u32 Loop; while( Inp32( sCh->m_uBaseAddr+SDHC_PRESENT_STAT ) & 0x1 ); // Check CommandInhibit_CMD if ( rType == SDHC_RES_R1B_TYPE ) { while( Inp32( sCh->m_uBaseAddr+SDHC_PRESENT_STAT ) & (1<<1) );// Check CommandInhibit_DAT } sfrData = (uCmd<<8) | SDHC_cmd_sfr_data[ rType ]; if ( cType == SDHC_CMD_ADTC_TYPE ) { sfrData |= (1<<5); } if ( uCmd == 12 ) { // check abort bit when stop command. sfrData |= (3<<6); } // argument setting. Outp32( sCh->m_uBaseAddr+SDHC_ARG, uArg); Outp16( sCh->m_uBaseAddr+SDHC_COMMAND, sfrData); // Transfer Complete and Command Complete. - SDHC_COMMANDCOMPLETE_STS_INT_EN SDHC_INT_WAIT_CLEAR( sCh, 0, Loop); // Error Status Check - reduce too much error message. if ( (Inp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT ) & (1<<15)) && !(uCmd==1||uCmd==55||uCmd==41) ) { sdDbg(("Command = %d, Error Stat = %x\n", Inp16( sCh->m_uBaseAddr+SDHC_COMMAND )>>8, Inp16( sCh->m_uBaseAddr+SDHC_ERROR_INT_STAT ) )); return FALSE; } return TRUE;}//////////// File Name : SDHC_GetSdSCR// File Description : Setting sd card SCR infomation.// Input : SDHC, temp buffer for gather sd infomation up to 512 byte.// Output : success of failure.bool SDHC_GetSdScr(SDHC* sCh) { int i; u32 buffer[2]; if(!SDHC_IssueCommand( sCh, 16, 8, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ) ) return FALSE; SDHC_SetBlockSizeReg( sCh, 7, 8); SDHC_SetBlockCountReg( sCh, 1); SDHC_SetTransferModeReg(0, 1, 0, 0, 0, sCh); // CMD55 (For ACMD) if (!SDHC_IssueCommand( sCh, 55, sCh->m_uRca<<16, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ) ) return FALSE; // Acmd51 - Send SCR if(!SDHC_IssueCommand( sCh, 51, 0, SDHC_CMD_ADTC_TYPE, SDHC_RES_R1_TYPE ) ) return FALSE; sCh->m_uRemainBlock = 1; sCh->m_uBufferPtr = buffer; SDHC_ReadOneBlock( sCh, 2<<2 ); SDHC_INT_WAIT_CLEAR( sCh, 1, i ); // SDHC_TRANSFERCOMPLETE_STS_INT_EN// Transfer mode is determined by capacity register at OCR setting.// sCh->m_eTransMode = SDHC_BYTE_MODE; if ((*buffer&0xf) == 0x0) sCh->m_ucSpecVer = 0; // Version 1.0 ~ 1.01 else if ((*buffer&0xf) == 0x1) sCh->m_ucSpecVer = 1; // Version 1.10, support cmd6 else if((*buffer&0xf) == 0x2) { sCh->m_ucSpecVer = 2; // Version 2.0 support cmd6 and cmd8// sCh->m_eTransMode = SDHC_BLOCK_MODE; } else { sCh->m_ucSpecVer = 0; // Error... Deda } sdDbg(("SDSpecVer=%d\n", sCh->m_ucSpecVer)); return TRUE;}//////////// File Name : SDHC_ReadMMCExtCSD// File Description : Read mmc extended CSD Register.// Input : SDHC channel// Output : success of failure.bool SDHC_ReadMMCExtCSD(SDHC* sCh) { u32 S_CMD_SET, uHsTiming, i, uBusMode; u8 buffer[512]; // - to do - move to another memory. - too much stack. if (!SDHC_IssueCommand( sCh, 16, 512, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ) ) return FALSE; SDHC_SetBlockSizeReg(sCh, 7, 512); // Maximum DMA Buffer Size, Block Size SDHC_SetBlockCountReg(sCh, 1); // Block Numbers to Read SDHC_SetTransferModeReg(0, 1, 0, 0, 0,sCh); if ( sCh->m_ucSpecVer < 4 ) { sdDbg(("SKIP SDHC_ReadMMCExtCSD\n")); return TRUE; } if(!SDHC_IssueCommand( sCh, 8, 0, SDHC_CMD_ADTC_TYPE, SDHC_RES_R1_TYPE )) // cmd8 return FALSE; sCh->m_uRemainBlock = 1; sCh->m_uBufferPtr = (u32*)buffer; SDHC_ReadOneBlock( sCh, 0); SDHC_INT_WAIT_CLEAR( sCh, 1, i ); // SDHC_TRANSFERCOMPLETE_STS_INT_EN S_CMD_SET = buffer[504]; uHsTiming = buffer[185]; uBusMode = buffer[183]; sdDbg(( "uHsTiming : %d\n", uHsTiming )); sdDbg(( "uBusMode : %d\n", uBusMode )); sdDbg(( "Support Commmand Set : %d\n", buffer[504] )); sdDbg(( "sector count : %d\n", *((u32*)&buffer[212]) )); sdDbg(( "min Write performance 8 @52 : %d \n", buffer[210] )); sdDbg(( "min Read performance 8 @52 : %d \n", buffer[209] )); sdDbg(( "min Write performance 8 @26 : %d \n", buffer[208] )); sdDbg(( "min Read performance 8 @26 : %d \n", buffer[207] )); sdDbg(( "min Write performance 4 @26 : %d \n", buffer[206] )); sdDbg(( "min Read performance 4 @26 : %d \n", buffer[205] )); sdDbg(( "Card Type : %d \n", buffer[196] )); sdDbg(( "CSD structure Version : %d \n", buffer[194] )); sdDbg(( "CSD Revision : %d\n", buffer[192] )); sdDbg(( "Command Set : %d\n", buffer[191] )); sdDbg(( "Command Set Revision : %d\n", buffer[189] )); sdDbg(( "Power Class :%d \n", buffer[187] )); sdDbg(( "High Speed Interface Timing : %d\n", buffer[185] )); sdDbg(( "Bus width timing : %d\n", buffer[183] )); sdDbg(( "Erased memory content : %d\n", buffer[181] )); if(S_CMD_SET & (1<<4)) { sdDbg(("\n========CE ATA Card detect========\n")); sCh->m_eCardType = SDHC_CE_ATA_CARD; } else if(S_CMD_SET & (1<<2)) sdDbg(("\n========Content Protection SecureMMC Card detect========\n")); else if(S_CMD_SET & (1<<1)) sdDbg(("\n========SecureMMC Card detect========\n")); else if(S_CMD_SET & (1<<0)) sdDbg(("\n========Standard MMC Card detect========\n")); return TRUE;}//////////// File Name : SDHC_ClearErrInterruptStatus// File Description : Clear error interrupt status register.// Input : SDHC channel// Output : NONE.void SDHC_ClearErrInterruptStatus(SDHC* sCh) { u16 usSfr, usSfr1; usSfr = Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT); while (usSfr&(0x1<<15)) { usSfr1 = Inp16(sCh->m_uBaseAddr+SDHC_ERROR_INT_STAT); Outp16(sCh->m_uBaseAddr+SDHC_ERROR_INT_STAT, usSfr1); usSfr = Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT); }}//////////// File Name : SDHC_SetMmcOcr// File Description : Get MMC OCR Register from MMC Card.// Input : SDHC channel// Output : success or failure.bool SDHC_SetMmcOcr(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; for (i=0; i<500; i++) {#if 1 // for New Movinand 2007.3.29 // SDHC_IssueCommand( sCh, 1, 0x40FF8080, SDHC_CMD_BCR_TYPE, SDHC_RES_R3_TYPE ); // (Ocr:2.7V~3.6V) SDHC_IssueCommand( sCh, 1, 0x40FF8000, SDHC_CMD_BCR_TYPE, SDHC_RES_R3_TYPE ); // (Ocr:2.7V~3.6V) OCR = Inp32(sCh->m_uBaseAddr+SDHC_RSP0);#else SDHC_IssueCommand( sCh, 1, 0, SDHC_CMD_BCR_TYPE, SDHC_RES_R3_TYPE ); OCR = Inp32(sCh->m_uBaseAddr+SDHC_RSP0)|(1<<30); SDHC_IssueCommand( sCh, 1, OCR, SDHC_CMD_BCR_TYPE, SDHC_RES_R3_TYPE );#endif if (Inp32(sCh->m_uBaseAddr+SDHC_RSP0)&(unsigned int)(0x1<<31)) { 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<<19)) sdDbg(("Voltage range: 2.7V ~ 3.2V\n")); else if(OCR & (1<<18)) sdDbg(("Voltage range: 2.7V ~ 3.1V\n")); else continue; if ( Inp32(sCh->m_uBaseAddr+SDHC_RSP0) &(unsigned int)(0x1<<30) ) { sdDbg(("block mode\n")); sCh->m_ucSpecVer=4; // default spec version sCh->m_eTransMode=SDHC_BLOCK_MODE; } else { sdDbg(("byte mode\n")); sCh->m_ucSpecVer=1; // default spec version sCh->m_eTransMode=SDHC_BYTE_MODE; } sCh->m_eCardType= SDHC_MMC_CARD; // If the current card is SD card, then there's time out error, need to be cleared. SDHC_ClearErrInterruptStatus(sCh); return TRUE; } } // If the current card is SD card, then there's time out error, need to be cleared. SDHC_ClearErrInterruptStatus(sCh); return false;}//////////// File Name : SDHC_IssueCommand52// File Description : This function issue SDIO command.// Input : SDHC, command Index, Argument, Command Type, Response Type, Command Type// Output : Command Result.u32 SDHC_IssueCommand52( SDHC* sCh, u16 uCmd, u32 uArg, SDHC_CommandType cType, SDHC_ResponseType rType, u32 cmdType ) { u16 sfrData; u32 Loop; while( Inp32( sCh->m_uBaseAddr+SDHC_PRESENT_STAT ) & 0x1 ); // Check CommandInhibit_CMD// while( Inp32( sCh->m_uBaseAddr+SDHC_PRESENT_STAT ) & (1<<1) );// Check CommandInhibit_DAT sfrData = (uCmd<<8) | SDHC_cmd_sfr_data[ rType ]; if ( cType == SDHC_CMD_ADTC_TYPE ) { sfrData |= (1<<5); } // command Type. sfrData |= (cmdType<<6); // argument setting. Outp32( sCh->m_uBaseAddr+SDHC_ARG, uArg); Outp16( sCh->m_uBaseAddr+SDHC_COMMAND, sfrData); // Transfer Complete and Command Complete. - SDHC_COMMANDCOMPLETE_STS_INT_EN SDHC_INT_WAIT_CLEAR( sCh, 0, Loop); // Error Status Check - reduce too much error message. if ( (Inp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT ) & (1<<15)) && !(uCmd==1||uCmd==55||uCmd==41) ) { sdDbg(("Command = %d, Error Stat = %x\n", Inp16( sCh->m_uBaseAddr+SDHC_COMMAND )>>8, Inp16( sCh->m_uBaseAddr+SDHC_ERROR_INT_STAT ) )); return FALSE; } return Inp32(sCh->m_uBaseAddr+SDHC_RSP0);;}//////////// File Name : SDHC_SDIO_Interrupt_Handler// File Description : This Function is interrupt handler for SDIO interface.// Input : NONE.// Output : NONE.void __irq SDHC_SDIO_Interrupt_Handler(void) { u32 status; SDHC* sCh;// while( (Inp16(SDHC_curr_card[0]->m_uBaseAddr+SDHC_NORMAL_INT_STAT) ) == 0 &&// (Inp16(SDHC_curr_card[0]->m_uBaseAddr+SDHC_ERROR_INT_STAT) ) == 0 ); sCh=SDHC_curr_card[SDHC_CHANNEL_0]; //1 You have to fit on your SDIO channel.// SDHC_InterruptInspector(sCh); status = Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT); if ( status & SDHC_TRANSFERCOMPLETE_SIG_INT_EN ) { sCh->m_uRemainBlock = 0; }}// print SDIO Card infomation.bool SDHC_printSDIOInfo(SDHC* sCh) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -