1 /******************************************************************************
2 * Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 ******************************************************************************/
5
6 /*****************************************************************************/
7 /**
8 *
9 * @file xsdps.c
10 * @addtogroup sdps_v3_9
11 * @{
12 *
13 * Contains the interface functions of the XSdPs driver.
14 * See xsdps.h for a detailed description of the device and driver.
15 *
16 * <pre>
17 * MODIFICATION HISTORY:
18 *
19 * Ver Who Date Changes
20 * ----- --- -------- -----------------------------------------------
21 * 1.00a hk/sg 10/17/13 Initial release
22 * 2.0 hk 12/13/13 Added check for arm to use sleep.h and its API's
23 * 2.1 hk 04/18/14 Add sleep for microblaze designs. CR# 781117.
24 * 2.2 hk 07/28/14 Make changes to enable use of data cache.
25 * 2.3 sk 09/23/14 Send command for relative card address
26 * when re-initialization is done.CR# 819614.
27 * Use XSdPs_Change_ClkFreq API whenever changing
28 * clock.CR# 816586.
29 * 2.4 sk 12/04/14 Added support for micro SD without
30 * WP/CD. CR# 810655.
31 * Checked for DAT Inhibit mask instead of CMD
32 * Inhibit mask in Cmd Transfer API.
33 * Added Support for SD Card v1.0
34 * 2.5 sg 07/09/15 Added SD 3.0 features
35 * kvn 07/15/15 Modified the code according to MISRAC-2012.
36 * 2.6 sk 10/12/15 Added support for SD card v1.0 CR# 840601.
37 * 2.7 sk 11/24/15 Considered the slot type befoe checking CD/WP pins.
38 * sk 12/10/15 Added support for MMC cards.
39 * sk 02/16/16 Corrected the Tuning logic.
40 * sk 03/01/16 Removed Bus Width check for eMMC. CR# 938311.
41 * 2.8 sk 05/03/16 Standard Speed for SD to 19MHz in ZynqMPSoC. CR#951024
42 * 3.0 sk 06/09/16 Added support for mkfs to calculate sector count.
43 * sk 07/16/16 Added support for UHS modes.
44 * sk 07/07/16 Used usleep API for both arm and microblaze.
45 * sk 07/16/16 Added Tap delays accordingly to different SD/eMMC
46 * operating modes.
47 * 3.1 mi 09/07/16 Removed compilation warnings with extra compiler flags.
48 * sk 10/13/16 Reduced the delay during power cycle to 1ms as per spec
49 * sk 10/19/16 Used emmc_hwreset pin to reset eMMC.
50 * sk 11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
51 * 3.2 sk 11/30/16 Modified the voltage switching sequence as per spec.
52 * sk 02/01/17 Added HSD and DDR mode support for eMMC.
53 * vns 02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
54 * sk 03/20/17 Add support for EL1 non-secure mode.
55 * 3.3 mn 05/17/17 Add support for 64bit DMA addressing
56 * mn 07/17/17 Add support for running SD at 200MHz
57 * mn 07/26/17 Fixed compilation warnings
58 * mn 08/07/17 Modify driver to support 64-bit DMA in arm64 only
59 * mn 08/17/17 Added CCI support for A53 and disabled data cache
60 * operations when it is enabled.
61 * mn 08/22/17 Updated for Word Access System support
62 * mn 09/06/17 Resolved compilation errors with IAR toolchain
63 * mn 09/26/17 Added UHS_MODE_ENABLE macro to enable UHS mode
64 * 3.4 mn 10/17/17 Use different commands for single and multi block
65 * transfers
66 * mn 03/02/18 Move UHS macro check to SD card initialization routine
67 * 3.5 mn 04/18/18 Resolve compilation warnings for sdps driver
68 * 3.6 mn 07/06/18 Fix Cppcheck and Doxygen warnings for sdps driver
69 * mn 08/01/18 Add support for using 64Bit DMA with 32-Bit Processor
70 * mn 08/01/18 Add cache invalidation call before returning from
71 * ReadPolled API
72 * mn 08/14/18 Resolve compilation warnings for ARMCC toolchain
73 * mn 10/01/18 Change Expected Response for CMD3 to R1 for MMC
74 * mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
75 * 3.7 mn 02/01/19 Add support for idling of SDIO
76 * aru 03/12/19 Modified the code according to MISRAC-2012.
77 * 3.8 mn 04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
78 * mn 09/17/19 Modified ADMA handling API for 32bit and 64bit addresses
79 * 3.9 sd 02/07/20 Added clock support
80 * mn 03/03/20 Restructured the code for more readability and modularity
81 * mn 03/30/20 Return XST_DEVICE_IS_STARTED when host is already started
82 * mn 03/30/20 Move Clock enabling before checking for Host already started
83 *
84 * </pre>
85 *
86 ******************************************************************************/
87
88 /***************************** Include Files *********************************/
89 #include "xsdps_core.h"
90
91 /************************** Constant Definitions *****************************/
92
93 /**************************** Type Definitions *******************************/
94
95 /***************** Macros (Inline Functions) Definitions *********************/
96
97 /************************** Function Prototypes ******************************/
98 /*****************************************************************************/
99 /**
100 *
101 * @brief
102 * Initializes a specific XSdPs instance such that the driver is ready to use.
103 *
104 *
105 * @param InstancePtr is a pointer to the XSdPs instance.
106 * @param ConfigPtr is a reference to a structure containing information
107 * about a specific SD device. This function initializes an
108 * InstancePtr object for a specific device specified by the
109 * contents of Config.
110 * @param EffectiveAddr is the device base address in the virtual memory
111 * address space. The caller is responsible for keeping the address
112 * mapping from EffectiveAddr to the device physical base address
113 * unchanged once this function is invoked. Unexpected errors may
114 * occur if the address mapping changes after this function is
115 * called. If address translation is not used, use
116 * ConfigPtr->Config.BaseAddress for this device.
117 *
118 * @return
119 * - XST_SUCCESS if successful.
120 * - XST_DEVICE_IS_STARTED if the device is already started.
121 * It must be stopped to re-initialize.
122 *
123 * @note This function initializes the host controller.
124 * Initial clock of 400KHz is set.
125 * Voltage of 3.3V is selected as that is supported by host.
126 * Interrupts status is enabled and signal disabled by default.
127 * Default data direction is card to host and
128 * 32 bit ADMA2 is selected. Default Block size is 512 bytes.
129 *
130 ******************************************************************************/
XSdPs_CfgInitialize(XSdPs * InstancePtr,XSdPs_Config * ConfigPtr,u32 EffectiveAddr)131 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
132 u32 EffectiveAddr)
133 {
134 s32 Status;
135
136 Xil_AssertNonvoid(InstancePtr != NULL);
137 Xil_AssertNonvoid(ConfigPtr != NULL);
138
139 #if defined (XCLOCKING)
140 InstancePtr->Config.RefClk = ConfigPtr->RefClk;
141 Xil_ClockEnable(InstancePtr->Config.RefClk);
142 #endif
143 /* If this API is getting called twice, return value accordingly */
144 if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
145 Status = (s32)XST_DEVICE_IS_STARTED;
146 goto RETURN_PATH ;
147 }
148
149 /* Set some default values. */
150 InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
151 InstancePtr->Config.BaseAddress = EffectiveAddr;
152 InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
153 InstancePtr->Config.CardDetect = ConfigPtr->CardDetect;
154 InstancePtr->Config.WriteProtect = ConfigPtr->WriteProtect;
155 InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
156 InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
157 InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
158 InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
159 InstancePtr->SectorCount = 0U;
160 InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
161 InstancePtr->OTapDelay = 0U;
162 InstancePtr->ITapDelay = 0U;
163 InstancePtr->Dma64BitAddr = 0U;
164 InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
165
166 /* Host Controller version is read. */
167 InstancePtr->HC_Version =
168 (u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
169 XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
170
171 /*
172 * Read capabilities register and update it in Instance pointer.
173 * It is sufficient to read this once on power on.
174 */
175 InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
176 XSDPS_CAPS_OFFSET);
177
178 /* Reset the SD bus lines */
179 Status = XSdPs_ResetConfig(InstancePtr);
180 if (Status != XST_SUCCESS) {
181 Status = XST_FAILURE;
182 goto RETURN_PATH ;
183 }
184
185 /* Configure the SD Host Controller */
186 XSdPs_HostConfig(InstancePtr);
187
188 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
189
190 RETURN_PATH:
191 #if defined (XCLOCKING)
192 Xil_ClockDisable(InstancePtr->Config.RefClk);
193 #endif
194 return Status;
195
196 }
197
198 /*****************************************************************************/
199 /**
200 *
201 * @brief
202 * Initialize Card with Identification mode sequence
203 *
204 *
205 * @param InstancePtr is a pointer to the instance to be worked on.
206 *
207 * @return
208 * - XST_SUCCESS if initialization was successful
209 * - XST_FAILURE if failure - could be because
210 * a) SD is already initialized
211 * b) There is no card inserted
212 * c) One of the steps (commands) in the
213 * initialization cycle failed
214 *
215 *
216 ******************************************************************************/
XSdPs_CardInitialize(XSdPs * InstancePtr)217 s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
218 {
219 s32 Status;
220
221 Xil_AssertNonvoid(InstancePtr != NULL);
222 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
223
224 /* Default settings */
225 InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
226 InstancePtr->CardType = XSDPS_CARD_SD;
227 InstancePtr->Switch1v8 = 0U;
228 InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;
229
230 #if defined (XCLOCKING)
231 Xil_ClockEnable(InstancePtr->Config.RefClk);
232 #endif
233
234 /* Change the clock frequency to 400 KHz */
235 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
236 if (Status != XST_SUCCESS) {
237 Status = XST_FAILURE;
238 goto RETURN_PATH ;
239 }
240
241 /* Identify the Card whether it is SD, MMC or eMMC */
242 Status = XSdPs_IdentifyCard(InstancePtr);
243 if (Status != XST_SUCCESS) {
244 Status = XST_FAILURE;
245 goto RETURN_PATH;
246 }
247
248 /* Initialize the identified card */
249 if (InstancePtr->CardType == XSDPS_CARD_SD) {
250 Status = XSdPs_SdCardInitialize(InstancePtr);
251 if (Status != XST_SUCCESS) {
252 Status = XST_FAILURE;
253 goto RETURN_PATH;
254 }
255 } else {
256 Status = XSdPs_MmcCardInitialize(InstancePtr);
257 if (Status != XST_SUCCESS) {
258 Status = XST_FAILURE;
259 goto RETURN_PATH;
260 }
261 }
262
263 RETURN_PATH:
264 #if defined (XCLOCKING)
265 Xil_ClockDisable(InstancePtr->Config.RefClk);
266 #endif
267 return Status;
268 }
269
270 /*****************************************************************************/
271 /**
272 * @brief
273 * This function performs SD read in polled mode.
274 *
275 * @param InstancePtr is a pointer to the instance to be worked on.
276 * @param Arg is the address passed by the user that is to be sent as
277 * argument along with the command.
278 * @param BlkCnt - Block count passed by the user.
279 * @param Buff - Pointer to the data buffer for a DMA transfer.
280 *
281 * @return
282 * - XST_SUCCESS if initialization was successful
283 * - XST_FAILURE if failure - could be because another transfer
284 * is in progress or command or data inhibit is set
285 *
286 ******************************************************************************/
XSdPs_ReadPolled(XSdPs * InstancePtr,u32 Arg,u32 BlkCnt,u8 * Buff)287 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
288 {
289 s32 Status;
290
291 Xil_AssertNonvoid(InstancePtr != NULL);
292 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
293
294 #if defined (XCLOCKING)
295 Xil_ClockEnable(InstancePtr->Config.RefClk);
296 #endif
297
298 /* Setup the Read Transfer */
299 Status = XSdPs_SetupTransfer(InstancePtr);
300 if (Status != XST_SUCCESS) {
301 Status = XST_FAILURE;
302 goto RETURN_PATH;
303 }
304
305 /* Read from the card */
306 Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
307 if (Status != XST_SUCCESS) {
308 Status = XST_FAILURE;
309 goto RETURN_PATH;
310 }
311
312 RETURN_PATH:
313 #if defined (XCLOCKING)
314 Xil_ClockDisable(InstancePtr->Config.RefClk);
315 #endif
316 return Status;
317 }
318
319 /*****************************************************************************/
320 /**
321 * @brief
322 * This function performs SD write in polled mode.
323 *
324 * @param InstancePtr is a pointer to the instance to be worked on.
325 * @param Arg is the address passed by the user that is to be sent as
326 * argument along with the command.
327 * @param BlkCnt - Block count passed by the user.
328 * @param Buff - Pointer to the data buffer for a DMA transfer.
329 *
330 * @return
331 * - XST_SUCCESS if initialization was successful
332 * - XST_FAILURE if failure - could be because another transfer
333 * is in progress or command or data inhibit is set
334 *
335 ******************************************************************************/
XSdPs_WritePolled(XSdPs * InstancePtr,u32 Arg,u32 BlkCnt,const u8 * Buff)336 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
337 {
338 s32 Status;
339
340 Xil_AssertNonvoid(InstancePtr != NULL);
341 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
342
343 #if defined (XCLOCKING)
344 Xil_ClockEnable(InstancePtr->Config.RefClk);
345 #endif
346
347 /* Setup the Write Transfer */
348 Status = XSdPs_SetupTransfer(InstancePtr);
349 if (Status != XST_SUCCESS) {
350 Status = XST_FAILURE;
351 goto RETURN_PATH;
352 }
353
354 /* Write to the card */
355 Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
356 if (Status != XST_SUCCESS) {
357 Status = XST_FAILURE;
358 goto RETURN_PATH;
359 }
360
361 RETURN_PATH:
362 #if defined (XCLOCKING)
363 Xil_ClockDisable(InstancePtr->Config.RefClk);
364 #endif
365 return Status;
366 }
367
368 /*****************************************************************************/
369 /**
370 *
371 * @brief
372 * API to idle the SDIO Interface
373 *
374 *
375 * @param InstancePtr is a pointer to the XSdPs instance.
376 *
377 * @return None
378 *
379 * @note None.
380 *
381 ******************************************************************************/
XSdPs_Idle(XSdPs * InstancePtr)382 s32 XSdPs_Idle(XSdPs *InstancePtr)
383 {
384 s32 Status;
385
386 Xil_AssertNonvoid(InstancePtr != NULL);
387 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
388
389 #if defined (XCLOCKING)
390 Xil_ClockEnable(InstancePtr->Config.RefClk);
391 #endif
392
393 /* Check if the bus is idle */
394 Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
395 | XSDPS_PSR_INHIBIT_DAT_MASK
396 | XSDPS_PSR_DAT_ACTIVE_MASK);
397 if (Status != XST_SUCCESS) {
398 Status = XST_FAILURE;
399 goto RETURN_PATH ;
400 }
401
402 /* Disable the Bus Power */
403 XSdPs_DisableBusPower(InstancePtr);
404
405 /* Reset Command and Data Lines */
406 Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
407 if (Status != XST_SUCCESS) {
408 Status = XST_FAILURE;
409 goto RETURN_PATH ;
410 }
411
412 Status = XST_SUCCESS;
413
414 RETURN_PATH:
415 #if defined (XCLOCKING)
416 Xil_ClockDisable(InstancePtr->Config.RefClk);
417 #endif
418 return Status;
419 }
420 /** @} */
421