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