1 /*
2  * Copyright 2020 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 /*******************************************************************************
44  * Code
45  ******************************************************************************/
BOARD_USDHC1ClockConfiguration(void)46 uint32_t BOARD_USDHC1ClockConfiguration(void)
47 {
48     clock_root_config_t rootCfg = {0};
49     /* SYS PLL2 528MHz. */
50     const clock_sys_pll2_config_t sysPll2Config = {
51         .ssEnable = false,
52     };
53 
54     CLOCK_InitSysPll2(&sysPll2Config);
55     CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd2, 24);
56 
57     rootCfg.mux = 4;
58     rootCfg.div = 2;
59     CLOCK_SetRootClock(kCLOCK_Root_Usdhc1, &rootCfg);
60 
61     return CLOCK_GetRootClockFreq(kCLOCK_Root_Usdhc1);
62 }
63 
64 #if __CORTEX_M == 7
BOARD_USDHC_Errata(void)65 void BOARD_USDHC_Errata(void)
66 {
67     /* ERR050396
68      * Errata description:
69      * AXI to AHB conversion for CM7 AHBS port (port to access CM7 to TCM) is by a NIC301 block, instead of XHB400
70      * block. NIC301 doesn’t support sparse write conversion. Any AXI to AHB conversion need XHB400, not by NIC. This
71      * will result in data corruption in case of AXI sparse write reaches the NIC301 ahead of AHBS. Errata workaround:
72      * For uSDHC, don’t set the bit#1 of IOMUXC_GPR28 (AXI transaction is cacheable), if write data to TCM aligned in 4
73      * bytes; No such write access limitation for OCRAM or external RAM
74      */
75     IOMUXC_GPR->GPR28 &= (~IOMUXC_GPR_GPR28_AWCACHE_USDHC_MASK);
76 }
77 #endif
78 
79 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
BOARD_SDCardGetDetectStatus(void)80 bool BOARD_SDCardGetDetectStatus(void)
81 {
82     return GPIO_PinRead(BOARD_SDMMC_SD_CD_GPIO_BASE, BOARD_SDMMC_SD_CD_GPIO_PIN) == BOARD_SDMMC_SD_CD_INSERT_LEVEL;
83 }
84 
BOARD_SDMMC_SD_CD_PORT_IRQ_HANDLER(void)85 void BOARD_SDMMC_SD_CD_PORT_IRQ_HANDLER(void)
86 {
87     if (GPIO_PortGetInterruptFlags(BOARD_SDMMC_SD_CD_GPIO_BASE) & (1U << BOARD_SDMMC_SD_CD_GPIO_PIN))
88     {
89         if (s_cd.callback != NULL)
90         {
91             s_cd.callback(BOARD_SDCardGetDetectStatus(), s_cd.userData);
92         }
93     }
94     /* Clear interrupt flag.*/
95     GPIO_PortClearInterruptFlags(BOARD_SDMMC_SD_CD_GPIO_BASE, ~0U);
96 }
97 
BOARD_SDCardDAT3PullFunction(uint32_t status)98 void BOARD_SDCardDAT3PullFunction(uint32_t status)
99 {
100     if (status == kSD_DAT3PullDown)
101     {
102         IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_USDHC1_DATA3,
103                             0xCU); /* no pull in IOMUX configuration, 100K pull down externally is required. */
104     }
105     else
106     {
107         IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_USDHC1_DATA3, 0x4U);
108     }
109 }
110 
BOARD_SDCardDetectInit(sd_cd_t cd,void * userData)111 void BOARD_SDCardDetectInit(sd_cd_t cd, void *userData)
112 {
113     /* install card detect callback */
114     s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CARD_DETECT_DEBOUNCE_DELAY_MS;
115     s_cd.type          = BOARD_SDMMC_SD_CD_TYPE;
116     s_cd.cardDetected  = BOARD_SDCardGetDetectStatus;
117     s_cd.callback      = cd;
118     s_cd.userData      = userData;
119 
120     if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByGpioCD)
121     {
122         gpio_pin_config_t sw_config = {
123             kGPIO_DigitalInput,
124             0,
125             kGPIO_IntRisingOrFallingEdge,
126         };
127         GPIO_PinInit(BOARD_SDMMC_SD_CD_GPIO_BASE, BOARD_SDMMC_SD_CD_GPIO_PIN, &sw_config);
128         GPIO_PortEnableInterrupts(BOARD_SDMMC_SD_CD_GPIO_BASE, 1U << BOARD_SDMMC_SD_CD_GPIO_PIN);
129 
130         /* set IRQ priority */
131         NVIC_SetPriority(BOARD_SDMMC_SD_CD_IRQ, BOARD_SDMMC_SD_CD_IRQ_PRIORITY);
132         GPIO_PortClearInterruptFlags(BOARD_SDMMC_SD_CD_GPIO_BASE, ~0);
133         /* Open card detection pin NVIC. */
134         EnableIRQ(BOARD_SDMMC_SD_CD_IRQ);
135 
136         if (GPIO_PinRead(BOARD_SDMMC_SD_CD_GPIO_BASE, BOARD_SDMMC_SD_CD_GPIO_PIN) == BOARD_SDMMC_SD_CD_INSERT_LEVEL)
137         {
138             if (cd != NULL)
139             {
140                 cd(true, userData);
141             }
142         }
143     }
144 
145     /* register DAT3 pull function switch function pointer */
146     if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByHostDATA3)
147     {
148         s_cd.dat3PullFunc = BOARD_SDCardDAT3PullFunction;
149         /* make sure the card is power on for DAT3 pull up */
150         BOARD_SDCardPowerControl(true);
151     }
152 }
153 
BOARD_SDCardPowerResetInit(void)154 void BOARD_SDCardPowerResetInit(void)
155 {
156     gpio_pin_config_t sw_config = {
157         kGPIO_DigitalOutput,
158         1,
159         kGPIO_NoIntmode,
160     };
161     GPIO_PinInit(BOARD_SDMMC_SD_POWER_RESET_GPIO_BASE, BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN, &sw_config);
162 }
163 
BOARD_SDCardPowerControl(bool enable)164 void BOARD_SDCardPowerControl(bool enable)
165 {
166     if (enable)
167     {
168         GPIO_PinWrite(BOARD_SDMMC_SD_POWER_RESET_GPIO_BASE, BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN, 0);
169     }
170     else
171     {
172         /* Power off the card only when the card is inserted, since the card detect circuit is depend on the power on
173          * the EVK, card detect will not work if the power is off */
174         if (BOARD_SDCardGetDetectStatus() == true)
175         {
176             GPIO_PinWrite(BOARD_SDMMC_SD_POWER_RESET_GPIO_BASE, BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN, 1);
177         }
178     }
179 }
180 #endif
181 
182 #ifdef SD_ENABLED
BOARD_SD_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,void * userData)183 void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, void *userData)
184 {
185     assert(card);
186 
187     s_host.dmaDesBuffer         = s_sdmmcHostDmaBuffer;
188     s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
189 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
190     s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
191 #endif
192 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
193     s_host.cacheAlignBuffer     = s_sdmmcCacheLineAlignBuffer;
194     s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
195 #endif
196 
197     ((sd_card_t *)card)->host                                = &s_host;
198     ((sd_card_t *)card)->host->hostController.base           = BOARD_SDMMC_SD_HOST_BASEADDR;
199     ((sd_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
200 
201     ((sd_card_t *)card)->usrParam.cd         = &s_cd;
202     ((sd_card_t *)card)->usrParam.pwr        = BOARD_SDCardPowerControl;
203     ((sd_card_t *)card)->usrParam.ioStrength = NULL;
204     ((sd_card_t *)card)->usrParam.ioVoltage  = &s_ioVoltage;
205     ((sd_card_t *)card)->usrParam.maxFreq    = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
206 
207     BOARD_SDCardPowerResetInit();
208 
209     BOARD_SDCardDetectInit(cd, userData);
210 
211     NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, hostIRQPriority);
212 
213 #if __CORTEX_M == 7
214     BOARD_USDHC_Errata();
215 #endif
216 }
217 #endif
218 
219 #ifdef SDIO_ENABLED
BOARD_SDIO_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,sdio_int_t cardInt)220 void BOARD_SDIO_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, sdio_int_t cardInt)
221 {
222     assert(card);
223 
224     s_host.dmaDesBuffer         = s_sdmmcHostDmaBuffer;
225     s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
226 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
227     s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
228 #endif
229 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
230     s_host.cacheAlignBuffer     = s_sdmmcCacheLineAlignBuffer;
231     s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
232 #endif
233 
234     ((sdio_card_t *)card)->host                                = &s_host;
235     ((sdio_card_t *)card)->host->hostController.base           = BOARD_SDMMC_SDIO_HOST_BASEADDR;
236     ((sdio_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
237 
238     ((sdio_card_t *)card)->usrParam.cd         = &s_cd;
239     ((sdio_card_t *)card)->usrParam.pwr        = BOARD_SDCardPowerControl;
240     ((sdio_card_t *)card)->usrParam.ioStrength = NULL;
241     ((sdio_card_t *)card)->usrParam.ioVoltage  = &s_ioVoltage;
242     ((sdio_card_t *)card)->usrParam.maxFreq    = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
243     if (cardInt != NULL)
244     {
245         s_sdioInt.cardInterrupt                 = cardInt;
246         ((sdio_card_t *)card)->usrParam.sdioInt = &s_sdioInt;
247     }
248 
249     BOARD_SDCardPowerResetInit();
250     BOARD_SDCardDetectInit(cd, NULL);
251 
252     NVIC_SetPriority(BOARD_SDMMC_SDIO_HOST_IRQ, hostIRQPriority);
253 
254 #if __CORTEX_M == 7
255     BOARD_USDHC_Errata();
256 #endif
257 }
258 #endif
259 
260 #ifdef MMC_ENABLED
BOARD_MMC_Config(void * card,uint32_t hostIRQPriority)261 void BOARD_MMC_Config(void *card, uint32_t hostIRQPriority)
262 {
263     assert(card);
264 
265     s_host.dmaDesBuffer         = s_sdmmcHostDmaBuffer;
266     s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
267 #if ((defined __DCACHE_PRESENT) && __DCACHE_PRESENT) || (defined FSL_FEATURE_HAS_L1CACHE && FSL_FEATURE_HAS_L1CACHE)
268     s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
269 #endif
270 #if defined SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER && SDMMCHOST_ENABLE_CACHE_LINE_ALIGN_TRANSFER
271     s_host.cacheAlignBuffer     = s_sdmmcCacheLineAlignBuffer;
272     s_host.cacheAlignBufferSize = BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE * 2U;
273 #endif
274 
275     ((mmc_card_t *)card)->host                                = &s_host;
276     ((mmc_card_t *)card)->host->hostController.base           = BOARD_SDMMC_MMC_HOST_BASEADDR;
277     ((mmc_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC1ClockConfiguration();
278     ((mmc_card_t *)card)->host->tuningType                    = BOARD_SDMMC_MMC_TUNING_TYPE;
279     ((mmc_card_t *)card)->usrParam.ioStrength                 = NULL;
280     ((mmc_card_t *)card)->usrParam.maxFreq                    = BOARD_SDMMC_MMC_HOST_SUPPORT_HS200_FREQ;
281 
282     ((mmc_card_t *)card)->usrParam.capability |= BOARD_SDMMC_MMC_SUPPORT_8_BIT_DATA_WIDTH;
283 
284     ((mmc_card_t *)card)->hostVoltageWindowVCC  = BOARD_SDMMC_MMC_VCC_SUPPLY;
285     ((mmc_card_t *)card)->hostVoltageWindowVCCQ = BOARD_SDMMC_MMC_VCCQ_SUPPLY;
286 
287     NVIC_SetPriority(BOARD_SDMMC_MMC_HOST_IRQ, hostIRQPriority);
288 
289 #if __CORTEX_M == 7
290     BOARD_USDHC_Errata();
291 #endif
292 }
293 #endif
294