📄 sdhcslot.cpp
字号:
)
{
BOOL fSuccess;
DEBUGCHK(pv);
fSuccess = FreePhysMem(pv);
DEBUGCHK(fSuccess);
}
VOID
CSDHCSlotBase::SetHardwarePowerState(
CEDEVICE_POWER_STATE cpsNew
)
{
DEBUGCHK(VALID_DX(cpsNew));
DEBUGCHK(!DX_D1_OR_D2(cpsNew));
DEBUGCHK(m_cpsCurrent != cpsNew);
CEDEVICE_POWER_STATE cpsCurrent = m_cpsCurrent;
m_cpsCurrent = cpsNew;
BYTE bWakeupControl = m_bWakeupControl;
RETAILMSG(1,(TEXT("CSDHCSlotBase::SetHardwarePowerState 0x%08X\n"),this));
if (cpsCurrent == D0) {
SDClockOff();
if (cpsNew == D3) {
if ( m_fSDIOInterruptsEnabled &&
(bWakeupControl & WAKEUP_INTERRUPT) ) {
DEBUGCHK(m_fCardPresent);
m_fSleepsWithPower = TRUE;
m_fPowerUpDisabledInts = FALSE;
}
else {
// Wake on status changes only
WriteByte(SDHC_POWER_CONTROL, 0);
bWakeupControl &= ~WAKEUP_INTERRUPT;
}
// enable wakeup sources
m_wIntSignals = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, 0);
WriteWord(SDHC_NORMAL_INT_STATUS, ReadWord(SDHC_NORMAL_INT_STATUS));
WriteByte(SDHC_WAKEUP_CONTROL, bWakeupControl);
}
else {
DEBUGCHK(cpsNew == D4);
WriteByte(SDHC_CLOCK_CONTROL, 0);
WriteByte(SDHC_POWER_CONTROL, 0);
}
}
else if (cpsCurrent == D3) {
// Coming out of wakeup state
if (cpsNew == D0) {
WriteByte(SDHC_WAKEUP_CONTROL, 0);
if (!m_fSleepsWithPower) {
// Power was turned off to the socket. Re-enumerate card.
if (m_fCardPresent) {
HandleRemoval(TRUE);
}
m_fCheckSlot = TRUE;
SetInterruptEvent();
}
else {
if (m_fCardPresent) {
// Do not do this if the card was removed or
// if power was not kept.
if (m_fPowerUpDisabledInts) {
EnableSDIOInterrupts(TRUE);
}
}
}
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, m_wIntSignals);
}
else {
DEBUGCHK(cpsNew == D4);
WriteByte(SDHC_CLOCK_CONTROL, 0);
WriteByte(SDHC_WAKEUP_CONTROL, 0);
WriteByte(SDHC_POWER_CONTROL, 0);
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, m_wIntSignals);
}
m_fSleepsWithPower = FALSE;
}
else {
DEBUGCHK(cpsCurrent == D4);
// Coming out of unpowered state - signal card removal
// so any card present will be re-enumerated.
//
// We do the same thing when we go to D3 as D0 because
// the slot has lost power so it could have been removed
// or changed. In other words, D3 is a meaningless state
// after D4.
m_cpsCurrent = D0; // Force to D0
// Do not call HandleRemoval here because it could cause
// a context switch in a PowerUp callback.
m_fFakeCardRemoval = TRUE;
m_fCheckSlot = TRUE;
SetInterruptEvent();
}
}
BOOL
CSDHCSlotBase::IsOnlySDIOInterrupt()
{
WORD wIntStatus = ReadWord(SDHC_NORMAL_INT_STATUS);
if (wIntStatus == NORMAL_INT_STATUS_CARD_INT && isSDIOInterrupt == TRUE ) {
return TRUE;
}
return FALSE;
}
VOID
CSDHCSlotBase::DoEnableSDIOInterrupts(
BOOL fEnable
)
{
WORD wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
if (fEnable) {
isSDIOInterrupt = FALSE;
RETAILMSG(0,(TEXT("DoEnableSDIOInterrupts TRUE\n")));
wIntStatusEn |= NORMAL_INT_ENABLE_CARD_INT;
}
else {
isSDIOInterrupt = TRUE;
RETAILMSG(0,(TEXT("DoEnableSDIOInterrupts FALSE\n")));
wIntStatusEn &= (~NORMAL_INT_ENABLE_CARD_INT);
}
WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, wIntStatusEn);
}
template<class T>
BOOL
CSDHCSlotBase::WaitForReg(
T (CSDHCSlotBase::*pfnReadReg)(DWORD),
DWORD dwRegOffset,
T tMask,
T tWaitForEqual,
DWORD dwTimeout
)
{
SETFNAME();
const DWORD dwStart = GetTickCount();
T tValue;
BOOL fRet = TRUE;
DWORD dwIteration = 1;
// Verify that reset has completed.
do {
tValue = (this->*pfnReadReg)(dwRegOffset);
if ( (dwIteration % 16) == 0 ) {
// Check time
DWORD dwCurr = GetTickCount();
// Unsigned arithmetic handles rollover.
DWORD dwTotal = dwCurr - dwStart;
if (dwTotal > dwTimeout) {
// Timeout
fRet = FALSE;
DEBUGMSG(SDCARD_ZONE_WARN, (_T("%s Timeout (%u ms) waiting for (ReadReg<%u>(0x%02x) & 0x%08x) == 0x%08x\r\n"),
pszFname, dwTimeout, sizeof(T), dwRegOffset, tMask, tWaitForEqual));
break;
}
}
++dwIteration;
} while ((tValue & tMask) != tWaitForEqual);
return fRet;
}
BOOL
CSDHCSlotBase::SoftwareReset(
BYTE bResetBits
)
{
SETFNAME();
// Reset the controller
WriteByte(SDHC_SOFT_RESET, bResetBits);
BOOL fSuccess = WaitForReg<BYTE>(ReadByte, SDHC_SOFT_RESET, bResetBits, 0);
if (!fSuccess) {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for controller reset - 0x%02x\r\n"),
pszFname, bResetBits));
}
// set Clock Source to EPLL added by JJG 06.10.11
WriteDword(SDHC_CONTROL2, (0x1<<15)|(0x1<<14)|(0x1<<8)|(0x2/*EPLL*/<<4) );
WriteDword(SDHC_CONTROL3, (0<<31) | (1<<23) | (0<<15) | (1<<7) );
return fSuccess;
}
VOID
CSDHCSlotBase::EnableLED(
BOOL fEnable
)
{
BYTE bHostControl = ReadByte(SDHC_HOST_CONTROL);
if (fEnable) {
bHostControl |= HOSTCTL_LED_CONTROL;
}
else {
bHostControl &= ~HOSTCTL_LED_CONTROL;
}
WriteByte(SDHC_HOST_CONTROL, bHostControl);
}
VOID
CSDHCSlotBase::IndicateSlotStateChange(SD_SLOT_EVENT sdEvent) {
SDHCDIndicateSlotStateChange(m_pHCDContext,
(UCHAR) m_dwSlot, sdEvent);
}
PSD_BUS_REQUEST
CSDHCSlotBase::GetAndLockCurrentRequest() {
return SDHCDGetAndLockCurrentRequest(m_pHCDContext,
(UCHAR) m_dwSlot);
}
VOID CSDHCSlotBase::PowerUpDown(BOOL fPowerUp, BOOL fKeepPower) {
SDHCDPowerUpDown(m_pHCDContext, fPowerUp, fKeepPower,
(UCHAR) m_dwSlot);
}
VOID
CSDHCSlotBase::IndicateBusRequestComplete(
PSD_BUS_REQUEST pRequest,
SD_API_STATUS status
)
{
RETAILMSG(0,(TEXT("CSDHCSlotBase::IndicateBusRequestComplete\n")));
const WORD c_wTransferIntSources =
NORMAL_INT_STATUS_CMD_COMPLETE |
NORMAL_INT_STATUS_TRX_COMPLETE |
NORMAL_INT_STATUS_DMA |
NORMAL_INT_STATUS_BUF_WRITE_RDY |
NORMAL_INT_STATUS_BUF_READ_RDY;
DEBUGCHK(pRequest);
if ( (m_fSDIOInterruptsEnabled && m_f4BitMode) == FALSE ) {
SDClockOff();
}
// else need to leave clock on in order to receive interrupts in 4 bit mode
// Turn off LED.
EnableLED(FALSE);
// Turn off interrupt sources
WORD wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
wIntStatusEn &= ~c_wTransferIntSources;
WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, wIntStatusEn);
// Clear any remaining spurious interrupts.
WriteWord(SDHC_NORMAL_INT_STATUS, c_wTransferIntSources);
#ifdef DEBUG
m_dwReadyInts = 0;
#endif
m_fCommandCompleteOccurred = FALSE;
SDHCDIndicateBusRequestComplete(m_pHCDContext,
pRequest, status);
}
VOID
CSDHCSlotBase::SetClockRate(
PDWORD pdwRate
)
{
RETAILMSG(0,(TEXT("DEBUGCHK(m_dwMaxClockRate)\n")));
DEBUGCHK(m_dwMaxClockRate);
RETAILMSG(0,(TEXT("DEBUGCHK(m_dwMaxClockRate) success\n")));
DWORD dwClockRate = *pdwRate;
DWORD dwMaxClockRate = m_dwMaxClockRate;
int i = 0; // 2^i is the divisor value
// For supporting lower Clock
// added by JJG 06.10.16
if(*pdwRate <= 400000)
{
dwMaxClockRate = 12000000; // 12Mhz
WriteDword(SDHC_CONTROL2, (0x1<<15)|(0x1<<14)|(0x1<<8)|(0x3/*EXT*/<<4) );
}
else if(*pdwRate <= 20000000)
{
dwMaxClockRate = 133000000;//S3C2443_HCLK; // maybe 133Mhz
WriteDword(SDHC_CONTROL2, (0x1<<15)|(0x1<<14)|(0x1<<8)|(0x1/*EPLL*/<<4) );
}
else
{
WriteDword(SDHC_CONTROL2, (0x1<<15)|(0x1<<14)|(0x1<<8)|(0x2/*EPLL*/<<4) );
}
/////////////////////////////////////////////
// shift MaxClockRate until we find the closest frequency <= target
while ( (dwClockRate < dwMaxClockRate) && ( i < 8 ) ) {
dwMaxClockRate = dwMaxClockRate >> 1;
i++;
}
// set the actual clock rate
*pdwRate = dwMaxClockRate;
m_wRegClockControl = CLOCK_INTERNAL_ENABLE;
if (i != 0) {
DWORD dwDivisor = 1 << (i - 1);
m_wRegClockControl |= (dwDivisor << 8);
}
RETAILMSG(1,(TEXT("SDHCSetRate - Clock Control Reg = %X\n"),
m_wRegClockControl));
RETAILMSG(1,(TEXT("SDHCSetRate - Actual clock rate = %d\n"), *pdwRate));
DEBUGMSG(SDHC_CLOCK_ZONE,(TEXT("SDHCSetRate - Clock Control Reg = %X\n"),
m_wRegClockControl));
DEBUGMSG(SDHC_CLOCK_ZONE,(TEXT("SDHCSetRate - Actual clock rate = %d\n"), *pdwRate));
}
VOID
CSDHCSlotBase::SDClockOn(
)
{
SETFNAME();
// Must call SetClockRate() first to init m_wRegClockControl
// We separate clock divisor calculation with ClockOn, so we can call
// ClockOn without recalcuating the divisor.
WriteWord(SDHC_CLOCK_CONTROL, m_wRegClockControl);
RETAILMSG(0,(TEXT("SDHC_CLOCK_CONTROL = 0x%X\n"),m_wRegClockControl));
RETAILMSG(0,(TEXT("CONTROL2 = 0x%X\n"),ReadDword(SDHC_CONTROL2)));
RETAILMSG(0,(TEXT("CONTROL3 = 0x%X\n"),ReadDword(SDHC_CONTROL3)));
// wait until clock stable
BOOL fSuccess = WaitForReg<WORD>(ReadWord, SDHC_CLOCK_CONTROL,
CLOCK_STABLE, CLOCK_STABLE);
if (fSuccess) {
RETAILMSG(0, (_T("%s Enable Clock\r\n"), pszFname));
// enable it
//WriteWord(SDHC_CLOCK_CONTROL, (0x20<<8) | CLOCK_ENABLE | CLOCK_INTERNAL_ENABLE);
WriteWord(SDHC_CLOCK_CONTROL, m_wRegClockControl | CLOCK_ENABLE);
fSuccess = WaitForReg<WORD>(ReadWord, SDHC_CLOCK_CONTROL,
CLOCK_EXTERNAL_ENABLE, CLOCK_EXTERNAL_ENABLE);
RETAILMSG(0,(TEXT("fSuccess = 0x%X\n"),fSuccess));
}
else {
RETAILMSG(0, (_T("%s Timeout waiting for CLOCK_STABLE\r\n"),
pszFname));
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for CLOCK_STABLE\r\n"),
pszFname));
}
}
VOID
CSDHCSlotBase::SDClockOff(
)
{
WriteWord(SDHC_CLOCK_CONTROL, m_wRegClockCont
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -