// 08.03.14 by KYS
// The function that initilize SYSCON for a clock gating.
BOOL CSDHController::InitClkPwr() {
volatile S3C6410_SYSCON_REG *pCLKPWR = NULL;
pCLKPWR = (volatile S3C6410_SYSCON_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_SYSCON, sizeof(S3C6410_SYSCON_REG), FALSE);
if (pCLKPWR == NULL) {
RETAILMSG(1, (TEXT("[HSMMC0] Clock & Power Management Special Register is *NOT* mapped.\n")));
return FALSE;
}
#ifdef _SRCCLK_48MHZ_
RETAILMSG(_DBG_, (TEXT("[HSMMC0] Setting registers for the USB48MHz (EXTCLK for SDCLK) : SYSCon.\n")));
// SCLK_HSMMC#_48 : CLK48M_PHY(OTH PHY 48MHz Clock Source from SYSCON block)
// To use the USB clock, must be set the "USB_SIG_MASK" bit in the syscon register.
pCLKPWR->OTHERS |= (0x1<<16); // set USB_SIG_MASK
pCLKPWR->HCLK_GATE |= (0x1<<17); // Gating HCLK for HSMMC1
pCLKPWR->SCLK_GATE |= (0x1<<27); // Gating special clock for HSMMC1 (SCLK_MMC1_48)
#else
RETAILMSG(_DBG_, (TEXT("[HSMMC0] Setting registers for the EPLL (for SDCLK) : SYSCon.\n")));
// SCLK_HSMMC# : EPLLout, MPLLout, PLL_source_clk or CLK27 clock
// (from SYSCON block, can be selected by MMC#_SEL[1:0] fields of the CLK_SRC register in SYSCON block)
// Set the clock source to EPLL out for CLKMMC1
pCLKPWR->CLK_SRC = (pCLKPWR->CLK_SRC & ~(0x3<<18) & ~(0x1<<2)) | // Control MUX(MMC1:MOUT EPLL)
(0x1<<2); // Control MUX(EPLL:FOUT EPLL)
pCLKPWR->HCLK_GATE |= (0x1<<17); // Gating HCLK for HSMMC1
pCLKPWR->SCLK_GATE = (pCLKPWR->SCLK_GATE) | (0x1<<25); // Gating special clock for HSMMC1 (SCLK_MMC1)
#endif
// 08.03.14 by KYS
// The function that initilize GPIO for DAT, CD and WP lines.
BOOL CSDHController::InitGPIO() {
volatile S3C6410_GPIO_REG *pIOPreg = NULL;
pIOPreg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);
if (pIOPreg == NULL) {
RETAILMSG(1, (TEXT("[HSMMC0] GPIO registers is *NOT* mapped.\n")));
return FALSE;
}
RETAILMSG(_DBG_, (TEXT("[HSMMC0] Setting registers for the GPIO.\n")));
pIOPreg->GPGCON = (pIOPreg->GPGCON & ~(0xFFFFFF)) | (0x222222); // 4'b0010 for the MMC 0
pIOPreg->GPGPUD &= ~(0xFFF); // Pull-up/down disabled
// 08.03.14 by KYS
// The function that initilize the register for HSMMC Control.
BOOL CSDHController::InitHSMMC() {
volatile S3C6410_HSMMC_REG *pHSMMC = NULL;
pHSMMC = (volatile S3C6410_HSMMC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_HSMMC0, sizeof(S3C6410_HSMMC_REG), FALSE);
if (pHSMMC == NULL) {
RETAILMSG(1, (TEXT("[HSMMC0] HSMMC Special Register is *NOT* mapped.\n")));
return FALSE;
}
#ifdef _SRCCLK_48MHZ_
RETAILMSG(_DBG_, (TEXT("[HSMMC0] Setting registers for the USB48MHz (EXTCLK) : HSMMCCon.\n")));
// Set the clock source to USB_PHY for CLKMMC1
pHSMMC->CONTROL2 = (pHSMMC->CONTROL2 & ~(0xffffffff)) |
(0x3<<9) | // Debounce Filter Count 0x3=64 iSDCLK
(0x1<<8) | // SDCLK Hold Enable
(0x3<<4); // Base Clock Source = External Clock
#else
RETAILMSG(_DBG_, (TEXT("[HSMMC0] Setting registers for the EPLL : HSMMCCon.\n")));
// Set the clock source to EPLL out for CLKMMC1
pHSMMC->CONTROL2 = (pHSMMC->CONTROL2 & ~(0xffffffff)) |
(0x3<<9) | // Debounce Filter Count 0x3=64 iSDCLK
(0x1<<8) | // SDCLK Hold Enable
(0x2<<4); // Base Clock Source = EPLL out
#endif
// 08.03.22 by KYS
// New function to request a SYSINTR for Card detect interrupt of HSMMC ch0 on SMDK6410.
BOOL CSDHController::InitializeHardware() {
m_dwSDDetectIrq = SD_CD0_IRQ;
// convert the SDI hardware IRQ into a logical SYSINTR value
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwSDDetectIrq, sizeof(DWORD), &m_dwSDDetectSysIntr, sizeof(DWORD), NULL)) {
// invalid SDDetect SYSINTR value!
RETAILMSG(1, (TEXT("[HSMMC0] invalid SD detect SYSINTR value!\n")));
m_dwSDDetectSysIntr = SYSINTR_UNDEFINED;
return FALSE;
}
return CSDHCBase::InitializeHardware();
}
// 08.03.22 by KYS
// New Start function for Card detect of HSMMC ch0 on SMDK6410.
SD_API_STATUS CSDHController::Start() {
SD_API_STATUS status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
m_fDriverShutdown = FALSE;
// allocate the interrupt event
m_hevInterrupt = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == m_hevInterrupt) {
goto EXIT;
}
// initialize the interrupt event
if (!InterruptInitialize (m_dwSysIntr, m_hevInterrupt, NULL, 0)) {
goto EXIT;
}
m_fInterruptInitialized = TRUE;
// create the interrupt thread for controller interrupts
m_htIST = CreateThread(NULL, 0, ISTStub, this, 0, NULL);
if (NULL == m_htIST) {
goto EXIT;
}