1 /*
2  * Copyright 2017-2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_semc.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.semc"
17 #endif
18 
19 /*! @brief Define macros for SEMC driver. */
20 #define SEMC_IPCOMMANDDATASIZEBYTEMAX (4U)
21 #define SEMC_IPCOMMANDMAGICKEY        (0xA55A)
22 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
23 #define SEMC_IOCR_PINMUXBITWIDTH (0x4UL)
24 #else
25 #define SEMC_IOCR_PINMUXBITWIDTH (0x3UL)
26 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
27 #define SEMC_IOCR_NAND_CE   (4UL)
28 #define SEMC_IOCR_NOR_CE    (5UL)
29 #define SEMC_IOCR_NOR_CE_A8 (2UL)
30 #define SEMC_IOCR_PSRAM_CE  (6UL)
31 #if defined(SEMC_IOCR_PINMUXBITWIDTH) && (SEMC_IOCR_PINMUXBITWIDTH == 0x4UL)
32 #define SEMC_IOCR_PSRAM_CE_A8 (6UL)
33 #else
34 #define SEMC_IOCR_PSRAM_CE_A8 (3UL)
35 #endif /* SEMC_IOCR_PINMUXBITWIDTH */
36 #define SEMC_IOCR_DBI_CSX                     (7UL)
37 #define SEMC_IOCR_DBI_CSX_A8                  (4UL)
38 #define SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE (24U)
39 #define SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX  (28U)
40 #define SEMC_BMCR0_TYPICAL_WQOS               (5U)
41 #define SEMC_BMCR0_TYPICAL_WAGE               (8U)
42 #define SEMC_BMCR0_TYPICAL_WSH                (0x40U)
43 #define SEMC_BMCR0_TYPICAL_WRWS               (0x10U)
44 #define SEMC_BMCR1_TYPICAL_WQOS               (5U)
45 #define SEMC_BMCR1_TYPICAL_WAGE               (8U)
46 #define SEMC_BMCR1_TYPICAL_WPH                (0x60U)
47 #define SEMC_BMCR1_TYPICAL_WBR                (0x40U)
48 #define SEMC_BMCR1_TYPICAL_WRWS               (0x24U)
49 #define SEMC_STARTADDRESS                     (0x80000000UL)
50 #define SEMC_ENDADDRESS                       (0xDFFFFFFFUL)
51 #define SEMC_BR_MEMSIZE_MIN                   (4U)
52 #define SEMC_BR_MEMSIZE_OFFSET                (2U)
53 #define SEMC_BR_MEMSIZE_MAX                   (4UL * 1024UL * 1024UL)
54 #define SEMC_SDRAM_MODESETCAL_OFFSET          (4U)
55 #define SEMC_BR_REG_NUM                       (9U)
56 #define SEMC_BYTE_NUMBIT                      (8U)
57 
58 #ifdef SEMC_DBICR1_REH_MASK
59 #if ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0x1U)
60 #define SEMC_DBICR1_REH_WIDTH 1U
61 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0x3U)
62 #define SEMC_DBICR1_REH_WIDTH 2U
63 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0x7U)
64 #define SEMC_DBICR1_REH_WIDTH 3U
65 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0xFU)
66 #define SEMC_DBICR1_REH_WIDTH 4U
67 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0x1FU)
68 #define SEMC_DBICR1_REH_WIDTH 5U
69 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0x3FU)
70 #define SEMC_DBICR1_REH_WIDTH 6U
71 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0x7FU)
72 #define SEMC_DBICR1_REH_WIDTH 7U
73 #elif ((SEMC_DBICR1_REH_MASK >> SEMC_DBICR1_REH_SHIFT) == 0xFFU)
74 #define SEMC_DBICR1_REH_WIDTH 8U
75 #else
76 #error SEMC_DBICR1_REH width not supported
77 #endif
78 #endif /* SEMC_DBICR1_REH_MASK */
79 
80 #ifdef SEMC_DBICR1_REL_MASK
81 #if ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0x1U)
82 #define SEMC_DBICR1_REL_WIDTH 1U
83 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0x3U)
84 #define SEMC_DBICR1_REL_WIDTH 2U
85 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0x7U)
86 #define SEMC_DBICR1_REL_WIDTH 3U
87 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0xFU)
88 #define SEMC_DBICR1_REL_WIDTH 4U
89 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0x1FU)
90 #define SEMC_DBICR1_REL_WIDTH 5U
91 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0x3FU)
92 #define SEMC_DBICR1_REL_WIDTH 6U
93 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0x7FU)
94 #define SEMC_DBICR1_REL_WIDTH 7U
95 #elif ((SEMC_DBICR1_REL_MASK >> SEMC_DBICR1_REL_SHIFT) == 0xFFU)
96 #define SEMC_DBICR1_REL_WIDTH 8U
97 #else
98 #error SEMC_DBICR1_REL width not supported
99 #endif
100 #endif /* SEMC_DBICR1_REL_MASK */
101 
102 /*******************************************************************************
103  * Prototypes
104  ******************************************************************************/
105 /*!
106  * @brief Get instance number for SEMC module.
107  *
108  * @param base SEMC peripheral base address
109  */
110 static uint32_t SEMC_GetInstance(SEMC_Type *base);
111 
112 /*!
113  * @brief Covert the input memory size to internal register set value.
114  *
115  * @param size_kbytes SEMC memory size in unit of kbytes.
116  * @param sizeConverted SEMC converted memory size to 0 ~ 0x1F.
117  * @return Execution status.
118  */
119 static status_t SEMC_CovertMemorySize(uint32_t size_kbytes, uint8_t *sizeConverted);
120 
121 /*!
122  * @brief Covert the external timing nanosecond to internal clock cycle.
123  *
124  * @param time_ns   SEMC external time interval in unit of nanosecond.
125  * @param clkSrc_Hz SEMC clock source frequency.
126  * @return The changed internal clock cycle.
127  */
128 static uint8_t SEMC_ConvertTiming(uint32_t time_ns, uint32_t clkSrc_Hz);
129 
130 /*!
131  * @brief Configure IP command.
132  *
133  * @param base SEMC peripheral base address.
134  * @param size_bytes SEMC IP command data size.
135  * @return Execution status.
136  */
137 static status_t SEMC_ConfigureIPCommand(SEMC_Type *base, uint8_t size_bytes);
138 
139 /*!
140  * @brief Check if the IP command has finished.
141  *
142  * @param base SEMC peripheral base address.
143  * @return Execution status.
144  */
145 static status_t SEMC_IsIPCommandDone(SEMC_Type *base);
146 
147 /*******************************************************************************
148  * Variables
149  ******************************************************************************/
150 
151 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
152 /*! @brief Pointers to SEMC clocks for each instance. */
153 static const clock_ip_name_t s_semcClock[FSL_FEATURE_SOC_SEMC_COUNT] = SEMC_CLOCKS;
154 #if (defined(SEMC_EXSC_CLOCKS))
155 static const clock_ip_name_t s_semcExtClock[FSL_FEATURE_SOC_SEMC_COUNT] = SEMC_EXSC_CLOCKS;
156 #endif /* SEMC_EXSC_CLOCKS */
157 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
158 
159 /*! @brief Pointers to SEMC bases for each instance. */
160 static SEMC_Type *const s_semcBases[] = SEMC_BASE_PTRS;
161 /*******************************************************************************
162  * Code
163  ******************************************************************************/
SEMC_GetInstance(SEMC_Type * base)164 static uint32_t SEMC_GetInstance(SEMC_Type *base)
165 {
166     uint32_t instance;
167 
168     /* Find the instance index from base address mappings. */
169     for (instance = 0UL; instance < ARRAY_SIZE(s_semcBases); instance++)
170     {
171         if (s_semcBases[instance] == base)
172         {
173             break;
174         }
175     }
176 
177     assert(instance < ARRAY_SIZE(s_semcBases));
178 
179     return instance;
180 }
181 
SEMC_CovertMemorySize(uint32_t size_kbytes,uint8_t * sizeConverted)182 static status_t SEMC_CovertMemorySize(uint32_t size_kbytes, uint8_t *sizeConverted)
183 {
184     assert(sizeConverted != NULL);
185     uint32_t memsize;
186     status_t status = kStatus_Success;
187 
188     if ((size_kbytes < SEMC_BR_MEMSIZE_MIN) || (size_kbytes > SEMC_BR_MEMSIZE_MAX))
189     {
190         status = kStatus_SEMC_InvalidMemorySize;
191     }
192     else
193     {
194         *sizeConverted = 0U;
195         memsize        = size_kbytes / 8U;
196         while (memsize != 0x00U)
197         {
198             memsize >>= 1U;
199             (*sizeConverted)++;
200         }
201     }
202 
203     return status;
204 }
205 
SEMC_ConvertTiming(uint32_t time_ns,uint32_t clkSrc_Hz)206 static uint8_t SEMC_ConvertTiming(uint32_t time_ns, uint32_t clkSrc_Hz)
207 {
208     assert(clkSrc_Hz != 0x00U);
209 
210     uint8_t clockCycles = 0;
211     uint32_t tClk_ps;
212 
213     clkSrc_Hz /= 1000000U;
214     /* Using ps for high resolution */
215     tClk_ps = 1000000U / clkSrc_Hz;
216 
217     while (tClk_ps * clockCycles < time_ns * 1000U)
218     {
219         clockCycles++;
220     }
221 
222     return (clockCycles == 0x00U) ? clockCycles : (clockCycles - 0x01U);
223 }
224 
SEMC_ConfigureIPCommand(SEMC_Type * base,uint8_t size_bytes)225 static status_t SEMC_ConfigureIPCommand(SEMC_Type *base, uint8_t size_bytes)
226 {
227     status_t status = kStatus_Success;
228 
229     if ((size_bytes > SEMC_IPCOMMANDDATASIZEBYTEMAX) || (size_bytes == 0x00U))
230     {
231         status = kStatus_SEMC_InvalidIpcmdDataSize;
232     }
233     else
234     {
235         /* Set data size. */
236         /* Note: It is better to set data size as the device data port width when transferring
237          *    device command data. But for device memory data transfer, it can be set freely.
238          * Note: If the data size is greater than data port width, for example, datsz = 4, data port = 16bit,
239          *    then the 4-byte data transfer will be split into two 2-byte transfers, the slave address
240          *    will be switched automatically according to connected device type*/
241         base->IPCR1 = SEMC_IPCR1_DATSZ(size_bytes);
242         /* Clear data size. */
243         base->IPCR2 = 0;
244         /* Set data size. */
245         if (size_bytes < 4U)
246         {
247             base->IPCR2 |= SEMC_IPCR2_BM3_MASK;
248         }
249         if (size_bytes < 3U)
250         {
251             base->IPCR2 |= SEMC_IPCR2_BM2_MASK;
252         }
253         if (size_bytes < 2U)
254         {
255             base->IPCR2 |= SEMC_IPCR2_BM1_MASK;
256         }
257     }
258 
259     return status;
260 }
261 
SEMC_IsIPCommandDone(SEMC_Type * base)262 static status_t SEMC_IsIPCommandDone(SEMC_Type *base)
263 {
264     status_t status = kStatus_Success;
265 
266     /* Poll status bit till command is done*/
267     while ((base->INTR & (uint32_t)SEMC_INTR_IPCMDDONE_MASK) == 0x00U)
268     {
269     };
270 
271     /* Clear status bit */
272     base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
273 
274     /* Check error status */
275     if ((base->INTR & (uint32_t)SEMC_INTR_IPCMDERR_MASK) != 0x00U)
276     {
277         base->INTR |= SEMC_INTR_IPCMDERR_MASK;
278         status = kStatus_SEMC_IpCommandExecutionError;
279     }
280 
281     return status;
282 }
283 
284 /*!
285  * brief Gets the SEMC default basic configuration structure.
286  *
287  * The purpose of this API is to get the default SEMC
288  * configure structure for SEMC_Init(). User may use the initialized
289  * structure unchanged in SEMC_Init(), or modify some fields of the
290  * structure before calling SEMC_Init().
291  * Example:
292    code
293    semc_config_t config;
294    SEMC_GetDefaultConfig(&config);
295    endcode
296  * param config The SEMC configuration structure pointer.
297  */
SEMC_GetDefaultConfig(semc_config_t * config)298 void SEMC_GetDefaultConfig(semc_config_t *config)
299 {
300     assert(config != NULL);
301 
302     /* Initializes the configure structure to zero. */
303     (void)memset(config, 0, sizeof(*config));
304 
305     config->queueWeight.queueaEnable          = true;
306     semc_queuea_weight_struct_t *queueaWeight = &(config->queueWeight.queueaWeight.queueaConfig);
307     config->queueWeight.queuebEnable          = true;
308     semc_queueb_weight_struct_t *queuebWeight = &(config->queueWeight.queuebWeight.queuebConfig);
309 
310     /* Get default settings. */
311     config->dqsMode          = kSEMC_Loopbackinternal;
312     config->cmdTimeoutCycles = 0xFF;
313     config->busTimeoutCycles = 0x1F;
314 
315     queueaWeight->qos              = SEMC_BMCR0_TYPICAL_WQOS;
316     queueaWeight->aging            = SEMC_BMCR0_TYPICAL_WAGE;
317     queueaWeight->slaveHitNoswitch = SEMC_BMCR0_TYPICAL_WSH;
318     queueaWeight->slaveHitSwitch   = SEMC_BMCR0_TYPICAL_WRWS;
319     queuebWeight->qos              = SEMC_BMCR1_TYPICAL_WQOS;
320     queuebWeight->aging            = SEMC_BMCR1_TYPICAL_WAGE;
321     queuebWeight->weightPagehit    = SEMC_BMCR1_TYPICAL_WPH;
322     queuebWeight->slaveHitNoswitch = SEMC_BMCR1_TYPICAL_WRWS;
323     queuebWeight->bankRotation     = SEMC_BMCR1_TYPICAL_WBR;
324 }
325 
326 /*!
327  * brief Initializes SEMC.
328  * This function ungates the SEMC clock and initializes SEMC.
329  * This function must be called before calling any other SEMC driver functions.
330  *
331  * param base SEMC peripheral base address.
332  * param configure The SEMC configuration structure pointer.
333  */
SEMC_Init(SEMC_Type * base,semc_config_t * configure)334 void SEMC_Init(SEMC_Type *base, semc_config_t *configure)
335 {
336     assert(configure != NULL);
337 
338     uint8_t index = 0;
339 
340 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
341     /* Un-gate sdram controller clock. */
342     CLOCK_EnableClock(s_semcClock[SEMC_GetInstance(base)]);
343 #if (defined(SEMC_EXSC_CLOCKS))
344     CLOCK_EnableClock(s_semcExtClock[SEMC_GetInstance(base)]);
345 #endif /* SEMC_EXSC_CLOCKS */
346 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
347 
348     /* Initialize all BR to zero due to the default base address set. */
349     for (index = 0; index < SEMC_BR_REG_NUM; index++)
350     {
351         base->BR[index] = 0;
352     }
353 
354     /* Software reset for SEMC internal logical . */
355     base->MCR = SEMC_MCR_SWRST_MASK;
356     while ((base->MCR & (uint32_t)SEMC_MCR_SWRST_MASK) != 0x00U)
357     {
358     }
359 
360     /* Configure, disable module first. */
361     base->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_BTO(configure->busTimeoutCycles) |
362                  SEMC_MCR_CTO(configure->cmdTimeoutCycles) | SEMC_MCR_DQSMD(configure->dqsMode);
363 
364     if (configure->queueWeight.queueaEnable == true)
365     {
366         /* Configure Queue A for AXI bus access to SDRAM, NAND, NOR, SRAM and DBI slaves.*/
367         base->BMCR0 = (uint32_t)(configure->queueWeight.queueaWeight.queueaValue);
368     }
369     else
370     {
371         base->BMCR0 = 0x00U;
372     }
373 
374     if (configure->queueWeight.queuebEnable == true)
375     {
376         /* Configure Queue B for AXI bus access to SDRAM slave. */
377         base->BMCR1 = (uint32_t)(configure->queueWeight.queuebWeight.queuebValue);
378     }
379     else
380     {
381         base->BMCR1 = 0x00U;
382     }
383 
384     /* Enable SEMC. */
385     base->MCR &= ~SEMC_MCR_MDIS_MASK;
386 }
387 
388 /*!
389  * brief Deinitializes the SEMC module and gates the clock.
390  * This function gates the SEMC clock. As a result, the SEMC
391  * module doesn't work after calling this function.
392  *
393  * param base SEMC peripheral base address.
394  */
SEMC_Deinit(SEMC_Type * base)395 void SEMC_Deinit(SEMC_Type *base)
396 {
397     /* Disable module.  Check there is no pending command before disable module.  */
398     while ((base->STS0 & (uint32_t)SEMC_STS0_IDLE_MASK) == 0x00U)
399     {
400         ;
401     }
402 
403     base->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_SWRST_MASK;
404 
405 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
406     /* Disable SDRAM clock. */
407     CLOCK_DisableClock(s_semcClock[SEMC_GetInstance(base)]);
408 #if (defined(SEMC_EXSC_CLOCKS))
409     CLOCK_DisableClock(s_semcExtClock[SEMC_GetInstance(base)]);
410 #endif /* SEMC_EXSC_CLOCKS */
411 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
412 }
413 
414 /*!
415  * brief Configures SDRAM controller in SEMC.
416  *
417  * param base SEMC peripheral base address.
418  * param cs The chip selection.
419  * param config The sdram configuration.
420  * param clkSrc_Hz The SEMC clock frequency.
421  */
SEMC_ConfigureSDRAM(SEMC_Type * base,semc_sdram_cs_t cs,semc_sdram_config_t * config,uint32_t clkSrc_Hz)422 status_t SEMC_ConfigureSDRAM(SEMC_Type *base, semc_sdram_cs_t cs, semc_sdram_config_t *config, uint32_t clkSrc_Hz)
423 {
424     assert(config != NULL);
425     assert(clkSrc_Hz > 0x00U);
426     assert(config->refreshBurstLen > 0x00U);
427 
428     uint8_t memsize;
429     uint8_t times;
430     status_t result   = kStatus_Success;
431     uint16_t prescale = (uint16_t)(config->tPrescalePeriod_Ns / 16U / (1000000000U / clkSrc_Hz));
432     uint32_t refresh;
433     uint32_t urgentRef;
434     uint32_t idle;
435     uint32_t mode;
436     uint32_t timing;
437 
438     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
439     {
440         return kStatus_SEMC_InvalidBaseAddress;
441     }
442 
443     if (config->csxPinMux == kSEMC_MUXA8)
444     {
445         return kStatus_SEMC_InvalidSwPinmuxSelection;
446     }
447 
448     if (prescale > 256U)
449     {
450         return kStatus_SEMC_InvalidTimerSetting;
451     }
452 
453     refresh   = config->refreshPeriod_nsPerRow / config->tPrescalePeriod_Ns;
454     urgentRef = config->refreshUrgThreshold / config->tPrescalePeriod_Ns;
455     idle      = config->tIdleTimeout_Ns / config->tPrescalePeriod_Ns;
456 
457     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->csxPinMux));
458 
459     /* Base control. */
460     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
461     if (result != kStatus_Success)
462     {
463         return result;
464     }
465 
466     base->BR[cs] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
467 
468 #if defined(FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT) && (FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT)
469     if (kSEMC_SdramColunm_8bit == config->columnAddrBitNum)
470     {
471         base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
472                          SEMC_SDRAMCR0_COL8(true) | SEMC_SDRAMCR0_CL(config->casLatency);
473     }
474     else
475 #endif /* FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT */
476     {
477         base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
478                          SEMC_SDRAMCR0_COL(config->columnAddrBitNum) | SEMC_SDRAMCR0_CL(config->casLatency);
479     }
480 
481     /* IOMUX setting. */
482     if (cs != kSEMC_SDRAM_CS0)
483     {
484         base->IOCR = iocReg | ((uint32_t)cs << (uint32_t)config->csxPinMux);
485     }
486 
487     base->IOCR &= ~SEMC_IOCR_MUX_A8_MASK;
488 
489 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
490     uint32_t tempDelayChain = base->DCCR;
491 
492     tempDelayChain &= ~(SEMC_DCCR_SDRAMVAL_MASK | SEMC_DCCR_SDRAMEN_MASK);
493     /* Configure delay chain. */
494     base->DCCR = tempDelayChain | SEMC_DCCR_SDRAMVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SDRAMEN_MASK;
495 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
496 
497     timing = SEMC_SDRAMCR1_PRE2ACT(SEMC_ConvertTiming(config->tPrecharge2Act_Ns, clkSrc_Hz));
498     timing |= SEMC_SDRAMCR1_ACT2RW(SEMC_ConvertTiming(config->tAct2ReadWrite_Ns, clkSrc_Hz));
499     timing |= SEMC_SDRAMCR1_RFRC(SEMC_ConvertTiming(config->tRefreshRecovery_Ns, clkSrc_Hz));
500     timing |= SEMC_SDRAMCR1_WRC(SEMC_ConvertTiming(config->tWriteRecovery_Ns, clkSrc_Hz));
501     timing |= SEMC_SDRAMCR1_CKEOFF(SEMC_ConvertTiming(config->tCkeOff_Ns, clkSrc_Hz));
502     timing |= SEMC_SDRAMCR1_ACT2PRE(SEMC_ConvertTiming(config->tAct2Prechage_Ns, clkSrc_Hz));
503     /* SDRAMCR1 timing setting. */
504     base->SDRAMCR1 = timing;
505 
506     timing = SEMC_SDRAMCR2_SRRC(SEMC_ConvertTiming(config->tSelfRefRecovery_Ns, clkSrc_Hz));
507     timing |= SEMC_SDRAMCR2_REF2REF(SEMC_ConvertTiming(config->tRefresh2Refresh_Ns, clkSrc_Hz));
508     timing |= SEMC_SDRAMCR2_ACT2ACT(SEMC_ConvertTiming(config->tAct2Act_Ns, clkSrc_Hz)) | SEMC_SDRAMCR2_ITO(idle);
509     /* SDRAMCR2 timing setting. */
510     base->SDRAMCR2 = timing;
511 
512     /* SDRAMCR3 timing setting. */
513     base->SDRAMCR3 = SEMC_SDRAMCR3_REBL((uint32_t)config->refreshBurstLen - 1UL) |
514                      /* N * 16 * 1s / clkSrc_Hz = config->tPrescalePeriod_Ns */
515                      SEMC_SDRAMCR3_PRESCALE(prescale) | SEMC_SDRAMCR3_RT(refresh - 1UL) | SEMC_SDRAMCR3_UT(urgentRef);
516 
517     SEMC->IPCR1 = 0x2U;
518     SEMC->IPCR2 = 0U;
519 
520     result =
521         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_Prechargeall, 0, NULL);
522     if (result != kStatus_Success)
523     {
524         return result;
525     }
526 
527     /* Generally, SDRAM requires 2 refresh cycles before and after setting the mode register. If the SDRAM used has special requirements,
528     *  please add autofreshTimes configuration in the initialization block of SDRAM */
529     times = ((config->autofreshTimes != 0U) ? config->autofreshTimes : 2U);
530     for(uint8_t count = 0U; count < times; count++)
531     {
532         result =
533             SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
534         if (result != kStatus_Success)
535         {
536             return result;
537         }
538     }
539 
540     /* Mode setting value. */
541     mode = (uint32_t)config->burstLen | (((uint32_t)config->casLatency) << SEMC_SDRAM_MODESETCAL_OFFSET);
542     result =
543         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_Modeset, mode, NULL);
544     if (result != kStatus_Success)
545     {
546         return result;
547     }
548     /* Enables refresh */
549     base->SDRAMCR3 |= SEMC_SDRAMCR3_REN_MASK;
550 
551     return kStatus_Success;
552 }
553 
554 /*!
555  * brief Configures NAND controller in SEMC.
556  *
557  * param base SEMC peripheral base address.
558  * param config The nand configuration.
559  * param clkSrc_Hz The SEMC clock frequency.
560  */
SEMC_ConfigureNAND(SEMC_Type * base,semc_nand_config_t * config,uint32_t clkSrc_Hz)561 status_t SEMC_ConfigureNAND(SEMC_Type *base, semc_nand_config_t *config, uint32_t clkSrc_Hz)
562 {
563     assert(config != NULL);
564     assert(config->timingConfig != NULL);
565 
566     uint8_t memsize;
567     status_t result;
568     uint32_t timing;
569 
570     if ((config->axiAddress < SEMC_STARTADDRESS) || (config->axiAddress > SEMC_ENDADDRESS))
571     {
572         return kStatus_SEMC_InvalidBaseAddress;
573     }
574 
575     if (config->cePinMux == kSEMC_MUXRDY)
576     {
577         return kStatus_SEMC_InvalidSwPinmuxSelection;
578     }
579 
580     /* Disable SEMC module during configuring control registers. */
581     base->MCR |= SEMC_MCR_MDIS_MASK;
582 
583     uint32_t iocReg =
584         base->IOCR & (~((SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux) | SEMC_IOCR_MUX_RDY_MASK));
585 
586     /* Base control. */
587     if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
588     {
589         base->MCR |= SEMC_MCR_WPOL1_MASK;
590     }
591     else
592     {
593         base->MCR &= ~SEMC_MCR_WPOL1_MASK;
594     }
595     result = SEMC_CovertMemorySize(config->axiMemsize_kbytes, &memsize);
596     if (result != kStatus_Success)
597     {
598         return result;
599     }
600     base->BR[4] = (config->axiAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
601 
602     result = SEMC_CovertMemorySize(config->ipgMemsize_kbytes, &memsize);
603     if (result != kStatus_Success)
604     {
605         return result;
606     }
607     base->BR[8] = (config->ipgAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
608 
609     /* IOMUX setting. */
610     if ((uint32_t)config->cePinMux != 0x00U)
611     {
612         base->IOCR = iocReg | (SEMC_IOCR_NAND_CE << (uint32_t)config->cePinMux);
613     }
614     else
615     {
616         base->IOCR = iocReg | (1UL << (uint32_t)config->cePinMux);
617     }
618 
619     base->NANDCR0 = SEMC_NANDCR0_PS(config->portSize) | SEMC_NANDCR0_BL(config->burstLen) |
620                     SEMC_NANDCR0_EDO(config->edoModeEnabled) | SEMC_NANDCR0_COL(config->columnAddrBitNum);
621 
622     timing = SEMC_NANDCR1_CES(SEMC_ConvertTiming(config->timingConfig->tCeSetup_Ns, clkSrc_Hz));
623     timing |= SEMC_NANDCR1_CEH(SEMC_ConvertTiming(config->timingConfig->tCeHold_Ns, clkSrc_Hz));
624     timing |= SEMC_NANDCR1_WEL(SEMC_ConvertTiming(config->timingConfig->tWeLow_Ns, clkSrc_Hz));
625     timing |= SEMC_NANDCR1_WEH(SEMC_ConvertTiming(config->timingConfig->tWeHigh_Ns, clkSrc_Hz));
626     timing |= SEMC_NANDCR1_REL(SEMC_ConvertTiming(config->timingConfig->tReLow_Ns, clkSrc_Hz));
627     timing |= SEMC_NANDCR1_REH(SEMC_ConvertTiming(config->timingConfig->tReHigh_Ns, clkSrc_Hz));
628     timing |= SEMC_NANDCR1_TA(SEMC_ConvertTiming(config->timingConfig->tTurnAround_Ns, clkSrc_Hz));
629     timing |= SEMC_NANDCR1_CEITV(SEMC_ConvertTiming(config->timingConfig->tCeInterval_Ns, clkSrc_Hz));
630     /* NANDCR1 timing setting. */
631     base->NANDCR1 = timing;
632 
633     timing = SEMC_NANDCR2_TWHR(SEMC_ConvertTiming(config->timingConfig->tWehigh2Relow_Ns, clkSrc_Hz));
634     timing |= SEMC_NANDCR2_TRHW(SEMC_ConvertTiming(config->timingConfig->tRehigh2Welow_Ns, clkSrc_Hz));
635     timing |= SEMC_NANDCR2_TADL(SEMC_ConvertTiming(config->timingConfig->tAle2WriteStart_Ns, clkSrc_Hz));
636     timing |= SEMC_NANDCR2_TRR(SEMC_ConvertTiming(config->timingConfig->tReady2Relow_Ns, clkSrc_Hz));
637     timing |= SEMC_NANDCR2_TWB(SEMC_ConvertTiming(config->timingConfig->tWehigh2Busy_Ns, clkSrc_Hz));
638 
639     /* NANDCR2 timing setting. */
640     base->NANDCR2 = timing;
641 
642     /* NANDCR3 timing setting. */
643     base->NANDCR3 = (uint32_t)config->arrayAddrOption;
644 
645     /* Enables SEMC module after configuring control registers completely. */
646     base->MCR &= ~SEMC_MCR_MDIS_MASK;
647 
648     return kStatus_Success;
649 }
650 
651 /*!
652  * brief Configures NOR controller in SEMC.
653  *
654  * param base SEMC peripheral base address.
655  * param config The nor configuration.
656  * param clkSrc_Hz The SEMC clock frequency.
657  */
SEMC_ConfigureNOR(SEMC_Type * base,semc_nor_config_t * config,uint32_t clkSrc_Hz)658 status_t SEMC_ConfigureNOR(SEMC_Type *base, semc_nor_config_t *config, uint32_t clkSrc_Hz)
659 {
660     assert(config != NULL);
661 
662     uint8_t memsize;
663     status_t result;
664     uint32_t timing;
665 
666     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
667     {
668         return kStatus_SEMC_InvalidBaseAddress;
669     }
670 
671     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux));
672     uint32_t muxCe  = (config->cePinMux == kSEMC_MUXRDY) ?
673                          (SEMC_IOCR_NOR_CE - 1U) :
674                          ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_NOR_CE_A8 : SEMC_IOCR_NOR_CE);
675 
676     /* IOMUX setting. */
677     base->IOCR = iocReg | (muxCe << (uint32_t)config->cePinMux);
678     /* Address bit setting. */
679     if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
680     {
681         /* Address bit 24 (A24) */
682         base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX0_MASK;
683         if (config->cePinMux == kSEMC_MUXCSX0)
684         {
685             return kStatus_SEMC_InvalidSwPinmuxSelection;
686         }
687 
688         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2U))
689         {
690             /* Address bit 25 (A25) */
691             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX1_MASK;
692             if (config->cePinMux == kSEMC_MUXCSX1)
693             {
694                 return kStatus_SEMC_InvalidSwPinmuxSelection;
695             }
696         }
697         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3U))
698         {
699             /* Address bit 26 (A26) */
700             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX2_MASK;
701             if (config->cePinMux == kSEMC_MUXCSX2)
702             {
703                 return kStatus_SEMC_InvalidSwPinmuxSelection;
704             }
705         }
706         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4U))
707         {
708             if (config->addr27 == kSEMC_NORA27_MUXCSX3)
709             {
710                 /* Address bit 27 (A27) */
711                 base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX3_MASK;
712             }
713             else if (config->addr27 == kSEMC_NORA27_MUXRDY)
714             {
715                 base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
716             }
717             else
718             {
719                 return kStatus_SEMC_InvalidSwPinmuxSelection;
720             }
721             if (config->cePinMux == kSEMC_MUXCSX3)
722             {
723                 return kStatus_SEMC_InvalidSwPinmuxSelection;
724             }
725         }
726         if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
727         {
728             return kStatus_SEMC_InvalidAddressPortWidth;
729         }
730     }
731 
732     /* Base control. */
733     if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
734     {
735         base->MCR |= SEMC_MCR_WPOL0_MASK;
736     }
737     else
738     {
739         base->MCR &= ~SEMC_MCR_WPOL0_MASK;
740     }
741     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
742     if (result != kStatus_Success)
743     {
744         return result;
745     }
746     base->BR[5]  = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
747     base->NORCR0 = SEMC_NORCR0_PS(config->portSize) | SEMC_NORCR0_BL(config->burstLen) |
748                    SEMC_NORCR0_AM(config->addrMode) | SEMC_NORCR0_ADVP(config->advActivePolarity) |
749                    SEMC_NORCR0_COL(config->columnAddrBitNum);
750 
751 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
752     uint32_t tempDelayChain = base->DCCR;
753 
754     tempDelayChain &= ~(SEMC_DCCR_NORVAL_MASK | SEMC_DCCR_NOREN_MASK);
755     /* Configure delay chain. */
756     base->DCCR = tempDelayChain | SEMC_DCCR_NORVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_NOREN_MASK;
757 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
758 
759     timing = SEMC_NORCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
760     timing |= SEMC_NORCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
761     timing |= SEMC_NORCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
762     timing |= SEMC_NORCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
763     timing |= SEMC_NORCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
764     timing |= SEMC_NORCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
765     timing |= SEMC_NORCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
766     timing |= SEMC_NORCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
767 
768     /* NORCR1 timing setting. */
769     base->NORCR1 = timing;
770 
771     timing = SEMC_NORCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
772 #if defined(FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME)
773     timing |= SEMC_NORCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
774 #endif /* FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME */
775 #if defined(FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME)
776     timing |= SEMC_NORCR2_WDH(SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz));
777 #endif /* FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME */
778     timing |= SEMC_NORCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
779     timing |= SEMC_NORCR2_AWDH((uint32_t)SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz) + 0x01UL);
780 #if defined(FSL_FEATURE_SEMC_HAS_NOR_LC_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_LC_TIME)
781     timing |= SEMC_NORCR2_LC(config->latencyCount);
782 #endif
783 #if defined(FSL_FEATURE_SEMC_HAS_NOR_RD_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_RD_TIME)
784     timing |= SEMC_NORCR2_RD((uint32_t)config->readCycle - 0x01UL);
785 #endif
786 
787     /* NORCR2 timing setting. */
788     base->NORCR2 = timing;
789 
790     return SEMC_ConfigureIPCommand(base, ((uint8_t)config->portSize + 1U));
791 }
792 
793 /*!
794  * brief Configures SRAM controller in SEMC, which can be used only for specific chip selection CS0.
795  *
796  * param base SEMC peripheral base address.
797  * param config The sram configuration.
798  * param clkSrc_Hz The SEMC clock frequency.
799  */
SEMC_ConfigureSRAM(SEMC_Type * base,semc_sram_config_t * config,uint32_t clkSrc_Hz)800 status_t SEMC_ConfigureSRAM(SEMC_Type *base, semc_sram_config_t *config, uint32_t clkSrc_Hz)
801 {
802     return SEMC_ConfigureSRAMWithChipSelection(base, kSEMC_SRAM_CS0, config, clkSrc_Hz);
803 }
804 
805 /*!
806  * brief Configures SRAM controller in SEMC, which can be used up to four chip selections CS0/CS1/CS2/CS3..
807  *
808  * param base SEMC peripheral base address.
809  * param cs The chip selection.
810  * param config The sram configuration.
811  * param clkSrc_Hz The SEMC clock frequency.
812  */
SEMC_ConfigureSRAMWithChipSelection(SEMC_Type * base,semc_sram_cs_t cs,semc_sram_config_t * config,uint32_t clkSrc_Hz)813 status_t SEMC_ConfigureSRAMWithChipSelection(SEMC_Type *base,
814                                              semc_sram_cs_t cs,
815                                              semc_sram_config_t *config,
816                                              uint32_t clkSrc_Hz)
817 {
818     assert(config != NULL);
819 
820     uint32_t tempBRVal;
821     uint32_t timing;
822     uint8_t memsize;
823     status_t result = kStatus_Success;
824 
825 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
826     bool waitEnable;
827 #endif
828 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
829     uint8_t waitSample;
830 #endif
831 
832     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
833     {
834         return kStatus_SEMC_InvalidBaseAddress;
835     }
836 
837     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux));
838 
839     uint32_t muxCe = (config->cePinMux == kSEMC_MUXRDY) ?
840                          (SEMC_IOCR_PSRAM_CE - 1U) :
841                          ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_PSRAM_CE_A8 : SEMC_IOCR_PSRAM_CE);
842 
843     /* IOMUX setting. */
844     base->IOCR = iocReg | (muxCe << (uint32_t)config->cePinMux);
845     /* Address bit setting. */
846     if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
847     {
848         /* Address bit 24 (A24) */
849         base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX0_MASK;
850         if (config->cePinMux == kSEMC_MUXCSX0)
851         {
852             return kStatus_SEMC_InvalidSwPinmuxSelection;
853         }
854 
855         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2U))
856         {
857             /* Address bit 25 (A25) */
858             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX1_MASK;
859             if (config->cePinMux == kSEMC_MUXCSX1)
860             {
861                 return kStatus_SEMC_InvalidSwPinmuxSelection;
862             }
863         }
864         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3U))
865         {
866             /* Address bit 26 (A26) */
867             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX2_MASK;
868             if (config->cePinMux == kSEMC_MUXCSX2)
869             {
870                 return kStatus_SEMC_InvalidSwPinmuxSelection;
871             }
872         }
873         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4U))
874         {
875             if (config->addr27 == kSEMC_NORA27_MUXCSX3)
876             {
877                 /* Address bit 27 (A27) */
878                 base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX3_MASK;
879             }
880             else if (config->addr27 == kSEMC_NORA27_MUXRDY)
881             {
882                 base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
883             }
884             else
885             {
886                 return kStatus_SEMC_InvalidSwPinmuxSelection;
887             }
888 
889             if (config->cePinMux == kSEMC_MUXCSX3)
890             {
891                 return kStatus_SEMC_InvalidSwPinmuxSelection;
892             }
893         }
894         if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
895         {
896             return kStatus_SEMC_InvalidAddressPortWidth;
897         }
898     }
899     /* Base control. */
900     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
901     if (result != kStatus_Success)
902     {
903         return result;
904     }
905 
906     tempBRVal = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
907 
908     uint32_t tempCtrlVal;
909 
910     switch (cs)
911     {
912         case kSEMC_SRAM_CS0:
913             base->BR[6] = tempBRVal;
914             break;
915 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
916         case kSEMC_SRAM_CS1:
917             base->BR9 = tempBRVal;
918             break;
919         case kSEMC_SRAM_CS2:
920             base->BR10 = tempBRVal;
921             break;
922         case kSEMC_SRAM_CS3:
923             base->BR11 = tempBRVal;
924             break;
925 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
926         default:
927             assert(NULL);
928             break;
929     }
930 
931 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
932     waitEnable = config->waitEnable;
933 #endif
934 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
935     waitSample = config->waitSample;
936 #endif
937 
938 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN) && (FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN)
939     /* Ready/wait(WAITEN and WAITSP) feature is only for async mode. */
940     if (kSEMC_AsyncMode != config->syncMode)
941     {
942         /* Set the waitEnable and waitSample to default value. */
943 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
944         waitEnable = false;
945 #endif
946 
947 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
948         waitSample = 0U;
949 #endif
950     }
951 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN */
952 
953     /* PSRAM0 SRAMCRx timing setting. */
954     if (kSEMC_SRAM_CS0 == cs)
955     {
956         tempCtrlVal = SEMC_SRAMCR0_PS(config->portSize) |
957 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN) && (FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN)
958                       SEMC_SRAMCR0_SYNCEN(config->syncMode) |
959 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN */
960 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
961                       SEMC_SRAMCR0_WAITEN(waitEnable) |
962 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITEN */
963 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
964                       SEMC_SRAMCR0_WAITSP(waitSample) |
965 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITSP */
966                       SEMC_SRAMCR0_BL(config->burstLen) | SEMC_SRAMCR0_AM(config->addrMode) |
967                       SEMC_SRAMCR0_ADVP(config->advActivePolarity) |
968 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_ADVH) && (FSL_FEATURE_SEMC_HAS_SRAM_ADVH)
969                       SEMC_SRAMCR0_ADVH(config->advLevelCtrl) |
970 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_ADVH */
971                       SEMC_SRAMCR0_COL_MASK;
972 
973         base->SRAMCR0 = tempCtrlVal;
974     }
975 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
976     /* PSRAM1~PSRAM3 SRAMCRx timing setting. */
977     else
978     {
979         tempCtrlVal = SEMC_SRAMCR4_PS(config->portSize) |
980 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN) && (FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN)
981                       SEMC_SRAMCR4_SYNCEN(config->syncMode) |
982 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN */
983 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
984                       SEMC_SRAMCR4_WAITEN(waitEnable) |
985 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITEN */
986 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
987                       SEMC_SRAMCR4_WAITSP(waitSample) |
988 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITSP */
989                       SEMC_SRAMCR4_BL(config->burstLen) | SEMC_SRAMCR4_AM(config->addrMode) |
990                       SEMC_SRAMCR4_ADVP(config->advActivePolarity) |
991 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_ADVH) && (FSL_FEATURE_SEMC_HAS_SRAM_ADVH)
992                       SEMC_SRAMCR4_ADVH(config->advLevelCtrl) |
993 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_ADVH */
994                       SEMC_SRAMCR4_COL_MASK;
995 
996         base->SRAMCR4 = tempCtrlVal;
997     }
998 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
999 
1000 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
1001     uint32_t tempDelayChain = base->DCCR;
1002 
1003     /* Configure delay chain. */
1004     switch (cs)
1005     {
1006         case kSEMC_SRAM_CS0:
1007             tempDelayChain &= ~(SEMC_DCCR_SRAM0VAL_MASK | SEMC_DCCR_SRAM0EN_MASK);
1008             base->DCCR =
1009                 tempDelayChain | SEMC_DCCR_SRAM0VAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SRAM0EN_MASK;
1010             break;
1011 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
1012         case kSEMC_SRAM_CS1:
1013             SUPPRESS_FALL_THROUGH_WARNING();
1014         case kSEMC_SRAM_CS2:
1015             SUPPRESS_FALL_THROUGH_WARNING();
1016         case kSEMC_SRAM_CS3:
1017             tempDelayChain &= ~(SEMC_DCCR_SRAMXVAL_MASK | SEMC_DCCR_SRAMXEN_MASK);
1018             base->DCCR =
1019                 tempDelayChain | SEMC_DCCR_SRAMXVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SRAMXEN_MASK;
1020             break;
1021 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
1022         default:
1023             assert(NULL);
1024             break;
1025     }
1026 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
1027 
1028     if (kSEMC_SRAM_CS0 == cs)
1029     {
1030         timing = SEMC_SRAMCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
1031         timing |= SEMC_SRAMCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
1032         timing |= SEMC_SRAMCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
1033         timing |= SEMC_SRAMCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
1034         timing |= SEMC_SRAMCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
1035         timing |= SEMC_SRAMCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
1036         timing |= SEMC_SRAMCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
1037         timing |= SEMC_SRAMCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
1038 
1039         /* SRAMCR1 timing setting. */
1040         base->SRAMCR1 = timing;
1041 
1042         timing = 0x00U;
1043 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME)
1044         timing |= SEMC_SRAMCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
1045 #endif
1046 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME)
1047         timing |= SEMC_SRAMCR2_WDH((uint32_t)SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz) + 1UL);
1048 #endif
1049         timing |= SEMC_SRAMCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
1050         timing |= SEMC_SRAMCR2_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz));
1051 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME)
1052         timing |= SEMC_SRAMCR2_LC(config->latencyCount);
1053 #endif
1054 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME)
1055         timing |= SEMC_SRAMCR2_RD((uint32_t)config->readCycle - 1UL);
1056 #endif
1057         timing |= SEMC_SRAMCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
1058 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME)
1059         timing |= SEMC_SRAMCR2_RDH((uint32_t)SEMC_ConvertTiming(config->readHoldTime_Ns, clkSrc_Hz) + 0x01U);
1060 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME */
1061 
1062         /* SRAMCR2 timing setting. */
1063         base->SRAMCR2 = timing;
1064     }
1065 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
1066     else
1067     {
1068         timing = SEMC_SRAMCR5_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
1069         timing |= SEMC_SRAMCR5_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
1070         timing |= SEMC_SRAMCR5_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
1071         timing |= SEMC_SRAMCR5_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
1072         timing |= SEMC_SRAMCR5_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
1073         timing |= SEMC_SRAMCR5_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
1074         timing |= SEMC_SRAMCR5_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
1075         timing |= SEMC_SRAMCR5_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
1076 
1077         /* SRAMCR5 timing setting. */
1078         base->SRAMCR5 = timing;
1079 
1080         timing = 0x00U;
1081 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME)
1082         timing = SEMC_SRAMCR6_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
1083 #endif
1084 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME)
1085         timing |= SEMC_SRAMCR6_WDH((uint32_t)SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz) + 1UL);
1086 #endif
1087         timing |= SEMC_SRAMCR6_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
1088         timing |= SEMC_SRAMCR6_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz));
1089 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME)
1090         timing |= SEMC_SRAMCR6_LC(config->latencyCount);
1091 #endif
1092 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME)
1093         timing |= SEMC_SRAMCR6_RD((uint32_t)config->readCycle - 1UL);
1094 #endif
1095         timing |= SEMC_SRAMCR6_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
1096 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME)
1097         timing |= SEMC_SRAMCR6_RDH((uint32_t)SEMC_ConvertTiming(config->readHoldTime_Ns, clkSrc_Hz) + 0x01U);
1098 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME */
1099 
1100         /* SRAMCR6 timing setting. */
1101         base->SRAMCR6 = timing;
1102     }
1103 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
1104 
1105     return result;
1106 }
1107 
1108 /*!
1109  * brief Configures DBI controller in SEMC.
1110  *
1111  * param base SEMC peripheral base address.
1112  * param config The dbi configuration.
1113  * param clkSrc_Hz The SEMC clock frequency.
1114  */
SEMC_ConfigureDBI(SEMC_Type * base,semc_dbi_config_t * config,uint32_t clkSrc_Hz)1115 status_t SEMC_ConfigureDBI(SEMC_Type *base, semc_dbi_config_t *config, uint32_t clkSrc_Hz)
1116 {
1117     assert(config != NULL);
1118 
1119     uint8_t memsize;
1120     status_t result;
1121     uint32_t timing;
1122 #if (defined(SEMC_DBICR1_REL2_MASK) || defined(SEMC_DBICR1_REH2_MASK))
1123     uint32_t cr1RE;
1124 #endif
1125 
1126     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
1127     {
1128         return kStatus_SEMC_InvalidBaseAddress;
1129     }
1130 
1131     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->csxPinMux));
1132     uint32_t muxCsx = (config->csxPinMux == kSEMC_MUXRDY) ?
1133                           (SEMC_IOCR_DBI_CSX - 1U) :
1134                           ((config->csxPinMux == kSEMC_MUXA8) ? SEMC_IOCR_DBI_CSX_A8 : SEMC_IOCR_DBI_CSX);
1135 
1136     /* IOMUX setting. */
1137     base->IOCR = iocReg | (muxCsx << (uint32_t)config->csxPinMux);
1138     /* Base control. */
1139     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
1140     if (result != kStatus_Success)
1141     {
1142         return result;
1143     }
1144     base->BR[7] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
1145 
1146     /* DBICR0 timing setting. */
1147     base->DBICR0 =
1148         SEMC_DBICR0_PS(config->portSize) | SEMC_DBICR0_BL(config->burstLen) | SEMC_DBICR0_COL(config->columnAddrBitNum);
1149 
1150     timing = SEMC_DBICR1_CES(SEMC_ConvertTiming(config->tCsxSetup_Ns, clkSrc_Hz));
1151     timing |= SEMC_DBICR1_CEH(SEMC_ConvertTiming(config->tCsxHold_Ns, clkSrc_Hz));
1152     timing |= SEMC_DBICR1_WEL(SEMC_ConvertTiming(config->tWexLow_Ns, clkSrc_Hz));
1153     timing |= SEMC_DBICR1_WEH(SEMC_ConvertTiming(config->tWexHigh_Ns, clkSrc_Hz));
1154 
1155 #if defined(SEMC_DBICR1_REL2_MASK)
1156     cr1RE = SEMC_ConvertTiming(config->tRdxLow_Ns, clkSrc_Hz);
1157     timing |= SEMC_DBICR1_REL(cr1RE);
1158     timing |= SEMC_DBICR1_REL2(cr1RE >> SEMC_DBICR1_REL_WIDTH);
1159 #else
1160     timing |= SEMC_DBICR1_REL(SEMC_ConvertTiming(config->tRdxLow_Ns, clkSrc_Hz));
1161 #endif
1162 
1163 #if defined(SEMC_DBICR1_REH2_MASK)
1164     cr1RE = SEMC_ConvertTiming(config->tRdxHigh_Ns, clkSrc_Hz);
1165     timing |= SEMC_DBICR1_REH(cr1RE);
1166     timing |= SEMC_DBICR1_REH2(cr1RE >> SEMC_DBICR1_REH_WIDTH);
1167 #else
1168     timing |= SEMC_DBICR1_REH(SEMC_ConvertTiming(config->tRdxHigh_Ns, clkSrc_Hz));
1169 #endif
1170 
1171 #if defined(SEMC_DBICR1_CEITV_MASK)
1172     timing |= SEMC_DBICR1_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
1173 #endif /* SEMC_DBICR1_CEITV_MASK */
1174 
1175     /* DBICR1 timing setting. */
1176     base->DBICR1 = timing;
1177 
1178 #if defined(SEMC_DBICR2_CEITV_MASK)
1179     timing = SEMC_DBICR2_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
1180 
1181     /* DBICR2 timing setting. */
1182     base->DBICR2 = timing;
1183 #endif /* SEMC_DBICR2_CEITV_MASK */
1184 
1185     return SEMC_ConfigureIPCommand(base, ((uint8_t)config->portSize + 1U));
1186 }
1187 
1188 /*!
1189  * brief SEMC IP command access.
1190  *
1191  * param base  SEMC peripheral base address.
1192  * param memType  SEMC memory type. refer to "semc_mem_type_t"
1193  * param address  SEMC device address.
1194  * param command  SEMC IP command.
1195  * For NAND device, we should use the SEMC_BuildNandIPCommand to get the right nand command.
1196  * For NOR/DBI device, take refer to "semc_ipcmd_nor_dbi_t".
1197  * For SRAM device, take refer to "semc_ipcmd_sram_t".
1198  * For SDRAM device, take refer to "semc_ipcmd_sdram_t".
1199  * param write  Data for write access.
1200  * param read   Data pointer for read data out.
1201  */
SEMC_SendIPCommand(SEMC_Type * base,semc_mem_type_t memType,uint32_t address,uint32_t command,uint32_t write,uint32_t * read)1202 status_t SEMC_SendIPCommand(
1203     SEMC_Type *base, semc_mem_type_t memType, uint32_t address, uint32_t command, uint32_t write, uint32_t *read)
1204 {
1205     uint32_t cmdMode;
1206     bool readCmd  = false;
1207     bool writeCmd = false;
1208     status_t result;
1209 
1210     /* Clear status bit */
1211     base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
1212     /* Set address. */
1213     base->IPCR0 = address;
1214 
1215     /* Check command mode. */
1216     cmdMode = (uint32_t)command & 0x0FU;
1217     switch (memType)
1218     {
1219         case kSEMC_MemType_NAND:
1220             readCmd = (cmdMode == (uint32_t)kSEMC_NANDCM_CommandAddressRead) ||
1221                       (cmdMode == (uint32_t)kSEMC_NANDCM_CommandRead) || (cmdMode == (uint32_t)kSEMC_NANDCM_Read);
1222             writeCmd = (cmdMode == (uint32_t)kSEMC_NANDCM_CommandAddressWrite) ||
1223                        (cmdMode == (uint32_t)kSEMC_NANDCM_CommandWrite) || (cmdMode == (uint32_t)kSEMC_NANDCM_Write);
1224             break;
1225         case kSEMC_MemType_NOR:
1226         case kSEMC_MemType_8080:
1227             readCmd  = (cmdMode == (uint32_t)kSEMC_NORDBICM_Read);
1228             writeCmd = (cmdMode == (uint32_t)kSEMC_NORDBICM_Write);
1229             break;
1230         case kSEMC_MemType_SRAM:
1231             readCmd  = (cmdMode == (uint32_t)kSEMC_SRAMCM_ArrayRead) || (cmdMode == (uint32_t)kSEMC_SRAMCM_RegRead);
1232             writeCmd = (cmdMode == (uint32_t)kSEMC_SRAMCM_ArrayWrite) || (cmdMode == (uint32_t)kSEMC_SRAMCM_RegWrite);
1233             break;
1234         case kSEMC_MemType_SDRAM:
1235             readCmd  = (cmdMode == (uint32_t)kSEMC_SDRAMCM_Read);
1236             writeCmd = (cmdMode == (uint32_t)kSEMC_SDRAMCM_Write) || (cmdMode == (uint32_t)kSEMC_SDRAMCM_Modeset);
1237             break;
1238         default:
1239             assert(false);
1240             break;
1241     }
1242 
1243     if (writeCmd)
1244     {
1245         /* Set data. */
1246         base->IPTXDAT = write;
1247     }
1248 
1249     /* Set command code. */
1250     base->IPCMD = command | SEMC_IPCMD_KEY(SEMC_IPCOMMANDMAGICKEY);
1251     /* Wait for command done. */
1252     result = SEMC_IsIPCommandDone(base);
1253     if (result != kStatus_Success)
1254     {
1255         return result;
1256     }
1257 
1258     if (readCmd)
1259     {
1260         /* Get the read data */
1261         *read = base->IPRXDAT;
1262     }
1263 
1264     return kStatus_Success;
1265 }
1266 
1267 /*!
1268  * brief SEMC NAND device memory write through IP command.
1269  *
1270  * param base  SEMC peripheral base address.
1271  * param address  SEMC NAND device address.
1272  * param data  Data for write access.
1273  * param size_bytes   Data length.
1274  */
SEMC_IPCommandNandWrite(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1275 status_t SEMC_IPCommandNandWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1276 {
1277     assert(data != NULL);
1278 
1279     status_t result = kStatus_Success;
1280     uint16_t ipCmd;
1281     uint32_t tempData = 0UL;
1282 
1283     /* Write command built */
1284     ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Write);
1285     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1286     {
1287         /* Configure IP command data size. */
1288         (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1289         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, *(uint32_t *)(void *)data, NULL);
1290         if (result != kStatus_Success)
1291         {
1292             break;
1293         }
1294 
1295         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1296         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1297     }
1298 
1299     if ((result == kStatus_Success) && (size_bytes != 0x00UL))
1300     {
1301         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1302 
1303         while (size_bytes != 0x00UL)
1304         {
1305             size_bytes--;
1306             tempData <<= SEMC_BYTE_NUMBIT;
1307             tempData |= data[size_bytes];
1308         }
1309 
1310         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, tempData, NULL);
1311     }
1312 
1313     return result;
1314 }
1315 
1316 /*!
1317  * brief SEMC NAND device memory read through IP command.
1318  *
1319  * param base  SEMC peripheral base address.
1320  * param address  SEMC NAND device address.
1321  * param data  Data pointer for data read out.
1322  * param size_bytes   Data length.
1323  */
SEMC_IPCommandNandRead(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1324 status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1325 {
1326     assert(data != NULL);
1327 
1328     status_t result = kStatus_Success;
1329     uint16_t ipCmd;
1330     uint32_t tempData = 0;
1331 
1332     /* Configure IP command data size. */
1333     (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1334     /* Read command built */
1335     ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Read);
1336 
1337     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1338     {
1339         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, (uint32_t *)(void *)data);
1340         if (result != kStatus_Success)
1341         {
1342             break;
1343         }
1344 
1345         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1346         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1347     }
1348 
1349     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1350     {
1351         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1352         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, &tempData);
1353 
1354         while (size_bytes != 0x00U)
1355         {
1356             size_bytes--;
1357             *(data + size_bytes) = (uint8_t)((tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU);
1358         }
1359     }
1360 
1361     return result;
1362 }
1363 
1364 /*!
1365  * brief SEMC NOR device memory read through IP command.
1366  *
1367  * param base  SEMC peripheral base address.
1368  * param address  SEMC NOR device address.
1369  * param data  Data pointer for data read out.
1370  * param size_bytes   Data length.
1371  */
SEMC_IPCommandNorRead(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1372 status_t SEMC_IPCommandNorRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1373 {
1374     assert(data != NULL);
1375 
1376     uint32_t tempData = 0;
1377     status_t result   = kStatus_Success;
1378     uint8_t dataSize  = (uint8_t)base->NORCR0 & SEMC_NORCR0_PS_MASK;
1379 
1380     /* Configure IP command data size. */
1381     (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1382 
1383     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1384     {
1385         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint32_t)kSEMC_NORDBICM_Read, 0,
1386                                     (uint32_t *)(void *)data);
1387         if (result != kStatus_Success)
1388         {
1389             break;
1390         }
1391 
1392         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1393         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1394     }
1395 
1396     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1397     {
1398         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1399         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Read, 0, &tempData);
1400         while (size_bytes != 0x00U)
1401         {
1402             size_bytes--;
1403             *(data + size_bytes) = (uint8_t)((tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU);
1404         }
1405     }
1406 
1407     (void)SEMC_ConfigureIPCommand(base, dataSize);
1408     return result;
1409 }
1410 
1411 /*!
1412  * brief SEMC NOR device memory write through IP command.
1413  *
1414  * param base  SEMC peripheral base address.
1415  * param address  SEMC NOR device address.
1416  * param data  Data for write access.
1417  * param size_bytes   Data length.
1418  */
SEMC_IPCommandNorWrite(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1419 status_t SEMC_IPCommandNorWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1420 {
1421     assert(data != NULL);
1422 
1423     uint32_t tempData = 0;
1424     status_t result   = kStatus_Success;
1425     uint8_t dataSize  = (uint8_t)base->NORCR0 & SEMC_NORCR0_PS_MASK;
1426 
1427     /* Write command built */
1428     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1429     {
1430         /* Configure IP command data size. */
1431         (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1432         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Write,
1433                                     *(uint32_t *)(void *)data, NULL);
1434         if (result != kStatus_Success)
1435         {
1436             break;
1437         }
1438         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1439         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1440     }
1441 
1442     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1443     {
1444         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1445 
1446         while (size_bytes != 0x00U)
1447         {
1448             tempData |= ((uint32_t) * (data + size_bytes - 1U) << ((size_bytes - 1U) * SEMC_BYTE_NUMBIT));
1449             size_bytes--;
1450         }
1451 
1452         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Write, tempData, NULL);
1453     }
1454     (void)SEMC_ConfigureIPCommand(base, dataSize);
1455 
1456     return result;
1457 }
1458