1 /*
2 * Copyright 2021-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 }
118 else
119 {
120 IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_USDHC1_DATA3, 0x4U);
121 }
122 }
123
BOARD_SDCardDetectInit(sd_cd_t cd,void * userData)124 void BOARD_SDCardDetectInit(sd_cd_t cd, void *userData)
125 {
126 uint8_t pinState;
127
128 /* install card detect callback */
129 s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CARD_DETECT_DEBOUNCE_DELAY_MS;
130 s_cd.type = BOARD_SDMMC_SD_CD_TYPE;
131 s_cd.cardDetected = BOARD_SDCardGetDetectStatus;
132 s_cd.callback = cd;
133 s_cd.userData = userData;
134
135 if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByGpioCD)
136 {
137 hal_gpio_pin_config_t sw_config = {
138 kHAL_GpioDirectionIn,
139 0,
140 BOARD_SDMMC_SD_CD_GPIO_PORT,
141 BOARD_SDMMC_SD_CD_GPIO_PIN,
142 };
143 HAL_GpioInit(s_CardDetectGpioHandle, &sw_config);
144 HAL_GpioSetTriggerMode(s_CardDetectGpioHandle, BOARD_SDMMC_SD_CD_INTTERUPT_TYPE);
145 HAL_GpioInstallCallback(s_CardDetectGpioHandle, SDMMC_SD_CD_Callback, NULL);
146
147 if (HAL_GpioGetInput(s_CardDetectGpioHandle, &pinState) == kStatus_HAL_GpioSuccess)
148 {
149 if (pinState == BOARD_SDMMC_SD_CD_INSERT_LEVEL)
150 {
151 if (cd != NULL)
152 {
153 cd(true, userData);
154 }
155 }
156 }
157 }
158
159 /* register DAT3 pull function switch function pointer */
160 if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByHostDATA3)
161 {
162 s_cd.dat3PullFunc = BOARD_SDCardDAT3PullFunction;
163 /* make sure the card is power on for DAT3 pull up */
164 BOARD_SDCardPowerControl(true);
165 }
166 }
167
BOARD_SDCardPowerResetInit(void)168 void BOARD_SDCardPowerResetInit(void)
169 {
170 hal_gpio_pin_config_t sw_config = {
171 kHAL_GpioDirectionOut,
172 1,
173 BOARD_SDMMC_SD_POWER_RESET_GPIO_PORT,
174 BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN,
175 };
176 HAL_GpioInit(s_PowerResetGpioHandle, &sw_config);
177 }
178
BOARD_SDCardPowerControl(bool enable)179 void BOARD_SDCardPowerControl(bool enable)
180 {
181 if (enable)
182 {
183 HAL_GpioSetOutput(s_PowerResetGpioHandle, 0);
184 }
185 else
186 {
187 HAL_GpioSetOutput(s_PowerResetGpioHandle, 1);
188 }
189 }
190 #endif
191
192 #ifdef SD_ENABLED
BOARD_SD_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,void * userData)193 void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, void *userData)
194 {
195 assert(card);
196
197 s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer;
198 s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
199 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
200 s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
201 #endif
202 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
203 s_host.cacheAlignBuffer = s_sdmmcCacheLineAlignBuffer;
204 s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
205 #endif
206
207 ((sd_card_t *)card)->host = &s_host;
208 ((sd_card_t *)card)->host->hostController.base = BOARD_SDMMC_SD_HOST_BASEADDR;
209 ((sd_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
210
211 ((sd_card_t *)card)->usrParam.cd = &s_cd;
212 ((sd_card_t *)card)->usrParam.pwr = BOARD_SDCardPowerControl;
213 ((sd_card_t *)card)->usrParam.ioStrength = NULL;
214 ((sd_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage;
215 ((sd_card_t *)card)->usrParam.maxFreq = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
216
217 BOARD_SDCardPowerResetInit();
218
219 BOARD_SDCardDetectInit(cd, userData);
220
221 NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, hostIRQPriority);
222
223 #if __CORTEX_M == 7
224 BOARD_USDHC_Errata();
225 #endif
226 }
227 #endif
228
229 #ifdef SDIO_ENABLED
BOARD_SDIO_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,sdio_int_t cardInt)230 void BOARD_SDIO_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, sdio_int_t cardInt)
231 {
232 assert(card);
233
234 s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer;
235 s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
236 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
237 s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
238 #endif
239 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
240 s_host.cacheAlignBuffer = s_sdmmcCacheLineAlignBuffer;
241 s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
242 #endif
243
244 ((sdio_card_t *)card)->host = &s_host;
245 ((sdio_card_t *)card)->host->hostController.base = BOARD_SDMMC_SDIO_HOST_BASEADDR;
246 ((sdio_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
247
248 ((sdio_card_t *)card)->usrParam.cd = &s_cd;
249 ((sdio_card_t *)card)->usrParam.pwr = BOARD_SDCardPowerControl;
250 ((sdio_card_t *)card)->usrParam.ioStrength = NULL;
251 ((sdio_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage;
252 ((sdio_card_t *)card)->usrParam.maxFreq = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
253 if (cardInt != NULL)
254 {
255 s_sdioInt.cardInterrupt = cardInt;
256 ((sdio_card_t *)card)->usrParam.sdioInt = &s_sdioInt;
257 }
258
259 BOARD_SDCardPowerResetInit();
260 BOARD_SDCardDetectInit(cd, NULL);
261
262 NVIC_SetPriority(BOARD_SDMMC_SDIO_HOST_IRQ, hostIRQPriority);
263
264 #if __CORTEX_M == 7
265 BOARD_USDHC_Errata();
266 #endif
267 }
268 #endif
269
270 #ifdef MMC_ENABLED
BOARD_MMC_Config(void * card,uint32_t hostIRQPriority)271 void BOARD_MMC_Config(void *card, uint32_t hostIRQPriority)
272 {
273 assert(card);
274
275 s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer;
276 s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
277 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
278 s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
279 #endif
280 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
281 s_host.cacheAlignBuffer = s_sdmmcCacheLineAlignBuffer;
282 s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
283 #endif
284
285 ((mmc_card_t *)card)->host = &s_host;
286 ((mmc_card_t *)card)->host->hostController.base = BOARD_SDMMC_MMC_HOST_BASEADDR;
287 ((mmc_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
288 ((mmc_card_t *)card)->host->tuningType = BOARD_SDMMC_MMC_TUNING_TYPE;
289 ((mmc_card_t *)card)->usrParam.ioStrength = NULL;
290 ((mmc_card_t *)card)->usrParam.maxFreq = BOARD_SDMMC_MMC_HOST_SUPPORT_HS200_FREQ;
291
292 ((mmc_card_t *)card)->usrParam.capability |= BOARD_SDMMC_MMC_SUPPORT_8_BIT_DATA_WIDTH;
293
294 ((mmc_card_t *)card)->hostVoltageWindowVCC = BOARD_SDMMC_MMC_VCC_SUPPLY;
295 ((mmc_card_t *)card)->hostVoltageWindowVCCQ = BOARD_SDMMC_MMC_VCCQ_SUPPLY;
296
297 NVIC_SetPriority(BOARD_SDMMC_MMC_HOST_IRQ, hostIRQPriority);
298
299 #if __CORTEX_M == 7
300 BOARD_USDHC_Errata();
301 #endif
302 }
303 #endif
304