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_pca9420.h"
11 #include "board.h"
12 #include "fsl_iopctl.h"
13
14 /*******************************************************************************
15 * Definitions
16 ******************************************************************************/
17
18 /*******************************************************************************
19 * Prototypes
20 ******************************************************************************/
21 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
22 void BOARD_SDCardIoVoltageControl(sdmmc_operation_voltage_t voltage);
23 #endif
24 void BOARD_SDCardPowerControl(bool enable);
25
26 /*******************************************************************************
27 * Variables
28 ******************************************************************************/
29 /*!brief sdmmc dma buffer */
30 AT_NONCACHEABLE_SECTION_ALIGN(static uint32_t s_sdmmcHostDmaBuffer[BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE],
31 SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE);
32 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
33 static sd_detect_card_t s_cd;
34 static sd_io_voltage_t s_ioVoltage = {
35 .type = BOARD_SDMMC_SD_IO_VOLTAGE_CONTROL_TYPE,
36 .func = BOARD_SDCardIoVoltageControl,
37 };
38 #endif
39 static sdmmchost_t s_host;
40
41 static pca9420_handle_t pca9420Handle;
42 #ifdef SDIO_ENABLED
43 static sdio_card_int_t s_sdioInt;
44 #endif
45
46 GPIO_HANDLE_DEFINE(s_PowerResetGpioHandle);
47 /******************************************************************************* \
48 * Code \
49 ******************************************************************************/
BOARD_USDHC0ClockConfiguration(void)50 uint32_t BOARD_USDHC0ClockConfiguration(void)
51 {
52 /*Make sure USDHC ram buffer has power up*/
53 POWER_DisablePD(kPDRUNCFG_APD_USDHC0_SRAM);
54 POWER_DisablePD(kPDRUNCFG_PPD_USDHC0_SRAM);
55 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
56 POWER_ApplyPD();
57
58 /* SDIO0 */
59 /* usdhc depend on 32K clock also */
60 CLOCK_AttachClk(kLPOSC_DIV32_to_32KHZWAKE_CLK);
61 CLOCK_AttachClk(kAUX0_PLL_to_SDIO0_CLK);
62 CLOCK_SetClkDiv(kCLOCK_DivSdio0Clk, 1);
63
64 return CLOCK_GetSdioClkFreq(0);
65 }
66
67 #if defined(SDIO_ENABLED) || defined(SD_ENABLED)
BOARD_SDCardDAT3PullFunction(uint32_t status)68 void BOARD_SDCardDAT3PullFunction(uint32_t status)
69 {
70 if (status == kSD_DAT3PullDown)
71 {
72 IOPCTL_PinMuxSet(IOPCTL, 2U, 3U, 0x51);
73 }
74 else
75 {
76 IOPCTL_PinMuxSet(IOPCTL, 2U, 3U, 0x71);
77 }
78 }
79
BOARD_SDCardDetectInit(sd_cd_t cd,void * userData)80 void BOARD_SDCardDetectInit(sd_cd_t cd, void *userData)
81 {
82 /* install card detect callback */
83 s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CARD_DETECT_DEBOUNCE_DELAY_MS;
84 s_cd.type = BOARD_SDMMC_SD_CD_TYPE;
85 s_cd.callback = cd;
86 s_cd.userData = userData;
87
88 /* register DAT3 pull function switch function pointer */
89 if (BOARD_SDMMC_SD_CD_TYPE == kSD_DetectCardByHostDATA3)
90 {
91 s_cd.dat3PullFunc = BOARD_SDCardDAT3PullFunction;
92 /* make sure the card is power on for DAT3 pull up */
93 BOARD_SDCardPowerControl(true);
94 }
95 }
96
BOARD_SDCardIoVoltageControlInit(void)97 void BOARD_SDCardIoVoltageControlInit(void)
98 {
99 pca9420_config_t pca9420Config;
100 pca9420_modecfg_t pca9420ModeCfg[2];
101 uint32_t i;
102
103 /* PMIC PCA9420 */
104 CLOCK_AttachClk(kSFRO_to_FLEXCOMM15);
105 BOARD_PMIC_I2C_Init();
106 PCA9420_GetDefaultConfig(&pca9420Config);
107 pca9420Config.I2C_SendFunc = BOARD_PMIC_I2C_Send;
108 pca9420Config.I2C_ReceiveFunc = BOARD_PMIC_I2C_Receive;
109 PCA9420_Init(&pca9420Handle, &pca9420Config);
110 for (i = 0; i < ARRAY_SIZE(pca9420ModeCfg); i++)
111 {
112 PCA9420_GetDefaultModeConfig(&pca9420ModeCfg[i]);
113 }
114 pca9420ModeCfg[0].ldo2OutVolt = kPCA9420_Ldo2OutVolt3V300;
115 pca9420ModeCfg[1].ldo2OutVolt = kPCA9420_Ldo2OutVolt1V800;
116 PCA9420_WriteModeConfigs(&pca9420Handle, kPCA9420_Mode0, &pca9420ModeCfg[0], ARRAY_SIZE(pca9420ModeCfg));
117 }
118
BOARD_SDCardIoVoltageControl(sdmmc_operation_voltage_t voltage)119 void BOARD_SDCardIoVoltageControl(sdmmc_operation_voltage_t voltage)
120 {
121 if (voltage == kSDMMC_OperationVoltage330V)
122 {
123 bool result = PCA9420_SwitchMode(&pca9420Handle, kPCA9420_Mode0);
124 if (!result)
125 {
126 assert(false);
127 }
128 }
129 else if (voltage == kSDMMC_OperationVoltage180V)
130 {
131 bool result = PCA9420_SwitchMode(&pca9420Handle, kPCA9420_Mode1);
132 if (!result)
133 {
134 assert(false);
135 }
136 }
137 }
138
BOARD_SDCardPowerResetInit(void)139 void BOARD_SDCardPowerResetInit(void)
140 {
141 hal_gpio_pin_config_t sw_config = {
142 kHAL_GpioDirectionOut,
143 0,
144 BOARD_SDMMC_SD_POWER_RESET_GPIO_PORT,
145 BOARD_SDMMC_SD_POWER_RESET_GPIO_PIN,
146 };
147
148 /* workaround for calling GPIO_PortInit may reset the configuration already done for the port */
149 CLOCK_EnableClock(BOARD_SDMMC_SD_POWER_RESET_GPIO_CLOCK_NAME);
150 RESET_ClearPeripheralReset(BOARD_SDMMC_SD_POWER_RESET_GPIO_RESET_SOURCE);
151
152 HAL_GpioInit(s_PowerResetGpioHandle, &sw_config);
153 }
154
BOARD_SDCardPowerControl(bool enable)155 void BOARD_SDCardPowerControl(bool enable)
156 {
157 if (enable)
158 {
159 HAL_GpioSetOutput(s_PowerResetGpioHandle, 1);
160 }
161 else
162 {
163 HAL_GpioSetOutput(s_PowerResetGpioHandle, 0);
164 }
165 }
166 #endif
167
168 #ifdef SD_ENABLED
BOARD_SD_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,void * userData)169 void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, void *userData)
170 {
171 assert(card);
172
173 s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer;
174 s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
175 ((sd_card_t *)card)->host = &s_host;
176 ((sd_card_t *)card)->host->hostController.base = BOARD_SDMMC_SD_HOST_BASEADDR;
177 ((sd_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC0ClockConfiguration();
178
179 ((sd_card_t *)card)->usrParam.cd = &s_cd;
180 ((sd_card_t *)card)->usrParam.pwr = BOARD_SDCardPowerControl;
181 ((sd_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage;
182
183 BOARD_SDCardPowerResetInit();
184 BOARD_SDCardIoVoltageControlInit();
185 BOARD_SDCardDetectInit(cd, userData);
186
187 NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, hostIRQPriority);
188 }
189 #endif
190
191 #ifdef SDIO_ENABLED
BOARD_SDIO_Config(void * card,sd_cd_t cd,uint32_t hostIRQPriority,sdio_int_t cardInt)192 void BOARD_SDIO_Config(void *card, sd_cd_t cd, uint32_t hostIRQPriority, sdio_int_t cardInt)
193 {
194 assert(card);
195
196 s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer;
197 s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
198 ((sdio_card_t *)card)->host = &s_host;
199 ((sdio_card_t *)card)->host->hostController.base = BOARD_SDMMC_SDIO_HOST_BASEADDR;
200 ((sdio_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC0ClockConfiguration();
201
202 ((sdio_card_t *)card)->usrParam.cd = &s_cd;
203 if (cardInt != NULL)
204 {
205 s_sdioInt.cardInterrupt = cardInt;
206 ((sdio_card_t *)card)->usrParam.sdioInt = &s_sdioInt;
207 }
208
209 ((sdio_card_t *)card)->usrParam.pwr = BOARD_SDCardPowerControl;
210 ((sdio_card_t *)card)->usrParam.ioVoltage = &s_ioVoltage;
211
212 BOARD_SDCardPowerResetInit();
213 BOARD_SDCardIoVoltageControlInit();
214 BOARD_SDCardDetectInit(cd, NULL);
215
216 NVIC_SetPriority(BOARD_SDMMC_SDIO_HOST_IRQ, hostIRQPriority);
217 }
218 #endif
219
220 #ifdef MMC_ENABLED
221
BOARD_MMC_Config(void * card,uint32_t hostIRQPriority)222 void BOARD_MMC_Config(void *card, uint32_t hostIRQPriority)
223 {
224 assert(card);
225
226 s_host.dmaDesBuffer = s_sdmmcHostDmaBuffer;
227 s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
228 ((mmc_card_t *)card)->host = &s_host;
229 ((mmc_card_t *)card)->host->hostController.base = BOARD_SDMMC_MMC_HOST_BASEADDR;
230 ((mmc_card_t *)card)->host->hostController.sourceClock_Hz = BOARD_USDHC0ClockConfiguration();
231
232 ((mmc_card_t *)card)->hostVoltageWindowVCC = BOARD_SDMMC_MMC_VCC_SUPPLY;
233 ((mmc_card_t *)card)->hostVoltageWindowVCCQ = BOARD_SDMMC_MMC_VCCQ_SUPPLY;
234
235 NVIC_SetPriority(BOARD_SDMMC_MMC_HOST_IRQ, hostIRQPriority);
236 }
237 #endif
238