Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:01

0001 /*
0002  * Copyright 2017-2022 NXP
0003  * All rights reserved.
0004  *
0005  * SPDX-License-Identifier: BSD-3-Clause
0006  */
0007 
0008 #include "fsl_semc.h"
0009 
0010 /*******************************************************************************
0011  * Definitions
0012  ******************************************************************************/
0013 
0014 /* Component ID definition, used by tools. */
0015 #ifndef FSL_COMPONENT_ID
0016 #define FSL_COMPONENT_ID "platform.drivers.semc"
0017 #endif
0018 
0019 /*! @brief Define macros for SEMC driver. */
0020 #define SEMC_IPCOMMANDDATASIZEBYTEMAX (4U)
0021 #define SEMC_IPCOMMANDMAGICKEY        (0xA55A)
0022 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
0023 #define SEMC_IOCR_PINMUXBITWIDTH (0x4UL)
0024 #else
0025 #define SEMC_IOCR_PINMUXBITWIDTH (0x3UL)
0026 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
0027 #define SEMC_IOCR_NAND_CE   (4UL)
0028 #define SEMC_IOCR_NOR_CE    (5UL)
0029 #define SEMC_IOCR_NOR_CE_A8 (2UL)
0030 #define SEMC_IOCR_PSRAM_CE  (6UL)
0031 #if defined(SEMC_IOCR_PINMUXBITWIDTH) && (SEMC_IOCR_PINMUXBITWIDTH == 0x4UL)
0032 #define SEMC_IOCR_PSRAM_CE_A8 (6UL)
0033 #else
0034 #define SEMC_IOCR_PSRAM_CE_A8 (3UL)
0035 #endif /* SEMC_IOCR_PINMUXBITWIDTH */
0036 #define SEMC_IOCR_DBI_CSX                     (7UL)
0037 #define SEMC_IOCR_DBI_CSX_A8                  (4UL)
0038 #define SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE (24U)
0039 #define SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX  (28U)
0040 #define SEMC_BMCR0_TYPICAL_WQOS               (5U)
0041 #define SEMC_BMCR0_TYPICAL_WAGE               (8U)
0042 #define SEMC_BMCR0_TYPICAL_WSH                (0x40U)
0043 #define SEMC_BMCR0_TYPICAL_WRWS               (0x10U)
0044 #define SEMC_BMCR1_TYPICAL_WQOS               (5U)
0045 #define SEMC_BMCR1_TYPICAL_WAGE               (8U)
0046 #define SEMC_BMCR1_TYPICAL_WPH                (0x60U)
0047 #define SEMC_BMCR1_TYPICAL_WBR                (0x40U)
0048 #define SEMC_BMCR1_TYPICAL_WRWS               (0x24U)
0049 #define SEMC_STARTADDRESS                     (0x80000000UL)
0050 #define SEMC_ENDADDRESS                       (0xDFFFFFFFUL)
0051 #define SEMC_BR_MEMSIZE_MIN                   (4U)
0052 #define SEMC_BR_MEMSIZE_OFFSET                (2U)
0053 #define SEMC_BR_MEMSIZE_MAX                   (4UL * 1024UL * 1024UL)
0054 #define SEMC_SDRAM_MODESETCAL_OFFSET          (4U)
0055 #define SEMC_BR_REG_NUM                       (9U)
0056 #define SEMC_BYTE_NUMBIT                      (8U)
0057 /*******************************************************************************
0058  * Prototypes
0059  ******************************************************************************/
0060 /*!
0061  * @brief Get instance number for SEMC module.
0062  *
0063  * @param base SEMC peripheral base address
0064  */
0065 static uint32_t SEMC_GetInstance(SEMC_Type *base);
0066 
0067 /*!
0068  * @brief Covert the input memory size to internal register set value.
0069  *
0070  * @param size_kbytes SEMC memory size in unit of kbytes.
0071  * @param sizeConverted SEMC converted memory size to 0 ~ 0x1F.
0072  * @return Execution status.
0073  */
0074 static status_t SEMC_CovertMemorySize(uint32_t size_kbytes, uint8_t *sizeConverted);
0075 
0076 /*!
0077  * @brief Covert the external timing nanosecond to internal clock cycle.
0078  *
0079  * @param time_ns   SEMC external time interval in unit of nanosecond.
0080  * @param clkSrc_Hz SEMC clock source frequency.
0081  * @return The changed internal clock cycle.
0082  */
0083 static uint8_t SEMC_ConvertTiming(uint32_t time_ns, uint32_t clkSrc_Hz);
0084 
0085 /*!
0086  * @brief Configure IP command.
0087  *
0088  * @param base SEMC peripheral base address.
0089  * @param size_bytes SEMC IP command data size.
0090  * @return Execution status.
0091  */
0092 static status_t SEMC_ConfigureIPCommand(SEMC_Type *base, uint8_t size_bytes);
0093 
0094 /*!
0095  * @brief Check if the IP command has finished.
0096  *
0097  * @param base SEMC peripheral base address.
0098  * @return Execution status.
0099  */
0100 static status_t SEMC_IsIPCommandDone(SEMC_Type *base);
0101 
0102 /*******************************************************************************
0103  * Variables
0104  ******************************************************************************/
0105 
0106 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0107 /*! @brief Pointers to SEMC clocks for each instance. */
0108 static const clock_ip_name_t s_semcClock[FSL_FEATURE_SOC_SEMC_COUNT] = SEMC_CLOCKS;
0109 #if (defined(SEMC_EXSC_CLOCKS))
0110 static const clock_ip_name_t s_semcExtClock[FSL_FEATURE_SOC_SEMC_COUNT] = SEMC_EXSC_CLOCKS;
0111 #endif /* SEMC_EXSC_CLOCKS */
0112 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0113 
0114 /*! @brief Pointers to SEMC bases for each instance. */
0115 static SEMC_Type *const s_semcBases[] = SEMC_BASE_PTRS;
0116 /*******************************************************************************
0117  * Code
0118  ******************************************************************************/
0119 static uint32_t SEMC_GetInstance(SEMC_Type *base)
0120 {
0121     uint32_t instance;
0122 
0123     /* Find the instance index from base address mappings. */
0124     for (instance = 0; instance < ARRAY_SIZE(s_semcBases); instance++)
0125     {
0126         if (s_semcBases[instance] == base)
0127         {
0128             break;
0129         }
0130     }
0131 
0132     assert(instance < ARRAY_SIZE(s_semcBases));
0133 
0134     return instance;
0135 }
0136 
0137 static status_t SEMC_CovertMemorySize(uint32_t size_kbytes, uint8_t *sizeConverted)
0138 {
0139     assert(sizeConverted != NULL);
0140     uint32_t memsize;
0141     status_t status = kStatus_Success;
0142 
0143     if ((size_kbytes < SEMC_BR_MEMSIZE_MIN) || (size_kbytes > SEMC_BR_MEMSIZE_MAX))
0144     {
0145         status = kStatus_SEMC_InvalidMemorySize;
0146     }
0147     else
0148     {
0149         *sizeConverted = 0U;
0150         memsize        = size_kbytes / 8U;
0151         while (memsize != 0x00U)
0152         {
0153             memsize >>= 1U;
0154             (*sizeConverted)++;
0155         }
0156     }
0157 
0158     return status;
0159 }
0160 
0161 static uint8_t SEMC_ConvertTiming(uint32_t time_ns, uint32_t clkSrc_Hz)
0162 {
0163     assert(clkSrc_Hz != 0x00U);
0164 
0165     uint8_t clockCycles = 0;
0166     uint32_t tClk_ps;
0167 
0168     clkSrc_Hz /= 1000000U;
0169     /* Using ps for high resolution */
0170     tClk_ps = 1000000U / clkSrc_Hz;
0171 
0172     while (tClk_ps * clockCycles < time_ns * 1000U)
0173     {
0174         clockCycles++;
0175     }
0176 
0177     return (clockCycles == 0x00U) ? clockCycles : (clockCycles - 0x01U);
0178 }
0179 
0180 static status_t SEMC_ConfigureIPCommand(SEMC_Type *base, uint8_t size_bytes)
0181 {
0182     status_t status = kStatus_Success;
0183 
0184     if ((size_bytes > SEMC_IPCOMMANDDATASIZEBYTEMAX) || (size_bytes == 0x00U))
0185     {
0186         status = kStatus_SEMC_InvalidIpcmdDataSize;
0187     }
0188     else
0189     {
0190         /* Set data size. */
0191         /* Note: It is better to set data size as the device data port width when transferring
0192          *    device command data. But for device memory data transfer, it can be set freely.
0193          * Note: If the data size is greater than data port width, for example, datsz = 4, data port = 16bit,
0194          *    then the 4-byte data transfer will be split into two 2-byte transfers, the slave address
0195          *    will be switched automatically according to connected device type*/
0196         base->IPCR1 = SEMC_IPCR1_DATSZ(size_bytes);
0197         /* Clear data size. */
0198         base->IPCR2 = 0;
0199         /* Set data size. */
0200         if (size_bytes < 4U)
0201         {
0202             base->IPCR2 |= SEMC_IPCR2_BM3_MASK;
0203         }
0204         if (size_bytes < 3U)
0205         {
0206             base->IPCR2 |= SEMC_IPCR2_BM2_MASK;
0207         }
0208         if (size_bytes < 2U)
0209         {
0210             base->IPCR2 |= SEMC_IPCR2_BM1_MASK;
0211         }
0212     }
0213 
0214     return status;
0215 }
0216 
0217 static status_t SEMC_IsIPCommandDone(SEMC_Type *base)
0218 {
0219     status_t status = kStatus_Success;
0220 
0221     /* Poll status bit till command is done*/
0222     while ((base->INTR & (uint32_t)SEMC_INTR_IPCMDDONE_MASK) == 0x00U)
0223     {
0224     };
0225 
0226     /* Clear status bit */
0227     base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
0228 
0229     /* Check error status */
0230     if ((base->INTR & (uint32_t)SEMC_INTR_IPCMDERR_MASK) != 0x00U)
0231     {
0232         base->INTR |= SEMC_INTR_IPCMDERR_MASK;
0233         status = kStatus_SEMC_IpCommandExecutionError;
0234     }
0235 
0236     return status;
0237 }
0238 
0239 /*!
0240  * brief Gets the SEMC default basic configuration structure.
0241  *
0242  * The purpose of this API is to get the default SEMC
0243  * configure structure for SEMC_Init(). User may use the initialized
0244  * structure unchanged in SEMC_Init(), or modify some fields of the
0245  * structure before calling SEMC_Init().
0246  * Example:
0247    code
0248    semc_config_t config;
0249    SEMC_GetDefaultConfig(&config);
0250    endcode
0251  * param config The SEMC configuration structure pointer.
0252  */
0253 void SEMC_GetDefaultConfig(semc_config_t *config)
0254 {
0255     assert(config != NULL);
0256 
0257     /* Initializes the configure structure to zero. */
0258     (void)memset(config, 0, sizeof(*config));
0259 
0260     config->queueWeight.queueaEnable          = true;
0261     semc_queuea_weight_struct_t *queueaWeight = &(config->queueWeight.queueaWeight.queueaConfig);
0262     config->queueWeight.queuebEnable          = true;
0263     semc_queueb_weight_struct_t *queuebWeight = &(config->queueWeight.queuebWeight.queuebConfig);
0264 
0265     /* Get default settings. */
0266     config->dqsMode          = kSEMC_Loopbackinternal;
0267     config->cmdTimeoutCycles = 0xFF;
0268     config->busTimeoutCycles = 0x1F;
0269 
0270     queueaWeight->qos              = SEMC_BMCR0_TYPICAL_WQOS;
0271     queueaWeight->aging            = SEMC_BMCR0_TYPICAL_WAGE;
0272     queueaWeight->slaveHitSwith    = SEMC_BMCR0_TYPICAL_WSH;
0273     queueaWeight->slaveHitNoswitch = SEMC_BMCR0_TYPICAL_WRWS;
0274     queuebWeight->qos              = SEMC_BMCR1_TYPICAL_WQOS;
0275     queuebWeight->aging            = SEMC_BMCR1_TYPICAL_WAGE;
0276     queuebWeight->slaveHitSwith    = SEMC_BMCR1_TYPICAL_WRWS;
0277     queuebWeight->weightPagehit    = SEMC_BMCR1_TYPICAL_WPH;
0278     queuebWeight->bankRotation     = SEMC_BMCR1_TYPICAL_WBR;
0279 }
0280 
0281 /*!
0282  * brief Initializes SEMC.
0283  * This function ungates the SEMC clock and initializes SEMC.
0284  * This function must be called before calling any other SEMC driver functions.
0285  *
0286  * param base SEMC peripheral base address.
0287  * param configure The SEMC configuration structure pointer.
0288  */
0289 void SEMC_Init(SEMC_Type *base, semc_config_t *configure)
0290 {
0291     assert(configure != NULL);
0292 
0293     uint8_t index = 0;
0294 
0295 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0296     /* Un-gate sdram controller clock. */
0297     CLOCK_EnableClock(s_semcClock[SEMC_GetInstance(base)]);
0298 #if (defined(SEMC_EXSC_CLOCKS))
0299     CLOCK_EnableClock(s_semcExtClock[SEMC_GetInstance(base)]);
0300 #endif /* SEMC_EXSC_CLOCKS */
0301 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0302 
0303     /* Initialize all BR to zero due to the default base address set. */
0304     for (index = 0; index < SEMC_BR_REG_NUM; index++)
0305     {
0306         base->BR[index] = 0;
0307     }
0308 
0309     /* Software reset for SEMC internal logical . */
0310     base->MCR = SEMC_MCR_SWRST_MASK;
0311     while ((base->MCR & (uint32_t)SEMC_MCR_SWRST_MASK) != 0x00U)
0312     {
0313     }
0314 
0315     /* Configure, disable module first. */
0316     base->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_BTO(configure->busTimeoutCycles) |
0317                  SEMC_MCR_CTO(configure->cmdTimeoutCycles) | SEMC_MCR_DQSMD(configure->dqsMode);
0318 
0319     if (configure->queueWeight.queueaEnable == true)
0320     {
0321         /* Configure Queue A for AXI bus access to SDRAM, NAND, NOR, SRAM and DBI slaves.*/
0322         base->BMCR0 = (uint32_t)(configure->queueWeight.queueaWeight.queueaValue);
0323     }
0324     else
0325     {
0326         base->BMCR0 = 0x00U;
0327     }
0328 
0329     if (configure->queueWeight.queuebEnable == true)
0330     {
0331         /* Configure Queue B for AXI bus access to SDRAM slave. */
0332         base->BMCR1 = (uint32_t)(configure->queueWeight.queuebWeight.queuebValue);
0333     }
0334     else
0335     {
0336         base->BMCR1 = 0x00U;
0337     }
0338 
0339     /* Enable SEMC. */
0340     base->MCR &= ~SEMC_MCR_MDIS_MASK;
0341 }
0342 
0343 /*!
0344  * brief Deinitializes the SEMC module and gates the clock.
0345  * This function gates the SEMC clock. As a result, the SEMC
0346  * module doesn't work after calling this function.
0347  *
0348  * param base SEMC peripheral base address.
0349  */
0350 void SEMC_Deinit(SEMC_Type *base)
0351 {
0352     /* Disable module.  Check there is no pending command before disable module.  */
0353     while ((base->STS0 & (uint32_t)SEMC_STS0_IDLE_MASK) == 0x00U)
0354     {
0355         ;
0356     }
0357 
0358     base->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_SWRST_MASK;
0359 
0360 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0361     /* Disable SDRAM clock. */
0362     CLOCK_DisableClock(s_semcClock[SEMC_GetInstance(base)]);
0363 #if (defined(SEMC_EXSC_CLOCKS))
0364     CLOCK_DisableClock(s_semcExtClock[SEMC_GetInstance(base)]);
0365 #endif /* SEMC_EXSC_CLOCKS */
0366 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0367 }
0368 
0369 /*!
0370  * brief Configures SDRAM controller in SEMC.
0371  *
0372  * param base SEMC peripheral base address.
0373  * param cs The chip selection.
0374  * param config The sdram configuration.
0375  * param clkSrc_Hz The SEMC clock frequency.
0376  */
0377 status_t SEMC_ConfigureSDRAM(SEMC_Type *base, semc_sdram_cs_t cs, semc_sdram_config_t *config, uint32_t clkSrc_Hz)
0378 {
0379     assert(config != NULL);
0380     assert(clkSrc_Hz > 0x00U);
0381     assert(config->refreshBurstLen > 0x00U);
0382 
0383     uint8_t memsize;
0384     status_t result   = kStatus_Success;
0385     uint16_t prescale = (uint16_t)(config->tPrescalePeriod_Ns / 16U / (1000000000U / clkSrc_Hz));
0386     uint32_t refresh;
0387     uint32_t urgentRef;
0388     uint32_t idle;
0389     uint32_t mode;
0390     uint32_t timing;
0391 
0392     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
0393     {
0394         return kStatus_SEMC_InvalidBaseAddress;
0395     }
0396 
0397     if (config->csxPinMux == kSEMC_MUXA8)
0398     {
0399         return kStatus_SEMC_InvalidSwPinmuxSelection;
0400     }
0401 
0402     if (prescale > 256U)
0403     {
0404         return kStatus_SEMC_InvalidTimerSetting;
0405     }
0406 
0407     refresh   = config->refreshPeriod_nsPerRow / config->tPrescalePeriod_Ns;
0408     urgentRef = config->refreshUrgThreshold / config->tPrescalePeriod_Ns;
0409     idle      = config->tIdleTimeout_Ns / config->tPrescalePeriod_Ns;
0410 
0411     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->csxPinMux));
0412 
0413     /* Base control. */
0414     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
0415     if (result != kStatus_Success)
0416     {
0417         return result;
0418     }
0419 
0420     base->BR[cs] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
0421 
0422 #if defined(FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT) && (FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT)
0423     if (kSEMC_SdramColunm_8bit == config->columnAddrBitNum)
0424     {
0425         base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
0426                          SEMC_SDRAMCR0_COL8(true) | SEMC_SDRAMCR0_CL(config->casLatency);
0427     }
0428     else
0429 #endif /* FSL_FEATURE_SEMC_SDRAM_SUPPORT_COLUMN_ADDRESS_8BIT */
0430     {
0431         base->SDRAMCR0 = SEMC_SDRAMCR0_PS(config->portSize) | SEMC_SDRAMCR0_BL(config->burstLen) |
0432                          SEMC_SDRAMCR0_COL(config->columnAddrBitNum) | SEMC_SDRAMCR0_CL(config->casLatency);
0433     }
0434 
0435     /* IOMUX setting. */
0436     if (cs != kSEMC_SDRAM_CS0)
0437     {
0438         base->IOCR = iocReg | ((uint32_t)cs << (uint32_t)config->csxPinMux);
0439     }
0440 
0441     base->IOCR &= ~SEMC_IOCR_MUX_A8_MASK;
0442 
0443 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
0444     uint32_t tempDelayChain = base->DCCR;
0445 
0446     tempDelayChain &= ~(SEMC_DCCR_SDRAMVAL_MASK | SEMC_DCCR_SDRAMEN_MASK);
0447     /* Configure delay chain. */
0448     base->DCCR = tempDelayChain | SEMC_DCCR_SDRAMVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SDRAMEN_MASK;
0449 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
0450 
0451     timing = SEMC_SDRAMCR1_PRE2ACT(SEMC_ConvertTiming(config->tPrecharge2Act_Ns, clkSrc_Hz));
0452     timing |= SEMC_SDRAMCR1_ACT2RW(SEMC_ConvertTiming(config->tAct2ReadWrite_Ns, clkSrc_Hz));
0453     timing |= SEMC_SDRAMCR1_RFRC(SEMC_ConvertTiming(config->tRefreshRecovery_Ns, clkSrc_Hz));
0454     timing |= SEMC_SDRAMCR1_WRC(SEMC_ConvertTiming(config->tWriteRecovery_Ns, clkSrc_Hz));
0455     timing |= SEMC_SDRAMCR1_CKEOFF(SEMC_ConvertTiming(config->tCkeOff_Ns, clkSrc_Hz));
0456     timing |= SEMC_SDRAMCR1_ACT2PRE(SEMC_ConvertTiming(config->tAct2Prechage_Ns, clkSrc_Hz));
0457     /* SDRAMCR1 timing setting. */
0458     base->SDRAMCR1 = timing;
0459 
0460     timing = SEMC_SDRAMCR2_SRRC(SEMC_ConvertTiming(config->tSelfRefRecovery_Ns, clkSrc_Hz));
0461     timing |= SEMC_SDRAMCR2_REF2REF(SEMC_ConvertTiming(config->tRefresh2Refresh_Ns, clkSrc_Hz));
0462     timing |= SEMC_SDRAMCR2_ACT2ACT(SEMC_ConvertTiming(config->tAct2Act_Ns, clkSrc_Hz)) | SEMC_SDRAMCR2_ITO(idle);
0463     /* SDRAMCR2 timing setting. */
0464     base->SDRAMCR2 = timing;
0465 
0466     /* SDRAMCR3 timing setting. */
0467     base->SDRAMCR3 = SEMC_SDRAMCR3_REBL((uint32_t)config->refreshBurstLen - 1UL) |
0468                      /* N * 16 * 1s / clkSrc_Hz = config->tPrescalePeriod_Ns */
0469                      SEMC_SDRAMCR3_PRESCALE(prescale) | SEMC_SDRAMCR3_RT(refresh - 1UL) | SEMC_SDRAMCR3_UT(urgentRef);
0470 
0471     SEMC->IPCR1 = 0x2U;
0472     SEMC->IPCR2 = 0U;
0473 
0474     result =
0475         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_Prechargeall, 0, NULL);
0476     if (result != kStatus_Success)
0477     {
0478         return result;
0479     }
0480     result =
0481         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
0482     if (result != kStatus_Success)
0483     {
0484         return result;
0485     }
0486     result =
0487         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
0488     if (result != kStatus_Success)
0489     {
0490         return result;
0491     }
0492     /* Mode setting value. */
0493     mode = (uint32_t)config->burstLen | (((uint32_t)config->casLatency) << SEMC_SDRAM_MODESETCAL_OFFSET);
0494     result =
0495         SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, (uint32_t)kSEMC_SDRAMCM_Modeset, mode, NULL);
0496     if (result != kStatus_Success)
0497     {
0498         return result;
0499     }
0500     /* Enables refresh */
0501     base->SDRAMCR3 |= SEMC_SDRAMCR3_REN_MASK;
0502 
0503     return kStatus_Success;
0504 }
0505 
0506 /*!
0507  * brief Configures NAND controller in SEMC.
0508  *
0509  * param base SEMC peripheral base address.
0510  * param config The nand configuration.
0511  * param clkSrc_Hz The SEMC clock frequency.
0512  */
0513 status_t SEMC_ConfigureNAND(SEMC_Type *base, semc_nand_config_t *config, uint32_t clkSrc_Hz)
0514 {
0515     assert(config != NULL);
0516     assert(config->timingConfig != NULL);
0517 
0518     uint8_t memsize;
0519     status_t result;
0520     uint32_t timing;
0521 
0522     if ((config->axiAddress < SEMC_STARTADDRESS) || (config->axiAddress > SEMC_ENDADDRESS))
0523     {
0524         return kStatus_SEMC_InvalidBaseAddress;
0525     }
0526 
0527     if (config->cePinMux == kSEMC_MUXRDY)
0528     {
0529         return kStatus_SEMC_InvalidSwPinmuxSelection;
0530     }
0531 
0532     /* Disable SEMC module during configuring control registers. */
0533     base->MCR |= SEMC_MCR_MDIS_MASK;
0534 
0535     uint32_t iocReg =
0536         base->IOCR & (~((SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux) | SEMC_IOCR_MUX_RDY_MASK));
0537 
0538     /* Base control. */
0539     if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
0540     {
0541         base->MCR |= SEMC_MCR_WPOL1_MASK;
0542     }
0543     else
0544     {
0545         base->MCR &= ~SEMC_MCR_WPOL1_MASK;
0546     }
0547     result = SEMC_CovertMemorySize(config->axiMemsize_kbytes, &memsize);
0548     if (result != kStatus_Success)
0549     {
0550         return result;
0551     }
0552     base->BR[4] = (config->axiAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
0553 
0554     result = SEMC_CovertMemorySize(config->ipgMemsize_kbytes, &memsize);
0555     if (result != kStatus_Success)
0556     {
0557         return result;
0558     }
0559     base->BR[8] = (config->ipgAddress & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
0560 
0561     /* IOMUX setting. */
0562     if ((uint32_t)config->cePinMux != 0x00U)
0563     {
0564         base->IOCR = iocReg | (SEMC_IOCR_NAND_CE << (uint32_t)config->cePinMux);
0565     }
0566     else
0567     {
0568         base->IOCR = iocReg | (1UL << (uint32_t)config->cePinMux);
0569     }
0570 
0571     base->NANDCR0 = SEMC_NANDCR0_PS(config->portSize) | SEMC_NANDCR0_BL(config->burstLen) |
0572                     SEMC_NANDCR0_EDO(config->edoModeEnabled) | SEMC_NANDCR0_COL(config->columnAddrBitNum);
0573 
0574     timing = SEMC_NANDCR1_CES(SEMC_ConvertTiming(config->timingConfig->tCeSetup_Ns, clkSrc_Hz));
0575     timing |= SEMC_NANDCR1_CEH(SEMC_ConvertTiming(config->timingConfig->tCeHold_Ns, clkSrc_Hz));
0576     timing |= SEMC_NANDCR1_WEL(SEMC_ConvertTiming(config->timingConfig->tWeLow_Ns, clkSrc_Hz));
0577     timing |= SEMC_NANDCR1_WEH(SEMC_ConvertTiming(config->timingConfig->tWeHigh_Ns, clkSrc_Hz));
0578     timing |= SEMC_NANDCR1_REL(SEMC_ConvertTiming(config->timingConfig->tReLow_Ns, clkSrc_Hz));
0579     timing |= SEMC_NANDCR1_REH(SEMC_ConvertTiming(config->timingConfig->tReHigh_Ns, clkSrc_Hz));
0580     timing |= SEMC_NANDCR1_TA(SEMC_ConvertTiming(config->timingConfig->tTurnAround_Ns, clkSrc_Hz));
0581     timing |= SEMC_NANDCR1_CEITV(SEMC_ConvertTiming(config->timingConfig->tCeInterval_Ns, clkSrc_Hz));
0582     /* NANDCR1 timing setting. */
0583     base->NANDCR1 = timing;
0584 
0585     timing = SEMC_NANDCR2_TWHR(SEMC_ConvertTiming(config->timingConfig->tWehigh2Relow_Ns, clkSrc_Hz));
0586     timing |= SEMC_NANDCR2_TRHW(SEMC_ConvertTiming(config->timingConfig->tRehigh2Welow_Ns, clkSrc_Hz));
0587     timing |= SEMC_NANDCR2_TADL(SEMC_ConvertTiming(config->timingConfig->tAle2WriteStart_Ns, clkSrc_Hz));
0588     timing |= SEMC_NANDCR2_TRR(SEMC_ConvertTiming(config->timingConfig->tReady2Relow_Ns, clkSrc_Hz));
0589     timing |= SEMC_NANDCR2_TWB(SEMC_ConvertTiming(config->timingConfig->tWehigh2Busy_Ns, clkSrc_Hz));
0590 
0591     /* NANDCR2 timing setting. */
0592     base->NANDCR2 = timing;
0593 
0594     /* NANDCR3 timing setting. */
0595     base->NANDCR3 = (uint32_t)config->arrayAddrOption;
0596 
0597     /* Enables SEMC module after configuring control registers completely. */
0598     base->MCR &= ~SEMC_MCR_MDIS_MASK;
0599 
0600     return kStatus_Success;
0601 }
0602 
0603 /*!
0604  * brief Configures NOR controller in SEMC.
0605  *
0606  * param base SEMC peripheral base address.
0607  * param config The nor configuration.
0608  * param clkSrc_Hz The SEMC clock frequency.
0609  */
0610 status_t SEMC_ConfigureNOR(SEMC_Type *base, semc_nor_config_t *config, uint32_t clkSrc_Hz)
0611 {
0612     assert(config != NULL);
0613 
0614     uint8_t memsize;
0615     status_t result;
0616     uint32_t timing;
0617 
0618     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
0619     {
0620         return kStatus_SEMC_InvalidBaseAddress;
0621     }
0622 
0623     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux));
0624     uint32_t muxCe  = (config->cePinMux == kSEMC_MUXRDY) ?
0625                          (SEMC_IOCR_NOR_CE - 1U) :
0626                          ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_NOR_CE_A8 : SEMC_IOCR_NOR_CE);
0627 
0628     /* IOMUX setting. */
0629     base->IOCR = iocReg | (muxCe << (uint32_t)config->cePinMux);
0630     /* Address bit setting. */
0631     if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
0632     {
0633         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 1U))
0634         {
0635             /* Address bit 24 (A24) */
0636             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX0_MASK;
0637             if (config->cePinMux == kSEMC_MUXCSX0)
0638             {
0639                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0640             }
0641         }
0642         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2U))
0643         {
0644             /* Address bit 25 (A25) */
0645             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX1_MASK;
0646             if (config->cePinMux == kSEMC_MUXCSX1)
0647             {
0648                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0649             }
0650         }
0651         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3U))
0652         {
0653             /* Address bit 26 (A26) */
0654             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX2_MASK;
0655             if (config->cePinMux == kSEMC_MUXCSX2)
0656             {
0657                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0658             }
0659         }
0660         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4U))
0661         {
0662             if (config->addr27 == kSEMC_NORA27_MUXCSX3)
0663             {
0664                 /* Address bit 27 (A27) */
0665                 base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX3_MASK;
0666             }
0667             else if (config->addr27 == kSEMC_NORA27_MUXRDY)
0668             {
0669                 base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
0670             }
0671             else
0672             {
0673                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0674             }
0675             if (config->cePinMux == kSEMC_MUXCSX3)
0676             {
0677                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0678             }
0679         }
0680         if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
0681         {
0682             return kStatus_SEMC_InvalidAddressPortWidth;
0683         }
0684     }
0685 
0686     /* Base control. */
0687     if (config->rdyactivePolarity == kSEMC_RdyActivehigh)
0688     {
0689         base->MCR |= SEMC_MCR_WPOL0_MASK;
0690     }
0691     else
0692     {
0693         base->MCR &= ~SEMC_MCR_WPOL0_MASK;
0694     }
0695     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
0696     if (result != kStatus_Success)
0697     {
0698         return result;
0699     }
0700     base->BR[5]  = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
0701     base->NORCR0 = SEMC_NORCR0_PS(config->portSize) | SEMC_NORCR0_BL(config->burstLen) |
0702                    SEMC_NORCR0_AM(config->addrMode) | SEMC_NORCR0_ADVP(config->advActivePolarity) |
0703                    SEMC_NORCR0_COL(config->columnAddrBitNum);
0704 
0705 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
0706     uint32_t tempDelayChain = base->DCCR;
0707 
0708     tempDelayChain &= ~(SEMC_DCCR_NORVAL_MASK | SEMC_DCCR_NOREN_MASK);
0709     /* Configure delay chain. */
0710     base->DCCR = tempDelayChain | SEMC_DCCR_NORVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_NOREN_MASK;
0711 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
0712 
0713     timing = SEMC_NORCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
0714     timing |= SEMC_NORCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
0715     timing |= SEMC_NORCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
0716     timing |= SEMC_NORCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
0717     timing |= SEMC_NORCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
0718     timing |= SEMC_NORCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
0719     timing |= SEMC_NORCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
0720     timing |= SEMC_NORCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
0721 
0722     /* NORCR1 timing setting. */
0723     base->NORCR1 = timing;
0724 
0725     timing = SEMC_NORCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
0726 #if defined(FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME)
0727     timing |= SEMC_NORCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
0728 #endif /* FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME */
0729 #if defined(FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME)
0730     timing |= SEMC_NORCR2_WDH(SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz));
0731 #endif /* FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME */
0732     timing |= SEMC_NORCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
0733     timing |= SEMC_NORCR2_AWDH((uint32_t)SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz) + 0x01UL);
0734 #if defined(FSL_FEATURE_SEMC_HAS_NOR_LC_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_LC_TIME)
0735     timing |= SEMC_NORCR2_LC(config->latencyCount);
0736 #endif
0737 #if defined(FSL_FEATURE_SEMC_HAS_NOR_RD_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_RD_TIME)
0738     timing |= SEMC_NORCR2_RD((uint32_t)config->readCycle - 0x01UL);
0739 #endif
0740 
0741     /* NORCR2 timing setting. */
0742     base->NORCR2 = timing;
0743 
0744     return SEMC_ConfigureIPCommand(base, ((uint8_t)config->portSize + 1U));
0745 }
0746 
0747 /*!
0748  * brief Configures SRAM controller in SEMC, which can be used only for specific chip selection CS0.
0749  *
0750  * param base SEMC peripheral base address.
0751  * param config The sram configuration.
0752  * param clkSrc_Hz The SEMC clock frequency.
0753  */
0754 status_t SEMC_ConfigureSRAM(SEMC_Type *base, semc_sram_config_t *config, uint32_t clkSrc_Hz)
0755 {
0756     return SEMC_ConfigureSRAMWithChipSelection(base, kSEMC_SRAM_CS0, config, clkSrc_Hz);
0757 }
0758 
0759 /*!
0760  * brief Configures SRAM controller in SEMC, which can be used up to four chip selections CS0/CS1/CS2/CS3..
0761  *
0762  * param base SEMC peripheral base address.
0763  * param cs The chip selection.
0764  * param config The sram configuration.
0765  * param clkSrc_Hz The SEMC clock frequency.
0766  */
0767 status_t SEMC_ConfigureSRAMWithChipSelection(SEMC_Type *base,
0768                                              semc_sram_cs_t cs,
0769                                              semc_sram_config_t *config,
0770                                              uint32_t clkSrc_Hz)
0771 {
0772     assert(config != NULL);
0773 
0774     uint32_t tempBRVal;
0775     uint32_t timing;
0776     uint8_t memsize;
0777     status_t result = kStatus_Success;
0778 
0779     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
0780     {
0781         return kStatus_SEMC_InvalidBaseAddress;
0782     }
0783 
0784     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->cePinMux));
0785 
0786     uint32_t muxCe = (config->cePinMux == kSEMC_MUXRDY) ?
0787                          (SEMC_IOCR_PSRAM_CE - 1U) :
0788                          ((config->cePinMux == kSEMC_MUXA8) ? SEMC_IOCR_PSRAM_CE_A8 : SEMC_IOCR_PSRAM_CE);
0789 
0790     /* IOMUX setting. */
0791     base->IOCR = iocReg | (muxCe << (uint32_t)config->cePinMux);
0792     /* Address bit setting. */
0793     if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE)
0794     {
0795         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 1U))
0796         {
0797             /* Address bit 24 (A24) */
0798             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX0_MASK;
0799             if (config->cePinMux == kSEMC_MUXCSX0)
0800             {
0801                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0802             }
0803         }
0804         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 2U))
0805         {
0806             /* Address bit 25 (A25) */
0807             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX1_MASK;
0808             if (config->cePinMux == kSEMC_MUXCSX1)
0809             {
0810                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0811             }
0812         }
0813         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 3U))
0814         {
0815             /* Address bit 26 (A26) */
0816             base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX2_MASK;
0817             if (config->cePinMux == kSEMC_MUXCSX2)
0818             {
0819                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0820             }
0821         }
0822         if (config->addrPortWidth >= (SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHBASE + 4U))
0823         {
0824             if (config->addr27 == kSEMC_NORA27_MUXCSX3)
0825             {
0826                 /* Address bit 27 (A27) */
0827                 base->IOCR &= ~(uint32_t)SEMC_IOCR_MUX_CSX3_MASK;
0828             }
0829             else if (config->addr27 == kSEMC_NORA27_MUXRDY)
0830             {
0831                 base->IOCR |= SEMC_IOCR_MUX_RDY_MASK;
0832             }
0833             else
0834             {
0835                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0836             }
0837 
0838             if (config->cePinMux == kSEMC_MUXCSX3)
0839             {
0840                 return kStatus_SEMC_InvalidSwPinmuxSelection;
0841             }
0842         }
0843         if (config->addrPortWidth > SEMC_NORFLASH_SRAM_ADDR_PORTWIDTHMAX)
0844         {
0845             return kStatus_SEMC_InvalidAddressPortWidth;
0846         }
0847     }
0848     /* Base control. */
0849     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
0850     if (result != kStatus_Success)
0851     {
0852         return result;
0853     }
0854 
0855     tempBRVal = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
0856 
0857     uint32_t tempCtrlVal;
0858 
0859     switch (cs)
0860     {
0861         case kSEMC_SRAM_CS0:
0862             base->BR[6] = tempBRVal;
0863             break;
0864 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
0865         case kSEMC_SRAM_CS1:
0866             base->BR9 = tempBRVal;
0867             break;
0868         case kSEMC_SRAM_CS2:
0869             base->BR10 = tempBRVal;
0870             break;
0871         case kSEMC_SRAM_CS3:
0872             base->BR11 = tempBRVal;
0873             break;
0874 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
0875         default:
0876             assert(NULL);
0877             break;
0878     }
0879 
0880     /* PSRAM0 SRAMCRx timing setting. */
0881     if (kSEMC_SRAM_CS0 == cs)
0882     {
0883 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
0884         /* Ready/wait(WAITEN and WAITSP) feature is only for async mode. */
0885         if (kSEMC_AsyncMode == config->syncMode)
0886         {
0887             tempCtrlVal = SEMC_SRAMCR0_PS(config->portSize) |
0888 #if defined(SEMC_SRAMCR4_SYNCEN_MASK) && (SEMC_SRAMCR4_SYNCEN_MASK)
0889                           SEMC_SRAMCR4_SYNCEN(config->syncMode) |
0890 #endif /* SEMC_SRAMCR4_SYNCEN_MASK */
0891 #if defined(SEMC_SRAMCR0_WAITEN_MASK) && (SEMC_SRAMCR0_WAITEN_MASK)
0892                           SEMC_SRAMCR0_WAITEN(config->waitEnable) |
0893 #endif /* SEMC_SRAMCR0_WAITEN_MASK */
0894 #if defined(SEMC_SRAMCR0_WAITSP_MASK) && (SEMC_SRAMCR0_WAITSP_MASK)
0895                           SEMC_SRAMCR0_WAITSP(config->waitSample) |
0896 #endif /* SEMC_SRAMCR0_WAITSP_MASK */
0897                           SEMC_SRAMCR0_BL(config->burstLen) | SEMC_SRAMCR0_AM(config->addrMode) |
0898                           SEMC_SRAMCR0_ADVP(config->advActivePolarity) |
0899 #if defined(SEMC_SRAMCR4_ADVH_MASK) && (SEMC_SRAMCR4_ADVH_MASK)
0900                           SEMC_SRAMCR4_ADVH(config->advLevelCtrl) |
0901 #endif /* SEMC_SRAMCR4_ADVH_MASK */
0902                           SEMC_SRAMCR0_COL_MASK;
0903         }
0904         else
0905 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
0906         {
0907             tempCtrlVal = SEMC_SRAMCR0_PS(config->portSize) |
0908 #if defined(SEMC_SRAMCR4_SYNCEN_MASK) && (SEMC_SRAMCR4_SYNCEN_MASK)
0909                           SEMC_SRAMCR4_SYNCEN(config->syncMode) |
0910 #endif /* SEMC_SRAMCR4_SYNCEN_MASK */
0911                           SEMC_SRAMCR0_BL(config->burstLen) | SEMC_SRAMCR0_AM(config->addrMode) |
0912                           SEMC_SRAMCR0_ADVP(config->advActivePolarity) |
0913 #if defined(SEMC_SRAMCR4_ADVH_MASK) && (SEMC_SRAMCR4_ADVH_MASK)
0914                           SEMC_SRAMCR4_ADVH(config->advLevelCtrl) |
0915 #endif /* SEMC_SRAMCR4_ADVH_MASK */
0916                           SEMC_SRAMCR0_COL_MASK;
0917         }
0918 
0919         base->SRAMCR0 = tempCtrlVal;
0920     }
0921 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
0922     /* PSRAM1~PSRAM3 SRAMCRx timing setting. */
0923     else
0924     {
0925         /* Ready/wait(WAITEN and WAITSP) feature is only for async mode. */
0926         if (kSEMC_AsyncMode == config->syncMode)
0927         {
0928             tempCtrlVal = SEMC_SRAMCR4_PS(config->portSize) | SEMC_SRAMCR4_SYNCEN(config->syncMode) |
0929                           SEMC_SRAMCR4_WAITEN(config->waitEnable) | SEMC_SRAMCR4_WAITSP(config->waitSample) |
0930                           SEMC_SRAMCR4_BL(config->burstLen) | SEMC_SRAMCR4_AM(config->addrMode) |
0931                           SEMC_SRAMCR4_ADVP(config->advActivePolarity) | SEMC_SRAMCR4_ADVH(config->advLevelCtrl) |
0932                           SEMC_SRAMCR4_COL_MASK;
0933         }
0934         else
0935         {
0936             tempCtrlVal = SEMC_SRAMCR4_PS(config->portSize) | SEMC_SRAMCR4_SYNCEN(config->syncMode) |
0937                           SEMC_SRAMCR4_BL(config->burstLen) | SEMC_SRAMCR4_AM(config->addrMode) |
0938                           SEMC_SRAMCR4_ADVP(config->advActivePolarity) | SEMC_SRAMCR4_ADVH(config->advLevelCtrl) |
0939                           SEMC_SRAMCR4_COL_MASK;
0940         }
0941 
0942         base->SRAMCR4 = tempCtrlVal;
0943     }
0944 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
0945 
0946 #if defined(FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL) && (FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL)
0947     uint32_t tempDelayChain = base->DCCR;
0948 
0949     /* Configure delay chain. */
0950     switch (cs)
0951     {
0952         case kSEMC_SRAM_CS0:
0953             tempDelayChain &= ~(SEMC_DCCR_SRAM0VAL_MASK | SEMC_DCCR_SRAM0EN_MASK);
0954             base->DCCR =
0955                 tempDelayChain | SEMC_DCCR_SRAM0VAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SRAM0EN_MASK;
0956             break;
0957 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
0958         case kSEMC_SRAM_CS1:
0959             SUPPRESS_FALL_THROUGH_WARNING();
0960         case kSEMC_SRAM_CS2:
0961             SUPPRESS_FALL_THROUGH_WARNING();
0962         case kSEMC_SRAM_CS3:
0963             tempDelayChain &= ~(SEMC_DCCR_SRAMXVAL_MASK | SEMC_DCCR_SRAMXEN_MASK);
0964             base->DCCR =
0965                 tempDelayChain | SEMC_DCCR_SRAMXVAL((uint32_t)config->delayChain - 0x01U) | SEMC_DCCR_SRAMXEN_MASK;
0966             break;
0967 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
0968         default:
0969             assert(NULL);
0970             break;
0971     }
0972 #endif /* FSL_FEATURE_SEMC_HAS_DELAY_CHAIN_CONTROL */
0973 
0974     if (kSEMC_SRAM_CS0 == cs)
0975     {
0976         timing = SEMC_SRAMCR1_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
0977         timing |= SEMC_SRAMCR1_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
0978         timing |= SEMC_SRAMCR1_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
0979         timing |= SEMC_SRAMCR1_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
0980         timing |= SEMC_SRAMCR1_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
0981         timing |= SEMC_SRAMCR1_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
0982         timing |= SEMC_SRAMCR1_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
0983         timing |= SEMC_SRAMCR1_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
0984 
0985         /* SRAMCR1 timing setting. */
0986         base->SRAMCR1 = timing;
0987 
0988         timing = 0x00U;
0989 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME)
0990         timing |= SEMC_SRAMCR2_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
0991 #endif
0992 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME)
0993         timing |= SEMC_SRAMCR2_WDH((uint32_t)SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz) + 1UL);
0994 #endif
0995         timing |= SEMC_SRAMCR2_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
0996         timing |= SEMC_SRAMCR2_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz));
0997 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME)
0998         timing |= SEMC_SRAMCR2_LC(config->latencyCount);
0999 #endif
1000 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME)
1001         timing |= SEMC_SRAMCR2_RD((uint32_t)config->readCycle - 1UL);
1002 #endif
1003         timing |= SEMC_SRAMCR2_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
1004 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME)
1005         timing |= SEMC_SRAMCR2_RDH((uint32_t)SEMC_ConvertTiming(config->readHoldTime_Ns, clkSrc_Hz) + 0x01U);
1006 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME */
1007 
1008         /* SRAMCR2 timing setting. */
1009         base->SRAMCR2 = timing;
1010     }
1011 #if defined(FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT) && (FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT > 0x01U)
1012     else
1013     {
1014         timing = SEMC_SRAMCR5_CES(SEMC_ConvertTiming(config->tCeSetup_Ns, clkSrc_Hz));
1015         timing |= SEMC_SRAMCR5_CEH(SEMC_ConvertTiming(config->tCeHold_Ns, clkSrc_Hz));
1016         timing |= SEMC_SRAMCR5_AS(SEMC_ConvertTiming(config->tAddrSetup_Ns, clkSrc_Hz));
1017         timing |= SEMC_SRAMCR5_AH(SEMC_ConvertTiming(config->tAddrHold_Ns, clkSrc_Hz));
1018         timing |= SEMC_SRAMCR5_WEL(SEMC_ConvertTiming(config->tWeLow_Ns, clkSrc_Hz));
1019         timing |= SEMC_SRAMCR5_WEH(SEMC_ConvertTiming(config->tWeHigh_Ns, clkSrc_Hz));
1020         timing |= SEMC_SRAMCR5_REL(SEMC_ConvertTiming(config->tReLow_Ns, clkSrc_Hz));
1021         timing |= SEMC_SRAMCR5_REH(SEMC_ConvertTiming(config->tReHigh_Ns, clkSrc_Hz));
1022 
1023         /* SRAMCR5 timing setting. */
1024         base->SRAMCR5 = timing;
1025 
1026         timing = 0x00U;
1027 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDS_TIME)
1028         timing = SEMC_SRAMCR6_WDS(SEMC_ConvertTiming(config->tWriteSetup_Ns, clkSrc_Hz));
1029 #endif
1030 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_WDH_TIME)
1031         timing |= SEMC_SRAMCR6_WDH((uint32_t)SEMC_ConvertTiming(config->tWriteHold_Ns, clkSrc_Hz) + 1UL);
1032 #endif
1033         timing |= SEMC_SRAMCR6_TA(SEMC_ConvertTiming(config->tTurnAround_Ns, clkSrc_Hz));
1034         timing |= SEMC_SRAMCR6_AWDH(SEMC_ConvertTiming(config->tAddr2WriteHold_Ns, clkSrc_Hz));
1035 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_LC_TIME)
1036         timing |= SEMC_SRAMCR6_LC(config->latencyCount);
1037 #endif
1038 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RD_TIME)
1039         timing |= SEMC_SRAMCR6_RD((uint32_t)config->readCycle - 1UL);
1040 #endif
1041         timing |= SEMC_SRAMCR6_CEITV(SEMC_ConvertTiming(config->tCeInterval_Ns, clkSrc_Hz));
1042 #if defined(FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME) && (FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME)
1043         timing |= SEMC_SRAMCR6_RDH((uint32_t)SEMC_ConvertTiming(config->readHoldTime_Ns, clkSrc_Hz) + 0x01U);
1044 #endif /* FSL_FEATURE_SEMC_HAS_SRAM_RDH_TIME */
1045 
1046         /* SRAMCR6 timing setting. */
1047         base->SRAMCR6 = timing;
1048     }
1049 #endif /* FSL_FEATURE_SEMC_SUPPORT_SRAM_COUNT */
1050 
1051     return result;
1052 }
1053 
1054 /*!
1055  * brief Configures DBI controller in SEMC.
1056  *
1057  * param base SEMC peripheral base address.
1058  * param config The dbi configuration.
1059  * param clkSrc_Hz The SEMC clock frequency.
1060  */
1061 status_t SEMC_ConfigureDBI(SEMC_Type *base, semc_dbi_config_t *config, uint32_t clkSrc_Hz)
1062 {
1063     assert(config != NULL);
1064 
1065     uint8_t memsize;
1066     status_t result;
1067     uint32_t timing;
1068 
1069     if ((config->address < SEMC_STARTADDRESS) || (config->address > SEMC_ENDADDRESS))
1070     {
1071         return kStatus_SEMC_InvalidBaseAddress;
1072     }
1073 
1074     uint32_t iocReg = base->IOCR & (~(SEMC_IOCR_PINMUXBITWIDTH << (uint32_t)config->csxPinMux));
1075     uint32_t muxCsx = (config->csxPinMux == kSEMC_MUXRDY) ?
1076                           (SEMC_IOCR_DBI_CSX - 1U) :
1077                           ((config->csxPinMux == kSEMC_MUXA8) ? SEMC_IOCR_DBI_CSX_A8 : SEMC_IOCR_DBI_CSX);
1078 
1079     /* IOMUX setting. */
1080     base->IOCR = iocReg | (muxCsx << (uint32_t)config->csxPinMux);
1081     /* Base control. */
1082     result = SEMC_CovertMemorySize(config->memsize_kbytes, &memsize);
1083     if (result != kStatus_Success)
1084     {
1085         return result;
1086     }
1087     base->BR[7] = (config->address & SEMC_BR_BA_MASK) | SEMC_BR_MS(memsize) | SEMC_BR_VLD_MASK;
1088 
1089     /* DBICR0 timing setting. */
1090     base->DBICR0 =
1091         SEMC_DBICR0_PS(config->portSize) | SEMC_DBICR0_BL(config->burstLen) | SEMC_DBICR0_COL(config->columnAddrBitNum);
1092 
1093     timing = SEMC_DBICR1_CES(SEMC_ConvertTiming(config->tCsxSetup_Ns, clkSrc_Hz));
1094     timing |= SEMC_DBICR1_CEH(SEMC_ConvertTiming(config->tCsxHold_Ns, clkSrc_Hz));
1095     timing |= SEMC_DBICR1_WEL(SEMC_ConvertTiming(config->tWexLow_Ns, clkSrc_Hz));
1096     timing |= SEMC_DBICR1_WEH(SEMC_ConvertTiming(config->tWexHigh_Ns, clkSrc_Hz));
1097     timing |= SEMC_DBICR1_REL(SEMC_ConvertTiming(config->tRdxLow_Ns, clkSrc_Hz));
1098     timing |= SEMC_DBICR1_REH(SEMC_ConvertTiming(config->tRdxHigh_Ns, clkSrc_Hz));
1099 #if defined(SEMC_DBICR1_CEITV_MASK)
1100     timing |= SEMC_DBICR1_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
1101 #endif /* SEMC_DBICR1_CEITV_MASK */
1102 
1103     /* DBICR1 timing setting. */
1104     base->DBICR1 = timing;
1105 
1106 #if defined(SEMC_DBICR2_CEITV_MASK)
1107     timing = SEMC_DBICR2_CEITV(SEMC_ConvertTiming(config->tCsxInterval_Ns, clkSrc_Hz));
1108 
1109     /* DBICR2 timing setting. */
1110     base->DBICR2 = timing;
1111 #endif /* SEMC_DBICR2_CEITV_MASK */
1112 
1113     return SEMC_ConfigureIPCommand(base, ((uint8_t)config->portSize + 1U));
1114 }
1115 
1116 /*!
1117  * brief SEMC IP command access.
1118  *
1119  * param base  SEMC peripheral base address.
1120  * param memType  SEMC memory type. refer to "semc_mem_type_t"
1121  * param address  SEMC device address.
1122  * param command  SEMC IP command.
1123  * For NAND device, we should use the SEMC_BuildNandIPCommand to get the right nand command.
1124  * For NOR/DBI device, take refer to "semc_ipcmd_nor_dbi_t".
1125  * For SRAM device, take refer to "semc_ipcmd_sram_t".
1126  * For SDRAM device, take refer to "semc_ipcmd_sdram_t".
1127  * param write  Data for write access.
1128  * param read   Data pointer for read data out.
1129  */
1130 status_t SEMC_SendIPCommand(
1131     SEMC_Type *base, semc_mem_type_t memType, uint32_t address, uint32_t command, uint32_t write, uint32_t *read)
1132 {
1133     uint32_t cmdMode;
1134     bool readCmd  = false;
1135     bool writeCmd = false;
1136     status_t result;
1137 
1138     /* Clear status bit */
1139     base->INTR |= SEMC_INTR_IPCMDDONE_MASK;
1140     /* Set address. */
1141     base->IPCR0 = address;
1142 
1143     /* Check command mode. */
1144     cmdMode = (uint32_t)command & 0x0FU;
1145     switch (memType)
1146     {
1147         case kSEMC_MemType_NAND:
1148             readCmd = (cmdMode == (uint32_t)kSEMC_NANDCM_CommandAddressRead) ||
1149                       (cmdMode == (uint32_t)kSEMC_NANDCM_CommandRead) || (cmdMode == (uint32_t)kSEMC_NANDCM_Read);
1150             writeCmd = (cmdMode == (uint32_t)kSEMC_NANDCM_CommandAddressWrite) ||
1151                        (cmdMode == (uint32_t)kSEMC_NANDCM_CommandWrite) || (cmdMode == (uint32_t)kSEMC_NANDCM_Write);
1152             break;
1153         case kSEMC_MemType_NOR:
1154         case kSEMC_MemType_8080:
1155             readCmd  = (cmdMode == (uint32_t)kSEMC_NORDBICM_Read);
1156             writeCmd = (cmdMode == (uint32_t)kSEMC_NORDBICM_Write);
1157             break;
1158         case kSEMC_MemType_SRAM:
1159             readCmd  = (cmdMode == (uint32_t)kSEMC_SRAMCM_ArrayRead) || (cmdMode == (uint32_t)kSEMC_SRAMCM_RegRead);
1160             writeCmd = (cmdMode == (uint32_t)kSEMC_SRAMCM_ArrayWrite) || (cmdMode == (uint32_t)kSEMC_SRAMCM_RegWrite);
1161             break;
1162         case kSEMC_MemType_SDRAM:
1163             readCmd  = (cmdMode == (uint32_t)kSEMC_SDRAMCM_Read);
1164             writeCmd = (cmdMode == (uint32_t)kSEMC_SDRAMCM_Write) || (cmdMode == (uint32_t)kSEMC_SDRAMCM_Modeset);
1165             break;
1166         default:
1167             assert(false);
1168             break;
1169     }
1170 
1171     if (writeCmd)
1172     {
1173         /* Set data. */
1174         base->IPTXDAT = write;
1175     }
1176 
1177     /* Set command code. */
1178     base->IPCMD = command | SEMC_IPCMD_KEY(SEMC_IPCOMMANDMAGICKEY);
1179     /* Wait for command done. */
1180     result = SEMC_IsIPCommandDone(base);
1181     if (result != kStatus_Success)
1182     {
1183         return result;
1184     }
1185 
1186     if (readCmd)
1187     {
1188         /* Get the read data */
1189         *read = base->IPRXDAT;
1190     }
1191 
1192     return kStatus_Success;
1193 }
1194 
1195 /*!
1196  * brief SEMC NAND device memory write through IP command.
1197  *
1198  * param base  SEMC peripheral base address.
1199  * param address  SEMC NAND device address.
1200  * param data  Data for write access.
1201  * param size_bytes   Data length.
1202  */
1203 status_t SEMC_IPCommandNandWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1204 {
1205     assert(data != NULL);
1206 
1207     status_t result = kStatus_Success;
1208     uint16_t ipCmd;
1209     uint32_t tempData = 0;
1210 
1211     /* Write command built */
1212     ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Write);
1213     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1214     {
1215         /* Configure IP command data size. */
1216         (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1217         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, *(uint32_t *)(void *)data, NULL);
1218         if (result != kStatus_Success)
1219         {
1220             break;
1221         }
1222 
1223         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1224         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1225     }
1226 
1227     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1228     {
1229         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1230 
1231         while (size_bytes != 0x00U)
1232         {
1233             size_bytes--;
1234             tempData <<= SEMC_BYTE_NUMBIT;
1235             tempData |= data[size_bytes];
1236         }
1237 
1238         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, tempData, NULL);
1239     }
1240 
1241     return result;
1242 }
1243 
1244 /*!
1245  * brief SEMC NAND device memory read through IP command.
1246  *
1247  * param base  SEMC peripheral base address.
1248  * param address  SEMC NAND device address.
1249  * param data  Data pointer for data read out.
1250  * param size_bytes   Data length.
1251  */
1252 status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1253 {
1254     assert(data != NULL);
1255 
1256     status_t result = kStatus_Success;
1257     uint16_t ipCmd;
1258     uint32_t tempData = 0;
1259 
1260     /* Configure IP command data size. */
1261     (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1262     /* Read command built */
1263     ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Read);
1264 
1265     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1266     {
1267         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, (uint32_t *)(void *)data);
1268         if (result != kStatus_Success)
1269         {
1270             break;
1271         }
1272 
1273         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1274         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1275     }
1276 
1277     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1278     {
1279         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1280         result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, &tempData);
1281 
1282         while (size_bytes != 0x00U)
1283         {
1284             size_bytes--;
1285             *(data + size_bytes) = (uint8_t)((tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU);
1286         }
1287     }
1288 
1289     return result;
1290 }
1291 
1292 /*!
1293  * brief SEMC NOR device memory read through IP command.
1294  *
1295  * param base  SEMC peripheral base address.
1296  * param address  SEMC NOR device address.
1297  * param data  Data pointer for data read out.
1298  * param size_bytes   Data length.
1299  */
1300 status_t SEMC_IPCommandNorRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1301 {
1302     assert(data != NULL);
1303 
1304     uint32_t tempData = 0;
1305     status_t result   = kStatus_Success;
1306     uint8_t dataSize  = (uint8_t)base->NORCR0 & SEMC_NORCR0_PS_MASK;
1307 
1308     /* Configure IP command data size. */
1309     (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1310 
1311     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1312     {
1313         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint32_t)kSEMC_NORDBICM_Read, 0,
1314                                     (uint32_t *)(void *)data);
1315         if (result != kStatus_Success)
1316         {
1317             break;
1318         }
1319 
1320         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1321         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1322     }
1323 
1324     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1325     {
1326         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1327         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Read, 0, &tempData);
1328         while (size_bytes != 0x00U)
1329         {
1330             size_bytes--;
1331             *(data + size_bytes) = (uint8_t)((tempData >> (SEMC_BYTE_NUMBIT * size_bytes)) & 0xFFU);
1332         }
1333     }
1334 
1335     (void)SEMC_ConfigureIPCommand(base, dataSize);
1336     return result;
1337 }
1338 
1339 /*!
1340  * brief SEMC NOR device memory write through IP command.
1341  *
1342  * param base  SEMC peripheral base address.
1343  * param address  SEMC NOR device address.
1344  * param data  Data for write access.
1345  * param size_bytes   Data length.
1346  */
1347 status_t SEMC_IPCommandNorWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
1348 {
1349     assert(data != NULL);
1350 
1351     uint32_t tempData = 0;
1352     status_t result   = kStatus_Success;
1353     uint8_t dataSize  = (uint8_t)base->NORCR0 & SEMC_NORCR0_PS_MASK;
1354 
1355     /* Write command built */
1356     while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
1357     {
1358         /* Configure IP command data size. */
1359         (void)SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
1360         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Write,
1361                                     *(uint32_t *)(void *)data, NULL);
1362         if (result != kStatus_Success)
1363         {
1364             break;
1365         }
1366         size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
1367         data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
1368     }
1369 
1370     if ((result == kStatus_Success) && (size_bytes != 0x00U))
1371     {
1372         (void)SEMC_ConfigureIPCommand(base, (uint8_t)size_bytes);
1373 
1374         while (size_bytes != 0x00U)
1375         {
1376             tempData |= ((uint32_t) * (data + size_bytes - 1U) << ((size_bytes - 1U) * SEMC_BYTE_NUMBIT));
1377             size_bytes--;
1378         }
1379 
1380         result = SEMC_SendIPCommand(base, kSEMC_MemType_NOR, address, (uint16_t)kSEMC_NORDBICM_Write, tempData, NULL);
1381     }
1382     (void)SEMC_ConfigureIPCommand(base, dataSize);
1383 
1384     return result;
1385 }