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_iomuxc.h"
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /*******************************************************************************
15  * Prototypes
16  ******************************************************************************/
17 void BOARD_SDCardPowerControl(bool enable);
18 
19 /*******************************************************************************
20  * Variables
21  ******************************************************************************/
22 /*!brief sdmmc dma buffer */
23 AT_NONCACHEABLE_SECTION_ALIGN(static uint32_t s_sdmmcHostDmaBuffer[BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE],
24                               SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE);
25 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
26 /* two cache line length for sdmmc host driver maintain unalign transfer */
27 SDK_ALIGN(static uint8_t s_sdmmcCacheLineAlignBuffer[BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U],
28           BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE);
29 #endif
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 = NULL,
35 };
36 #endif
37 static sdmmchost_t s_host;
38 
39 #ifdef SDIO_ENABLED
40 static sdio_card_int_t s_sdioInt;
41 #endif
42 
43 GPIO_HANDLE_DEFINE(s_CardDetectGpioHandle);
44 GPIO_HANDLE_DEFINE(s_PowerResetGpioHandle);
45 
46 /*******************************************************************************
47  * Code
48  ******************************************************************************/
BOARD_USDHC1ClockConfiguration(void)49 uint32_t BOARD_USDHC1ClockConfiguration(void)
50 {
51     clock_root_config_t rootCfg = {0};
52     /* SYS PLL2 528MHz. */
53     const clock_sys_pll2_config_t sysPll2Config = {
54         .ssEnable = false,
55     };
56 
57     CLOCK_InitSysPll2(&sysPll2Config);
58     CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd2, 24);
59 
60     rootCfg.mux = 4;
61     rootCfg.div = 2;
62     CLOCK_SetRootClock(kCLOCK_Root_Usdhc1, &rootCfg);
63 
64     return CLOCK_GetRootClockFreq(kCLOCK_Root_Usdhc1);
65 }
66 
67 #if __CORTEX_M == 7
BOARD_USDHC_Errata(void)68 void BOARD_USDHC_Errata(void)
69 {
70     /* ERR050396
71      * Errata description:
72      * AXI to AHB conversion for CM7 AHBS port (port to access CM7 to TCM) is by a NIC301 block, instead of XHB400
73      * block. NIC301 doesn’t support sparse write conversion. Any AXI to AHB conversion need XHB400, not by NIC. This
74      * will result in data corruption in case of AXI sparse write reaches the NIC301 ahead of AHBS. Errata workaround:
75      * For uSDHC, don’t set the bit#1 of IOMUXC_GPR28 (AXI transaction is cacheable), if write data to TCM aligned in 4
76      * bytes; No such write access limitation for OCRAM or external RAM
77      */
78     IOMUXC_GPR->GPR28 &= (~IOMUXC_GPR_GPR28_AWCACHE_USDHC_MASK);
79 }
80 #endif
81 
82 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
BOARD_SDCardGetDetectStatus(void)83 bool BOARD_SDCardGetDetectStatus(void)
84 {
85     uint8_t pinState;
86 
87     if (HAL_GpioGetInput(s_CardDetectGpioHandle, &pinState) == kStatus_HAL_GpioSuccess)
88     {
89         if (pinState == BOARD_SDMMC_SD_CD_INSERT_LEVEL)
90         {
91             return true;
92         }
93     }
94 
95     return false;
96 }
97 
SDMMC_SD_CD_Callback(void * param)98 void SDMMC_SD_CD_Callback(void *param)
99 {
100     if (s_cd.callback != NULL)
101     {
102         s_cd.callback(BOARD_SDCardGetDetectStatus(), s_cd.userData);
103     }
104 }
105 
BOARD_SDCardDAT3PullFunction(uint32_t status)106 void BOARD_SDCardDAT3PullFunction(uint32_t status)
107 {
108     if (status == kSD_DAT3PullDown)
109     {
110         IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_USDHC1_DATA3,
111                             0xCU); /* no pull in IOMUX configuration, 100K pull down externally is required. */
112         /* power reset the card to clear DAT3 legacy status */
113         BOARD_SDCardPowerControl(false);
114         SDK_DelayAtLeastUs(1000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
115         /* make sure the card is power on for DAT3 pull up */
116         BOARD_SDCardPowerControl(true);
117         /* power on delay */
118         SDK_DelayAtLeastUs(1000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
119     }
120     else
121     {
122         IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_USDHC1_DATA3, 0x4U);
123     }
124 }
125 
BOARD_SDCardDetectInit(sd_cd_t cd,void * userData)126 void BOARD_SDCardDetectInit(sd_cd_t cd, void *userData)
127 {
128     uint8_t pinState;
129 
130     /* install card detect callback */
131     s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CARD_DETECT_DEBOUNCE_DELAY_MS;
132     s_cd.type          = BOARD_SDMMC_SD_CD_TYPE;
133     s_cd.cardDetected  = BOARD_SDCardGetDetectStatus;
134     s_cd.callback      = cd;
135     s_cd.userData      = userData;
136 
137     if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByGpioCD)
138     {
139         hal_gpio_pin_config_t sw_config = {
140             kHAL_GpioDirectionIn,
141             0,
142             BOARD_SDMMC_SD_CD_GPIO_PORT,
143             BOARD_SDMMC_SD_CD_GPIO_PIN,
144         };
145         HAL_GpioInit(s_CardDetectGpioHandle, &sw_config);
146         HAL_GpioSetTriggerMode(s_CardDetectGpioHandle, BOARD_SDMMC_SD_CD_INTTERUPT_TYPE);
147         HAL_GpioInstallCallback(s_CardDetectGpioHandle, SDMMC_SD_CD_Callback, NULL);
148 
149         if (HAL_GpioGetInput(s_CardDetectGpioHandle, &pinState) == kStatus_HAL_GpioSuccess)
150         {
151             if (pinState == BOARD_SDMMC_SD_CD_INSERT_LEVEL)
152             {
153                 if (cd != NULL)
154                 {
155                     cd(true, userData);
156                 }
157             }
158         }
159     }
160 
161     /* register DAT3 pull function switch function pointer */
162     if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByHostDATA3)
163     {
164         s_cd.dat3PullFunc = BOARD_SDCardDAT3PullFunction;
165         BOARD_SDCardPowerControl(true);
166     }
167 }
168 
BOARD_SDCardPowerResetInit(void)169 void BOARD_SDCardPowerResetInit(void)
170 {
171     hal_gpio_pin_config_t sw_config = {
172         kHAL_GpioDirectionOut,
173         1,
174         BOARD_SDMMC_SD_POWER_RESET_GPIO_PORT,
175         BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN,
176     };
177     HAL_GpioInit(s_PowerResetGpioHandle, &sw_config);
178 }
179 
BOARD_SDCardPowerControl(bool enable)180 void BOARD_SDCardPowerControl(bool enable)
181 {
182     if (enable)
183     {
184         HAL_GpioSetOutput(s_PowerResetGpioHandle, 0);
185     }
186     else
187     {
188         HAL_GpioSetOutput(s_PowerResetGpioHandle, 1);
189     }
190 }
191 #endif
192 
193 #ifdef SD_ENABLED
BOARD_SD_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,void * userData)194 void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, void *userData)
195 {
196     assert(card);
197 
198     s_host.dmaDesBuffer         = s_sdmmcHostDmaBuffer;
199     s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
200 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
201     s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
202 #endif
203 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
204     s_host.cacheAlignBuffer     = s_sdmmcCacheLineAlignBuffer;
205     s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
206 #endif
207 
208     ((sd_card_t *)card)->host                                = &s_host;
209     ((sd_card_t *)card)->host->hostController.base           = BOARD_SDMMC_SD_HOST_BASEADDR;
210     ((sd_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
211 
212     ((sd_card_t *)card)->usrParam.cd         = &s_cd;
213     ((sd_card_t *)card)->usrParam.pwr        = BOARD_SDCardPowerControl;
214     ((sd_card_t *)card)->usrParam.ioStrength = NULL;
215     ((sd_card_t *)card)->usrParam.ioVoltage  = &s_ioVoltage;
216     ((sd_card_t *)card)->usrParam.maxFreq    = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
217 
218     BOARD_SDCardPowerResetInit();
219 
220     BOARD_SDCardDetectInit(cd, userData);
221 
222     NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, hostIRQPriority);
223 
224 #if __CORTEX_M == 7
225     BOARD_USDHC_Errata();
226 #endif
227 }
228 #endif
229 
230 #ifdef SDIO_ENABLED
BOARD_SDIO_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,sdio_int_t cardInt)231 void BOARD_SDIO_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, sdio_int_t cardInt)
232 {
233     assert(card);
234 
235     s_host.dmaDesBuffer         = s_sdmmcHostDmaBuffer;
236     s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
237 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
238     s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
239 #endif
240 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
241     s_host.cacheAlignBuffer     = s_sdmmcCacheLineAlignBuffer;
242     s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
243 #endif
244 
245     ((sdio_card_t *)card)->host                                = &s_host;
246     ((sdio_card_t *)card)->host->hostController.base           = BOARD_SDMMC_SDIO_HOST_BASEADDR;
247     ((sdio_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
248 
249     ((sdio_card_t *)card)->usrParam.cd         = &s_cd;
250     ((sdio_card_t *)card)->usrParam.pwr        = BOARD_SDCardPowerControl;
251     ((sdio_card_t *)card)->usrParam.ioStrength = NULL;
252     ((sdio_card_t *)card)->usrParam.ioVoltage  = &s_ioVoltage;
253     ((sdio_card_t *)card)->usrParam.maxFreq    = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
254     if (cardInt != NULL)
255     {
256         s_sdioInt.cardInterrupt                 = cardInt;
257         ((sdio_card_t *)card)->usrParam.sdioInt = &s_sdioInt;
258     }
259 
260     BOARD_SDCardPowerResetInit();
261     BOARD_SDCardDetectInit(cd, NULL);
262 
263     NVIC_SetPriority(BOARD_SDMMC_SDIO_HOST_IRQ, hostIRQPriority);
264 
265 #if __CORTEX_M == 7
266     BOARD_USDHC_Errata();
267 #endif
268 }
269 #endif
270 
271 #ifdef MMC_ENABLED
BOARD_MMC_Config(void * card,uint32_t hostIRQPriority)272 void BOARD_MMC_Config(void *card, uint32_t hostIRQPriority)
273 {
274     assert(card);
275 
276     s_host.dmaDesBuffer         = s_sdmmcHostDmaBuffer;
277     s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
278 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
279     s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
280 #endif
281 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
282     s_host.cacheAlignBuffer     = s_sdmmcCacheLineAlignBuffer;
283     s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
284 #endif
285 
286     ((mmc_card_t *)card)->host                                = &s_host;
287     ((mmc_card_t *)card)->host->hostController.base           = BOARD_SDMMC_MMC_HOST_BASEADDR;
288     ((mmc_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
289     ((mmc_card_t *)card)->host->tuningType                    = BOARD_SDMMC_MMC_TUNING_TYPE;
290     ((mmc_card_t *)card)->usrParam.ioStrength                 = NULL;
291     ((mmc_card_t *)card)->usrParam.maxFreq                    = BOARD_SDMMC_MMC_HOST_SUPPORT_HS200_FREQ;
292 
293     ((mmc_card_t *)card)->usrParam.capability |= BOARD_SDMMC_MMC_SUPPORT_8_BIT_DATA_WIDTH;
294 
295     ((mmc_card_t *)card)->hostVoltageWindowVCC  = BOARD_SDMMC_MMC_VCC_SUPPLY;
296     ((mmc_card_t *)card)->hostVoltageWindowVCCQ = BOARD_SDMMC_MMC_VCCQ_SUPPLY;
297 
298     NVIC_SetPriority(BOARD_SDMMC_MMC_HOST_IRQ, hostIRQPriority);
299 
300 #if __CORTEX_M == 7
301     BOARD_USDHC_Errata();
302 #endif
303 }
304 #endif
305