xsdps.c 15 KB

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