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