fsl_flexspi.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_flexspi.h"
  35. /* Component ID definition, used by tools. */
  36. #ifndef FSL_COMPONENT_ID
  37. #define FSL_COMPONENT_ID "platform.drivers.flexspi"
  38. #endif
  39. /*******************************************************************************
  40. * Definitations
  41. ******************************************************************************/
  42. #define FREQ_1MHz (1000000UL)
  43. #define FLEXSPI_DLLCR_DEFAULT (0x100UL)
  44. #define FLEXSPI_LUT_KEY_VAL (0x5AF05AF0ul)
  45. enum
  46. {
  47. kFLEXSPI_DelayCellUnitMin = 75, /* 75ps. */
  48. kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
  49. };
  50. /*! @brief Common sets of flags used by the driver. */
  51. enum _flexspi_flag_constants
  52. {
  53. /*! IRQ sources enabled by the non-blocking transactional API. */
  54. kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmpltyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
  55. kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
  56. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag,
  57. /*! Errors to check for. */
  58. kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
  59. kFLEXSPI_IpCommandGrantTimeoutFlag,
  60. };
  61. enum _flexspi_transfer_state
  62. {
  63. kFLEXSPI_Idle = 0x0U, /*!< Transfer is done. */
  64. kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */
  65. kFLEXSPI_BusyRead = 0x2U, /*!< FLEXSPI is busy write transfer. */
  66. };
  67. /*! @brief Typedef for interrupt handler. */
  68. typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, void *flexspiHandle);
  69. /*******************************************************************************
  70. * Prototypes
  71. ******************************************************************************/
  72. /*!
  73. * @brief Get the instance number for FLEXSPI.
  74. *
  75. * @param base FLEXSPI base pointer.
  76. */
  77. uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base);
  78. /*!
  79. * @brief Configure flash A/B sample clock DLL.
  80. *
  81. * @param base FLEXSPI base pointer.
  82. * @param config Flash configuration parameters.
  83. */
  84. static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
  85. /*!
  86. * @brief Check and clear IP command execution errors.
  87. *
  88. * @param base FLEXSPI base pointer.
  89. * @param status interrupt status.
  90. */
  91. status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status);
  92. /*******************************************************************************
  93. * Variables
  94. ******************************************************************************/
  95. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  96. /*! @brief Pointers to flexspi handles for each instance. */
  97. static void *s_flexspiHandle[FSL_FEATURE_SOC_FLEXSPI_COUNT];
  98. #endif
  99. /*! @brief Pointers to flexspi bases for each instance. */
  100. static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
  101. /*! @brief Pointers to flexspi IRQ number for each instance. */
  102. static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
  103. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  104. /* Clock name array */
  105. static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
  106. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  107. /*******************************************************************************
  108. * Code
  109. ******************************************************************************/
  110. uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
  111. {
  112. uint32_t instance;
  113. /* Find the instance index from base address mappings. */
  114. for (instance = 0; instance < FSL_FEATURE_SOC_FLEXSPI_COUNT; instance++)
  115. {
  116. if (s_flexspiBases[instance] == base)
  117. {
  118. break;
  119. }
  120. }
  121. assert(instance < FSL_FEATURE_SOC_FLEXSPI_COUNT);
  122. return instance;
  123. }
  124. static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
  125. {
  126. bool isUnifiedConfig = true;
  127. uint32_t flexspiDllValue;
  128. uint32_t dllValue;
  129. uint32_t temp;
  130. uint8_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
  131. switch (rxSampleClock)
  132. {
  133. case kFLEXSPI_ReadSampleClkLoopbackInternally:
  134. case kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
  135. case kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
  136. isUnifiedConfig = true;
  137. break;
  138. case kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
  139. if (config->isSck2Enabled)
  140. {
  141. isUnifiedConfig = true;
  142. }
  143. else
  144. {
  145. isUnifiedConfig = false;
  146. }
  147. break;
  148. default:
  149. break;
  150. }
  151. if (isUnifiedConfig)
  152. {
  153. flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
  154. }
  155. else
  156. {
  157. if (config->flexspiRootClk >= 100 * FREQ_1MHz)
  158. {
  159. /* DLLEN = 1, SLVDLYTARGET = 0xF, */
  160. flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
  161. }
  162. else
  163. {
  164. temp = config->dataValidTime * 1000; /* Convert data valid time in ns to ps. */
  165. dllValue = temp / kFLEXSPI_DelayCellUnitMin;
  166. if (dllValue * kFLEXSPI_DelayCellUnitMin < temp)
  167. {
  168. dllValue++;
  169. }
  170. flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue);
  171. }
  172. }
  173. return flexspiDllValue;
  174. }
  175. status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status)
  176. {
  177. status_t result = kStatus_Success;
  178. /* Check for error. */
  179. status &= kErrorFlags;
  180. if (status)
  181. {
  182. /* Select the correct error code.. */
  183. if (status & kFLEXSPI_SequenceExecutionTimeoutFlag)
  184. {
  185. result = kStatus_FLEXSPI_SequenceExecutionTimeout;
  186. }
  187. else if (status & kFLEXSPI_IpCommandSequenceErrorFlag)
  188. {
  189. result = kStatus_FLEXSPI_IpCommandSequenceError;
  190. }
  191. else if (status & kFLEXSPI_IpCommandGrantTimeoutFlag)
  192. {
  193. result = kStatus_FLEXSPI_IpCommandGrantTimeout;
  194. }
  195. else
  196. {
  197. assert(false);
  198. }
  199. /* Clear the flags. */
  200. FLEXSPI_ClearInterruptStatusFlags(base, status);
  201. /* Reset fifos. These flags clear automatically. */
  202. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  203. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  204. }
  205. return result;
  206. }
  207. void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
  208. {
  209. uint32_t configValue = 0;
  210. uint8_t i = 0;
  211. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  212. /* Enable the flexspi clock */
  213. CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
  214. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  215. /* Reset peripheral before configuring it. */
  216. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  217. FLEXSPI_SoftwareReset(base);
  218. /* Configure MCR0 configuration items. */
  219. configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) |
  220. FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) |
  221. FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) |
  222. FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) |
  223. FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) |
  224. FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
  225. FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
  226. FLEXSPI_MCR0_ARDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) | FLEXSPI_MCR0_MDIS_MASK;
  227. base->MCR0 = configValue;
  228. /* Configure MCR1 configurations. */
  229. configValue =
  230. FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle);
  231. base->MCR1 = configValue;
  232. /* Configure MCR2 configurations. */
  233. configValue = base->MCR2;
  234. configValue &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK | FLEXSPI_MCR2_SCKBDIFFOPT_MASK | FLEXSPI_MCR2_SAMEDEVICEEN_MASK |
  235. FLEXSPI_MCR2_CLRAHBBUFOPT_MASK);
  236. configValue |= FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
  237. FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
  238. FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
  239. FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
  240. base->MCR2 = configValue;
  241. /* Configure AHB control items. */
  242. configValue = base->AHBCR;
  243. configValue &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_BUFFERABLEEN_MASK |
  244. FLEXSPI_AHBCR_CACHABLEEN_MASK);
  245. configValue |= FLEXSPI_AHBCR_READADDROPT(config->ahbConfig.enableReadAddressOpt) |
  246. FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
  247. FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
  248. FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
  249. base->AHBCR = configValue;
  250. /* Configure AHB rx buffers. */
  251. for (i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
  252. {
  253. configValue = base->AHBRXBUFCR0[i];
  254. configValue &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK |
  255. FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK);
  256. configValue |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN(config->ahbConfig.buffer[i].enablePrefetch) |
  257. FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
  258. FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
  259. FLEXSPI_AHBRXBUFCR0_BUFSZ(config->ahbConfig.buffer[i].bufferSize * 8);
  260. base->AHBRXBUFCR0[i] = configValue;
  261. }
  262. /* Configure IP Fifo watermarks. */
  263. base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK;
  264. base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK(config->rxWatermark / 8 - 1);
  265. base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK;
  266. base->IPTXFCR |= FLEXSPI_IPTXFCR_TXWMRK(config->txWatermark / 8 - 1);
  267. }
  268. void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
  269. {
  270. config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
  271. config->enableSckFreeRunning = false;
  272. config->enableCombination = false;
  273. config->enableDoze = true;
  274. config->enableHalfSpeedAccess = false;
  275. config->enableSckBDiffOpt = false;
  276. config->enableSameConfigForAll = false;
  277. config->seqTimeoutCycle = 0xFFFFU;
  278. config->ipGrantTimeoutCycle = 0xFFU;
  279. config->txWatermark = 8;
  280. config->rxWatermark = 8;
  281. config->ahbConfig.enableAHBWriteIpTxFifo = false;
  282. config->ahbConfig.enableAHBWriteIpRxFifo = false;
  283. config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
  284. config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU;
  285. config->ahbConfig.resumeWaitCycle = 0x20U;
  286. memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
  287. for (uint8_t i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
  288. {
  289. config->ahbConfig.buffer[i].bufferSize = 256; /* Default buffer size 256 bytes*/
  290. }
  291. config->ahbConfig.enableClearAHBBufferOpt = false;
  292. config->ahbConfig.enableReadAddressOpt = false;
  293. config->ahbConfig.enableAHBPrefetch = false;
  294. config->ahbConfig.enableAHBBufferable = false;
  295. config->ahbConfig.enableAHBCachable = false;
  296. }
  297. void FLEXSPI_Deinit(FLEXSPI_Type *base)
  298. {
  299. /* Reset peripheral. */
  300. FLEXSPI_SoftwareReset(base);
  301. }
  302. void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
  303. {
  304. uint32_t configValue = 0;
  305. uint8_t index = port >> 1; /* PortA with index 0, PortB with index 1. */
  306. /* Wait for bus idle before change flash configuration. */
  307. while (!FLEXSPI_GetBusIdleStatus(base))
  308. {
  309. }
  310. /* Configure flash size. */
  311. base->FLSHCR0[index] = 0;
  312. base->FLSHCR0[port] = config->flashSize;
  313. /* Configure flash parameters. */
  314. base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
  315. FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
  316. FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
  317. FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
  318. /* Configure AHB operation items. */
  319. configValue = base->FLSHCR2[port];
  320. configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
  321. FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_AWRSEQID_MASK);
  322. configValue |=
  323. FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
  324. if (config->AWRSeqNumber > 0U)
  325. {
  326. configValue |=
  327. FLEXSPI_FLSHCR2_AWRSEQID(config->AWRSeqIndex) | FLEXSPI_FLSHCR2_AWRSEQNUM(config->AWRSeqNumber - 1U);
  328. }
  329. if (config->ARDSeqNumber > 0U)
  330. {
  331. configValue |=
  332. FLEXSPI_FLSHCR2_ARDSEQID(config->ARDSeqIndex) | FLEXSPI_FLSHCR2_ARDSEQNUM(config->ARDSeqNumber - 1U);
  333. }
  334. base->FLSHCR2[port] = configValue;
  335. /* Configure DLL. */
  336. base->DLLCR[index] = FLEXSPI_ConfigureDll(base, config);
  337. /* Configure write mask. */
  338. if (config->enableWriteMask)
  339. {
  340. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK;
  341. }
  342. else
  343. {
  344. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK;
  345. }
  346. if (index == 0) /*PortA*/
  347. {
  348. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
  349. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
  350. }
  351. else
  352. {
  353. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
  354. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
  355. }
  356. /* Exit stop mode. */
  357. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  358. }
  359. void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
  360. {
  361. assert(index < 64U);
  362. uint8_t i = 0;
  363. volatile uint32_t *lutBase;
  364. /* Wait for bus idle before change flash configuration. */
  365. while (!FLEXSPI_GetBusIdleStatus(base))
  366. {
  367. }
  368. /* Unlock LUT for update. */
  369. base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
  370. base->LUTCR = 0x02;
  371. lutBase = &base->LUT[index];
  372. for (i = index; i < count; i++)
  373. {
  374. *lutBase++ = *cmd++;
  375. }
  376. /* Lock LUT. */
  377. base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
  378. base->LUTCR = 0x01;
  379. }
  380. status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
  381. {
  382. uint8_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1;
  383. uint32_t status;
  384. status_t result = kStatus_Success;
  385. uint32_t i = 0;
  386. /* Send data buffer */
  387. while (size)
  388. {
  389. /* Wait until there is room in the fifo. This also checks for errors. */
  390. while (!((status = base->INTR) & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag))
  391. {
  392. }
  393. result = FLEXSPI_CheckAndClearError(base, status);
  394. if (result)
  395. {
  396. return result;
  397. }
  398. /* Write watermark level data into tx fifo . */
  399. if (size >= 8 * txWatermark)
  400. {
  401. for (i = 0; i < 2 * txWatermark; i++)
  402. {
  403. base->TFDR[i] = *buffer++;
  404. }
  405. size = size - 8 * txWatermark;
  406. }
  407. else
  408. {
  409. for (i = 0; i < (size / 4 + 1); i++)
  410. {
  411. base->TFDR[i] = *buffer++;
  412. }
  413. size = 0;
  414. }
  415. /* Push a watermark level datas into IP TX FIFO. */
  416. base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag;
  417. }
  418. return result;
  419. }
  420. status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
  421. {
  422. uint8_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1;
  423. uint32_t status;
  424. status_t result = kStatus_Success;
  425. uint32_t i = 0;
  426. /* Send data buffer */
  427. while (size)
  428. {
  429. if (size >= 8 * rxWatermark)
  430. {
  431. /* Wait until there is room in the fifo. This also checks for errors. */
  432. while (!((status = base->INTR) & kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
  433. {
  434. result = FLEXSPI_CheckAndClearError(base, status);
  435. if (result)
  436. {
  437. return result;
  438. }
  439. }
  440. }
  441. else
  442. {
  443. /* Wait fill level. This also checks for errors. */
  444. while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U))
  445. {
  446. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  447. if (result)
  448. {
  449. return result;
  450. }
  451. }
  452. }
  453. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  454. if (result)
  455. {
  456. return result;
  457. }
  458. /* Read watermark level data from rx fifo . */
  459. if (size >= 8 * rxWatermark)
  460. {
  461. for (i = 0; i < 2 * rxWatermark; i++)
  462. {
  463. *buffer++ = base->RFDR[i];
  464. }
  465. size = size - 8 * rxWatermark;
  466. }
  467. else
  468. {
  469. for (i = 0; i < (size / 4 + 1); i++)
  470. {
  471. *buffer++ = base->RFDR[i];
  472. }
  473. size = 0;
  474. }
  475. /* Pop out a watermark level datas from IP RX FIFO. */
  476. base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
  477. }
  478. return result;
  479. }
  480. status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
  481. {
  482. uint32_t configValue = 0;
  483. status_t result = kStatus_Success;
  484. /* Clear sequence pointer before sending data to external devices. */
  485. base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
  486. /* Clear former pending status before start this tranfer. */
  487. base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
  488. FLEXSPI_INTR_IPCMDGE_MASK;
  489. /* Configure base addresss. */
  490. base->IPCR0 = xfer->deviceAddress;
  491. /* Reset fifos. */
  492. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  493. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  494. /* Configure data size. */
  495. if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
  496. {
  497. configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
  498. }
  499. /* Configure sequence ID. */
  500. configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1);
  501. base->IPCR1 = configValue;
  502. /* Start Transfer. */
  503. base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
  504. if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
  505. {
  506. result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
  507. }
  508. else if (xfer->cmdType == kFLEXSPI_Read)
  509. {
  510. result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
  511. }
  512. else
  513. {
  514. }
  515. /* Wait for bus idle. */
  516. while (!FLEXSPI_GetBusIdleStatus(base))
  517. {
  518. }
  519. if (xfer->cmdType == kFLEXSPI_Command)
  520. {
  521. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  522. }
  523. return result;
  524. }
  525. void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
  526. flexspi_handle_t *handle,
  527. flexspi_transfer_callback_t callback,
  528. void *userData)
  529. {
  530. assert(handle);
  531. uint32_t instance = FLEXSPI_GetInstance(base);
  532. /* Zero handle. */
  533. memset(handle, 0, sizeof(*handle));
  534. /* Set callback and userData. */
  535. handle->completionCallback = callback;
  536. handle->userData = userData;
  537. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  538. /* Save the context in global variables to support the double weak mechanism. */
  539. s_flexspiHandle[instance] = handle;
  540. #endif
  541. /* Enable NVIC interrupt. */
  542. EnableIRQ(s_flexspiIrqs[instance]);
  543. }
  544. status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer)
  545. {
  546. uint32_t configValue = 0;
  547. status_t result = kStatus_Success;
  548. assert(handle);
  549. assert(xfer);
  550. /* Check if the I2C bus is idle - if not return busy status. */
  551. if (handle->state != kFLEXSPI_Idle)
  552. {
  553. result = kStatus_FLEXSPI_Busy;
  554. }
  555. else
  556. {
  557. handle->data = xfer->data;
  558. handle->dataSize = xfer->dataSize;
  559. handle->transferTotalSize = xfer->dataSize;
  560. handle->state = (xfer->cmdType == kFLEXSPI_Read) ? kFLEXSPI_BusyRead : kFLEXSPI_BusyWrite;
  561. /* Clear sequence pointer before sending data to external devices. */
  562. base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
  563. /* Clear former pending status before start this tranfer. */
  564. base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
  565. FLEXSPI_INTR_IPCMDGE_MASK;
  566. /* Configure base addresss. */
  567. base->IPCR0 = xfer->deviceAddress;
  568. /* Reset fifos. */
  569. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  570. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  571. /* Configure data size. */
  572. if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
  573. {
  574. configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
  575. }
  576. /* Configure sequence ID. */
  577. configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1);
  578. base->IPCR1 = configValue;
  579. /* Start Transfer. */
  580. base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
  581. if (handle->state == kFLEXSPI_BusyRead)
  582. {
  583. FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
  584. kFLEXSPI_SequenceExecutionTimeoutFlag |
  585. kFLEXSPI_IpCommandSequenceErrorFlag |
  586. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag);
  587. }
  588. else
  589. {
  590. FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpTxFifoWatermarkEmpltyFlag |
  591. kFLEXSPI_SequenceExecutionTimeoutFlag |
  592. kFLEXSPI_IpCommandSequenceErrorFlag |
  593. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag);
  594. }
  595. }
  596. return result;
  597. }
  598. status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
  599. {
  600. assert(handle);
  601. status_t result = kStatus_Success;
  602. if (handle->state == kFLEXSPI_Idle)
  603. {
  604. result = kStatus_NoTransferInProgress;
  605. }
  606. else
  607. {
  608. *count = handle->transferTotalSize - handle->dataSize;
  609. }
  610. return result;
  611. }
  612. void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
  613. {
  614. assert(handle);
  615. FLEXSPI_DisableInterrupts(base, kIrqFlags);
  616. handle->state = kFLEXSPI_Idle;
  617. }
  618. void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
  619. {
  620. uint8_t status;
  621. status_t result;
  622. uint8_t txWatermark;
  623. uint8_t rxWatermark;
  624. uint8_t i = 0;
  625. status = base->INTR;
  626. result = FLEXSPI_CheckAndClearError(base, status);
  627. if ((result != kStatus_Success) && (handle->completionCallback != NULL))
  628. {
  629. FLEXSPI_TransferAbort(base, handle);
  630. if (handle->completionCallback)
  631. {
  632. handle->completionCallback(base, handle, result, handle->userData);
  633. }
  634. return;
  635. }
  636. if ((status & kFLEXSPI_IpRxFifoWatermarkAvailableFlag) && (handle->state == kFLEXSPI_BusyRead))
  637. {
  638. rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1;
  639. /* Read watermark level data from rx fifo . */
  640. if (handle->dataSize >= 8 * rxWatermark)
  641. {
  642. /* Read watermark level data from rx fifo . */
  643. for (i = 0; i < 2 * rxWatermark; i++)
  644. {
  645. *handle->data++ = base->RFDR[i];
  646. }
  647. handle->dataSize = handle->dataSize - 8 * rxWatermark;
  648. }
  649. else
  650. {
  651. for (i = 0; i < (handle->dataSize / 4 + 1); i++)
  652. {
  653. *handle->data++ = base->RFDR[i];
  654. }
  655. handle->dataSize = 0;
  656. }
  657. /* Pop out a watermark level datas from IP RX FIFO. */
  658. base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
  659. }
  660. if (status & kFLEXSPI_IpCommandExcutionDoneFlag)
  661. {
  662. base->INTR |= kFLEXSPI_IpCommandExcutionDoneFlag;
  663. FLEXSPI_TransferAbort(base, handle);
  664. if (handle->completionCallback)
  665. {
  666. handle->completionCallback(base, handle, kStatus_Success, handle->userData);
  667. }
  668. }
  669. /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
  670. if ((status & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag) && (handle->state == kFLEXSPI_BusyWrite))
  671. {
  672. if (handle->dataSize)
  673. {
  674. txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1;
  675. /* Write watermark level data into tx fifo . */
  676. if (handle->dataSize >= 8 * txWatermark)
  677. {
  678. for (i = 0; i < 2 * txWatermark; i++)
  679. {
  680. base->TFDR[i] = *handle->data++;
  681. }
  682. handle->dataSize = handle->dataSize - 8 * txWatermark;
  683. }
  684. else
  685. {
  686. for (i = 0; i < (handle->dataSize / 4 + 1); i++)
  687. {
  688. base->TFDR[i] = *handle->data++;
  689. }
  690. handle->dataSize = 0;
  691. }
  692. /* Push a watermark level datas into IP TX FIFO. */
  693. base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag;
  694. }
  695. }
  696. else
  697. {
  698. }
  699. }
  700. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  701. #if defined(FLEXSPI)
  702. void FLEXSPI_DriverIRQHandler(void)
  703. {
  704. FLEXSPI_TransferHandleIRQ(FLEXSPI, s_flexspiHandle[0]);
  705. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  706. exception return operation might vector to incorrect interrupt */
  707. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  708. __DSB();
  709. #endif
  710. }
  711. #endif
  712. #if defined(FLEXSPI0)
  713. void FLEXSPI0_DriverIRQHandler(void)
  714. {
  715. FLEXSPI_TransferHandleIRQ(FLEXSPI0, s_flexspiHandle[0]);
  716. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  717. exception return operation might vector to incorrect interrupt */
  718. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  719. __DSB();
  720. #endif
  721. }
  722. #endif
  723. #if defined(FLEXSPI1)
  724. void FLEXSPI1_DriverIRQHandler(void)
  725. {
  726. FLEXSPI_TransferHandleIRQ(FLEXSPI1, s_flexspiHandle[1]);
  727. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  728. exception return operation might vector to incorrect interrupt */
  729. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  730. __DSB();
  731. #endif
  732. }
  733. #endif
  734. #endif