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