/* * Copyright 2020-2022 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "sdmmc_config.h" #include "fsl_iomuxc.h" /******************************************************************************* * Definitions ******************************************************************************/ /******************************************************************************* * Prototypes ******************************************************************************/ void BOARD_SDCardPowerControl(bool enable); /******************************************************************************* * Variables ******************************************************************************/ /*!brief sdmmc dma buffer */ AT_NONCACHEABLE_SECTION_ALIGN(static uint32_t s_sdmmcHostDmaBuffer[BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE], SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE); #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER /* two cache line length for sdmmc host driver maintain unalign transfer */ SDK_ALIGN(static uint8_t s_sdmmcCacheLineAlignBuffer[BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U], BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE); #endif #if defined(SDIO_ENABLED) || defined(SD_ENABLED) static sd_detect_card_t s_cd; static sd_io_voltage_t s_ioVoltage = { .type = BOARD_SDMMC_SD_IO_VOLTAGE_CONTROL_TYPE, .func = NULL, }; #endif static sdmmchost_t s_host; #ifdef SDIO_ENABLED static sdio_card_int_t s_sdioInt; #endif GPIO_HANDLE_DEFINE(s_CardDetectGpioHandle); GPIO_HANDLE_DEFINE(s_PowerResetGpioHandle); /******************************************************************************* * Code ******************************************************************************/ uint32_t BOARD_USDHC1ClockConfiguration(void) { CLOCK_InitSysPll(&sysPllConfig_BOARD_BootClockRUN); /*configure system pll PFD0 fractional divider to 24, output clock is 528MHZ * 18 / 24 = 396 MHZ*/ CLOCK_InitSysPfd(kCLOCK_Pfd0, 24U); /* Configure USDHC clock source and divider */ CLOCK_SetDiv(kCLOCK_Usdhc1Div, 1U); /* USDHC clock root frequency maximum: 198MHZ */ CLOCK_SetMux(kCLOCK_Usdhc1Mux, 1U); return 396000000U / 2U; } #if defined(SDIO_ENABLED) || defined(SD_ENABLED) bool BOARD_SDCardGetDetectStatus(void) { uint8_t pinState; if (HAL_GpioGetInput(s_CardDetectGpioHandle, &pinState) == kStatus_HAL_GpioSuccess) { if (pinState == BOARD_SDMMC_SD_CD_INSERT_LEVEL) { return true; } } return false; } void SDMMC_SD_CD_Callback(void *param) { if (s_cd.callback != NULL) { s_cd.callback(BOARD_SDCardGetDetectStatus(), s_cd.userData); } } void BOARD_SDCardDAT3PullFunction(uint32_t status) { if (status == kSD_DAT3PullDown) { IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_05_USDHC1_DATA3, IOMUXC_SW_PAD_CTL_PAD_SPEED(1) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(0) | IOMUXC_SW_PAD_CTL_PAD_DSE(1)); } else { IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_05_USDHC1_DATA3, IOMUXC_SW_PAD_CTL_PAD_SPEED(1) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(1)); } } void BOARD_SDCardDetectInit(sd_cd_t cd, void *userData) { uint8_t pinState; /* install card detect callback */ s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CARD_DETECT_DEBOUNCE_DELAY_MS; s_cd.type = BOARD_SDMMC_SD_CD_TYPE; s_cd.cardDetected = BOARD_SDCardGetDetectStatus; s_cd.callback = cd; s_cd.userData = userData; if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByGpioCD) { hal_gpio_pin_config_t sw_config = { kHAL_GpioDirectionIn, 0, BOARD_SDMMC_SD_CD_GPIO_PORT, BOARD_SDMMC_SD_CD_GPIO_PIN, }; HAL_GpioInit(s_CardDetectGpioHandle, &sw_config); HAL_GpioSetTriggerMode(s_CardDetectGpioHandle, BOARD_SDMMC_SD_CD_INTTERUPT_TYPE); HAL_GpioInstallCallback(s_CardDetectGpioHandle, SDMMC_SD_CD_Callback, NULL); if (HAL_GpioGetInput(s_CardDetectGpioHandle, &pinState) == kStatus_HAL_GpioSuccess) { if (pinState == BOARD_SDMMC_SD_CD_INSERT_LEVEL) { if (cd != NULL) { cd(true, userData); } } } } /* register DAT3 pull function switch function pointer */ if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByHostDATA3) { s_cd.dat3PullFunc = BOARD_SDCardDAT3PullFunction; /* make sure the card is power on for DAT3 pull up */ BOARD_SDCardPowerControl(true); } } void BOARD_SDCardPowerResetInit(void) { hal_gpio_pin_config_t sw_config = { kHAL_GpioDirectionOut, 1, BOARD_SDMMC_SD_POWER_RESET_GPIO_PORT, BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN, }; HAL_GpioInit(s_PowerResetGpioHandle, &sw_config); } void BOARD_SDCardPowerControl(bool enable) { if (enable) { HAL_GpioSetOutput(s_PowerResetGpioHandle, 1); } else { /* Power off the card only when the card is inserted, since the card detect circuit is depend on the power on * the EVK, card detect will not work if the power is off */ if (BOARD_SDCardGetDetectStatus() == true) { HAL_GpioSetOutput(s_PowerResetGpioHandle, 0); } } } void BOARD_SD_Pin_Config(uint32_t freq) { uint32_t speed = 0U, strength = 0U; if (freq <= 50000000) { speed = 0U; strength = 7U; } else if (freq <= 100000000) { speed = 2U; strength = 7U; } else { speed = 3U; strength = 7U; } IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_USDHC1_CMD, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_01_USDHC1_CLK, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(0) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_02_USDHC1_DATA0, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_03_USDHC1_DATA1, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_04_USDHC1_DATA2, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_05_USDHC1_DATA3, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); } #endif #ifdef SD_ENABLED void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, void *userData) { assert(card); s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer; s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE; s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL; #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER s_host.cacheAlignBuffer = s_sdmmcCacheLineAlignBuffer; s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U; #endif ((sd_card_t *)card)->host = &s_host; ((sd_card_t *)card)->host->hostController.base = BOARD_SDMMC_SD_HOST_BASEADDR; ((sd_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration(); ((sd_card_t *)card)->usrParam.cd = &s_cd; ((sd_card_t *)card)->usrParam.pwr = BOARD_SDCardPowerControl; ((sd_card_t *)card)->usrParam.ioStrength = BOARD_SD_Pin_Config; ((sd_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage; ((sd_card_t *)card)->usrParam.maxFreq = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ; BOARD_SDCardPowerResetInit(); BOARD_SDCardDetectInit(cd, userData); NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, hostIRQPriority); } #endif #ifdef SDIO_ENABLED void BOARD_SDIO_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, sdio_int_t cardInt) { assert(card); s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer; s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE; s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL; #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER s_host.cacheAlignBuffer = s_sdmmcCacheLineAlignBuffer; s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U; #endif ((sdio_card_t *)card)->host = &s_host; ((sdio_card_t *)card)->host->hostController.base = BOARD_SDMMC_SDIO_HOST_BASEADDR; ((sdio_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration(); ((sdio_card_t *)card)->usrParam.cd = &s_cd; ((sdio_card_t *)card)->usrParam.pwr = BOARD_SDCardPowerControl; ((sdio_card_t *)card)->usrParam.ioStrength = BOARD_SD_Pin_Config; ((sdio_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage; ((sdio_card_t *)card)->usrParam.maxFreq = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ; if (cardInt != NULL) { s_sdioInt.cardInterrupt = cardInt; ((sdio_card_t *)card)->usrParam.sdioInt = &s_sdioInt; } BOARD_SDCardPowerResetInit(); BOARD_SDCardDetectInit(cd, NULL); NVIC_SetPriority(BOARD_SDMMC_SDIO_HOST_IRQ, hostIRQPriority); } #endif #ifdef MMC_ENABLED static void BOARD_MMC_Pin_Config(uint32_t freq) { uint32_t speed = 0U, strength = 0U; if (freq <= 50000000) { speed = 0U; strength = 7U; } else if (freq <= 100000000) { speed = 2U; strength = 7U; } else { speed = 3U; strength = 7U; } IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_USDHC2_CMD, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_04_USDHC2_CLK, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(0) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_USDHC2_DATA0, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_02_USDHC2_DATA1, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_01_USDHC2_DATA2, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_00_USDHC2_DATA3, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_08_USDHC2_DATA4, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_09_USDHC2_DATA5, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_10_USDHC2_DATA6, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_11_USDHC2_DATA7, IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(strength)); } void BOARD_MMC_Config(void *card, uint32_t hostIRQPriority) { assert(card); s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer; s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE; s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL; #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER s_host.cacheAlignBuffer = s_sdmmcCacheLineAlignBuffer; s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U; #endif ((mmc_card_t *)card)->host = &s_host; ((mmc_card_t *)card)->host->hostController.base = BOARD_SDMMC_MMC_HOST_BASEADDR; ((mmc_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration(); ((mmc_card_t *)card)->usrParam.ioStrength = BOARD_MMC_Pin_Config; ((mmc_card_t *)card)->usrParam.maxFreq = BOARD_SDMMC_MMC_HOST_SUPPORT_HS200_FREQ; ((mmc_card_t *)card)->hostVoltageWindowVCC = BOARD_SDMMC_MMC_VCC_SUPPLY; ((mmc_card_t *)card)->hostVoltageWindowVCCQ = BOARD_SDMMC_MMC_VCCQ_SUPPLY; NVIC_SetPriority(BOARD_SDMMC_MMC_HOST_IRQ, hostIRQPriority); } #endif