📄 sdhc.c
字号:
void __irq SDHC_normalInt1(void) { SDHC_normalIntHandler( SDHC_curr_card[SDHC_CHANNEL_1] ); INTC_ClearVectAddr();}//////////// File Name : SDHC_normalInt2// File Description : Normal Interrupt Handler 2// Input : NONE// Output : NONE.void __irq SDHC_normalInt2(void) { SDHC_normalIntHandler( SDHC_curr_card[SDHC_CHANNEL_2] ); INTC_ClearVectAddr();}//////////// File Name : SDHC_InitCh// File Description : Initialize channel information.// Input : SDHC Channel Number, SDHC pointer..// Output : NONE.void SDHC_InitCh(SDHC_channel eCh, SDHC *sCh) { sCh->m_eChannel = eCh; SDHC_curr_card[sCh->m_eChannel]=sCh; // Pointer... if ( eCh == SDHC_CHANNEL_0 ) { // Channel 0 sCh->m_uBaseAddr = (u8*)HSMMC0_BASE; sCh->m_fDmaFn = SDHC_DMAInt0; sCh->m_fReadFn = SDHC_ReadInt0; sCh->m_fWriteFn = SDHC_WriteInt0; sCh->m_fNormalFn = SDHC_normalInt0; sCh->m_ucIntChannelNum = NUM_HSMMC0; } else if ( eCh == SDHC_CHANNEL_1 ) { // Channel 1 sCh->m_uBaseAddr = (u8*)HSMMC1_BASE; sCh->m_fDmaFn = SDHC_DMAInt1; sCh->m_fReadFn = SDHC_ReadInt1; sCh->m_fWriteFn = SDHC_WriteInt1; sCh->m_fNormalFn = SDHC_normalInt1; sCh->m_ucIntChannelNum = NUM_HSMMC1; } else if ( eCh == SDHC_CHANNEL_2 ) { // channel 2->SPI muxed. sCh->m_uBaseAddr = (u8*)HSMMC2_BASE; sCh->m_fDmaFn = SDHC_DMAInt2; sCh->m_fReadFn = SDHC_ReadInt2; sCh->m_fWriteFn = SDHC_WriteInt2; sCh->m_fNormalFn = SDHC_normalInt2; sCh->m_ucIntChannelNum = NUM_SPI1; } else { Assert(0); }}//////////// File Name : SDHC_OpenMedia// File Description : Initialize channel information.// Input : SDHC Clock Source, SDHC pointer.// Output : Success or Failure.bool SDHC_OpenMedia(SDHC_clockSource eClkSrc, SDHC* sCh){ SDHC_SpeedMode speed; u32 uSrcFreq; u32 uOperFreq; sCh->m_eClockSource = eClkSrc; sCh->m_ucHostCtrlReg = 0; sCh->m_usClkCtrlReg = 0; if ( sCh->m_ucBandwidth == 0 ) sCh->m_ucBandwidth = 4; // bit width. // GPIO Setting. SDHC_SetGPIO(sCh->m_eChannel, sCh->m_ucBandwidth); if ( eClkSrc == SDHC_HCLK || eClkSrc == 0 ) { uSrcFreq = g_HCLK; } else if ( eClkSrc == SDHC_EPLL ) { uSrcFreq = Inp32(0x7E00F014); // temp // ((uSrcFreq>>16)&0xff) //M // ((uSrcFreq>>8)&0x3f) //P // (uSrcFreq&0x07) //S // ignore K value uSrcFreq = (u32)(((float)FIN)*((uSrcFreq>>16)&0xff)/(((uSrcFreq>>8)&0x3f)*(1<<(uSrcFreq&0x07)))); } else if ( eClkSrc == SDHC_EXTCLK ) { uSrcFreq = 48000000; // 48MHz External crystal } else { Assert(FALSE); } if ( sCh->m_uClockDivision == 0 ) { uOperFreq = uSrcFreq; if(uOperFreq>52000000) { sCh->m_uClockDivision = 2; uOperFreq = uSrcFreq / (sCh->m_uClockDivision*2); } } else { uOperFreq = uSrcFreq / (sCh->m_uClockDivision*2); } sdDbg(("WorkingFreq = %dMHz\n", uOperFreq/1000000 )); SDHC_ResetController(sCh);// youngbo.song -SDIO test.// if( !SDHC_newOCR(sCh) ) { // for SDIO. if (!SDHC_IdentifyCard(sCh)) return FALSE;// } if ( sCh->m_eCardType == SDHC_SDIO_CARD ) { return TRUE; } // SDIO Test.... end // card Selection if ( !SDHC_IssueCommand( sCh, 7, (u32)(sCh->m_uRca<<16), SDHC_CMD_AC_TYPE, SDHC_RES_R1B_TYPE ) ) return FALSE; if (sCh->m_eCardType == SDHC_MMC_CARD ) { if (sCh->m_ucSpecVer >= 4) { speed = ( uOperFreq > SDHC_MMC_HIGH_SPEED_CLOCK) ? (SDHC_HIGH_SPEED) : (SDHC_NORMAL_SPEED); if (!SDHC_SetMmcSpeedMode(speed, sCh)) { return FALSE; } } else // old version Assert(uOperFreq<=SDHC_MMC_HIGH_SPEED_CLOCK); // Error! Old version MMC card can not support working frequency higher than 20MHz"); } else if ( sCh->m_eCardType == SDHC_SD_CARD ) { SDHC_GetSdScr(sCh); if (sCh->m_ucSpecVer==1||sCh->m_ucSpecVer==2) { speed = ( uOperFreq > SDHC_SD_HIGH_SPEED_CLOCK) ? (SDHC_HIGH_SPEED) : (SDHC_NORMAL_SPEED); if (!SDHC_SetSdCardSpeedMode(speed, sCh)) { return FALSE; } } else Assert(uOperFreq<=SDHC_SD_HIGH_SPEED_CLOCK); // Error! Old version SD card can not support working frequency higher than 25MHz"); } // host controller speed setting. speed = ( uOperFreq > SDHC_MMC_HIGH_SPEED_CLOCK) ? (SDHC_HIGH_SPEED) : (SDHC_NORMAL_SPEED); SDHC_SetHostCtrlSpeedMode( speed, sCh ); SDHC_SetSdClockOnOff(0, sCh); // If the sd clock is to be changed, you need to stop sd-clock. SDHC_SetSdClock(sCh->m_uClockDivision, sCh, speed, uOperFreq); // After a card was selected, then the bus width can be changed. if (!SDHC_SetDataTransferWidth( sCh)) return FALSE; if (!SDHC_WaitForCard2TransferState(sCh)) return FALSE; if ( sCh->m_eCardType == SDHC_MMC_CARD ) { SDHC_ReadMMCExtCSD( sCh ); } else { // CMD16 can not be set while card is in programming state. if (!SDHC_IssueCommand(sCh, 16, 512, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ) ) // Set the block size return FALSE; } // youngbo.song Outp32( sCh->m_uBaseAddr+SDHC_CONTROL2, Inp32(sCh->m_uBaseAddr+SDHC_CONTROL2)|(1<<8)|(2<<9)|(1<<28)); return TRUE;}//////////// File Name : SDHC_OpenMediaWithMode// File Description : SD/MMC Channel initialize with parameter.// Input : Bus width, Operation mode, Clock source, Clock divider, channel Number, Information Structuer pointer.// Output : Success or Failure.bool SDHC_OpenMediaWithMode(u32 uBusWidth, SDHC_operation eOpMode, SDHC_clockSource eClkSrc, u32 uSdClkDivisor, SDHC_channel channel, SDHC* sCh){ sCh->m_eOpMode = eOpMode; sCh->m_ucBandwidth = uBusWidth; sCh->m_uClockDivision = uSdClkDivisor; // channel initialize. SDHC_InitCh(channel, sCh); if ( !SDHC_OpenMedia(eClkSrc, sCh ) ) return FALSE; return TRUE;}//////////// File Name : SDHC_CloseMedia// File Description : This function close media session.// Input : SDHC// Output : NONE.bool SDHC_IdentifyCard(SDHC* sCh){ 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);// INTC_SetVectAddr( sCh->m_ucIntChannelNum, sCh->m_fDmaFn );// INTC_Enable( sCh->m_ucIntChannelNum );// Outp16( sCh->m_uBaseAddr+SDHC_NORMAL_INT_SIGNAL_ENABLE,// SDHC_DMA_SIG_INT_EN|// SDHC_TRANSFERCOMPLETE_SIG_INT_EN|// SDHC_COMMANDCOMPLETE_SIG_INT_EN); // Check card OCR(Operation Condition Register) if (SDHC_SetSDOCR(sCh)) sCh->m_eCardType = SDHC_SD_CARD; else if (SDHC_SetMmcOcr(sCh)) sCh->m_eCardType = SDHC_MMC_CARD; else return FALSE; // Check the attached card and place the card in the IDENT state rHM_RSPREG0 SDHC_IssueCommand( sCh, 2, 0, SDHC_CMD_BCR_TYPE, SDHC_RES_R2_TYPE ); sdDbg(("- Product Name : %c%c%c%c%c%c\n",((Inp32(sCh->m_uBaseAddr+SDHC_RSP2)>>24)&0xFF), ((Inp32(sCh->m_uBaseAddr+SDHC_RSP2)>>16)&0xFF), ((Inp32(sCh->m_uBaseAddr+SDHC_RSP2)>>8)&0xFF), (Inp32(sCh->m_uBaseAddr+SDHC_RSP2)&0xFF), ((Inp32(sCh->m_uBaseAddr+SDHC_RSP1)>>24)&0xFF), ((Inp32(sCh->m_uBaseAddr+SDHC_RSP1)>>16)&0xFF))); // Send RCA(Relative Card Address). It places the card in the STBY state sCh->m_uRca= (sCh->m_eCardType==SDHC_MMC_CARD) ? (1): (0); SDHC_IssueCommand( sCh, 3, sCh->m_uRca<<16, SDHC_CMD_AC_TYPE, SDHC_RES_R1_TYPE ); if( sCh->m_eCardType == SDHC_SD_CARD) { sCh->m_uRca = (Inp32(sCh->m_uBaseAddr+SDHC_RSP0)>>16)&0xFFFF; sdDbg(("=> RCA=0x%x\n", sCh->m_uRca)); } //Send CSD SDHC_IssueCommand( sCh, 9, sCh->m_uRca<<16, SDHC_CMD_AC_TYPE, SDHC_RES_R2_TYPE ); SDHC_DisplayCardInformation(sCh); return true;}//////////// File Name : SDHC_CloseMedia// File Description : This function close media session.// Input : SDHC// Output : NONE.void SDHC_CloseMedia(SDHC* sCh){ SDHC_SetSdClockOnOff(FALSE, sCh); // SDCLK Disable}//////////// File Name : SDHC_WriteOneBlock// File Description : This function writes one block data by CPU transmission mode.// Input : SDHC( assert buffer pointer and remain data length.)// Output : NONE.void SDHC_WriteOneBlock( SDHC* sCh, int block_size ) { u32* source_Ptr = sCh->m_uBufferPtr; int i; if ( block_size < 1 || block_size > 512 ) block_size = 512; // Wait for buffer write ready... - SDHC_BUFFER_WRITEREADY_STS_INT_EN SDHC_INT_WAIT_CLEAR( sCh, 4, i ); if ( 100000 - i > 1 ) printf( "100000 to time:%d\n", 100000-i); block_size = (block_size+3) >> 2; // block_size = (block_size+3) / 4; for(i=block_size; i>0; i--) //512/4 { Outp32( sCh->m_uBaseAddr+SDHC_BUF_DAT_PORT, *source_Ptr++); } sCh->m_uRemainBlock--; sCh->m_uBufferPtr = source_Ptr;}//////////// File Name : SDHC_ReadOneBlock// File Description : This function reads one block data by CPU transmission mode.// Input : SDHC( assert buffer pointer and remain data length.)// one block size : If set 0, than assume 512 byte.// Output : NONE.void SDHC_ReadOneBlock( SDHC* sCh, int block_size ) { u32* target_Ptr = sCh->m_uBufferPtr; int i; if ( block_size < 1 || block_size > 512 ) block_size = 512; // Wait for buffer read ready...- SDHC_BUFFER_READREADY_STS_INT_EN SDHC_INT_WAIT_CLEAR( sCh, 5, i ); if ( 100000 - i > 1 ) printf( "100000 to time:%d\n", 100000-i); block_size = (block_size+3) >> 2; // block_size = (block_size+3) / 4; for(i=block_size; i>0; i--) { *target_Ptr++ = Inp32( sCh->m_uBaseAddr+SDHC_BUF_DAT_PORT ); } sCh->m_uRemainBlock--; sCh->m_uBufferPtr = target_Ptr;}//////////// File Name : SDHC_GetCeATATaskFile// File Description : This function gets CE-ATA Taskfile from CE-ATA Device.// Input : SDHC channel, CE-ATA Command, Taskfile buffer// Output : success or failurebool SDHC_GetCeATATaskFile( SDHC* sCh, SDHC_CEATACommand cmd, SDHC_ataTaskFile * taskFile ) { int i; SDHC_SetBlockSizeReg(sCh, 7, 0x10); // Maximum DMA Buffer Size, Block Size // SDHC_SetBlockCountReg(sCh, 1); // Block Numbers to Read SDHC_SetTransferModeReg(0, 1, 0, 0, 0, sCh); if ( SDHC_IssueCommand( sCh, 60, (u32)((0<<31)|(0<<16)|(0x10)), SDHC_CMD_ADTC_TYPE, SDHC_RES_R1_TYPE) == FALSE ) { return FALSE; } memset ( taskFile, 0, sizeof(SDHC_ataTaskFile) ); taskFile->device_head = 0; taskFile->command_status = cmd; sCh->m_uRemainBlock = 1; sCh->m_uBufferPtr = (u32*)taskFile; SDHC_ReadOneBlock( sCh, 0x10); SDHC_INT_WAIT_CLEAR( sCh, 1, i ); // SDHC_TRANSFERCOMPLETE_STS_INT_EN return TRUE;}//////////// File Name : SDHC_SetCeATATaskFile// File Description : This function sets CE-ATA Taskfile to CE-ATA Device.// Input : SDHC channel, CE-ATA Command, start block address, Block Count, Taskfile buffer// Output : success or failurebool SDHC_SetCeATATaskFile( SDHC* sCh, SDHC_CEATACommand cmd, u32 startBlock, u32 blockCount, SDHC_ataTaskFile * taskFile ) { int i; SDHC_SetBlockSizeReg(sCh, 0, 0x10);// SDHC_SetBlockCountReg(sCh, 1); // Block Numbers to Read SDHC_SetTransferModeReg(0, 0, 0, 0, 0, sCh); // Write Mode. if ( SDHC_IssueCommand( sCh, 60, (u32)((1<<31)|(0<<16)|(0x10)), SDHC_CMD_ADTC_TYPE, SDHC_RES_R1B_TYPE) == FALSE ) { return FALSE; } memset ( taskFile, 0, sizeof(SDHC_ataTaskFile) ); taskFile->sectorCountExp = (u8)(blockCount>>8 & 0xff);; taskFile->sectorCount = (u8)(blockCount & 0xff); taskFile->LBALow = (u8)(startBlock & 0xff); taskFile->LBAMID = (u8)(startBlock>>8 & 0xff); taskFile->LBAHigh = (u8)(startBlock>>16 & 0xff); taskFile->LBALowExp = (u8)(startBlock>>24 & 0xff); taskFile->LBAMidExp = 0; taskFile->LBAHighExp = 0; taskFile->device_head = 0; taskFile->command_status = cmd; sCh->m_uRemainBlock = 1; sCh->m_uBufferPtr = (u32*)taskFile; SDHC_WriteOneBlock( sCh, 0x10); SDHC_INT_WAIT_CLEAR( sCh, 1, i ); // SDHC_TRANSFERCOMPLETE_STS_INT_EN return TRUE;}//////////// File Name : SDHC_GetCeATAIdentifyData// File Description : This function gets identify data from CE-ATA Device.// Input : SDHC channel, ATA-Taskfile, Buffer(512byte)// Output : success or failurebool SDHC_GetCeATAIdentifyData( SDHC* sCh, SDHC_ataTaskFile* taskFile, u8* buffer ) { int i; if ( SDHC_SetCeATATaskFile( sCh, SDHC_ATCMD_IDENTIFY_DEVICE, 0, 0, taskFile ) == FALSE ) { return FALSE; } SDHC_SetBlockSizeReg(sCh, 7, 512); // Maximum DMA Buffer Size, Block Size // SDHC_SetBlockCountReg(sCh, 1); // Block Numbers to Read
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -