fsl_semc.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. /*
  2. * The Clear BSD License
  3. * Copyright 2017 NXP
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted (subject to the limitations in the disclaimer below) provided
  8. * that the following conditions are met:
  9. *
  10. * o Redistributions of source code must retain the above copyright notice, this list
  11. * of conditions and the following disclaimer.
  12. *
  13. * o Redistributions in binary form must reproduce the above copyright notice, this
  14. * list of conditions and the following disclaimer in the documentation and/or
  15. * other materials provided with the distribution.
  16. *
  17. * o Neither the name of the copyright holder nor the names of its
  18. * contributors may be used to endorse or promote products derived from this
  19. * software without specific prior written permission.
  20. *
  21. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  26. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  29. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include "fsl_semc.h"
  34. /*******************************************************************************
  35. * Definitions
  36. ******************************************************************************/
  37. /* Component ID definition, used by tools. */
  38. #ifndef FSL_COMPONENT_ID
  39. #define FSL_COMPONENT_ID "platform.drivers.semc"
  40. #endif
  41. /*! @brief Define macros for SEMC driver. */
  42. #define SEMC_IPCOMMANDDATASIZEBYTEMAX (4U)
  43. #define SEMC_IPCOMMANDMAGICKEY (0xA55A)
  44. #define SEMC_IOCR_PINMUXBITWIDTH (0x3U)
  45. #define SEMC_IOCR_NAND_CE (4U)
  46. #define SEMC_IOCR_NOR_CE (5U)
  47. #define SEMC_IOCR_NOR_CE_A8 (2U)
  48. #define SEMC_IOCR_PSRAM_CE (6U)
  49. #define SEMC_IOCR_PSRAM_CE_A8 (3U)
  50. #define SEMC_IOCR_DBI_CSX (7U)
  51. #define SEMC_IOCR_DBI_CSX_A8 (4U)
  52. #define SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE (24U)
  53. #define SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX (28U)
  54. #define SEMC_BMCR0_TYPICAL_WQOS (5U)
  55. #define SEMC_BMCR0_TYPICAL_WAGE (8U)
  56. #define SEMC_BMCR0_TYPICAL_WSH (0x40U)
  57. #define SEMC_BMCR0_TYPICAL_WRWS (0x10U)
  58. #define SEMC_BMCR1_TYPICAL_WQOS (5U)
  59. #define SEMC_BMCR1_TYPICAL_WAGE (8U)
  60. #define SEMC_BMCR1_TYPICAL_WPH (0x60U)
  61. #define SEMC_BMCR1_TYPICAL_WBR (0x40U)
  62. #define SEMC_BMCR1_TYPICAL_WRWS (0x24U)
  63. #define SEMC_STARTADDRESS (0x80000000U)
  64. #define SEMC_ENDADDRESS (0xDFFFFFFFU)
  65. #define SEMC_BR_MEMSIZE_MIN (4)
  66. #define SEMC_BR_MEMSIZE_OFFSET (2)
  67. #define SEMC_BR_MEMSIZE_MAX (4 * 1024 * 1024)
  68. #define SEMC_SDRAM_MODESETCAL_OFFSET (4)
  69. #define SEMC_BR_REG_NUM (9)
  70. #define SEMC_BYTE_NUMBIT (8)
  71. /*******************************************************************************
  72. * Prototypes
  73. ******************************************************************************/
  74. /*!
  75. * @brief Get instance number for SEMC module.
  76. *
  77. * @param base SEMC peripheral base address
  78. */
  79. static uint32_t SEMC_GetInstance(SEMC_Type *base);
  80. /*!
  81. * @brief Covert the input memory size to internal register set value.
  82. *
  83. * @param base SEMC peripheral base address
  84. * @param size_kbytes SEMC memory size in unit of kbytes.
  85. * @param sizeConverted SEMC converted memory size to 0 ~ 0x1F.
  86. * @return Execution status.
  87. */
  88. static status_t SEMC_CovertMemorySize(SEMC_Type *base, uint32_t size_kbytes, uint8_t *sizeConverted);
  89. /*!
  90. * @brief Covert the external timing nanosecond to internal clock cycle.
  91. *
  92. * @param time_ns SEMC external time interval in unit of nanosecond.
  93. * @param clkSrc_Hz SEMC clock source frequency.
  94. * @return The changed internal clock cycle.
  95. */
  96. static uint8_t SEMC_ConvertTiming(uint32_t time_ns, uint32_t clkSrc_Hz);
  97. /*!
  98. * @brief Configure IP command.
  99. *
  100. * @param base SEMC peripheral base address.
  101. * @param size_bytes SEMC IP command data size.
  102. * @return Execution status.
  103. */
  104. static status_t SEMC_ConfigureIPCommand(SEMC_Type *base, uint8_t size_bytes);
  105. /*!
  106. * @brief Check if the IP command has finished.
  107. *
  108. * @param base SEMC peripheral base address.
  109. * @return Execution status.
  110. */
  111. static status_t SEMC_IsIPCommandDone(SEMC_Type *base);
  112. /*******************************************************************************
  113. * Variables
  114. ******************************************************************************/
  115. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  116. /*! @brief Pointers to SEMC clocks for each instance. */
  117. static const clock_ip_name_t s_semcClock[FSL_FEATURE_SOC_SEMC_COUNT] = SEMC_CLOCKS;
  118. static const clock_ip_name_t s_semcExtClock[FSL_FEATURE_SOC_SEMC_COUNT] = SEMC_EXSC_CLOCKS;
  119. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  120. /*! @brief Pointers to SEMC bases for each instance. */
  121. static SEMC_Type *const s_semcBases[] = SEMC_BASE_PTRS;
  122. /*******************************************************************************
  123. * Code
  124. ******************************************************************************/
  125. static uint32_t SEMC_GetInstance(SEMC_Type *base)
  126. {
  127. uint32_t instance;
  128. /* Find the instance index from base address mappings. */
  129. for (instance = 0; instance < ARRAY_SIZE(s_semcBases); instance++)
  130. {
  131. if (s_semcBases[instance] == base)
  132. {
  133. break;
  134. }
  135. }
  136. assert(instance < ARRAY_SIZE(s_semcBases));
  137. return instance;
  138. }
  139. static status_t SEMC_CovertMemorySize(SEMC_Type *base, uint32_t size_kbytes, uint8_t *sizeConverted)
  140. {
  141. assert(sizeConverted);
  142. uint32_t memsize;
  143. if ((size_kbytes < SEMC_BR_MEMSIZE_MIN) || (size_kbytes > SEMC_BR_MEMSIZE_MAX))
  144. {
  145. return kStatus_SEMC_InvalidMemorySize;
  146. }
  147. *sizeConverted = 0;
  148. memsize = size_kbytes / 8;
  149. while (memsize)
  150. {
  151. memsize >>= 1;
  152. (*sizeConverted)++;
  153. }
  154. return kStatus_Success;
  155. }
  156. static uint8_t SEMC_ConvertTiming(uint32_t time_ns, uint32_t clkSrc_Hz)
  157. {
  158. assert(clkSrc_Hz);
  159. uint8_t clockCycles = 0;
  160. uint32_t tClk_us;
  161. clkSrc_Hz /= 1000000;
  162. tClk_us = 1000000 / clkSrc_Hz;
  163. while (tClk_us * clockCycles < (time_ns * 1000))
  164. {
  165. clockCycles++;
  166. }
  167. return clockCycles;
  168. }
  169. static status_t SEMC_ConfigureIPCommand(SEMC_Type *base, uint8_t size_bytes)
  170. {
  171. if ((size_bytes > SEMC_IPCOMMANDDATASIZEBYTEMAX) || (!size_bytes))
  172. {
  173. return kStatus_SEMC_InvalidIpcmdDataSize;
  174. }
  175. /* Set data size. */
  176. /* Note: It is better to set data size as the device data port width when transfering
  177. * device command data. but for device memory data transfer, it can be set freely.
  178. * Note: If the data size is greater than data port width, for example, datsz = 4, data port = 16bit,
  179. * then the 4-byte data transfer will be split into two 2-byte transfer, the slave address
  180. * will be switched automatically according to connected device type*/
  181. base->IPCR1 = SEMC_IPCR1_DATSZ(size_bytes);
  182. /* Clear data size. */
  183. base->IPCR2 = 0;
  184. /* Set data size. */
  185. if (size_bytes < 4)
  186. {
  187. base->IPCR2 |= SEMC_IPCR2_BM3_MASK;
  188. }
  189. if (size_bytes < 3)
  190. {
  191. base->IPCR2 |= SEMC_IPCR2_BM2_MASK;
  192. }
  193. if (size_bytes < 2)
  194. {
  195. base->IPCR2 |= SEMC_IPCR2_BM1_MASK;
  196. }
  197. return kStatus_Success;
  198. }
  199. static status_t SEMC_IsIPCommandDone(SEMC_Type *base)
  200. {
  201. /* Poll status bit till command is done*/
  202. while (!(base->INTR & SEMC_INTR_IPCMDDONE_MASK))
  203. {
  204. };
  205. /* Clear status bit */
  206. base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
  207. /* Check error status */
  208. if (base->INTR & SEMC_INTR_IPCMDERR_MASK)
  209. {
  210. base->INTR |= SEMC_INTR_IPCMDERR_MASK;
  211. return kStatus_SEMC_IpCommandExecutionError;
  212. }
  213. return kStatus_Success;
  214. }
  215. void SEMC_GetDefaultConfig(semc_config_t *config)
  216. {
  217. assert(config);
  218. semc_axi_queueweight_t queueWeight; /*!< AXI queue weight. */
  219. semc_queuea_weight_t queueaWeight;
  220. semc_queueb_weight_t queuebWeight;
  221. /* Get default settings. */
  222. config->dqsMode = kSEMC_Loopbackinternal;
  223. config->cmdTimeoutCycles = 0;
  224. config->busTimeoutCycles = 0x1F;
  225. /* Set a typical weight settings. */
  226. memset((void *)&queueWeight, 0, sizeof(semc_axi_queueweight_t));
  227. queueaWeight.qos = SEMC_BMCR0_TYPICAL_WQOS;
  228. queueaWeight.aging = SEMC_BMCR0_TYPICAL_WAGE;
  229. queueaWeight.slaveHitSwith = SEMC_BMCR0_TYPICAL_WSH;
  230. queueaWeight.slaveHitNoswitch = SEMC_BMCR0_TYPICAL_WRWS;
  231. queuebWeight.qos = SEMC_BMCR1_TYPICAL_WQOS;
  232. queuebWeight.aging = SEMC_BMCR1_TYPICAL_WAGE;
  233. queuebWeight.slaveHitSwith = SEMC_BMCR1_TYPICAL_WRWS;
  234. queuebWeight.weightPagehit = SEMC_BMCR1_TYPICAL_WPH;
  235. queuebWeight.bankRotation = SEMC_BMCR1_TYPICAL_WBR;
  236. config->queueWeight.queueaWeight = &queueaWeight;
  237. config->queueWeight.queuebWeight = &queuebWeight;
  238. }
  239. void SEMC_Init(SEMC_Type *base, semc_config_t *configure)
  240. {
  241. assert(configure);
  242. uint8_t index = 0;
  243. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  244. /* Un-gate sdram controller clock. */
  245. CLOCK_EnableClock(s_semcClock[SEMC_GetInstance(base)]);
  246. CLOCK_EnableClock(s_semcExtClock[SEMC_GetInstance(base)]);
  247. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  248. /* Initialize all BR to zero due to the default base address set. */
  249. for (index = 0; index < SEMC_BR_REG_NUM; index++)
  250. {
  251. base->BR[index] = 0;
  252. }
  253. /* Software reset for SEMC internal logical . */
  254. base->MCR = SEMC_MCR_SWRST_MASK;
  255. while (base->MCR & SEMC_MCR_SWRST_MASK)
  256. {
  257. }
  258. /* Configure, disable module first. */
  259. base->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_BTO(configure->busTimeoutCycles) |
  260. SEMC_MCR_CTO(configure->cmdTimeoutCycles) | SEMC_MCR_DQSMD(configure->dqsMode);
  261. /* Configure Queue 0/1 for AXI bus. */
  262. if (configure->queueWeight.queueaWeight)
  263. {
  264. base->BMCR0 = (uint32_t)(configure->queueWeight.queueaWeight);
  265. }
  266. if (configure->queueWeight.queuebWeight)
  267. {
  268. base->BMCR1 = (uint32_t)(configure->queueWeight.queuebWeight);
  269. }
  270. /* Enable SEMC. */
  271. base->MCR &= ~SEMC_MCR_MDIS_MASK;
  272. }
  273. void SEMC_Deinit(SEMC_Type *base)
  274. {
  275. /* Disable module. Check there is no pending command before disable module. */
  276. while (!(base->STS0 & SEMC_STS0_IDLE_MASK))
  277. {
  278. ;
  279. }
  280. base->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_SWRST_MASK;
  281. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  282. /* Disable SDRAM clock. */
  283. CLOCK_DisableClock(s_semcClock[SEMC_GetInstance(base)]);
  284. CLOCK_DisableClock(s_semcExtClock[SEMC_GetInstance(base)]);
  285. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  286. }
  287. status_t SEMC_ConfigureSDRAM(SEMC_Type *base, semc_sdram_cs_t cs, semc_sdram_config_t *config, uint32_t clkSrc_Hz)
  288. {
  289. assert(config);
  290. assert(clkSrc_Hz);
  291. assert(config->refreshBurstLen);
  292. uint8_t memsize;
  293. status_t result = kStatus_Success;
  294. uint16_t prescale = config->tPrescalePeriod_Ns / 16 / (1000000000 / clkSrc_Hz);
  295. uint16_t refresh;
  296. uint16_t urgentRef;
  297. uint16_t idle;
  298. uint16_t mode;
  299. if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
  300. {
  301. return kStatus_SEMC_InvalidBaseAddress;
  302. }
  303. if (config->csxPinMux == kSEMC_MUXA8)
  304. {
  305. return kStatus_SEMC_InvalidSwPinmuxSelection;
  306. }
  307. if (prescale > 256)
  308. {
  309. return kStatus_SEMC_InvalidTimerSetting;
  310. }
  311. refresh = config->refreshPeriod_nsPerRow / config->tPrescalePeriod_Ns;
  312. urgentRef = config->refreshUrgThreshold / config->tPrescalePeriod_Ns;
  313. idle = config->tIdleTimeout_Ns / config->tPrescalePeriod_Ns;
  314. uint32_t iocReg = base->IOCR & ~(SEMC_IOCR_PINMUXBITWIDTH << config->csxPinMux);
  315. /* Base control. */
  316. result = SEMC_CovertMemorySize(base, config->memsize_kbytes, &memsize);
  317. if (result != kStatus_Success)
  318. {
  319. return result;
  320. }
  321. base->BR[cs] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
  322. base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
  323. SEMC_SDRAMCR0_COL(config->columnAddrBitNum) | SEMC_SDRAMCR0_CL(config->casLatency);
  324. /* IOMUX setting. */
  325. if (cs)
  326. {
  327. base->IOCR = iocReg | (cs << config->csxPinMux);
  328. }
  329. base->IOCR &= ~SEMC_IOCR_MUX_A8_MASK;
  330. /* Timing setting. */
  331. base->SDRAMCR1 = SEMC_SDRAMCR1_PRE2ACT(SEMC_ConvertTiming(config->tPrecharge2Act_Ns, clkSrc_Hz) - 1) |
  332. SEMC_SDRAMCR1_ACT2RW(SEMC_ConvertTiming(config->tAct2ReadWrite_Ns, clkSrc_Hz) - 1) |
  333. SEMC_SDRAMCR1_RFRC(SEMC_ConvertTiming(config->tRefreshRecovery_Ns, clkSrc_Hz) - 1) |
  334. SEMC_SDRAMCR1_WRC(SEMC_ConvertTiming(config->tWriteRecovery_Ns, clkSrc_Hz) - 1) |
  335. SEMC_SDRAMCR1_CKEOFF(SEMC_ConvertTiming(config->tCkeOff_Ns, clkSrc_Hz) - 1) |
  336. SEMC_SDRAMCR1_ACT2PRE(SEMC_ConvertTiming(config->tAct2Prechage_Ns, clkSrc_Hz) - 1);
  337. base->SDRAMCR2 =
  338. SEMC_SDRAMCR2_SRRC(SEMC_ConvertTiming(config->tSelfRefRecovery_Ns, clkSrc_Hz) - 1) |
  339. SEMC_SDRAMCR2_REF2REF(
  340. SEMC_ConvertTiming(config->tRefresh2Refresh_Ns, clkSrc_Hz)) | /* No Minus one to keep with RM */
  341. SEMC_SDRAMCR2_ACT2ACT(SEMC_ConvertTiming(config->tAct2Act_Ns, clkSrc_Hz)) | /* No Minus one to keep with RM */
  342. SEMC_SDRAMCR2_ITO(idle);
  343. base->SDRAMCR3 = SEMC_SDRAMCR3_REBL(config->refreshBurstLen - 1) |
  344. /* N * 16 * 1s / clkSrc_Hz = config->tPrescalePeriod_Ns */
  345. SEMC_SDRAMCR3_PRESCALE(prescale) | SEMC_SDRAMCR3_RT(refresh) | SEMC_SDRAMCR3_UT(urgentRef);
  346. SEMC->IPCR1 = 0x2;
  347. SEMC->IPCR2 = 0;
  348. result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_Prechargeall, 0, NULL);
  349. if (result != kStatus_Success)
  350. {
  351. return result;
  352. }
  353. result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
  354. if (result != kStatus_Success)
  355. {
  356. return result;
  357. }
  358. result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
  359. if (result != kStatus_Success)
  360. {
  361. return result;
  362. }
  363. /* Mode setting value. */
  364. mode = (uint16_t)config->burstLen | (uint16_t)(config->casLatency << SEMC_SDRAM_MODESETCAL_OFFSET);
  365. result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_Modeset, mode, NULL);
  366. if (result != kStatus_Success)
  367. {
  368. return result;
  369. }
  370. /* Enables refresh */
  371. base->SDRAMCR3 |= SEMC_SDRAMCR3_REN_MASK;
  372. return kStatus_Success;
  373. }
  374. status_t SEMC_ConfigureNAND(SEMC_Type *base, semc_nand_config_t *config, uint32_t clkSrc_Hz)
  375. {
  376. assert(config);
  377. assert(config->timingConfig);
  378. uint8_t memsize;
  379. status_t result;
  380. if ((config->axiAddress < SEMC_STARTADDRESS) || (config->axiAddress > SEMC_ENDADDRESS))
  381. {
  382. return kStatus_SEMC_InvalidBaseAddress;
  383. }
  384. if (config->cePinMux == kSEMC_MUXRDY)
  385. {
  386. return kStatus_SEMC_InvalidSwPinmuxSelection;
  387. }
  388. uint32_t iocReg = base->IOCR & ~((SEMC_IOCR_PINMUXBITWIDTH << config->cePinMux) | SEMC_IOCR_MUX_RDY_MASK);
  389. /* Base control. */
  390. if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
  391. {
  392. base->MCR |= SEMC_MCR_WPOL1_MASK;
  393. }
  394. else
  395. {
  396. base->MCR &= ~SEMC_MCR_WPOL1_MASK;
  397. }
  398. result = SEMC_CovertMemorySize(base, config->axiMemsize_kbytes, &memsize);
  399. if (result != kStatus_Success)
  400. {
  401. return result;
  402. }
  403. base->BR[4] = (config->axiAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
  404. result = SEMC_CovertMemorySize(base, config->ipgMemsize_kbytes, &memsize);
  405. if (result != kStatus_Success)
  406. {
  407. return result;
  408. }
  409. base->BR[8] = (config->ipgAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
  410. /* IOMUX setting. */
  411. if (config->cePinMux)
  412. {
  413. base->IOCR = iocReg | (SEMC_IOCR_NAND_CE << config->cePinMux);
  414. }
  415. else
  416. {
  417. base->IOCR = iocReg | (1U << config->cePinMux);
  418. }
  419. base->NANDCR0 = SEMC_NANDCR0_PS(config->portSize) | SEMC_NANDCR0_BL(config->burstLen) |
  420. SEMC_NANDCR0_EDO(config->edoModeEnabled) | SEMC_NANDCR0_COL(config->columnAddrBitNum);
  421. /* Timing setting. */
  422. base->NANDCR1 = SEMC_NANDCR1_CES(SEMC_ConvertTiming(config->timingConfig->tCeSetup_Ns, clkSrc_Hz) - 1) |
  423. SEMC_NANDCR1_CEH(SEMC_ConvertTiming(config->timingConfig->tCeHold_Ns, clkSrc_Hz) - 1) |
  424. SEMC_NANDCR1_WEL(SEMC_ConvertTiming(config->timingConfig->tWeLow_Ns, clkSrc_Hz) - 1) |
  425. SEMC_NANDCR1_WEH(SEMC_ConvertTiming(config->timingConfig->tWeHigh_Ns, clkSrc_Hz) - 1) |
  426. SEMC_NANDCR1_REL(SEMC_ConvertTiming(config->timingConfig->tReLow_Ns, clkSrc_Hz) - 1) |
  427. SEMC_NANDCR1_REH(SEMC_ConvertTiming(config->timingConfig->tReHigh_Ns, clkSrc_Hz) - 1) |
  428. SEMC_NANDCR1_TA(SEMC_ConvertTiming(config->timingConfig->tTurnAround_Ns, clkSrc_Hz) - 1) |
  429. SEMC_NANDCR1_CEITV(SEMC_ConvertTiming(config->timingConfig->tCeInterval_Ns, clkSrc_Hz) - 1);
  430. base->NANDCR2 = SEMC_NANDCR2_TWHR(SEMC_ConvertTiming(config->timingConfig->tWehigh2Relow_Ns, clkSrc_Hz) - 1) |
  431. SEMC_NANDCR2_TRHW(SEMC_ConvertTiming(config->timingConfig->tRehigh2Welow_Ns, clkSrc_Hz) - 1) |
  432. SEMC_NANDCR2_TADL(SEMC_ConvertTiming(config->timingConfig->tAle2WriteStart_Ns, clkSrc_Hz) - 1) |
  433. SEMC_NANDCR2_TRR(SEMC_ConvertTiming(config->timingConfig->tReady2Relow_Ns, clkSrc_Hz) - 1) |
  434. SEMC_NANDCR2_TWB(SEMC_ConvertTiming(config->timingConfig->tWehigh2Busy_Ns, clkSrc_Hz) - 1);
  435. base->NANDCR3 = config->arrayAddrOption;
  436. return kStatus_Success;
  437. }
  438. status_t SEMC_ConfigureNOR(SEMC_Type *base, semc_nor_config_t *config, uint32_t clkSrc_Hz)
  439. {
  440. assert(config);
  441. uint8_t memsize;
  442. status_t result;
  443. if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
  444. {
  445. return kStatus_SEMC_InvalidBaseAddress;
  446. }
  447. uint32_t iocReg = base->IOCR & ~(SEMC_IOCR_PINMUXBITWIDTH << config->cePinMux);
  448. uint32_t muxCe = (config->cePinMux == kSEMC_MUXRDY) ?
  449. SEMC_IOCR_NOR_CE - 1 :
  450. ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_NOR_CE_A8 : SEMC_IOCR_NOR_CE);
  451. /* IOMUX setting. */
  452. base->IOCR = iocReg | (muxCe << config->cePinMux);
  453. /* Address bit setting. */
  454. if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
  455. {
  456. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 1)
  457. {
  458. /* Address bit 24 (A24) */
  459. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX0_MASK;
  460. if (config->cePinMux == kSEMC_MUXCSX0)
  461. {
  462. return kStatus_SEMC_InvalidSwPinmuxSelection;
  463. }
  464. }
  465. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2)
  466. {
  467. /* Address bit 25 (A25) */
  468. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX1_MASK;
  469. if (config->cePinMux == kSEMC_MUXCSX1)
  470. {
  471. return kStatus_SEMC_InvalidSwPinmuxSelection;
  472. }
  473. }
  474. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3)
  475. {
  476. /* Address bit 26 (A26) */
  477. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX2_MASK;
  478. if (config->cePinMux == kSEMC_MUXCSX2)
  479. {
  480. return kStatus_SEMC_InvalidSwPinmuxSelection;
  481. }
  482. }
  483. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4)
  484. {
  485. if (config->addr27 == kSEMC_NORA27_MUXCSX3)
  486. {
  487. /* Address bit 27 (A27) */
  488. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX3_MASK;
  489. }
  490. else if (config->addr27 == kSEMC_NORA27_MUXRDY)
  491. {
  492. base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
  493. }
  494. else
  495. {
  496. return kStatus_SEMC_InvalidSwPinmuxSelection;
  497. }
  498. if (config->cePinMux == kSEMC_MUXCSX3)
  499. {
  500. return kStatus_SEMC_InvalidSwPinmuxSelection;
  501. }
  502. }
  503. if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
  504. {
  505. return kStatus_SEMC_InvalidAddressPortWidth;
  506. }
  507. }
  508. /* Base control. */
  509. if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
  510. {
  511. base->MCR |= SEMC_MCR_WPOL0_MASK;
  512. }
  513. else
  514. {
  515. base->MCR &= ~SEMC_MCR_WPOL0_MASK;
  516. }
  517. result = SEMC_CovertMemorySize(base, config->memsize_kbytes, &memsize);
  518. if (result != kStatus_Success)
  519. {
  520. return result;
  521. }
  522. base->BR[5] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
  523. base->NORCR0 = SEMC_NORCR0_PS(config->portSize) | SEMC_NORCR0_BL(config->burstLen) |
  524. SEMC_NORCR0_AM(config->addrMode) | SEMC_NORCR0_ADVP(config->advActivePolarity) |
  525. SEMC_NORCR0_COL(config->columnAddrBitNum);
  526. /* Timing setting. */
  527. base->NORCR1 = SEMC_NORCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz)) |
  528. SEMC_NORCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz)) |
  529. SEMC_NORCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz)) |
  530. SEMC_NORCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz)) |
  531. SEMC_NORCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz)) |
  532. SEMC_NORCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz)) |
  533. SEMC_NORCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz)) |
  534. SEMC_NORCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
  535. base->NORCR2 = SEMC_NORCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz)) |
  536. SEMC_NORCR2_WDH(SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz)) |
  537. SEMC_NORCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz)) |
  538. SEMC_NORCR2_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz) + 1) |
  539. SEMC_NORCR2_LC(config->latencyCount) | SEMC_NORCR2_RD(config->readCycle) |
  540. SEMC_NORCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
  541. return SEMC_ConfigureIPCommand(base, (config->portSize + 1));
  542. }
  543. status_t SEMC_ConfigureSRAM(SEMC_Type *base, semc_sram_config_t *config, uint32_t clkSrc_Hz)
  544. {
  545. assert(config);
  546. uint8_t memsize;
  547. status_t result = kStatus_Success;
  548. if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
  549. {
  550. return kStatus_SEMC_InvalidBaseAddress;
  551. }
  552. uint32_t iocReg = base->IOCR & ~(SEMC_IOCR_PINMUXBITWIDTH << config->cePinMux);
  553. uint32_t muxCe = (config->cePinMux == kSEMC_MUXRDY) ?
  554. SEMC_IOCR_PSRAM_CE - 1 :
  555. ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_PSRAM_CE_A8 : SEMC_IOCR_PSRAM_CE);
  556. /* IOMUX setting. */
  557. base->IOCR = iocReg | (muxCe << config->cePinMux);
  558. /* Address bit setting. */
  559. if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
  560. {
  561. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 1)
  562. {
  563. /* Address bit 24 (A24) */
  564. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX0_MASK;
  565. if (config->cePinMux == kSEMC_MUXCSX0)
  566. {
  567. return kStatus_SEMC_InvalidSwPinmuxSelection;
  568. }
  569. }
  570. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2)
  571. {
  572. /* Address bit 25 (A25) */
  573. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX1_MASK;
  574. if (config->cePinMux == kSEMC_MUXCSX1)
  575. {
  576. return kStatus_SEMC_InvalidSwPinmuxSelection;
  577. }
  578. }
  579. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3)
  580. {
  581. /* Address bit 26 (A26) */
  582. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX2_MASK;
  583. if (config->cePinMux == kSEMC_MUXCSX2)
  584. {
  585. return kStatus_SEMC_InvalidSwPinmuxSelection;
  586. }
  587. }
  588. if (config->addrPortWidth >= SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4)
  589. {
  590. if (config->addr27 == kSEMC_NORA27_MUXCSX3)
  591. {
  592. /* Address bit 27 (A27) */
  593. base->IOCR &= (uint32_t)~SEMC_IOCR_MUX_CSX3_MASK;
  594. }
  595. else if (config->addr27 == kSEMC_NORA27_MUXRDY)
  596. {
  597. base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
  598. }
  599. else
  600. {
  601. return kStatus_SEMC_InvalidSwPinmuxSelection;
  602. }
  603. if (config->cePinMux == kSEMC_MUXCSX3)
  604. {
  605. return kStatus_SEMC_InvalidSwPinmuxSelection;
  606. }
  607. }
  608. if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
  609. {
  610. return kStatus_SEMC_InvalidAddressPortWidth;
  611. }
  612. }
  613. /* Base control. */
  614. result = SEMC_CovertMemorySize(base, config->memsize_kbytes, &memsize);
  615. if (result != kStatus_Success)
  616. {
  617. return result;
  618. }
  619. base->BR[6] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
  620. base->SRAMCR0 = SEMC_SRAMCR0_PS(config->portSize) | SEMC_SRAMCR0_BL(config->burstLen) |
  621. SEMC_SRAMCR0_AM(config->addrMode) | SEMC_SRAMCR0_ADVP(config->advActivePolarity) |
  622. SEMC_SRAMCR0_COL_MASK;
  623. /* Timing setting. */
  624. base->SRAMCR1 = SEMC_SRAMCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz)) |
  625. SEMC_SRAMCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz)) |
  626. SEMC_SRAMCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz)) |
  627. SEMC_SRAMCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz)) |
  628. SEMC_SRAMCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz)) |
  629. SEMC_SRAMCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz)) |
  630. SEMC_SRAMCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz)) |
  631. SEMC_SRAMCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
  632. base->SRAMCR2 = SEMC_SRAMCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz)) |
  633. SEMC_SRAMCR2_WDH(SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz)) |
  634. SEMC_SRAMCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz)) |
  635. SEMC_SRAMCR2_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz) + 1) |
  636. SEMC_SRAMCR2_LC(config->latencyCount) | SEMC_SRAMCR2_RD(config->readCycle) |
  637. SEMC_SRAMCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
  638. return result;
  639. }
  640. status_t SEMC_ConfigureDBI(SEMC_Type *base, semc_dbi_config_t *config, uint32_t clkSrc_Hz)
  641. {
  642. assert(config);
  643. uint8_t memsize;
  644. status_t result;
  645. if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
  646. {
  647. return kStatus_SEMC_InvalidBaseAddress;
  648. }
  649. uint32_t iocReg = base->IOCR & ~(SEMC_IOCR_PINMUXBITWIDTH << config->csxPinMux);
  650. uint32_t muxCsx = (config->csxPinMux == kSEMC_MUXRDY) ?
  651. SEMC_IOCR_DBI_CSX - 1 :
  652. ((config->csxPinMux == kSEMC_MUXA8) ? SEMC_IOCR_DBI_CSX_A8 : SEMC_IOCR_DBI_CSX);
  653. /* IOMUX setting. */
  654. base->IOCR = iocReg | (muxCsx << config->csxPinMux);
  655. /* Base control. */
  656. result = SEMC_CovertMemorySize(base, config->memsize_kbytes, &memsize);
  657. if (result != kStatus_Success)
  658. {
  659. return result;
  660. }
  661. base->BR[7] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
  662. base->DBICR0 =
  663. SEMC_DBICR0_PS(config->portSize) | SEMC_DBICR0_BL(config->burstLen) | SEMC_DBICR0_COL(config->columnAddrBitNum);
  664. /* Timing setting. */
  665. base->DBICR1 = SEMC_DBICR1_CES(SEMC_ConvertTiming(config->tCsxSetup_Ns, clkSrc_Hz)) |
  666. SEMC_DBICR1_CEH(SEMC_ConvertTiming(config->tCsxHold_Ns, clkSrc_Hz)) |
  667. SEMC_DBICR1_WEL(SEMC_ConvertTiming(config->tWexLow_Ns, clkSrc_Hz)) |
  668. SEMC_DBICR1_WEH(SEMC_ConvertTiming(config->tWexHigh_Ns, clkSrc_Hz)) |
  669. SEMC_DBICR1_REL(SEMC_ConvertTiming(config->tRdxLow_Ns, clkSrc_Hz)) |
  670. SEMC_DBICR1_REH(SEMC_ConvertTiming(config->tRdxHigh_Ns, clkSrc_Hz)) |
  671. SEMC_DBICR1_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
  672. return SEMC_ConfigureIPCommand(base, (config->portSize + 1));
  673. }
  674. status_t SEMC_SendIPCommand(
  675. SEMC_Type *base, semc_mem_type_t type, uint32_t address, uint16_t command, uint32_t write, uint32_t *read)
  676. {
  677. uint32_t cmdMode;
  678. bool readCmd = 0;
  679. bool writeCmd = 0;
  680. status_t result;
  681. /* Clear status bit */
  682. base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
  683. /* Set address. */
  684. base->IPCR0 = address;
  685. /* Check command mode. */
  686. cmdMode = command & 0xFU;
  687. switch (type)
  688. {
  689. case kSEMC_MemType_NAND:
  690. readCmd = (cmdMode == kSEMC_NANDCM_CommandAddressRead) ||
  691. (cmdMode == kSEMC_NANDCM_CommandRead) || (cmdMode == kSEMC_NANDCM_Read);
  692. writeCmd = (cmdMode == kSEMC_NANDCM_CommandAddressWrite) ||
  693. (cmdMode == kSEMC_NANDCM_CommandWrite) || (cmdMode == kSEMC_NANDCM_Write);
  694. break;
  695. case kSEMC_MemType_NOR:
  696. case kSEMC_MemType_8080:
  697. readCmd = (cmdMode == kSEMC_NORDBICM_Read);
  698. writeCmd = (cmdMode == kSEMC_NORDBICM_Write);
  699. break;
  700. case kSEMC_MemType_SRAM:
  701. readCmd = (cmdMode == kSEMC_SRAMCM_ArrayRead) || (cmdMode == kSEMC_SRAMCM_RegRead);
  702. writeCmd = (cmdMode == kSEMC_SRAMCM_ArrayWrite) || (cmdMode == kSEMC_SRAMCM_RegWrite);
  703. break;
  704. case kSEMC_MemType_SDRAM:
  705. readCmd = (cmdMode == kSEMC_SDRAMCM_Read);
  706. writeCmd = (cmdMode == kSEMC_SDRAMCM_Write) || (cmdMode == kSEMC_SDRAMCM_Modeset);
  707. break;
  708. default:
  709. break;
  710. }
  711. if (writeCmd)
  712. {
  713. /* Set data. */
  714. base->IPTXDAT = write;
  715. }
  716. /* Set command code. */
  717. base->IPCMD = command | SEMC_IPCMD_KEY(SEMC_IPCOMMANDMAGICKEY);
  718. /* Wait for command done. */
  719. result = SEMC_IsIPCommandDone(base);
  720. if (result != kStatus_Success)
  721. {
  722. return result;
  723. }
  724. if (readCmd)
  725. {
  726. /* Get the read data */
  727. *read = base->IPRXDAT;
  728. }
  729. return kStatus_Success;
  730. }
  731. status_t SEMC_IPCommandNandWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
  732. {
  733. assert(data);
  734. status_t result = kStatus_Success;
  735. uint16_t ipCmd;
  736. uint32_t tempData = 0;
  737. /* Write command built */
  738. ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Write);
  739. while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
  740. {
  741. /* Configure IP command data size. */
  742. SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
  743. result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, *(uint32_t *)data, NULL);
  744. if (result != kStatus_Success)
  745. {
  746. break;
  747. }
  748. data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
  749. size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
  750. }
  751. if ((result == kStatus_Success) && size_bytes)
  752. {
  753. SEMC_ConfigureIPCommand(base, size_bytes);
  754. while (size_bytes)
  755. {
  756. tempData |= ((uint32_t) * (data + size_bytes - 1) << ((size_bytes - 1) * SEMC_BYTE_NUMBIT));
  757. size_bytes--;
  758. }
  759. result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, tempData, NULL);
  760. }
  761. return result;
  762. }
  763. status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
  764. {
  765. assert(data);
  766. status_t result = kStatus_Success;
  767. uint16_t ipCmd;
  768. uint32_t tempData = 0;
  769. /* Configure IP command data size. */
  770. SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
  771. /* Read command built */
  772. ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Read);
  773. while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
  774. {
  775. result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, (uint32_t *)data);
  776. if (result != kStatus_Success)
  777. {
  778. break;
  779. }
  780. data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
  781. size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
  782. }
  783. if ((result == kStatus_Success) && size_bytes)
  784. {
  785. SEMC_ConfigureIPCommand(base, size_bytes);
  786. result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, &tempData);
  787. while (size_bytes)
  788. {
  789. size_bytes--;
  790. *(data + size_bytes) = (tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU;
  791. }
  792. }
  793. return result;
  794. }
  795. status_t SEMC_IPCommandNorRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
  796. {
  797. assert(data);
  798. uint32_t tempData = 0;
  799. status_t result = kStatus_Success;
  800. uint8_t dataSize = base->NORCR0 & SEMC_NORCR0_PS_MASK;
  801. /* Configure IP command data size. */
  802. SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
  803. while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
  804. {
  805. result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, kSEMC_NORDBICM_Read, 0, (uint32_t *)data);
  806. if (result != kStatus_Success)
  807. {
  808. break;
  809. }
  810. data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
  811. size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
  812. }
  813. if ((result == kStatus_Success) && size_bytes)
  814. {
  815. SEMC_ConfigureIPCommand(base, size_bytes);
  816. result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, kSEMC_NORDBICM_Read, 0, &tempData);
  817. while (size_bytes)
  818. {
  819. size_bytes--;
  820. *(data + size_bytes) = (tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU;
  821. }
  822. }
  823. SEMC_ConfigureIPCommand(base, dataSize);
  824. return result;
  825. }
  826. status_t SEMC_IPCommandNorWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
  827. {
  828. assert(data);
  829. uint32_t tempData = 0;
  830. status_t result = kStatus_Success;
  831. uint8_t dataSize = base->NORCR0 & SEMC_NORCR0_PS_MASK;
  832. /* Write command built */
  833. while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
  834. {
  835. /* Configure IP command data size. */
  836. SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
  837. result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, kSEMC_NORDBICM_Write, *(uint32_t *)data, NULL);
  838. if (result != kStatus_Success)
  839. {
  840. break;
  841. }
  842. size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
  843. data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
  844. }
  845. if ((result == kStatus_Success) && size_bytes)
  846. {
  847. SEMC_ConfigureIPCommand(base, size_bytes);
  848. while (size_bytes)
  849. {
  850. tempData |= ((uint32_t) * (data + size_bytes - 1) << ((size_bytes - 1) * SEMC_BYTE_NUMBIT));
  851. size_bytes--;
  852. }
  853. result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, kSEMC_NORDBICM_Write, tempData, NULL);
  854. }
  855. SEMC_ConfigureIPCommand(base, dataSize);
  856. return result;
  857. }