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 = 0; 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     status_t result   = kStatus_Success;
430     uint16_t prescale = (uint16_t)(config->tPrescalePeriod_Ns / 16U / (1000000000U / clkSrc_Hz));
431     uint32_t refresh;
432     uint32_t urgentRef;
433     uint32_t idle;
434     uint32_t mode;
435     uint32_t timing;
436 
437     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
438     {
439         return kStatus_SEMC_InvalidBaseAddress;
440     }
441 
442     if (config->csxPinMux == kSEMC_MUXA8)
443     {
444         return kStatus_SEMC_InvalidSwPinmuxSelection;
445     }
446 
447     if (prescale > 256U)
448     {
449         return kStatus_SEMC_InvalidTimerSetting;
450     }
451 
452     refresh   = config->refreshPeriod_nsPerRow / config->tPrescalePeriod_Ns;
453     urgentRef = config->refreshUrgThreshold / config->tPrescalePeriod_Ns;
454     idle      = config->tIdleTimeout_Ns / config->tPrescalePeriod_Ns;
455 
456     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->csxPinMux));
457 
458     /* Base control. */
459     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
460     if (result != kStatus_Success)
461     {
462         return result;
463     }
464 
465     base->BR[cs] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
466 
467 #if defined(FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT) && (FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT)
468     if (kSEMC_SdramColunm_8bit == config->columnAddrBitNum)
469     {
470         base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
471                          SEMC_SDRAMCR0_COL8(true) | SEMC_SDRAMCR0_CL(config->casLatency);
472     }
473     else
474 #endif /* FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT */
475     {
476         base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
477                          SEMC_SDRAMCR0_COL(config->columnAddrBitNum) | SEMC_SDRAMCR0_CL(config->casLatency);
478     }
479 
480     /* IOMUX setting. */
481     if (cs != kSEMC_SDRAM_CS0)
482     {
483         base->IOCR = iocReg | ((uint32_t)cs << (uint32_t)config->csxPinMux);
484     }
485 
486     base->IOCR &= ~SEMC_IOCR_MUX_A8_MASK;
487 
488 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
489     uint32_t tempDelayChain = base->DCCR;
490 
491     tempDelayChain &= ~(SEMC_DCCR_SDRAMVAL_MASK | SEMC_DCCR_SDRAMEN_MASK);
492     /* Configure delay chain. */
493     base->DCCR = tempDelayChain | SEMC_DCCR_SDRAMVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SDRAMEN_MASK;
494 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
495 
496     timing = SEMC_SDRAMCR1_PRE2ACT(SEMC_ConvertTiming(config->tPrecharge2Act_Ns, clkSrc_Hz));
497     timing |= SEMC_SDRAMCR1_ACT2RW(SEMC_ConvertTiming(config->tAct2ReadWrite_Ns, clkSrc_Hz));
498     timing |= SEMC_SDRAMCR1_RFRC(SEMC_ConvertTiming(config->tRefreshRecovery_Ns, clkSrc_Hz));
499     timing |= SEMC_SDRAMCR1_WRC(SEMC_ConvertTiming(config->tWriteRecovery_Ns, clkSrc_Hz));
500     timing |= SEMC_SDRAMCR1_CKEOFF(SEMC_ConvertTiming(config->tCkeOff_Ns, clkSrc_Hz));
501     timing |= SEMC_SDRAMCR1_ACT2PRE(SEMC_ConvertTiming(config->tAct2Prechage_Ns, clkSrc_Hz));
502     /* SDRAMCR1 timing setting. */
503     base->SDRAMCR1 = timing;
504 
505     timing = SEMC_SDRAMCR2_SRRC(SEMC_ConvertTiming(config->tSelfRefRecovery_Ns, clkSrc_Hz));
506     timing |= SEMC_SDRAMCR2_REF2REF(SEMC_ConvertTiming(config->tRefresh2Refresh_Ns, clkSrc_Hz));
507     timing |= SEMC_SDRAMCR2_ACT2ACT(SEMC_ConvertTiming(config->tAct2Act_Ns, clkSrc_Hz)) | SEMC_SDRAMCR2_ITO(idle);
508     /* SDRAMCR2 timing setting. */
509     base->SDRAMCR2 = timing;
510 
511     /* SDRAMCR3 timing setting. */
512     base->SDRAMCR3 = SEMC_SDRAMCR3_REBL((uint32_t)config->refreshBurstLen - 1UL) |
513                      /* N * 16 * 1s / clkSrc_Hz = config->tPrescalePeriod_Ns */
514                      SEMC_SDRAMCR3_PRESCALE(prescale) | SEMC_SDRAMCR3_RT(refresh - 1UL) | SEMC_SDRAMCR3_UT(urgentRef);
515 
516     SEMC->IPCR1 = 0x2U;
517     SEMC->IPCR2 = 0U;
518 
519     result =
520         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_Prechargeall, 0, NULL);
521     if (result != kStatus_Success)
522     {
523         return result;
524     }
525     result =
526         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
527     if (result != kStatus_Success)
528     {
529         return result;
530     }
531     result =
532         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
533     if (result != kStatus_Success)
534     {
535         return result;
536     }
537     /* Mode setting value. */
538     mode = (uint32_t)config->burstLen | (((uint32_t)config->casLatency) << SEMC_SDRAM_MODESETCAL_OFFSET);
539     result =
540         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_Modeset, mode, NULL);
541     if (result != kStatus_Success)
542     {
543         return result;
544     }
545     /* Enables refresh */
546     base->SDRAMCR3 |= SEMC_SDRAMCR3_REN_MASK;
547 
548     return kStatus_Success;
549 }
550 
551 /*!
552  * brief Configures NAND controller in SEMC.
553  *
554  * param base SEMC peripheral base address.
555  * param config The nand configuration.
556  * param clkSrc_Hz The SEMC clock frequency.
557  */
SEMC_ConfigureNAND(SEMC_Type * base,semc_nand_config_t * config,uint32_t clkSrc_Hz)558 status_t SEMC_ConfigureNAND(SEMC_Type *base, semc_nand_config_t *config, uint32_t clkSrc_Hz)
559 {
560     assert(config != NULL);
561     assert(config->timingConfig != NULL);
562 
563     uint8_t memsize;
564     status_t result;
565     uint32_t timing;
566 
567     if ((config->axiAddress < SEMC_STARTADDRESS) || (config->axiAddress > SEMC_ENDADDRESS))
568     {
569         return kStatus_SEMC_InvalidBaseAddress;
570     }
571 
572     if (config->cePinMux == kSEMC_MUXRDY)
573     {
574         return kStatus_SEMC_InvalidSwPinmuxSelection;
575     }
576 
577     /* Disable SEMC module during configuring control registers. */
578     base->MCR |= SEMC_MCR_MDIS_MASK;
579 
580     uint32_t iocReg =
581         base->IOCR & (~((SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux) | SEMC_IOCR_MUX_RDY_MASK));
582 
583     /* Base control. */
584     if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
585     {
586         base->MCR |= SEMC_MCR_WPOL1_MASK;
587     }
588     else
589     {
590         base->MCR &= ~SEMC_MCR_WPOL1_MASK;
591     }
592     result = SEMC_CovertMemorySize(config->axiMemsize_kbytes, &memsize);
593     if (result != kStatus_Success)
594     {
595         return result;
596     }
597     base->BR[4] = (config->axiAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
598 
599     result = SEMC_CovertMemorySize(config->ipgMemsize_kbytes, &memsize);
600     if (result != kStatus_Success)
601     {
602         return result;
603     }
604     base->BR[8] = (config->ipgAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
605 
606     /* IOMUX setting. */
607     if ((uint32_t)config->cePinMux != 0x00U)
608     {
609         base->IOCR = iocReg | (SEMC_IOCR_NAND_CE << (uint32_t)config->cePinMux);
610     }
611     else
612     {
613         base->IOCR = iocReg | (1UL << (uint32_t)config->cePinMux);
614     }
615 
616     base->NANDCR0 = SEMC_NANDCR0_PS(config->portSize) | SEMC_NANDCR0_BL(config->burstLen) |
617                     SEMC_NANDCR0_EDO(config->edoModeEnabled) | SEMC_NANDCR0_COL(config->columnAddrBitNum);
618 
619     timing = SEMC_NANDCR1_CES(SEMC_ConvertTiming(config->timingConfig->tCeSetup_Ns, clkSrc_Hz));
620     timing |= SEMC_NANDCR1_CEH(SEMC_ConvertTiming(config->timingConfig->tCeHold_Ns, clkSrc_Hz));
621     timing |= SEMC_NANDCR1_WEL(SEMC_ConvertTiming(config->timingConfig->tWeLow_Ns, clkSrc_Hz));
622     timing |= SEMC_NANDCR1_WEH(SEMC_ConvertTiming(config->timingConfig->tWeHigh_Ns, clkSrc_Hz));
623     timing |= SEMC_NANDCR1_REL(SEMC_ConvertTiming(config->timingConfig->tReLow_Ns, clkSrc_Hz));
624     timing |= SEMC_NANDCR1_REH(SEMC_ConvertTiming(config->timingConfig->tReHigh_Ns, clkSrc_Hz));
625     timing |= SEMC_NANDCR1_TA(SEMC_ConvertTiming(config->timingConfig->tTurnAround_Ns, clkSrc_Hz));
626     timing |= SEMC_NANDCR1_CEITV(SEMC_ConvertTiming(config->timingConfig->tCeInterval_Ns, clkSrc_Hz));
627     /* NANDCR1 timing setting. */
628     base->NANDCR1 = timing;
629 
630     timing = SEMC_NANDCR2_TWHR(SEMC_ConvertTiming(config->timingConfig->tWehigh2Relow_Ns, clkSrc_Hz));
631     timing |= SEMC_NANDCR2_TRHW(SEMC_ConvertTiming(config->timingConfig->tRehigh2Welow_Ns, clkSrc_Hz));
632     timing |= SEMC_NANDCR2_TADL(SEMC_ConvertTiming(config->timingConfig->tAle2WriteStart_Ns, clkSrc_Hz));
633     timing |= SEMC_NANDCR2_TRR(SEMC_ConvertTiming(config->timingConfig->tReady2Relow_Ns, clkSrc_Hz));
634     timing |= SEMC_NANDCR2_TWB(SEMC_ConvertTiming(config->timingConfig->tWehigh2Busy_Ns, clkSrc_Hz));
635 
636     /* NANDCR2 timing setting. */
637     base->NANDCR2 = timing;
638 
639     /* NANDCR3 timing setting. */
640     base->NANDCR3 = (uint32_t)config->arrayAddrOption;
641 
642     /* Enables SEMC module after configuring control registers completely. */
643     base->MCR &= ~SEMC_MCR_MDIS_MASK;
644 
645     return kStatus_Success;
646 }
647 
648 /*!
649  * brief Configures NOR controller in SEMC.
650  *
651  * param base SEMC peripheral base address.
652  * param config The nor configuration.
653  * param clkSrc_Hz The SEMC clock frequency.
654  */
SEMC_ConfigureNOR(SEMC_Type * base,semc_nor_config_t * config,uint32_t clkSrc_Hz)655 status_t SEMC_ConfigureNOR(SEMC_Type *base, semc_nor_config_t *config, uint32_t clkSrc_Hz)
656 {
657     assert(config != NULL);
658 
659     uint8_t memsize;
660     status_t result;
661     uint32_t timing;
662 
663     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
664     {
665         return kStatus_SEMC_InvalidBaseAddress;
666     }
667 
668     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux));
669     uint32_t muxCe  = (config->cePinMux == kSEMC_MUXRDY) ?
670                          (SEMC_IOCR_NOR_CE - 1U) :
671                          ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_NOR_CE_A8 : SEMC_IOCR_NOR_CE);
672 
673     /* IOMUX setting. */
674     base->IOCR = iocReg | (muxCe << (uint32_t)config->cePinMux);
675     /* Address bit setting. */
676     if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
677     {
678         /* Address bit 24 (A24) */
679         base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX0_MASK;
680         if (config->cePinMux == kSEMC_MUXCSX0)
681         {
682             return kStatus_SEMC_InvalidSwPinmuxSelection;
683         }
684 
685         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2U))
686         {
687             /* Address bit 25 (A25) */
688             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX1_MASK;
689             if (config->cePinMux == kSEMC_MUXCSX1)
690             {
691                 return kStatus_SEMC_InvalidSwPinmuxSelection;
692             }
693         }
694         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3U))
695         {
696             /* Address bit 26 (A26) */
697             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX2_MASK;
698             if (config->cePinMux == kSEMC_MUXCSX2)
699             {
700                 return kStatus_SEMC_InvalidSwPinmuxSelection;
701             }
702         }
703         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4U))
704         {
705             if (config->addr27 == kSEMC_NORA27_MUXCSX3)
706             {
707                 /* Address bit 27 (A27) */
708                 base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX3_MASK;
709             }
710             else if (config->addr27 == kSEMC_NORA27_MUXRDY)
711             {
712                 base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
713             }
714             else
715             {
716                 return kStatus_SEMC_InvalidSwPinmuxSelection;
717             }
718             if (config->cePinMux == kSEMC_MUXCSX3)
719             {
720                 return kStatus_SEMC_InvalidSwPinmuxSelection;
721             }
722         }
723         if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
724         {
725             return kStatus_SEMC_InvalidAddressPortWidth;
726         }
727     }
728 
729     /* Base control. */
730     if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
731     {
732         base->MCR |= SEMC_MCR_WPOL0_MASK;
733     }
734     else
735     {
736         base->MCR &= ~SEMC_MCR_WPOL0_MASK;
737     }
738     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
739     if (result != kStatus_Success)
740     {
741         return result;
742     }
743     base->BR[5]  = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
744     base->NORCR0 = SEMC_NORCR0_PS(config->portSize) | SEMC_NORCR0_BL(config->burstLen) |
745                    SEMC_NORCR0_AM(config->addrMode) | SEMC_NORCR0_ADVP(config->advActivePolarity) |
746                    SEMC_NORCR0_COL(config->columnAddrBitNum);
747 
748 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
749     uint32_t tempDelayChain = base->DCCR;
750 
751     tempDelayChain &= ~(SEMC_DCCR_NORVAL_MASK | SEMC_DCCR_NOREN_MASK);
752     /* Configure delay chain. */
753     base->DCCR = tempDelayChain | SEMC_DCCR_NORVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_NOREN_MASK;
754 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
755 
756     timing = SEMC_NORCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
757     timing |= SEMC_NORCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
758     timing |= SEMC_NORCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
759     timing |= SEMC_NORCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
760     timing |= SEMC_NORCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
761     timing |= SEMC_NORCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
762     timing |= SEMC_NORCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
763     timing |= SEMC_NORCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
764 
765     /* NORCR1 timing setting. */
766     base->NORCR1 = timing;
767 
768     timing = SEMC_NORCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
769 #if defined(FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME)
770     timing |= SEMC_NORCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
771 #endif /* FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME */
772 #if defined(FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME)
773     timing |= SEMC_NORCR2_WDH(SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz));
774 #endif /* FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME */
775     timing |= SEMC_NORCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
776     timing |= SEMC_NORCR2_AWDH((uint32_t)SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz) + 0x01UL);
777 #if defined(FSL_FEATURE_SEMC_HAS_NOR_LC_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_LC_TIME)
778     timing |= SEMC_NORCR2_LC(config->latencyCount);
779 #endif
780 #if defined(FSL_FEATURE_SEMC_HAS_NOR_RD_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_RD_TIME)
781     timing |= SEMC_NORCR2_RD((uint32_t)config->readCycle - 0x01UL);
782 #endif
783 
784     /* NORCR2 timing setting. */
785     base->NORCR2 = timing;
786 
787     return SEMC_ConfigureIPCommand(base, ((uint8_t)config->portSize + 1U));
788 }
789 
790 /*!
791  * brief Configures SRAM controller in SEMC, which can be used only for specific chip selection CS0.
792  *
793  * param base SEMC peripheral base address.
794  * param config The sram configuration.
795  * param clkSrc_Hz The SEMC clock frequency.
796  */
SEMC_ConfigureSRAM(SEMC_Type * base,semc_sram_config_t * config,uint32_t clkSrc_Hz)797 status_t SEMC_ConfigureSRAM(SEMC_Type *base, semc_sram_config_t *config, uint32_t clkSrc_Hz)
798 {
799     return SEMC_ConfigureSRAMWithChipSelection(base, kSEMC_SRAM_CS0, config, clkSrc_Hz);
800 }
801 
802 /*!
803  * brief Configures SRAM controller in SEMC, which can be used up to four chip selections CS0/CS1/CS2/CS3..
804  *
805  * param base SEMC peripheral base address.
806  * param cs The chip selection.
807  * param config The sram configuration.
808  * param clkSrc_Hz The SEMC clock frequency.
809  */
SEMC_ConfigureSRAMWithChipSelection(SEMC_Type * base,semc_sram_cs_t cs,semc_sram_config_t * config,uint32_t clkSrc_Hz)810 status_t SEMC_ConfigureSRAMWithChipSelection(SEMC_Type *base,
811                                              semc_sram_cs_t cs,
812                                              semc_sram_config_t *config,
813                                              uint32_t clkSrc_Hz)
814 {
815     assert(config != NULL);
816 
817     uint32_t tempBRVal;
818     uint32_t timing;
819     uint8_t memsize;
820     status_t result = kStatus_Success;
821 
822 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
823     bool waitEnable;
824 #endif
825 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
826     uint8_t waitSample;
827 #endif
828 
829     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
830     {
831         return kStatus_SEMC_InvalidBaseAddress;
832     }
833 
834     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux));
835 
836     uint32_t muxCe = (config->cePinMux == kSEMC_MUXRDY) ?
837                          (SEMC_IOCR_PSRAM_CE - 1U) :
838                          ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_PSRAM_CE_A8 : SEMC_IOCR_PSRAM_CE);
839 
840     /* IOMUX setting. */
841     base->IOCR = iocReg | (muxCe << (uint32_t)config->cePinMux);
842     /* Address bit setting. */
843     if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
844     {
845         /* Address bit 24 (A24) */
846         base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX0_MASK;
847         if (config->cePinMux == kSEMC_MUXCSX0)
848         {
849             return kStatus_SEMC_InvalidSwPinmuxSelection;
850         }
851 
852         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2U))
853         {
854             /* Address bit 25 (A25) */
855             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX1_MASK;
856             if (config->cePinMux == kSEMC_MUXCSX1)
857             {
858                 return kStatus_SEMC_InvalidSwPinmuxSelection;
859             }
860         }
861         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3U))
862         {
863             /* Address bit 26 (A26) */
864             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX2_MASK;
865             if (config->cePinMux == kSEMC_MUXCSX2)
866             {
867                 return kStatus_SEMC_InvalidSwPinmuxSelection;
868             }
869         }
870         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4U))
871         {
872             if (config->addr27 == kSEMC_NORA27_MUXCSX3)
873             {
874                 /* Address bit 27 (A27) */
875                 base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX3_MASK;
876             }
877             else if (config->addr27 == kSEMC_NORA27_MUXRDY)
878             {
879                 base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
880             }
881             else
882             {
883                 return kStatus_SEMC_InvalidSwPinmuxSelection;
884             }
885 
886             if (config->cePinMux == kSEMC_MUXCSX3)
887             {
888                 return kStatus_SEMC_InvalidSwPinmuxSelection;
889             }
890         }
891         if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
892         {
893             return kStatus_SEMC_InvalidAddressPortWidth;
894         }
895     }
896     /* Base control. */
897     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
898     if (result != kStatus_Success)
899     {
900         return result;
901     }
902 
903     tempBRVal = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
904 
905     uint32_t tempCtrlVal;
906 
907     switch (cs)
908     {
909         case kSEMC_SRAM_CS0:
910             base->BR[6] = tempBRVal;
911             break;
912 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
913         case kSEMC_SRAM_CS1:
914             base->BR9 = tempBRVal;
915             break;
916         case kSEMC_SRAM_CS2:
917             base->BR10 = tempBRVal;
918             break;
919         case kSEMC_SRAM_CS3:
920             base->BR11 = tempBRVal;
921             break;
922 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
923         default:
924             assert(NULL);
925             break;
926     }
927 
928 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
929     waitEnable = config->waitEnable;
930 #endif
931 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
932     waitSample = config->waitSample;
933 #endif
934 
935 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN) && (FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN)
936     /* Ready/wait(WAITEN and WAITSP) feature is only for async mode. */
937     if (kSEMC_AsyncMode != config->syncMode)
938     {
939         /* Set the waitEnable and waitSample to default value. */
940 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
941         waitEnable = false;
942 #endif
943 
944 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
945         waitSample = 0U;
946 #endif
947     }
948 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN */
949 
950     /* PSRAM0 SRAMCRx timing setting. */
951     if (kSEMC_SRAM_CS0 == cs)
952     {
953         tempCtrlVal = SEMC_SRAMCR0_PS(config->portSize) |
954 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN) && (FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN)
955                       SEMC_SRAMCR0_SYNCEN(config->syncMode) |
956 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN */
957 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
958                       SEMC_SRAMCR0_WAITEN(waitEnable) |
959 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITEN */
960 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
961                       SEMC_SRAMCR0_WAITSP(waitSample) |
962 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITSP */
963                       SEMC_SRAMCR0_BL(config->burstLen) | SEMC_SRAMCR0_AM(config->addrMode) |
964                       SEMC_SRAMCR0_ADVP(config->advActivePolarity) |
965 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_ADVH) && (FSL_FEATURE_SEMC_HAS_SRAM_ADVH)
966                       SEMC_SRAMCR0_ADVH(config->advLevelCtrl) |
967 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_ADVH */
968                       SEMC_SRAMCR0_COL_MASK;
969 
970         base->SRAMCR0 = tempCtrlVal;
971     }
972 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
973     /* PSRAM1~PSRAM3 SRAMCRx timing setting. */
974     else
975     {
976         tempCtrlVal = SEMC_SRAMCR4_PS(config->portSize) |
977 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN) && (FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN)
978                       SEMC_SRAMCR4_SYNCEN(config->syncMode) |
979 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_SYNCEN */
980 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITEN) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITEN)
981                       SEMC_SRAMCR4_WAITEN(waitEnable) |
982 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITEN */
983 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WAITSP) && (FSL_FEATURE_SEMC_HAS_SRAM_WAITSP)
984                       SEMC_SRAMCR4_WAITSP(waitSample) |
985 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_WAITSP */
986                       SEMC_SRAMCR4_BL(config->burstLen) | SEMC_SRAMCR4_AM(config->addrMode) |
987                       SEMC_SRAMCR4_ADVP(config->advActivePolarity) |
988 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_ADVH) && (FSL_FEATURE_SEMC_HAS_SRAM_ADVH)
989                       SEMC_SRAMCR4_ADVH(config->advLevelCtrl) |
990 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_ADVH */
991                       SEMC_SRAMCR4_COL_MASK;
992 
993         base->SRAMCR4 = tempCtrlVal;
994     }
995 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
996 
997 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
998     uint32_t tempDelayChain = base->DCCR;
999 
1000     /* Configure delay chain. */
1001     switch (cs)
1002     {
1003         case kSEMC_SRAM_CS0:
1004             tempDelayChain &= ~(SEMC_DCCR_SRAM0VAL_MASK | SEMC_DCCR_SRAM0EN_MASK);
1005             base->DCCR =
1006                 tempDelayChain | SEMC_DCCR_SRAM0VAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SRAM0EN_MASK;
1007             break;
1008 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
1009         case kSEMC_SRAM_CS1:
1010             SUPPRESS_FALL_THROUGH_WARNING();
1011         case kSEMC_SRAM_CS2:
1012             SUPPRESS_FALL_THROUGH_WARNING();
1013         case kSEMC_SRAM_CS3:
1014             tempDelayChain &= ~(SEMC_DCCR_SRAMXVAL_MASK | SEMC_DCCR_SRAMXEN_MASK);
1015             base->DCCR =
1016                 tempDelayChain | SEMC_DCCR_SRAMXVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SRAMXEN_MASK;
1017             break;
1018 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
1019         default:
1020             assert(NULL);
1021             break;
1022     }
1023 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
1024 
1025     if (kSEMC_SRAM_CS0 == cs)
1026     {
1027         timing = SEMC_SRAMCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
1028         timing |= SEMC_SRAMCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
1029         timing |= SEMC_SRAMCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
1030         timing |= SEMC_SRAMCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
1031         timing |= SEMC_SRAMCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
1032         timing |= SEMC_SRAMCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
1033         timing |= SEMC_SRAMCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
1034         timing |= SEMC_SRAMCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
1035 
1036         /* SRAMCR1 timing setting. */
1037         base->SRAMCR1 = timing;
1038 
1039         timing = 0x00U;
1040 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME)
1041         timing |= SEMC_SRAMCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
1042 #endif
1043 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME)
1044         timing |= SEMC_SRAMCR2_WDH((uint32_t)SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz) + 1UL);
1045 #endif
1046         timing |= SEMC_SRAMCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
1047         timing |= SEMC_SRAMCR2_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz));
1048 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME)
1049         timing |= SEMC_SRAMCR2_LC(config->latencyCount);
1050 #endif
1051 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME)
1052         timing |= SEMC_SRAMCR2_RD((uint32_t)config->readCycle - 1UL);
1053 #endif
1054         timing |= SEMC_SRAMCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
1055 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME)
1056         timing |= SEMC_SRAMCR2_RDH((uint32_t)SEMC_ConvertTiming(config->readHoldTime_Ns, clkSrc_Hz) + 0x01U);
1057 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME */
1058 
1059         /* SRAMCR2 timing setting. */
1060         base->SRAMCR2 = timing;
1061     }
1062 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
1063     else
1064     {
1065         timing = SEMC_SRAMCR5_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
1066         timing |= SEMC_SRAMCR5_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
1067         timing |= SEMC_SRAMCR5_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
1068         timing |= SEMC_SRAMCR5_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
1069         timing |= SEMC_SRAMCR5_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
1070         timing |= SEMC_SRAMCR5_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
1071         timing |= SEMC_SRAMCR5_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
1072         timing |= SEMC_SRAMCR5_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
1073 
1074         /* SRAMCR5 timing setting. */
1075         base->SRAMCR5 = timing;
1076 
1077         timing = 0x00U;
1078 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME)
1079         timing = SEMC_SRAMCR6_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
1080 #endif
1081 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME)
1082         timing |= SEMC_SRAMCR6_WDH((uint32_t)SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz) + 1UL);
1083 #endif
1084         timing |= SEMC_SRAMCR6_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
1085         timing |= SEMC_SRAMCR6_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz));
1086 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME)
1087         timing |= SEMC_SRAMCR6_LC(config->latencyCount);
1088 #endif
1089 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME)
1090         timing |= SEMC_SRAMCR6_RD((uint32_t)config->readCycle - 1UL);
1091 #endif
1092         timing |= SEMC_SRAMCR6_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
1093 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME)
1094         timing |= SEMC_SRAMCR6_RDH((uint32_t)SEMC_ConvertTiming(config->readHoldTime_Ns, clkSrc_Hz) + 0x01U);
1095 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME */
1096 
1097         /* SRAMCR6 timing setting. */
1098         base->SRAMCR6 = timing;
1099     }
1100 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
1101 
1102     return result;
1103 }
1104 
1105 /*!
1106  * brief Configures DBI controller in SEMC.
1107  *
1108  * param base SEMC peripheral base address.
1109  * param config The dbi configuration.
1110  * param clkSrc_Hz The SEMC clock frequency.
1111  */
SEMC_ConfigureDBI(SEMC_Type * base,semc_dbi_config_t * config,uint32_t clkSrc_Hz)1112 status_t SEMC_ConfigureDBI(SEMC_Type *base, semc_dbi_config_t *config, uint32_t clkSrc_Hz)
1113 {
1114     assert(config != NULL);
1115 
1116     uint8_t memsize;
1117     status_t result;
1118     uint32_t timing;
1119 #if (defined(SEMC_DBICR1_REL2_MASK) || defined(SEMC_DBICR1_REH2_MASK))
1120     uint32_t cr1RE;
1121 #endif
1122 
1123     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
1124     {
1125         return kStatus_SEMC_InvalidBaseAddress;
1126     }
1127 
1128     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->csxPinMux));
1129     uint32_t muxCsx = (config->csxPinMux == kSEMC_MUXRDY) ?
1130                           (SEMC_IOCR_DBI_CSX - 1U) :
1131                           ((config->csxPinMux == kSEMC_MUXA8) ? SEMC_IOCR_DBI_CSX_A8 : SEMC_IOCR_DBI_CSX);
1132 
1133     /* IOMUX setting. */
1134     base->IOCR = iocReg | (muxCsx << (uint32_t)config->csxPinMux);
1135     /* Base control. */
1136     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
1137     if (result != kStatus_Success)
1138     {
1139         return result;
1140     }
1141     base->BR[7] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
1142 
1143     /* DBICR0 timing setting. */
1144     base->DBICR0 =
1145         SEMC_DBICR0_PS(config->portSize) | SEMC_DBICR0_BL(config->burstLen) | SEMC_DBICR0_COL(config->columnAddrBitNum);
1146 
1147     timing = SEMC_DBICR1_CES(SEMC_ConvertTiming(config->tCsxSetup_Ns, clkSrc_Hz));
1148     timing |= SEMC_DBICR1_CEH(SEMC_ConvertTiming(config->tCsxHold_Ns, clkSrc_Hz));
1149     timing |= SEMC_DBICR1_WEL(SEMC_ConvertTiming(config->tWexLow_Ns, clkSrc_Hz));
1150     timing |= SEMC_DBICR1_WEH(SEMC_ConvertTiming(config->tWexHigh_Ns, clkSrc_Hz));
1151 
1152 #if defined(SEMC_DBICR1_REL2_MASK)
1153     cr1RE = SEMC_ConvertTiming(config->tRdxLow_Ns, clkSrc_Hz);
1154     timing |= SEMC_DBICR1_REL(cr1RE);
1155     timing |= SEMC_DBICR1_REL2(cr1RE >> SEMC_DBICR1_REL_WIDTH);
1156 #else
1157     timing |= SEMC_DBICR1_REL(SEMC_ConvertTiming(config->tRdxLow_Ns, clkSrc_Hz));
1158 #endif
1159 
1160 #if defined(SEMC_DBICR1_REH2_MASK)
1161     cr1RE = SEMC_ConvertTiming(config->tRdxHigh_Ns, clkSrc_Hz);
1162     timing |= SEMC_DBICR1_REH(cr1RE);
1163     timing |= SEMC_DBICR1_REH2(cr1RE >> SEMC_DBICR1_REH_WIDTH);
1164 #else
1165     timing |= SEMC_DBICR1_REH(SEMC_ConvertTiming(config->tRdxHigh_Ns, clkSrc_Hz));
1166 #endif
1167 
1168 #if defined(SEMC_DBICR1_CEITV_MASK)
1169     timing |= SEMC_DBICR1_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
1170 #endif /* SEMC_DBICR1_CEITV_MASK */
1171 
1172     /* DBICR1 timing setting. */
1173     base->DBICR1 = timing;
1174 
1175 #if defined(SEMC_DBICR2_CEITV_MASK)
1176     timing = SEMC_DBICR2_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
1177 
1178     /* DBICR2 timing setting. */
1179     base->DBICR2 = timing;
1180 #endif /* SEMC_DBICR2_CEITV_MASK */
1181 
1182     return SEMC_ConfigureIPCommand(base, ((uint8_t)config->portSize + 1U));
1183 }
1184 
1185 /*!
1186  * brief SEMC IP command access.
1187  *
1188  * param base  SEMC peripheral base address.
1189  * param memType  SEMC memory type. refer to "semc_mem_type_t"
1190  * param address  SEMC device address.
1191  * param command  SEMC IP command.
1192  * For NAND device, we should use the SEMC_BuildNandIPCommand to get the right nand command.
1193  * For NOR/DBI device, take refer to "semc_ipcmd_nor_dbi_t".
1194  * For SRAM device, take refer to "semc_ipcmd_sram_t".
1195  * For SDRAM device, take refer to "semc_ipcmd_sdram_t".
1196  * param write  Data for write access.
1197  * param read   Data pointer for read data out.
1198  */
SEMC_SendIPCommand(SEMC_Type * base,semc_mem_type_t memType,uint32_t address,uint32_t command,uint32_t write,uint32_t * read)1199 status_t SEMC_SendIPCommand(
1200     SEMC_Type *base, semc_mem_type_t memType, uint32_t address, uint32_t command, uint32_t write, uint32_t *read)
1201 {
1202     uint32_t cmdMode;
1203     bool readCmd  = false;
1204     bool writeCmd = false;
1205     status_t result;
1206 
1207     /* Clear status bit */
1208     base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
1209     /* Set address. */
1210     base->IPCR0 = address;
1211 
1212     /* Check command mode. */
1213     cmdMode = (uint32_t)command & 0x0FU;
1214     switch (memType)
1215     {
1216         case kSEMC_MemType_NAND:
1217             readCmd = (cmdMode == (uint32_t)kSEMC_NANDCM_CommandAddressRead) ||
1218                       (cmdMode == (uint32_t)kSEMC_NANDCM_CommandRead) || (cmdMode == (uint32_t)kSEMC_NANDCM_Read);
1219             writeCmd = (cmdMode == (uint32_t)kSEMC_NANDCM_CommandAddressWrite) ||
1220                        (cmdMode == (uint32_t)kSEMC_NANDCM_CommandWrite) || (cmdMode == (uint32_t)kSEMC_NANDCM_Write);
1221             break;
1222         case kSEMC_MemType_NOR:
1223         case kSEMC_MemType_8080:
1224             readCmd  = (cmdMode == (uint32_t)kSEMC_NORDBICM_Read);
1225             writeCmd = (cmdMode == (uint32_t)kSEMC_NORDBICM_Write);
1226             break;
1227         case kSEMC_MemType_SRAM:
1228             readCmd  = (cmdMode == (uint32_t)kSEMC_SRAMCM_ArrayRead) || (cmdMode == (uint32_t)kSEMC_SRAMCM_RegRead);
1229             writeCmd = (cmdMode == (uint32_t)kSEMC_SRAMCM_ArrayWrite) || (cmdMode == (uint32_t)kSEMC_SRAMCM_RegWrite);
1230             break;
1231         case kSEMC_MemType_SDRAM:
1232             readCmd  = (cmdMode == (uint32_t)kSEMC_SDRAMCM_Read);
1233             writeCmd = (cmdMode == (uint32_t)kSEMC_SDRAMCM_Write) || (cmdMode == (uint32_t)kSEMC_SDRAMCM_Modeset);
1234             break;
1235         default:
1236             assert(false);
1237             break;
1238     }
1239 
1240     if (writeCmd)
1241     {
1242         /* Set data. */
1243         base->IPTXDAT = write;
1244     }
1245 
1246     /* Set command code. */
1247     base->IPCMD = command | SEMC_IPCMD_KEY(SEMC_IPCOMMANDMAGICKEY);
1248     /* Wait for command done. */
1249     result = SEMC_IsIPCommandDone(base);
1250     if (result != kStatus_Success)
1251     {
1252         return result;
1253     }
1254 
1255     if (readCmd)
1256     {
1257         /* Get the read data */
1258         *read = base->IPRXDAT;
1259     }
1260 
1261     return kStatus_Success;
1262 }
1263 
1264 /*!
1265  * brief SEMC NAND device memory write through IP command.
1266  *
1267  * param base  SEMC peripheral base address.
1268  * param address  SEMC NAND device address.
1269  * param data  Data for write access.
1270  * param size_bytes   Data length.
1271  */
SEMC_IPCommandNandWrite(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1272 status_t SEMC_IPCommandNandWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1273 {
1274     assert(data != NULL);
1275 
1276     status_t result = kStatus_Success;
1277     uint16_t ipCmd;
1278     uint32_t tempData = 0;
1279 
1280     /* Write command built */
1281     ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Write);
1282     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1283     {
1284         /* Configure IP command data size. */
1285         (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1286         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, *(uint32_t *)(void *)data, NULL);
1287         if (result != kStatus_Success)
1288         {
1289             break;
1290         }
1291 
1292         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1293         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1294     }
1295 
1296     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1297     {
1298         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1299 
1300         while (size_bytes != 0x00U)
1301         {
1302             size_bytes--;
1303             tempData <<= SEMC_BYTE_NUMBIT;
1304             tempData |= data[size_bytes];
1305         }
1306 
1307         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, tempData, NULL);
1308     }
1309 
1310     return result;
1311 }
1312 
1313 /*!
1314  * brief SEMC NAND device memory read through IP command.
1315  *
1316  * param base  SEMC peripheral base address.
1317  * param address  SEMC NAND device address.
1318  * param data  Data pointer for data read out.
1319  * param size_bytes   Data length.
1320  */
SEMC_IPCommandNandRead(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1321 status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1322 {
1323     assert(data != NULL);
1324 
1325     status_t result = kStatus_Success;
1326     uint16_t ipCmd;
1327     uint32_t tempData = 0;
1328 
1329     /* Configure IP command data size. */
1330     (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1331     /* Read command built */
1332     ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Read);
1333 
1334     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1335     {
1336         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, (uint32_t *)(void *)data);
1337         if (result != kStatus_Success)
1338         {
1339             break;
1340         }
1341 
1342         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1343         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1344     }
1345 
1346     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1347     {
1348         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1349         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, &tempData);
1350 
1351         while (size_bytes != 0x00U)
1352         {
1353             size_bytes--;
1354             *(data + size_bytes) = (uint8_t)((tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU);
1355         }
1356     }
1357 
1358     return result;
1359 }
1360 
1361 /*!
1362  * brief SEMC NOR device memory read through IP command.
1363  *
1364  * param base  SEMC peripheral base address.
1365  * param address  SEMC NOR device address.
1366  * param data  Data pointer for data read out.
1367  * param size_bytes   Data length.
1368  */
SEMC_IPCommandNorRead(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1369 status_t SEMC_IPCommandNorRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1370 {
1371     assert(data != NULL);
1372 
1373     uint32_t tempData = 0;
1374     status_t result   = kStatus_Success;
1375     uint8_t dataSize  = (uint8_t)base->NORCR0 & SEMC_NORCR0_PS_MASK;
1376 
1377     /* Configure IP command data size. */
1378     (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1379 
1380     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1381     {
1382         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint32_t)kSEMC_NORDBICM_Read, 0,
1383                                     (uint32_t *)(void *)data);
1384         if (result != kStatus_Success)
1385         {
1386             break;
1387         }
1388 
1389         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1390         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1391     }
1392 
1393     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1394     {
1395         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1396         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Read, 0, &tempData);
1397         while (size_bytes != 0x00U)
1398         {
1399             size_bytes--;
1400             *(data + size_bytes) = (uint8_t)((tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU);
1401         }
1402     }
1403 
1404     (void)SEMC_ConfigureIPCommand(base, dataSize);
1405     return result;
1406 }
1407 
1408 /*!
1409  * brief SEMC NOR device memory write through IP command.
1410  *
1411  * param base  SEMC peripheral base address.
1412  * param address  SEMC NOR device address.
1413  * param data  Data for write access.
1414  * param size_bytes   Data length.
1415  */
SEMC_IPCommandNorWrite(SEMC_Type * base,uint32_t address,uint8_t * data,uint32_t size_bytes)1416 status_t SEMC_IPCommandNorWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1417 {
1418     assert(data != NULL);
1419 
1420     uint32_t tempData = 0;
1421     status_t result   = kStatus_Success;
1422     uint8_t dataSize  = (uint8_t)base->NORCR0 & SEMC_NORCR0_PS_MASK;
1423 
1424     /* Write command built */
1425     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1426     {
1427         /* Configure IP command data size. */
1428         (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1429         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Write,
1430                                     *(uint32_t *)(void *)data, NULL);
1431         if (result != kStatus_Success)
1432         {
1433             break;
1434         }
1435         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1436         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1437     }
1438 
1439     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1440     {
1441         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1442 
1443         while (size_bytes != 0x00U)
1444         {
1445             tempData |= ((uint32_t) * (data + size_bytes - 1U) << ((size_bytes - 1U) * SEMC_BYTE_NUMBIT));
1446             size_bytes--;
1447         }
1448 
1449         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Write, tempData, NULL);
1450     }
1451     (void)SEMC_ConfigureIPCommand(base, dataSize);
1452 
1453     return result;
1454 }
1455