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