1 /*
2  * Copyright 2020-2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "sdmmc_config.h"
9 #include "fsl_power.h"
10 #include "fsl_iopctl.h"
11 
12 /*******************************************************************************
13  * Definitions
14  ******************************************************************************/
15 
16 /*******************************************************************************
17  * Prototypes
18  ******************************************************************************/
19 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
20 void BOARD_SDCardIoVoltageControl(sdmmc_operation_voltage_t voltage);
21 #endif
22 void BOARD_SDCardPowerControl(bool enable);
23 
24 /*******************************************************************************
25  * Variables
26  ******************************************************************************/
27 /*!brief sdmmc dma buffer */
28 AT_NONCACHEABLE_SECTION_ALIGN(static uint32_t s_sdmmcHostDmaBuffer[BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE],
29                               SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE);
30 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
31 static sd_detect_card_t s_cd;
32 static sd_io_voltage_t s_ioVoltage = {
33     .type = BOARD_SDMMC_SD_IO_VOLTAGE_CONTROL_TYPE,
34     .func = BOARD_SDCardIoVoltageControl,
35 };
36 #endif
37 static sdmmchost_t s_host;
38 GPIO_HANDLE_DEFINE(s_PowerResetGpioHandle);
39 
40 #ifdef SDIO_ENABLED
41 static sdio_card_int_t s_sdioInt;
42 #endif
43 /*******************************************************************************
44  * Code
45  ******************************************************************************/
BOARD_USDHC0ClockConfiguration(void)46 uint32_t BOARD_USDHC0ClockConfiguration(void)
47 {
48     /*Make sure USDHC ram buffer has power up*/
49     POWER_DisablePD(kPDRUNCFG_APD_USDHC0_SRAM);
50     POWER_DisablePD(kPDRUNCFG_PPD_USDHC0_SRAM);
51     POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
52     POWER_ApplyPD();
53 
54     /* SDIO0 */
55     /* usdhc depend on 32K clock also */
56     CLOCK_AttachClk(kLPOSC_DIV32_to_32KHZWAKE_CLK);
57     CLOCK_AttachClk(kAUX0_PLL_to_SDIO0_CLK);
58     CLOCK_SetClkDiv(kCLOCK_DivSdio0Clk, 1);
59 
60     return CLOCK_GetSdioClkFreq(0);
61 }
62 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
BOARD_SDCardDAT3PullFunction(uint32_t status)63 void BOARD_SDCardDAT3PullFunction(uint32_t status)
64 {
65     if (status == kSD_DAT3PullDown)
66     {
67         IOPCTL_PinMuxSet(IOPCTL, 2U, 3U, 0x41); /* PULL UP/PULL DOWN disable */
68     }
69     else
70     {
71         IOPCTL_PinMuxSet(IOPCTL, 2U, 3U, 0x71);
72     }
73 }
74 
BOARD_SDCardDetectInit(sd_cd_t cd,void * userData)75 void BOARD_SDCardDetectInit(sd_cd_t cd, void *userData)
76 {
77     /* install card detect callback */
78     s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CARD_DETECT_DEBOUNCE_DELAY_MS;
79     s_cd.type          = BOARD_SDMMC_SD_CD_TYPE;
80     s_cd.callback      = cd;
81     s_cd.userData      = userData;
82 
83     /* register DAT3 pull function switch function pointer */
84     if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByHostDATA3)
85     {
86         s_cd.dat3PullFunc = BOARD_SDCardDAT3PullFunction;
87         /* make sure the card is power on for DAT3 pull up */
88         BOARD_SDCardPowerControl(true);
89     }
90 }
91 #endif
BOARD_SDCardIoVoltageControlInit(void)92 void BOARD_SDCardIoVoltageControlInit(void)
93 {
94     /* Intentional empty, since the default SD signal voltage is 1.8V already which is againist with SD3.0 spec, so
95     leave the voltage switch function as empty to workaround the limitation, then some SD3.0 card may works, but SD2.0
96     card cannot works on this board */
97 }
98 
BOARD_SDCardIoVoltageControl(sdmmc_operation_voltage_t voltage)99 void BOARD_SDCardIoVoltageControl(sdmmc_operation_voltage_t voltage)
100 {
101     /* Intentional empty, since the default SD signal voltage is 1.8V already which is againist with SD3.0 spec, so
102     leave the voltage switch function as empty to workaround the limitation, then some SD3.0 card may works, but SD2.0
103     card cannot works on this board */
104 }
105 
BOARD_SDCardPowerResetInit(void)106 void BOARD_SDCardPowerResetInit(void)
107 {
108     hal_gpio_pin_config_t sw_config = {
109         kHAL_GpioDirectionOut,
110         0,
111         BOARD_SDMMC_SD_POWER_RESET_GPIO_PORT,
112         BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN,
113     };
114     HAL_GpioInit(s_PowerResetGpioHandle, &sw_config);
115 }
116 
BOARD_SDCardPowerControl(bool enable)117 void BOARD_SDCardPowerControl(bool enable)
118 {
119     if (enable)
120     {
121         HAL_GpioSetOutput(s_PowerResetGpioHandle, 1);
122     }
123     else
124     {
125         HAL_GpioSetOutput(s_PowerResetGpioHandle, 0);
126     }
127 }
128 
129 #ifdef SD_ENABLED
BOARD_SD_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,void * userData)130 void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, void *userData)
131 {
132     assert(card);
133 
134     s_host.dmaDesBuffer                                      = s_sdmmcHostDmaBuffer;
135     s_host.dmaDesBufferWordsNum                              = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
136     ((sd_card_t *)card)->host                                = &s_host;
137     ((sd_card_t *)card)->host->hostController.base           = BOARD_SDMMC_SD_HOST_BASEADDR;
138     ((sd_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC0ClockConfiguration();
139 
140     ((sd_card_t *)card)->host->tuningType = BOARD_SDMMC_SD_TUNING_TYPE;
141 
142     ((sd_card_t *)card)->usrParam.cd        = &s_cd;
143     ((sd_card_t *)card)->usrParam.pwr       = BOARD_SDCardPowerControl;
144     ((sd_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage;
145 
146     BOARD_SDCardPowerResetInit();
147 
148     BOARD_SDCardIoVoltageControlInit();
149 
150     BOARD_SDCardDetectInit(cd, userData);
151 
152     NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, hostIRQPriority);
153 }
154 #endif
155 
156 #ifdef SDIO_ENABLED
BOARD_SDIO_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,sdio_int_t cardInt)157 void BOARD_SDIO_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, sdio_int_t cardInt)
158 {
159     assert(card);
160 
161     s_host.dmaDesBuffer                                        = s_sdmmcHostDmaBuffer;
162     s_host.dmaDesBufferWordsNum                                = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
163     ((sdio_card_t *)card)->host                                = &s_host;
164     ((sdio_card_t *)card)->host->hostController.base           = BOARD_SDMMC_SDIO_HOST_BASEADDR;
165     ((sdio_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC0ClockConfiguration();
166     ((sdio_card_t *)card)->host->tuningType                    = BOARD_SDMMC_SD_TUNING_TYPE;
167 
168     ((sdio_card_t *)card)->usrParam.cd        = &s_cd;
169     ((sdio_card_t *)card)->usrParam.pwr       = BOARD_SDCardPowerControl;
170     ((sdio_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage;
171     if (cardInt != NULL)
172     {
173         s_sdioInt.cardInterrupt                 = cardInt;
174         ((sdio_card_t *)card)->usrParam.sdioInt = &s_sdioInt;
175     }
176     BOARD_SDCardPowerResetInit();
177 
178     BOARD_SDCardIoVoltageControlInit();
179 
180     BOARD_SDCardDetectInit(cd, NULL);
181 
182     NVIC_SetPriority(BOARD_SDMMC_SDIO_HOST_IRQ, hostIRQPriority);
183 }
184 #endif
185 
186 #ifdef MMC_ENABLED
BOARD_MMC_Config(void * card,uint32_t hostIRQPriority)187 void BOARD_MMC_Config(void *card, uint32_t hostIRQPriority)
188 {
189     assert(card);
190 
191     s_host.dmaDesBuffer                                       = s_sdmmcHostDmaBuffer;
192     s_host.dmaDesBufferWordsNum                               = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
193     ((mmc_card_t *)card)->host                                = &s_host;
194     ((mmc_card_t *)card)->host->hostController.base           = BOARD_SDMMC_MMC_HOST_BASEADDR;
195     ((mmc_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC0ClockConfiguration();
196     ((mmc_card_t *)card)->host->tuningType                    = BOARD_SDMMC_MMC_TUNING_TYPE;
197     ((mmc_card_t *)card)->hostVoltageWindowVCC                = BOARD_SDMMC_MMC_VCC_SUPPLY;
198     ((mmc_card_t *)card)->hostVoltageWindowVCCQ               = BOARD_SDMMC_MMC_VCCQ_SUPPLY;
199 
200     ((mmc_card_t *)card)->usrParam.capability |= BOARD_SDMMC_MMC_SUPPORT_8_BIT_DATA_WIDTH;
201 
202     BOARD_SDCardIoVoltageControlInit();
203     BOARD_SDCardIoVoltageControl(kSDMMC_OperationVoltage180V);
204 
205     NVIC_SetPriority(BOARD_SDMMC_MMC_HOST_IRQ, hostIRQPriority);
206 }
207 #endif
208