Newer
Older
mbed-os / targets / TARGET_Cypress / TARGET_PSOC6 / mtb-pdl-cat1 / drivers / include / cy_smif.h
@Dustin Crossman Dustin Crossman on 4 Jun 2021 79 KB Fix file modes.
/***************************************************************************//**
* \file cy_smif.h
* \version 2.20
*
* Provides an API declaration of the Cypress SMIF driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2021 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

/**
* \addtogroup group_smif
* \{
* The SPI-based communication interface to the external quad SPI (QSPI) 
* high-speed memory devices.
*
* The functions and other declarations used in this driver are in cy_smif.h and 
* cy_smif_memslot.h (if used). If you are using the ModusToolbox QSPI Configurator, 
* also include cycfg_qspi_memslot.h. 
*
* **SMIF: Serial Memory Interface**: This IP block implements an SPI-based
* communication interface for interfacing external memory devices to PSoC.
* The SMIF supports SPI, dual SPI (DSPI), quad SPI (QSPI), dual QSPI and octal SPI.
* 
* Features
*   - Standard SPI Master interface
*   - Supports single/dual/quad/octal SPI memory devices
*   - Supports dual quad SPI mode
*   - Design-time configurable support for multiple (up to 4) external serial
*   memory devices
*   - eXecute-In-Place (XIP) operation mode for both read and write accesses
*   with 4KB XIP read cache and on-the-fly encryption and decryption
*   - Supports external serial memory initialization via 
*   <a href="https://www.jedec.org/standards-documents/docs/jesd216b" target="_blank">
*   Serial Flash Discoverable Parameters (SFDP)</a> standard
*
* The primary usage model for the SMIF is that of an external memory interface.
* The SMIF is capable of interfacing with different types of memory, up to four
* types.
*
* \b SMIF driver is divided into three layers
*   - cy_smif.h API
*   - cy_smif_memslot.h API
*   - SMIF configuration structures
*
* The SMIF API is divided into the low-level functions and memory-slot functions. Use
* the low level API for the SMIF block initialization and for implementing a generic 
* SPI communication interface using the SMIF block.
*
* The memory slot API has functions to implement the basic memory operations such as 
* program, read, erase etc. These functions are implemented using the memory 
* parameters in the memory device configuration data structure. The 
* Cy_SMIF_MemInit() API initializes all the memory slots based on the settings
* in the array.
*
* \image html smif_3_0_p01_layers.png
*
* \note
* Above image is applicable only for SMIF v3 IP.
*
* \image html smif_1_0_p01_layers.png
*
* \note
* Above image is applicable only for SMIF v1 IP.
*
* SMIF Configuration Tool is a stand-alone application, which is a part of PDL 
* (Creator) and could be found in \<PDL_DIR\>/tools/\<OS_DIR\>/SMIFConfigurationTool
* (e.g. for PDL 3.0.0 and Windows OS PDL/3.0.0/tools/win/SMIFConfigurationTool). 
* 
* In ModusToolbox this tool is called QSPI Configurator. QSPI Configurator is a part of 
* PSoC 6 Software Library and can be found in \<ModusToolbox\>/tools/qspi-configurator-1.1
*  
* Tool generates *.c and *.h file with configuration structures. These configuration
* structures are input parameters for cy_smif_memslot API level
*
* \warning The driver is not responsible for external memory persistence. You cannot edit
* a buffer during the Read/Write operations. If there is a memory error, the SMIF ip block 
* can require a reset. To determine if this has happened, check the SMIF 
* busy status using Cy_SMIF_BusyCheck() and implement a timeout. Reset the SMIF 
* block by toggling CTL.ENABLED. Then reconfigure the SMIF block.
*
* For the Write operation, check that the SMIF driver has completed 
* transferring by calling Cy_SMIF_BusyCheck(). Also, check that the memory is 
* available with Cy_SMIF_MemIsBusy() before proceeding. 
*
* Simple example of external flash memory programming using low level SMIF API.
* All steps mentioned in example below are incorporated in
* \ref Cy_SMIF_MemCmdWriteEnable(), \ref Cy_SMIF_MemCmdProgram(), and
* \ref Cy_SMIF_MemIsBusy() of the
* \ref group_smif_mem_slot_functions "memory slot level API".
* \warning Example is simplified, without checks of error conditions.
* \note Flash memories need erase operation before programming. Refer to
* external memory datasheet for specific memory commands.
*
* \snippet smif/snippet/main.c SMIF_API: Write example
*
* For the Read operation, before accessing the read buffer, check that it is ready
* by calling Cy_SMIF_GetTxFifoStatus().
*
* Simple example of external flash memory read using low level SMIF API. All
* steps mentioned in example below are incorporated in
* \ref Cy_SMIF_MemCmdRead() of the
* \ref group_smif_mem_slot_functions "memory slot level API".
* \warning Example is simplified, without checks of error conditions.
* \note Refer to external memory datasheet for specific memory commands.
*
* \snippet smif/snippet/main.c SMIF_API: Read example
*
* The user should invalidate the cache by calling Cy_SMIF_CacheInvalidate() when 
* switching from the MMIO mode to XIP mode.
*
* \section group_smif_configuration Configuration Considerations
*
* PDL API has common parameters: base, context, config described in
* \ref page_getting_started_pdl_design "PDL Design" section.
*
* See the documentation for Cy_SMIF_Init() and Cy_SMIF_MemInit() for details
* on the required configuration structures and other initialization topics. 
*
* The normal (MMIO) mode is used for implementing a generic SPI/DSPI/QSPI/dual
* QSPI/octal SPI communication interface using the SMIF block. This
* interface can be used to implement special commands like Program/Erase of
* flash, memory device configuration, sleep mode entry for memory devices or
* other special commands specific to the memory device. The transfer width
* (SPI/DSPI/QSPI/octal SPI) of a transmission is a parameter set for each
* transmit/receive operation. So these can be changed at run time.
*
* In a typical memory interface with flash memory, the SMIF is used in the
* memory mode when reading from the memory and it switches to the normal mode when
* writing to flash memory.
* A typical memory device has multiple types of commands.
*
* The SMIF interface can be used to transmit different types of commands. Each
* command has different phases: command, dummy cycles, and transmit and receive
* data which require separate APIs.
*
* \subsection group_smif_init SMIF Initialization
* Create interrupt function and allocate memory for SMIF context
* structure
* \snippet smif/snippet/main.c SMIF_INIT: context and interrupt
* SMIF driver initialization for low level API usage (cysmif.h)
* \snippet smif/snippet/main.c SMIF_INIT: low level
* Additional steps to initialize SMIF driver for memory slot level API usage
* (cy_smif_memslot.h).
* \snippet smif/snippet/main.c SMIF_INIT: memslot level
* \note Example does not include initialization of all needed configuration
* structures (\ref cy_stc_smif_mem_device_cfg_t, \ref cy_stc_smif_mem_cmd_t).
* SMIF/QSPI Configuration tool generates all configuration structures needed for
* memslot level API usage.
*
* \subsection group_smif_xip_init SMIF XIP Initialization
* The eXecute In Place (XIP) is a mode of operation where read or write commands 
* to the memory device are directed through the SMIF without any use of API 
* function calls. In this mode the SMIF block maps the AHB bus-accesses to 
* external memory device addresses to make it behave similar to internal memory. 
* This allows the CPU to execute code directly from external memory. This mode 
* is not limited to code and is suitable also for data read and write accesses.
* The memory regions available for XIP addresses allocation are defined
* in a linker script file (.ld).
* \snippet smif/snippet/main.c SMIF_INIT: XIP
* \note Example of input parameters initialization is in \ref group_smif_init 
* section.
* \warning Functions that called from external memory should be declared with 
* long call attribute.  
*
* \subsection group_smif_usage_rules Rules for PSoC6 QSPI/SMIF Block Usage
* 1. All operations must use one or more dummy cycles between the PSoC 6 Command 
* and Address phase (when the PSoC 6 MCU drives the data pins) and the device's 
* Response phase (when the device drives the same data pins). Bus contention may 
* occur if no (zero) dummy cycles are used.
* 2. Any transfer that does not allow dummy cycles (such as Register Status 
* Reads) must use the single-bit transfer mode. In single-bit mode, the PSoC 6 
* drives the Command on the Data0 line and the device responds on the Data1 
* line, so bus contention cannot occur.
*
* \section group_smif_more_information More Information
*
* More information regarding the Serial Memory Interface can be found in the component 
* datasheet and the Technical Reference Manual (TRM).
* More information regarding the SMIF Configuration Tool are in SMIF
* Configuration Tool User Guide located in \<PDL_DIR\>/tools/\<OS_DIR\>/SMIFConfigurationTool/
* folder
*
* \section group_smif_changelog Changelog
* <table class="doxtable">
*   <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
*   <tr>
*     <td>2.20</td>
*     <td>Bug fixes in \ref Cy_SMIF_MemEraseSector for Hybrid memory configuration.
*         Updated \ref Cy_SMIF_MemIsReady to use \ref Cy_SysLib_Rtos_Delay and \ref Cy_SysLib_Rtos_DelayUs.</td>
*     <td>Code enhancement.</td>
*   </tr>
*   <tr>
*     <td>2.10</td>
*     <td>New silicon family support.</td>
*     <td>Added extended API for DDR support.</td>
*   </tr>
*   <tr>
*     <td rowspan="4">2.0</td>
*     <td>Reworked the \ref Cy_SMIF_MemRead and \ref Cy_SMIF_MemWrite functions to use polling instead of interrupts.</td>
*     <td>Extend the usability of these functions.</td>
*   </tr>
*   <tr>
*    <td>Reworked the length-parameter check in the \ref Cy_SMIF_MemEraseSector function.
*     The Erase operation is not performed and \ref CY_SMIF_SUCCESS is no longer returned when the sectors are not aligned.</td>
*     <td>Fix the user error-handling of the length parameter.</td>
*   </tr>
*   <tr>
*    <td>Fixed the address-parameter check in the \ref Cy_SMIF_MemLocateHybridRegion function.
*     \ref CY_SMIF_SUCCESS or \ref CY_SMIF_NOT_HYBRID_MEM is no longer returned when the address exceeds the memory size.</td>
*     <td>Address a defect.</td>
*   </tr>
*   <tr>
*     <td>Fixed MISRA 2012 violations.</td>
*     <td>MISRA 2012 compliance.</td>
*   </tr>
*   <tr>
*     <td>1.50.1</td>
*     <td>Minor documentation updates. </td>
*     <td>Documentation improvement. </td>
*   </tr>
*   <tr>
*     <td>1.50</td>
*     <td>Added a new function: \ref Cy_SMIF_MemLocateHybridRegion.\n
*     Added a new structure \ref cy_stc_smif_hybrid_region_info_t.\n
*     Updated the \ref Cy_SMIF_MemEraseSector and \ref Cy_SMIF_MemCmdSectorErase functions.\n
*     Updated the \ref Cy_SMIF_MemSfdpDetect function. \n
*     Updated the \ref cy_stc_smif_mem_device_cfg_t structure.</td>
*     <td>Support for memories with hybrid regions.</td>
*   </tr>
*   <tr>
*     <td rowspan="2">1.40.1</td>
*     <td>The \ref Cy_SMIF_MemInit is changed. </td>
*     <td>Corrected a false assertion during initialization in SFDP mode.</td>
*   </tr>
*   <tr>
*     <td>Minor documentation updates. </td>
*     <td></td>
*   </tr>
*   <tr>
*     <td rowspan="5">1.40</td>
*     <td>The following functions are renamed:\n
*        Cy_SMIF_GetTxfrStatus into Cy_SMIF_GetTransferStatus;\n
*        Cy_SMIF_Memslot_Init into Cy_SMIF_MemInit;\n
*        Cy_SMIF_Memslot_DeInit into Cy_SMIF_MemDeInit;\n
*        Cy_SMIF_Memslot_CmdWriteEnable into Cy_SMIF_MemCmdWriteEnable;\n
*        Cy_SMIF_Memslot_CmdWriteDisable into Cy_SMIF_MemCmdWriteDisable;\n
*        Cy_SMIF_Memslot_IsBusy into Cy_SMIF_MemIsBusy;\n
*        Cy_SMIF_Memslot_QuadEnable into Cy_SMIF_MemQuadEnable;\n
*        Cy_SMIF_Memslot_CmdReadSts into Cy_SMIF_MemCmdReadStatus;\n
*        Cy_SMIF_Memslot_CmdWriteSts into Cy_SMIF_MemCmdWriteStatus;\n
*        Cy_SMIF_Memslot_CmdChipErase into Cy_SMIF_MemCmdChipErase;\n
*        Cy_SMIF_Memslot_CmdSectorErase into Cy_SMIF_MemCmdSectorErase;\n
*        Cy_SMIF_Memslot_SfdpDetect into Cy_SMIF_MemSfdpDetect;\n
*        Cy_SMIF_Memslot_CmdProgram into Cy_SMIF_MemCmdProgram;\n
*        Cy_SMIF_Memslot_CmdRead into Cy_SMIF_MemCmdRead.\n
*          The following ENUMa are renamed:\n
*        CY_SMIF_SEND_CMPLT into CY_SMIF_SEND_COMPLETE;\n
*        CY_SMIF_REC_CMPLT into CY_SMIF_RX_COMPLETE;\n
*        CY_SMIF_REC_BUSY into CY_SMIF_RX_BUSY;\n
*        CY_SMIF_SEL_INV_INTERNAL_CLK into CY_SMIF_SEL_INVERTED_INTERNAL_CLK;\n
*        CY_SMIF_SEL_INV_FEEDBACK_CLK into CY_SMIF_SEL_INVERTED_FEEDBACK_CLK;\n
*        cy_en_smif_cache_en_t into cy_en_smif_cache_t.\n
*          The following MACROs are renamed:\n
*        CY_SMIF_FLAG_WR_EN into CY_SMIF_FLAG_WRITE_ENABLE;\n
*        CY_SMIF_FLAG_CRYPTO_EN into CY_SMIF_FLAG_CRYPTO_ENABLE;\n
*        CY_SMIF_SFDP_SING_BYTE_00 into CY_SMIF_SFDP_SIGNATURE_BYTE_00;\n
*        CY_SMIF_SFDP_SING_BYTE_01 into CY_SMIF_SFDP_SIGNATURE_BYTE_01;\n
*        CY_SMIF_SFDP_SING_BYTE_02 into CY_SMIF_SFDP_SIGNATURE_BYTE_02;\n
*        CY_SMIF_SFDP_SING_BYTE_03 into CY_SMIF_SFDP_SIGNATURE_BYTE_03;\n
*        CY_SMIF_WR_STS_REG1_CMD into CY_SMIF_WRITE_STATUS_REG1_CMD;\n
*        CY_SMIF_WR_DISABLE_CMD into CY_SMIF_WRITE_DISABLE_CMD;\n
*        CY_SMIF_RD_STS_REG1_CMD into CY_SMIF_READ_STATUS_REG1_CMD;\n
*        CY_SMIF_WR_ENABLE_CMD into CY_SMIF_WRITE_ENABLE_CMD;\n
*        CY_SMIF_RD_STS_REG2_T1_CMD into CY_SMIF_READ_STATUS_REG2_T1_CMD;\n          
*        CY_SMIF_WR_STS_REG2_CMD into CY_SMIF_WRITE_STATUS_REG2_CMD;\n
*        CY_SMIF_RD_STS_REG2_T2_CMD into CY_SMIF_READ_STATUS_REG2_T2_CMD;\n
*        CY_SMIF_QE_BIT_STS_REG2_T1 into CY_SMIF_QE_BIT_STATUS_REG2_T1;\n
*        CY_SMIF_STS_REG_BUSY_MASK into CY_SMIF_STATUS_REG_BUSY_MASK.\n
*      </td>
*      <td rowspan="2">Documentation improvement.</td>
*   </tr>
*   <tr>
*     <td>Updated the description of the Cy_SMIF_MemInit() function.
*         Updated the Cy_SMIF_Encrypt() function usage example.
*     </td>
*   </tr>
*   <tr>
*     <td>The type of arguments that are not modified by the functions are set to const.
*     </td>
*     <td>Usability improvement.
*     </td>
*   </tr>
*   <tr>
*     <td>The Cy_SMIF_MemSfdpDetect() function is updated to support new 
*         commands for 4 bytes addressing.
*     </td>
*     <td>Memory devices with new 4 byte addressing commands support.
*     </td>
*   </tr>
*   <tr>
*     <td>Added the blocking functions which take care of the 
*         busy-status check of the memory:
*         - \ref  Cy_SMIF_MemIsReady
*         - \ref  Cy_SMIF_MemIsQuadEnabled
*         - \ref  Cy_SMIF_MemEnableQuadMode
*         - \ref  Cy_SMIF_MemRead
*         - \ref  Cy_SMIF_MemWrite
*         - \ref  Cy_SMIF_MemEraseSector
*         - \ref  Cy_SMIF_MemEraseChip
*     </td>
*     <td>Added new high-level blocking functions.
*     </td>
*   </tr>
*   <tr>
*     <td rowspan="5">1.30</td>
*     <td>The CY_SMIF_CMD_FIFO_WR_RX_COUNT_Msk value is changed to 0x0000FFFFUL.</td>
*     <td rowspan="4">Driver maintenance.</td>
*   </tr>
*   <tr>
*     <td>Added the check of the size parameter in the Cy_SMIF_TransmitData() function.</td>
*   </tr>
*   <tr>
*     <td>Added conditional check for presence of the SMIF hardware IP.</td>
*   </tr>
*   <tr>
*     <td>Fixed the wrong erase command in the SFDP protocol for devices with Erase Type 3.</td>
*   </tr>
*   <tr>
*     <td>Updated the General Description section with minor changes.
*         Updated the ordering of the parameters descriptions for some functions.
*         Added the text saying that the Cy_SMIF_MemInit() function is applicable 
*      to use the external memory as memory-mapped to PSoC (XIP mode).
*         Added the snippet for the Cy_SMIF_Encrypt() function to show how to use this function.
*         Added below the picture in the Low-Level Functions section the sequence of PDL
*      functions required in a Read or Write transaction.
*         Added the text below the picture about the address.
*         Updated DUMMY COUNT in this picture.
*         Added checking of the size parameter in the Cy_SMIF_TransmitData() function.
*     </td>
*     <td>Documentation improvement.</td>
*   </tr>
*   <tr>
*     <td>1.20.1</td>
*     <td>Added upper limit to size parameter in several functions.</td>
*     <td>Documentation improvement.</td>
*   </tr>
*   <tr>
*     <td rowspan="3">1.20</td>
*     <td>Flattened the organization of the driver source code into the single 
*         source directory and the single include directory.
*     </td>
*     <td>Driver library directory-structure simplification.</td>
*   </tr>
*   <tr>
*     <td>Added a new return status and transfer width option for the case when the memory command is not supported.</td>
*     <td>Improved the memory command structure usability.</td>
*   </tr>
*   <tr>
*     <td>Added register access layer. Use register access macros instead
*         of direct register access using dereferenced pointers.</td>
*     <td>Makes register access device-independent, so that the PDL does 
*         not need to be recompiled for each supported part number.</td>
*   </tr>
*   <tr>
*     <td rowspan="2">1.11</td>
*     <td>Fixed internal function that writes to the SMIF FIFO</td>
*     <td>The write function stuck in the loop when write speed in external 
*         memory is significantly lower than PSoC CPU core speed and write 
*         transfer is not finished during the single function call.  
*     </td>
*   </tr>
*   <tr>
*     <td>Added optional mode part to the program command flow</td>
*     <td>Extend usability of program command</td>
*   </tr>
*   <tr>
*     <td>1.10.1</td>
*     <td>Added Low Power Callback section</td>
*     <td>Documentation update and clarification</td>
*   </tr>
*   <tr>
*     <td>1.10</td>
*     <td>Fix write to external memory from CM0+ core. Add checks of API input parameters. 
*         Minor documentation updates</td>
*     <td></td>
*   </tr>
*   <tr>
*     <td>1.0</td>
*     <td>Initial version</td>
*     <td></td>
*   </tr>
* </table>
*
* \defgroup group_smif_macros Macros
* \{
* \defgroup group_smif_macros_status Status Macros
* \defgroup group_smif_macros_cmd Command Macros
* \defgroup group_smif_macros_flags External Memory Flags
* \defgroup group_smif_macros_sfdp SFDP Macros
* \defgroup group_smif_macros_isr Interrupt Macros
* \}
* \defgroup group_smif_functions Functions
* \{
* \defgroup group_smif_low_level_functions Low Level Functions
* \{
* The SMIF interface can be used to transmit different types of commands.
* Each command has different phases: command, dummy cycles, and transmit and receive data which require separate APIs.
*
* During the time that Slave Select line is active (LOW) the clock signal (CLK) is toggled while command information is first
* transferred on the data (IO) signals from the master to the slave. The clock continues to toggle during any period required for
* information access in the slave. The clock continues to toggle during the transfer of read data from the slave to the master
* or write data from the master to the slave. When the master has transferred the desired amount of data, the master drives the
* Slave Select line inactive (HIGH).
* Basic flow for read/write commands using \ref Cy_SMIF_TransmitCommand, \ref Cy_SMIF_TransmitData, \ref Cy_SMIF_ReceiveData and
* \ref Cy_SMIF_SendDummyCycles with a Quad SPI interface.
*
*  \image html smif_1_0_p03_rw_cmd.png
*
* The sequence of the PDL functions required in a read or write transaction is:
* \ref Cy_SMIF_TransmitCommand() -> 
* \ref Cy_SMIF_SendDummyCycles() -> 
* \ref Cy_SMIF_ReceiveData() / \ref Cy_SMIF_TransmitData() -> 
* \ref Cy_SMIF_BusyCheck().
* The address is sent as part of the Cy_SMIF_TransmitCommand() function. 
* No separate function call is required. 
*
* \}
* \defgroup group_smif_mem_slot_functions Memory Slot Functions
* \defgroup group_smif_functions_syspm_callback  Low Power Callback
* \}
* \defgroup group_smif_data_structures Data Structures
* \{
* \defgroup group_smif_data_structures_memslot SMIF Memory Description Structures
* General hierarchy of memory structures are:
*
* \image html smif_3_0_p02_memslot_stc.png
*
* \note
* Above image is applicable only for SMIF v3 IP.
*
* \image html smif_1_0_p02_memslot_stc.png
*
* \note
* Above image is applicable only for SMIF v1 IP.
*
* Top structure is \ref cy_stc_smif_block_config_t, which could have links up to
* 4 \ref cy_stc_smif_mem_config_t which describes each connected to the SMIF
* external memory.
* \}
* \defgroup group_smif_enums Enumerated Types
*/

#if !defined (CY_SMIF_H)
#define CY_SMIF_H

#include "cy_device.h"

#if defined (CY_IP_MXSMIF)

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "cy_syslib.h"
#include "cy_syspm.h"

#if defined(__cplusplus)
extern "C" {
#endif

/***************************************
*            Constants
****************************************/

/**
* \addtogroup group_smif_macros
* \{
*/

/** The driver major version */
#define CY_SMIF_DRV_VERSION_MAJOR       2

/** The driver minor version */
#define CY_SMIF_DRV_VERSION_MINOR       20

/** One microsecond timeout for Cy_SMIF_TimeoutRun() */
#define CY_SMIF_WAIT_1_UNIT             (1U)

/** The SMIF driver ID, reported as part of an unsuccessful API return status
 * \ref cy_en_smif_status_t */
#define CY_SMIF_ID                      CY_PDL_DRV_ID(0x2CU)


/**
* \addtogroup group_smif_macros_isr
* \{
*/
#if (CY_IP_MXSMIF_VERSION>=3)
#define SMIF_INTR_RX_DATA_FIFO_UNDERFLOW_Msk SMIF_INTR_RX_DATA_MMIO_FIFO_UNDERFLOW_Msk
#define SMIF_TX_DATA_FIFO_CTL SMIF_TX_DATA_MMIO_FIFO_CTL
#define SMIF_RX_DATA_FIFO_CTL SMIF_RX_DATA_MMIO_FIFO_CTL
#define SMIF_TX_DATA_FIFO_WR4 SMIF_TX_DATA_MMIO_FIFO_WR4
#define SMIF_TX_DATA_FIFO_WR1 SMIF_TX_DATA_MMIO_FIFO_WR1
#define SMIF_TX_DATA_FIFO_WR2 SMIF_TX_DATA_MMIO_FIFO_WR2
#define SMIF_RX_DATA_FIFO_RD4 SMIF_RX_DATA_MMIO_FIFO_RD4
#define SMIF_RX_DATA_FIFO_RD1 SMIF_RX_DATA_MMIO_FIFO_RD1
#define SMIF_RX_DATA_FIFO_RD2 SMIF_RX_DATA_MMIO_FIFO_RD2
#define SMIF_CRYPTO_CMD_START_Msk SMIF_SMIF_CRYPTO_CRYPTO_CMD_START_Msk
#define SMIF_CRYPTO_CMD_START_Pos SMIF_SMIF_CRYPTO_CRYPTO_CMD_START_Pos
#endif /* CY_IP_MXSMIF_VERSION */

/** Enable XIP_ALIGNMENT_ERROR interrupt see TRM for details */
#define CY_SMIF_ALIGNMENT_ERROR                 (SMIF_INTR_XIP_ALIGNMENT_ERROR_Msk)
/** Enable RX_DATA_FIFO_UNDERFLOW interrupt see TRM for details */
#define CY_SMIF_RX_DATA_FIFO_UNDERFLOW          (SMIF_INTR_RX_DATA_FIFO_UNDERFLOW_Msk)
/** Enable TX_DATA_FIFO_OVERFLOW interrupt see TRM for details */
#define CY_SMIF_TX_DATA_FIFO_OVERFLOW           (SMIF_INTR_TX_DATA_FIFO_OVERFLOW_Msk)
/** Enable TX_CMD_FIFO_OVERFLOW interrupt see TRM for details */
#define CY_SMIF_TX_COMMAND_FIFO_OVERFLOW        (SMIF_INTR_TX_CMD_FIFO_OVERFLOW_Msk)
/** Enable TR_TX_REQ interrupt see TRM for details */
#define CY_SMIF_TX_DATA_FIFO_LEVEL_TRIGGER      (SMIF_INTR_TR_TX_REQ_Msk)
/** Enable TR_RX_REQ interrupt see TRM for details */
#define CY_SMIF_RX_DATA_FIFO_LEVEL_TRIGGER      (SMIF_INTR_TR_RX_REQ_Msk)

/** \} group_smif_macros_isr */

/** \cond INTERNAL */

#define CY_SMIF_CMD_FIFO_TX_MODE            (0UL)
#define CY_SMIF_CMD_FIFO_TX_COUNT_MODE      (1UL)
#define CY_SMIF_CMD_FIFO_RX_COUNT_MODE      (2UL)
#define CY_SMIF_CMD_FIFO_DUMMY_COUNT_MODE   (3UL)

#if (CY_IP_MXSMIF_VERSION>=3)
#define CY_SMIF_TX_CMD_FIFO_STATUS_RANGE    (8U)
#else
#define CY_SMIF_TX_CMD_FIFO_STATUS_RANGE    (4U)
#endif /* CY_IP_MXSMIF_VERSION */

#define CY_SMIF_TX_DATA_FIFO_STATUS_RANGE   (8U)
#define CY_SMIF_RX_DATA_FIFO_STATUS_RANGE   (8U)

#define CY_SMIF_ONE_BYTE                    (1U)
#define CY_SMIF_TWO_BYTES                   (2U)
#define CY_SMIF_THREE_BYTES                 (3U)
#define CY_SMIF_FOUR_BYTES                  (4U)
#define CY_SMIF_FIVE_BYTES                  (5U)
#define CY_SMIF_SIX_BYTES                   (6U)
#define CY_SMIF_SEVEN_BYTES                 (7U)
#define CY_SMIF_EIGHT_BYTES                 (8U)

#define CY_SMIF_CRYPTO_FIRST_WORD           (0U)
#define CY_SMIF_CRYPTO_SECOND_WORD          (4U)
#define CY_SMIF_CRYPTO_THIRD_WORD           (8U)
#define CY_SMIF_CRYPTO_FOURTH_WORD          (12U)

#define CY_SMIF_CRYPTO_START                (1UL)
#define CY_SMIF_CRYPTO_COMPLETED            (0UL)
#define CY_SMIF_CRYPTO_ADDR_MASK            (0xFFFFFFF0UL)
#define CY_SMIF_AES128_BYTES                (16U)

#define CY_SMIF_CTL_REG_DEFAULT             (0x00000300U) /* 3 - [13:12] CLOCK_IF_RX_SEL  */

#define CY_SMIF_SFDP_FAIL                   (0x08U)
#define CY_SMIF_SFDP_FAIL_SS0_POS           (0x00U)
#define CY_SMIF_SFDP_FAIL_SS1_POS           (0x01U)
#define CY_SMIF_SFDP_FAIL_SS2_POS           (0x02U)
#define CY_SMIF_SFDP_FAIL_SS3_POS           (0x03U)

#define CY_SMIF_MAX_DESELECT_DELAY          (7U)
#define CY_SMIF_MAX_TX_TR_LEVEL             (8U)
#define CY_SMIF_MAX_RX_TR_LEVEL             (8U)

#define CY_SMIF_MODE_VALID(mode)            ((CY_SMIF_NORMAL == (cy_en_smif_mode_t)(mode)) || \
                                             (CY_SMIF_MEMORY == (cy_en_smif_mode_t)(mode)))
#define CY_SMIF_BLOCK_EVENT_VALID(event)    ((CY_SMIF_BUS_ERROR == (cy_en_smif_error_event_t)(event)) || \
                                             (CY_SMIF_WAIT_STATES == (cy_en_smif_error_event_t)(event)))
#if (CY_IP_MXSMIF_VERSION>=3)
#define CY_SMIF_CLOCK_SEL_VALID(clkSel)     ((CY_SMIF_SEL_OUTPUT_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_INVERTED_OUTPUT_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_INTERNAL_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_INVERTED_INTERNAL_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_FEEDBACK_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_INVERTED_FEEDBACK_CLK == (cy_en_smif_clk_select_t)(clkSel)))
#else
#define CY_SMIF_CLOCK_SEL_VALID(clkSel)     ((CY_SMIF_SEL_INTERNAL_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_INVERTED_INTERNAL_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_FEEDBACK_CLK == (cy_en_smif_clk_select_t)(clkSel)) || \
                                             (CY_SMIF_SEL_INVERTED_FEEDBACK_CLK == (cy_en_smif_clk_select_t)(clkSel)))
#endif /* CY_IP_MXSMIF_VERSION */
                                             
#define CY_SMIF_DESELECT_DELAY_VALID(delay) ((delay) <= CY_SMIF_MAX_DESELECT_DELAY)
#define CY_SMIF_SLAVE_SEL_VALID(ss)         ((CY_SMIF_SLAVE_SELECT_0 == (ss)) || \
                                             (CY_SMIF_SLAVE_SELECT_1 == (ss)) || \
                                             (CY_SMIF_SLAVE_SELECT_2 == (ss)) || \
                                             (CY_SMIF_SLAVE_SELECT_3 == (ss)))
#define CY_SMIF_DATA_SEL_VALID(ss)          ((CY_SMIF_DATA_SEL0 == (ss)) || \
                                             (CY_SMIF_DATA_SEL1 == (ss)) || \
                                             (CY_SMIF_DATA_SEL2 == (ss)) || \
                                             (CY_SMIF_DATA_SEL3 == (ss)))
#define CY_SMIF_TXFR_WIDTH_VALID(width)     ((CY_SMIF_WIDTH_SINGLE == (width)) || \
                                             (CY_SMIF_WIDTH_DUAL == (width))   || \
                                             (CY_SMIF_WIDTH_QUAD == (width))   || \
                                             (CY_SMIF_WIDTH_OCTAL == (width))  || \
                                             (CY_SMIF_WIDTH_NA == (width)))
#define CY_SMIF_CMD_PARAM_VALID(param, paramSize)  (((paramSize) > 0U)? (NULL != (param)) : (true))

#define CY_SMIF_WIDTH_NA_VALID(paramWidth, paramSize)   (((paramSize) > 0U)? \
                                                         (CY_SMIF_WIDTH_NA != (paramWidth)) : (true))
#define CY_SMIF_CMD_DATA_RATE_VALID(rate)   ((CY_SMIF_SDR == (rate)) || \
                                             (CY_SMIF_DDR == (rate)))
#define CY_SMIF_CMD_PARAM_DATA_RATE_VALID(rate)   ((CY_SMIF_SDR == (rate)) || \
                                                    (CY_SMIF_DDR == (rate)))
#define CY_SMIF_DATA_DATA_RATE_VALID(rate)   ((CY_SMIF_SDR == (rate)) || \
                                               (CY_SMIF_DDR == (rate)))
                                                           
#define CY_SMIF_BUFFER_SIZE_MAX             (65536UL) 
#define CY_SMIF_BUF_SIZE_VALID(size)        (((CY_SMIF_BUFFER_SIZE_MAX) >= (size)) && ((0UL) < (size)))

/***************************************
*        Command FIFO Register
***************************************/

#if (CY_IP_MXSMIF_VERSION>=3)
/* SMIF->TX_CMD_FIFO_MMIO_WR Commands Fields */
#define CY_SMIF_CMD_MMIO_FIFO_WR_MODE_Pos            (24UL)           /* [26:24]         Command data mode */
#define CY_SMIF_CMD_MMIO_FIFO_WR_MODE_Msk            (0x07000000UL)   /* DATA[26:24]       Command data mode    */

#define CY_SMIF_CMD_MMIO_FIFO_WR_SS_Pos              (20UL)           /* [23:20]         Slave select         */
#define CY_SMIF_CMD_MMIO_FIFO_WR_SS_Msk              (0x00F00000UL)   /* DATA[23:20]     Slave select         */

#define CY_SMIF_CMD_MMIO_FIFO_WR_LAST_BYTE_Pos       (19UL)           /* [19]            Last byte            */
#define CY_SMIF_CMD_MMIO_FIFO_WR_LAST_BYTE_Msk       (0x00080000UL)   /* DATA[19]        Last byte               */

#define CY_SMIF_CMD_MMIO_FIFO_WR_DATA_RATE_Pos       (18UL)           /* [18]         Data Rate         */
#define CY_SMIF_CMD_MMIO_FIFO_WR_DATA_RATE_Msk       (0x00040000UL)   /* DATA[18]     Data Reate         */

#define CY_SMIF_CMD_MMIO_FIFO_WR_WIDTH_Pos           (16UL)           /* [17:16]         Transfer width       */
#define CY_SMIF_CMD_MMIO_FIFO_WR_WIDTH_Msk           (0x00030000UL)   /* DATA[17:16]     Transfer width  */

#define CY_SMIF_CMD_MMIO_FIFO_WR_TXDATA_BYTE_2_Pos   (8UL)            /* [15:8] */
#define CY_SMIF_CMD_MMIO_FIFO_WR_TXDATA_BYTE_2_Msk   (0x0000FF00UL)   /* DATA[15:8] second byte */

#define CY_SMIF_CMD_MMIO_FIFO_WR_TXDATA_BYTE_1_Pos   (0UL)            /* [7:0]         first byte         */
#define CY_SMIF_CMD_MMIO_FIFO_WR_TXDATA_BYTE_1_Msk   (0x000000FFUL)   /* DATA[7:0]     first byte         */

#define CY_SMIF_CMD_MMIO_FIFO_WR_DUMMY_Pos           (0UL)            /* [0]             Dummy count          */
#define CY_SMIF_CMD_MMIO_FIFO_WR_DUMMY_Msk           (0x0000FFFFUL)   /* DATA[15:0]      Dummy count          */

#define CY_SMIF_CMD_MMIO_FIFO_WR_TX_COUNT_Msk        (0x0000FFFFUL)   /* DATA[15:0]      TX count             */
#define CY_SMIF_CMD_MMIO_FIFO_WR_TX_COUNT_Pos        (0UL)            /* [0]             TX count             */

#define CY_SMIF_CMD_MMIO_FIFO_WR_RX_COUNT_Msk        (0x0000FFFFUL)   /* DATA[15:0]      RX count             */
#define CY_SMIF_CMD_MMIO_FIFO_WR_RX_COUNT_Pos        (0UL)            /* [0]             RX count             */
#else
/* SMIF->TX_CMD_FIFO_WR  */
#define CY_SMIF_TX_CMD_FIFO_WR_MODE_POS         (18U)   /* [19:18]  Command data mode */
#define CY_SMIF_TX_CMD_FIFO_WR_WIDTH_POS        (16U)   /* [17:16]  Transfer width    */
#define CY_SMIF_TX_CMD_FIFO_WR_LAST_BYTE_POS    (15U)   /* [15]     Last byte      */
#define CY_SMIF_TX_CMD_FIFO_WR_SS_POS           (8U)    /* [11:8]   Slave select      */
#define CY_SMIF_TX_CMD_FIFO_WR_TXDATA_POS       (0U)    /* [0]      Transmitted byte  */
#define CY_SMIF_TX_CMD_FIFO_WR_DUMMY_POS        (0U)    /* [0]      Dummy count       */
#define CY_SMIF_TX_CMD_FIFO_WR_TX_COUNT_POS     (0U)    /* [0]      TX count          */
#define CY_SMIF_TX_CMD_FIFO_WR_RX_COUNT_POS     (0U)    /* [0]      RX count          */

/* SMIF->TX_CMD_FIFO_WR Commands Fields */
#define CY_SMIF_CMD_FIFO_WR_MODE_Pos            (18UL)           /* [19:18]         Command data mode */
#define CY_SMIF_CMD_FIFO_WR_MODE_Msk            (0x000C0000UL)   /* DATA[19:18]       Command data mode    */

#define CY_SMIF_CMD_FIFO_WR_WIDTH_Pos           (16UL)           /* [17:16]         Transfer width       */
#define CY_SMIF_CMD_FIFO_WR_WIDTH_Msk           (0x00030000UL)   /* DATA[17:16]     Transfer width       */

#define CY_SMIF_CMD_FIFO_WR_LAST_BYTE_Pos       (15UL)           /* [15]            Last byte            */
#define CY_SMIF_CMD_FIFO_WR_LAST_BYTE_Msk       (0x00008000UL)   /* DATA[15]        Last byte            */

#define CY_SMIF_CMD_FIFO_WR_SS_Pos              (8UL)            /* [11:8]          Slave select         */
#define CY_SMIF_CMD_FIFO_WR_SS_Msk              (0x00000F00UL)   /* DATA[11:8]      Slave select         */
   
#define CY_SMIF_CMD_FIFO_WR_TXDATA_Pos          (0UL)            /* [0]             Transmitted byte     */
#define CY_SMIF_CMD_FIFO_WR_TXDATA_Msk          (0x000000FFUL)   /* DATA[7:0]         Transmitted byte     */
#define CY_SMIF_CMD_FIFO_WR_DUMMY_Pos           (0UL)            /* [0]             Dummy count          */
#define CY_SMIF_CMD_FIFO_WR_DUMMY_Msk           (0x0000FFFFUL)   /* DATA[15:0]      Dummy count          */
#define CY_SMIF_CMD_FIFO_WR_TX_COUNT_Msk        (0x0000FFFFUL)   /* DATA[15:0]      TX count             */
#define CY_SMIF_CMD_FIFO_WR_TX_COUNT_Pos        (0UL)            /* [0]             TX count             */
#define CY_SMIF_CMD_FIFO_WR_RX_COUNT_Msk        (0x0000FFFFUL)   /* DATA[15:0]      RX count             */
#define CY_SMIF_CMD_FIFO_WR_RX_COUNT_Pos        (0UL)            /* [0]             RX count             */
#endif /* CY_IP_MXSMIF_VERSION */

/** \endcond */
/** \} group_smif_macros */


/**
* \addtogroup group_smif_enums
* \{
*/

/** The Transfer width options for the command, data, the address and the mode. */
typedef enum
{
    CY_SMIF_WIDTH_SINGLE   = 0U,    /**< Single SPI mode. */
    CY_SMIF_WIDTH_DUAL     = 1U,    /**< Dual SPI mode. */
    CY_SMIF_WIDTH_QUAD     = 2U,    /**< Quad SPI mode. */
    CY_SMIF_WIDTH_OCTAL    = 3U,    /**< Octal SPI mode. */
    CY_SMIF_WIDTH_NA       = 0xFFU  /**< The specific width parameter is not applicable for this memory command. */
} cy_en_smif_txfr_width_t;

/** The SMIF error-event selection. */
typedef enum
{
    /**< Generates a bus error. */
    CY_SMIF_BUS_ERROR           = 0UL,
    /** Stalls the bus with the wait states. This option will increase the 
     * interrupt latency. 
     */
    CY_SMIF_WAIT_STATES         = 1UL
} cy_en_smif_error_event_t;

/** The data line-selection options for a slave device. */
typedef enum
{
    /**
    * smif.spi_data[0] = DATA0, smif.spi_data[1] = DATA1, ..., smif.spi_data[7] = DATA7.
    * This value is allowed for the SPI, DSPI, QSPI, dual QSPI, and octal SPI modes.
    */
    CY_SMIF_DATA_SEL0      = 0,
    /**
    * smif.spi_data[2] = DATA0, smif.spi_data[3] = DATA1.
    * This value is only allowed for the SPI and DSPI modes.
    */
    CY_SMIF_DATA_SEL1      = 1,
    /**
    * smif.spi_data[4] = DATA0, smif.spi_data[5] = DATA1, ..., smif.spi_data[7] = DATA3.
    * This value is only allowed for the SPI, DSPI, QSPI and dual QSPI modes.
    */
    CY_SMIF_DATA_SEL2      = 2,
    /**
    * smif.spi_data[6] = DATA0, smif.spi_data[7] = DATA1.
    * This value is only allowed for the SPI and DSPI modes.
    */
    CY_SMIF_DATA_SEL3      = 3
} cy_en_smif_data_select_t;

/** The SMIF modes to work with an external memory. */
typedef enum
{
    CY_SMIF_NORMAL,         /**< Command mode (MMIO mode). */
    CY_SMIF_MEMORY          /**< XIP (eXecute In Place) mode. */
} cy_en_smif_mode_t;

/** The SMIF transfer status return values. */
typedef enum
{
    CY_SMIF_STARTED,       /**< The SMIF started. */
    CY_SMIF_SEND_COMPLETE, /**< The data transmission is complete. */
    CY_SMIF_SEND_BUSY,     /**< The data transmission is in progress. */
    CY_SMIF_RX_COMPLETE,   /**< The data reception is completed. */
    CY_SMIF_RX_BUSY,       /**< The data reception is in progress. */
    CY_SMIF_XIP_ERROR,     /**< An XIP alignment error. */
    CY_SMIF_CMD_ERROR,     /**< A TX CMD FIFO overflow. */
    CY_SMIF_TX_ERROR,      /**< A TX DATA FIFO overflow. */
    CY_SMIF_RX_ERROR       /**< An RX DATA FIFO underflow. */

} cy_en_smif_txfr_status_t;

/** The SMIF API return values. */
typedef enum
{
    CY_SMIF_SUCCESS = 0x00U,           /**< Successful SMIF operation. */
    CY_SMIF_CMD_FIFO_FULL   = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x01U,     /**< The command is cancelled. The command FIFO is full. */
    CY_SMIF_EXCEED_TIMEOUT  = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x02U,    /**< The SMIF operation timeout exceeded. */
    /**
    * The device does not have a QE bit. The device detects
    * 1-1-4 and 1-4-4 Reads based on the instruction.
    */
    CY_SMIF_NO_QE_BIT       = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x03U,
    CY_SMIF_BAD_PARAM       = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x04U,   /**< The SMIF API received the wrong parameter */
    CY_SMIF_NO_SFDP_SUPPORT = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x05U,   /**< The external memory does not support SFDP (JESD216B). */
    CY_SMIF_NOT_HYBRID_MEM  = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x06U,   /**< The external memory is not hybrid */
    CY_SMIF_SFDP_CORRUPTED_TABLE = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x07U, /**< The SFDP table is corrupted */
    /** Failed to initialize the slave select 0 external memory by auto detection (SFDP). */
    CY_SMIF_SFDP_SS0_FAILED = CY_SMIF_ID |CY_PDL_STATUS_ERROR |
                            ((uint32_t)CY_SMIF_SFDP_FAIL << CY_SMIF_SFDP_FAIL_SS0_POS),
    /** Failed to initialize the slave select 1 external memory by auto detection (SFDP). */
    CY_SMIF_SFDP_SS1_FAILED = CY_SMIF_ID | CY_PDL_STATUS_ERROR |
                            ((uint32_t)CY_SMIF_SFDP_FAIL << CY_SMIF_SFDP_FAIL_SS1_POS),
    /** Failed to initialize the slave select 2 external memory by auto detection (SFDP). */
    CY_SMIF_SFDP_SS2_FAILED = CY_SMIF_ID |CY_PDL_STATUS_ERROR |
                            ((uint32_t)CY_SMIF_SFDP_FAIL << CY_SMIF_SFDP_FAIL_SS2_POS),
    /** Failed to initialize the slave select 3 external memory by auto detection (SFDP). */
    CY_SMIF_SFDP_SS3_FAILED = CY_SMIF_ID |CY_PDL_STATUS_ERROR |
                            ((uint32_t)CY_SMIF_SFDP_FAIL << CY_SMIF_SFDP_FAIL_SS3_POS),
    /** The command API is not supported for this memory device. */
    CY_SMIF_CMD_NOT_FOUND = CY_SMIF_ID |CY_PDL_STATUS_ERROR | 0x80U
} cy_en_smif_status_t;

/** The SMIF slave select definitions for the driver API. Each slave select is
 * represented by an enumeration that has the bit corresponding to the slave 
 * select number set. */
typedef enum
{
   CY_SMIF_SLAVE_SELECT_0 = 1U,  /**< The SMIF slave select 0  */
   CY_SMIF_SLAVE_SELECT_1 = 2U,  /**< The SMIF slave select 1  */
   CY_SMIF_SLAVE_SELECT_2 = 4U,  /**< The SMIF slave select 2  */
   CY_SMIF_SLAVE_SELECT_3 = 8U   /**< The SMIF slave select 3  */
} cy_en_smif_slave_select_t;

/** Specifies the clock source for the receiver clock. */
#if (CY_IP_MXSMIF_VERSION>=3) || defined (CY_DOXYGEN)
/**
* \note
* This enum is available for CAT1B devices.
**/
typedef enum
{
   CY_SMIF_SEL_OUTPUT_CLK   = 0U,  /**< The SMIF output clock */
   CY_SMIF_SEL_INVERTED_OUTPUT_CLK   = 1U,  /**< The SMIF inverted output clock */
   CY_SMIF_SEL_FEEDBACK_CLK     = 2U,  /**< The SMIF feedback clock */
   CY_SMIF_SEL_INVERTED_FEEDBACK_CLK = 3U,   /**< The SMIF feedback inverted clock */
   CY_SMIF_SEL_INTERNAL_CLK     = 4U,  /**< The SMIF internal clock */
   CY_SMIF_SEL_INVERTED_INTERNAL_CLK = 5U,  /**< The SMIF internal inverted clock */
} cy_en_smif_clk_select_t;
#endif
#if (CY_IP_MXSMIF_VERSION==1) || defined (CY_DOXYGEN)
/**
* \note
* This enum is available for CAT1A devices.
**/
typedef enum
{
   CY_SMIF_SEL_INTERNAL_CLK     = 0U,  /**< The SMIF internal clock */
   CY_SMIF_SEL_INVERTED_INTERNAL_CLK = 1U,  /**< The SMIF internal inverted clock */
   CY_SMIF_SEL_FEEDBACK_CLK     = 2U,  /**< The SMIF feedback clock */
   CY_SMIF_SEL_INVERTED_FEEDBACK_CLK = 3U   /**< The SMIF feedback inverted clock */
} cy_en_smif_clk_select_t;
#endif /* CY_IP_MXSMIF_VERSION */

/** Specifies enabled type of SMIF cache. */
typedef enum
{
    CY_SMIF_CACHE_SLOW      = 1U,   /**< The SMIF slow cache (in the clk_slow domain) see TRM for details */
    CY_SMIF_CACHE_FAST      = 2U,   /**< The SMIF fast cache  (in the clk_fast domain) see TRM for details */
    CY_SMIF_CACHE_BOTH      = 3U    /**< The SMIF both caches */
} cy_en_smif_cache_t;

#if (CY_IP_MXSMIF_VERSION>=3) || defined (CY_DOXYGEN)
/** Specifies the data rate. */
/**
* \note
* This enum is available for CAT1B devices.
**/
typedef enum
{
    CY_SMIF_SDR = 0,    /**< The SMIF Single Data Rate (SDR) */
    CY_SMIF_DDR = 1,    /**< The SMIF Double Data Rate (DDR) */
} cy_en_smif_data_rate_t;

/** Specifies the presence of the field. */
/**
* \note
* This enum is available for CAT1B devices.
**/
typedef enum
{
    CY_SMIF_NOT_PRESENT   = 0,
    CY_SMIF_PRESENT_1BYTE = 1,
    CY_SMIF_PRESENT_2BYTE = 2,
} cy_en_smif_field_presence_t;
#endif /* CY_IP_MXSMIF_VERSION */


/** \cond INTERNAL */
/*******************************************************************************
* These are legacy macros. They are left here just for backward compatibility.
* Do not use them in new designs.
*******************************************************************************/

#define CY_SMIF_SEND_CMPLT                          CY_SMIF_SEND_COMPLETE
#define CY_SMIF_REC_CMPLT                           CY_SMIF_RX_COMPLETE
#define CY_SMIF_REC_BUSY                            CY_SMIF_RX_BUSY
#define CY_SMIF_SEL_INV_INTERNAL_CLK                CY_SMIF_SEL_INVERTED_INTERNAL_CLK
#define CY_SMIF_SEL_INV_FEEDBACK_CLK                CY_SMIF_SEL_INVERTED_FEEDBACK_CLK
#define cy_en_smif_cache_en_t                       cy_en_smif_cache_t
#define Cy_SMIF_GetTxfrStatus                       Cy_SMIF_GetTransferStatus

/** \endcond */

/** \} group_smif_enums */


/**
* \addtogroup group_smif_data_structures
* \{
*/

/***************************************************************************//**
*
* The SMIF user callback function type called at the end of a transfer.
*
* \param event
* The event which caused a callback call.
*
*******************************************************************************/
typedef void (*cy_smif_event_cb_t)(uint32_t event);


/** The SMIF configuration structure. */
typedef struct
{
    uint32_t mode;              /**<  Specifies the mode of operation \ref cy_en_smif_mode_t. */
    uint32_t deselectDelay;     /**<  Specifies the minimum duration of SPI de-selection between SPI transfers:
                                *   - "0": 1 clock cycle.
                                *   - "1": 2 clock cycles.
                                *   - "2": 3 clock cycles.
                                *   - "3": 4 clock cycles.
                                *   - "4": 5 clock cycles.
                                *   - "5": 6 clock cycles.
                                *   - "6": 7 clock cycles.
                                *   - "7": 8 clock cycles. */
    uint32_t rxClockSel;        /**< Specifies the clock source for the receiver 
                                *  clock \ref cy_en_smif_clk_select_t. */
    uint32_t blockEvent;        /**< Specifies what happens when there is a Read  
                                * from an empty RX FIFO or a Write to a full 
                                * TX FIFO. \ref cy_en_smif_error_event_t. */
} cy_stc_smif_config_t;

/** The SMIF internal context data. The user must not modify it. */
typedef struct
{
    uint8_t const volatile * volatile txBufferAddress;    /**<  The pointer to the data to transfer */
    uint32_t txBufferSize;                          /**<  The size of the data to transmit in bytes */
    /**
    * The transfer counter. The number of the transmitted bytes = txBufferSize - txBufferCounter
    */
    uint32_t volatile txBufferCounter;
    uint8_t volatile * volatile rxBufferAddress;    /**<  The pointer to the variable where the received data is stored */
    uint32_t rxBufferSize;                          /**<  The size of the data to be received in bytes */
    /**
    * The transfer counter. The number of the received bytes = rxBufferSize - rxBufferCounter
    */
    uint32_t volatile rxBufferCounter;
    /**
    * The status of the transfer. The transmitting / receiving is completed / in progress
    */
    uint32_t volatile transferStatus;
    cy_smif_event_cb_t volatile txCompleteCb;          /**< The user-defined callback executed at the completion of a transmission */
    cy_smif_event_cb_t volatile rxCompleteCb;          /**< The user-defined callback executed at the completion of a reception */
    /**
    * The timeout in microseconds for the blocking functions. This timeout value applies to all blocking APIs.
    */
    uint32_t timeout;
#if (CY_IP_MXSMIF_VERSION>=3) || defined (CY_DOXYGEN)
    /**
    * \note
    * This parameter is available for CAT1B devices.
    **/
    cy_en_smif_data_rate_t  preCmdDataRate; /**< preferred command data rate */
    /**
    * \note
    * This parameter is available for CAT1B devices.
    **/
    cy_en_smif_txfr_width_t preCmdWidth; /**< preferred command data rate */
    /**
    * \note
    * This parameter is available for CAT1B devices.
    **/
    cy_en_smif_data_rate_t  preXIPDataRate; /**< preferred XIP data rate */
#endif /* CY_IP_MXSMIF_VERSION */
} cy_stc_smif_context_t;

/** \} group_smif_data_structures */


/**
* \addtogroup group_smif_low_level_functions
* \{
*/

cy_en_smif_status_t Cy_SMIF_Init(SMIF_Type *base, cy_stc_smif_config_t const *config,
                                uint32_t timeout,
                                cy_stc_smif_context_t *context);
void Cy_SMIF_DeInit(SMIF_Type *base);
void Cy_SMIF_SetDataSelect(SMIF_Type *base, cy_en_smif_slave_select_t slaveSelect,
                                cy_en_smif_data_select_t dataSelect);
void Cy_SMIF_SetMode(SMIF_Type *base, cy_en_smif_mode_t mode);
cy_en_smif_mode_t Cy_SMIF_GetMode(SMIF_Type const *base);
cy_en_smif_status_t Cy_SMIF_TransmitCommand(SMIF_Type *base,
                                uint8_t cmd,
                                cy_en_smif_txfr_width_t cmdTxfrWidth,
                                uint8_t const cmdParam[], uint32_t paramSize,
                                cy_en_smif_txfr_width_t paramTxfrWidth,
                                cy_en_smif_slave_select_t slaveSelect, uint32_t completeTxfr,
                                cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_TransmitData(SMIF_Type *base,
                                uint8_t const *txBuffer, uint32_t size,
                                cy_en_smif_txfr_width_t transferWidth,
                                cy_smif_event_cb_t TxCompleteCb,
                                cy_stc_smif_context_t *context);
cy_en_smif_status_t  Cy_SMIF_TransmitDataBlocking(SMIF_Type *base,
                                uint8_t const *txBuffer,
                                uint32_t size,
                                cy_en_smif_txfr_width_t transferWidth,
                                cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_ReceiveData(SMIF_Type *base,
                                uint8_t *rxBuffer, uint32_t size,
                                cy_en_smif_txfr_width_t transferWidth,
                                cy_smif_event_cb_t RxCompleteCb,
                                cy_stc_smif_context_t *context);
cy_en_smif_status_t  Cy_SMIF_ReceiveDataBlocking(SMIF_Type *base,
                                uint8_t *rxBuffer,
                                uint32_t size,
                                cy_en_smif_txfr_width_t transferWidth,
                                cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_SendDummyCycles(SMIF_Type *base, uint32_t cycles);
uint32_t Cy_SMIF_GetTransferStatus(SMIF_Type const *base, cy_stc_smif_context_t const *context);
void Cy_SMIF_Enable(SMIF_Type *base, cy_stc_smif_context_t *context);

#if (CY_IP_MXSMIF_VERSION>=3) || defined (CY_DOXYGEN)
cy_en_smif_status_t Cy_SMIF_TransmitCommand_Ext(SMIF_Type *base,
                                                 uint16_t cmd,
                                                 bool isCommand2byte,
                                                 cy_en_smif_txfr_width_t cmdTxfrWidth,
                                                 cy_en_smif_data_rate_t cmdDataRate,
                                                 uint8_t const cmdParam[],
                                                 uint32_t paramSize,
                                                 cy_en_smif_txfr_width_t paramTxfrWidth,
                                                 cy_en_smif_data_rate_t paramDataRate,
                                                 cy_en_smif_slave_select_t slaveSelect,
                                                 uint32_t cmpltTxfr,
                                                 cy_stc_smif_context_t const *context);

cy_en_smif_status_t Cy_SMIF_TransmitData_Ext(SMIF_Type *base,
                                                uint8_t const *txBuffer,
                                                uint32_t size,
                                                cy_en_smif_txfr_width_t transferWidth,
                                                cy_en_smif_data_rate_t dataDataRate,
                                                cy_smif_event_cb_t TxCmpltCb,
                                                cy_stc_smif_context_t *context);

cy_en_smif_status_t Cy_SMIF_TransmitDataBlocking_Ext(SMIF_Type *base,
                                                uint8_t const *txBuffer,
                                                uint32_t size,
                                                cy_en_smif_txfr_width_t transferWidth,
                                                cy_en_smif_data_rate_t dataRate,
                                                cy_stc_smif_context_t const *context);

cy_en_smif_status_t Cy_SMIF_ReceiveData_Ext(SMIF_Type *base,
                                                uint8_t *rxBuffer,
                                                uint32_t size,
                                                cy_en_smif_txfr_width_t transferWidth,
                                                cy_en_smif_data_rate_t dataRate,
                                                cy_smif_event_cb_t RxCmpltCb,
                                                cy_stc_smif_context_t *context);

cy_en_smif_status_t Cy_SMIF_ReceiveDataBlocking_Ext(SMIF_Type *base,
                                                uint8_t *rxBuffer,
                                                uint32_t size,
                                                cy_en_smif_txfr_width_t transferWidth,
                                                cy_en_smif_data_rate_t dataRate,
                                                cy_stc_smif_context_t const *context);

cy_en_smif_status_t Cy_SMIF_SendDummyCycles_Ext(SMIF_Type *base,
                                                cy_en_smif_txfr_width_t transferWidth,
                                                cy_en_smif_data_rate_t dataRate,
                                                uint32_t cycles);
#endif /* CY_IP_MXSMIF_VERSION */

__STATIC_INLINE void Cy_SMIF_Disable(SMIF_Type *base);
__STATIC_INLINE void  Cy_SMIF_SetInterruptMask(SMIF_Type *base, uint32_t interrupt);
__STATIC_INLINE uint32_t  Cy_SMIF_GetInterruptMask(SMIF_Type const *base);
__STATIC_INLINE uint32_t  Cy_SMIF_GetInterruptStatusMasked(SMIF_Type const *base);
__STATIC_INLINE uint32_t  Cy_SMIF_GetInterruptStatus(SMIF_Type const *base);
__STATIC_INLINE void  Cy_SMIF_SetInterrupt(SMIF_Type *base, uint32_t interrupt);
__STATIC_INLINE void  Cy_SMIF_ClearInterrupt(SMIF_Type *base, uint32_t interrupt);
__STATIC_INLINE void  Cy_SMIF_SetTxFifoTriggerLevel(SMIF_Type *base, uint32_t level);
__STATIC_INLINE void  Cy_SMIF_SetRxFifoTriggerLevel(SMIF_Type *base, uint32_t level);
__STATIC_INLINE uint32_t  Cy_SMIF_GetCmdFifoStatus(SMIF_Type const *base);
__STATIC_INLINE uint32_t  Cy_SMIF_GetTxFifoStatus(SMIF_Type const *base);
__STATIC_INLINE uint32_t  Cy_SMIF_GetRxFifoStatus(SMIF_Type const *base);
cy_en_smif_status_t  Cy_SMIF_Encrypt(SMIF_Type *base,
                                uint32_t address,
                                uint8_t data[],
                                uint32_t size,
                                cy_stc_smif_context_t const *context);
__STATIC_INLINE bool Cy_SMIF_BusyCheck(SMIF_Type const *base);
__STATIC_INLINE void Cy_SMIF_Interrupt(SMIF_Type *base, cy_stc_smif_context_t *context);
cy_en_smif_status_t Cy_SMIF_CacheEnable(SMIF_Type *base, cy_en_smif_cache_t cacheType);
cy_en_smif_status_t Cy_SMIF_CacheDisable(SMIF_Type *base, cy_en_smif_cache_t cacheType);
cy_en_smif_status_t Cy_SMIF_CachePrefetchingEnable(SMIF_Type *base, cy_en_smif_cache_t cacheType);
cy_en_smif_status_t Cy_SMIF_CachePrefetchingDisable(SMIF_Type *base, cy_en_smif_cache_t cacheType);
cy_en_smif_status_t Cy_SMIF_CacheInvalidate(SMIF_Type *base, cy_en_smif_cache_t cacheType);

/** \addtogroup group_smif_functions_syspm_callback
* The driver supports SysPm callback for Deep Sleep and Hibernate transition.
* \{
*/
cy_en_syspm_status_t Cy_SMIF_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
cy_en_syspm_status_t Cy_SMIF_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
/** \} */


/***************************************
*  Internal SMIF function declarations
****************************************/
/** \cond INTERNAL */
__STATIC_INLINE void Cy_SMIF_PushTxFifo(SMIF_Type *baseaddr, cy_stc_smif_context_t *context);      /**< Writes transmitted data into the FIFO. */
__STATIC_INLINE void Cy_SMIF_PopRxFifo(SMIF_Type *baseaddr, cy_stc_smif_context_t *context);       /**< Reads received data from the FIFO. */
__STATIC_INLINE uint32_t Cy_SMIF_PackBytesArray(uint8_t const buff[], bool fourBytes);
__STATIC_INLINE void Cy_SMIF_UnPackByteArray(uint32_t inValue, uint8_t outBuff[], bool fourBytes);
__STATIC_INLINE cy_en_smif_status_t Cy_SMIF_TimeoutRun(uint32_t *timeoutUnits);
__STATIC_INLINE SMIF_DEVICE_Type volatile * Cy_SMIF_GetDeviceBySlot(SMIF_Type *base,
                                cy_en_smif_slave_select_t slaveSelect);
/** \endcond */

/** \} group_smif_low_level_functions */


/**
* \addtogroup group_smif_low_level_functions
* \{
*/

/*******************************************************************************
* Function Name: Cy_SMIF_Disable
****************************************************************************//**
*
* Disables the operation of the SMIF block. The SMIF block can be disabled only
* when it is not in the active state. Use the Cy_SMIF_BusyCheck() API to check
* it before calling this API.
*
* \param base
* Holds the base address of the SMIF block registers.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SMIF_Disable(SMIF_Type *base)
{
    SMIF_CTL(base) &= ~SMIF_CTL_ENABLED_Msk;

}


/*******************************************************************************
* Function Name: Cy_SMIF_SetInterruptMask
****************************************************************************//**
*
* This function is used to set an interrupt mask for the SMIF Interrupt.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param interrupt
* This is the mask for different source options that can be masked. See
* \ref group_smif_macros_isr "Interrupt Macros" for possible values.
*
*******************************************************************************/
__STATIC_INLINE void  Cy_SMIF_SetInterruptMask(SMIF_Type *base, uint32_t interrupt)
{
    SMIF_INTR_MASK(base) = interrupt;
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetInterruptMask
****************************************************************************//**
*
* This function is used to read an interrupt mask for the SMIF Interrupt.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns the mask set for the SMIF interrupt.
*
*******************************************************************************/
__STATIC_INLINE uint32_t  Cy_SMIF_GetInterruptMask(SMIF_Type const *base)
{
  return (SMIF_INTR_MASK(base));
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetInterruptStatusMasked
****************************************************************************//**
*
* This function is used to read an active masked interrupt. This function can
* be used in the interrupt service-routine to find which source triggered the
* interrupt.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns a word with bits set at positions corresponding to the
* interrupts triggered in the system.
*
*******************************************************************************/
__STATIC_INLINE uint32_t  Cy_SMIF_GetInterruptStatusMasked(SMIF_Type const *base)
{
  return (SMIF_INTR_MASKED(base));
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetInterruptStatus
****************************************************************************//**
*
* This function is used to read an active interrupt. This status is the unmasked
* result, so will also show interrupts that will not generate active interrupts.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns a word with bits set at positions corresponding to the
* interrupts triggered in the system.
*
*******************************************************************************/
__STATIC_INLINE uint32_t  Cy_SMIF_GetInterruptStatus(SMIF_Type const *base)
{
  return (SMIF_INTR(base));
}


/*******************************************************************************
* Function Name: Cy_SMIF_SetInterrupt
****************************************************************************//**
*
* This function is used to set an interrupt source. This function can be used
* to activate interrupts through the software.
*
* \note Interrupt sources set using this interrupt will generate interrupts only
* if they are not masked.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param interrupt
* An encoded integer with a bit set corresponding to the interrupt to be
* triggered. See \ref group_smif_macros_isr "Interrupt Macros" for possible
* values.
*
*******************************************************************************/
__STATIC_INLINE void  Cy_SMIF_SetInterrupt(SMIF_Type *base, uint32_t interrupt)
{
    SMIF_INTR_SET(base) = interrupt;
}


/*******************************************************************************
* Function Name: Cy_SMIF_ClearInterrupt
****************************************************************************//**
*
* This function is used to clear an interrupt source. This function can be used
* in the user code to clear all pending interrupts.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param interrupt
* An encoded integer with a bit set corresponding to the interrupt that must
* be cleared. See \ref group_smif_macros_isr "Interrupt Macros" for possible
* values.
*
*******************************************************************************/
__STATIC_INLINE void  Cy_SMIF_ClearInterrupt(SMIF_Type *base, uint32_t interrupt)
{
    SMIF_INTR(base) = interrupt;

    /* Ensure that the initial Write has been flushed out to the hardware. */
    interrupt = SMIF_INTR(base);
}


/*******************************************************************************
* Function Name: Cy_SMIF_SetTxFifoTriggerLevel()
****************************************************************************//**
*
* This function is used to set a trigger level for the TX FIFO. This value must
* be an integer between 0 and 7. For the normal mode only.
* The triggering is active when TX_DATA_FIFO_STATUS <= level.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param level
* The trigger level to set (0-8).
*
*******************************************************************************/
__STATIC_INLINE void  Cy_SMIF_SetTxFifoTriggerLevel(SMIF_Type *base, uint32_t level)
{
    CY_ASSERT_L2(level <= CY_SMIF_MAX_TX_TR_LEVEL);
    SMIF_TX_DATA_FIFO_CTL(base) = level;
}


/*******************************************************************************
* Function Name: Cy_SMIF_SetRxFifoTriggerLevel()
****************************************************************************//**
*
* This function is used to set a trigger level for the RX FIFO. This value must
* be an integer between 0 and 7. For the normal mode only.
* The triggering is active when RX_DATA_FIFOSTATUS > level.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param level
* The trigger level to set(0-8).
*
*******************************************************************************/
__STATIC_INLINE void  Cy_SMIF_SetRxFifoTriggerLevel(SMIF_Type *base, uint32_t level)
{
    CY_ASSERT_L2(level <= CY_SMIF_MAX_RX_TR_LEVEL);
    SMIF_RX_DATA_FIFO_CTL(base) = level;
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetCmdFifoStatus()
****************************************************************************//**
*
* This function is used to read the status of the CMD FIFO.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns the number of the entries in the CMD FIFO.
*
*******************************************************************************/
__STATIC_INLINE uint32_t  Cy_SMIF_GetCmdFifoStatus(SMIF_Type const *base)
{
#if (CY_IP_MXSMIF_VERSION>=3)
    return (_FLD2VAL(SMIF_TX_CMD_MMIO_FIFO_STATUS_USED4, SMIF_TX_CMD_MMIO_FIFO_STATUS(base)));
#else
    return (_FLD2VAL(SMIF_TX_CMD_FIFO_STATUS_USED3, SMIF_TX_CMD_FIFO_STATUS(base)));
#endif /* CY_IP_MXSMIF_VERSION */
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetTxFifoStatus()
****************************************************************************//**
*
* This function is used to read the status of the TX FIFO.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns the number of the entries in the TX FIFO.
*
*******************************************************************************/
__STATIC_INLINE uint32_t  Cy_SMIF_GetTxFifoStatus(SMIF_Type const *base)
{
#if (CY_IP_MXSMIF_VERSION>=3)
    return (_FLD2VAL(SMIF_TX_DATA_MMIO_FIFO_STATUS_USED4, SMIF_TX_DATA_MMIO_FIFO_STATUS(base)));
#else
    return (_FLD2VAL(SMIF_TX_DATA_FIFO_STATUS_USED4, SMIF_TX_DATA_FIFO_STATUS(base)));
#endif /* CY_IP_MXSMIF_VERSION */
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetRxFifoStatus()
****************************************************************************//**
*
* This function is used to read the status of the RX FIFO.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns the number of the entries in the RX FIFO.
*
*******************************************************************************/
__STATIC_INLINE uint32_t  Cy_SMIF_GetRxFifoStatus(SMIF_Type const *base)
{
#if (CY_IP_MXSMIF_VERSION>=3)
    return (_FLD2VAL(SMIF_RX_DATA_MMIO_FIFO_STATUS_USED4, SMIF_RX_DATA_MMIO_FIFO_STATUS(base)));
#else
    return (_FLD2VAL(SMIF_RX_DATA_FIFO_STATUS_USED4, SMIF_RX_DATA_FIFO_STATUS(base)));
#endif /* CY_IP_MXSMIF_VERSION */
}


/*******************************************************************************
* Function Name: Cy_SMIF_BusyCheck
****************************************************************************//**
*
* This function provides the status of the IP block (False - not busy,
* True - busy).
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \return Returns an IP block status.
*
*******************************************************************************/
__STATIC_INLINE bool Cy_SMIF_BusyCheck(SMIF_Type const *base)
{
  return (1UL == _FLD2VAL(SMIF_STATUS_BUSY, SMIF_STATUS(base)));
}


/*******************************************************************************
* Function Name: Cy_SMIF_Interrupt
****************************************************************************//**
*
* The Interrupt Service Routine for the SMIF. The interrupt code will be
* responsible for the FIFO operations on FIFO interrupts during ongoing transfers.
* The user must place a call to this interrupt function in the interrupt
* routine corresponding to the interrupt attached to the SMIF. If the
* user does not do this, will break: the functionality of all the API functions in
* the SMIF driver that use SMIF interrupts to affect transfers.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param context
* Passes a configuration structure that contains the transfer parameters of the
* SMIF block.
*
* \globalvars
*  - context->txBufferAddress - The pointer to the data to be transferred.
*
*  - context->txBufferSize - The size of txBuffer.
*
*  - context->txBufferCounter - The number of data entries left to be transferred.
*
* All the Global variables described above are used when the Software Buffer is
* used.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SMIF_Interrupt(SMIF_Type *base, cy_stc_smif_context_t *context)
{
    uint32_t interruptStatus = Cy_SMIF_GetInterruptStatusMasked(base);

    /* Check which interrupt occurred */
    if (0U != (interruptStatus & SMIF_INTR_TR_TX_REQ_Msk))
    {
        /* Send data */
        Cy_SMIF_PushTxFifo(base, context);

        Cy_SMIF_ClearInterrupt(base, SMIF_INTR_TR_TX_REQ_Msk);
    }
    else if (0U != (interruptStatus & SMIF_INTR_TR_RX_REQ_Msk))
    {
        /* Receive data */
        Cy_SMIF_PopRxFifo(base, context);

        Cy_SMIF_ClearInterrupt(base, SMIF_INTR_TR_RX_REQ_Msk);
    }
    else if (0U != (interruptStatus & SMIF_INTR_XIP_ALIGNMENT_ERROR_Msk))
    {
        /* An XIP alignment error */
        context->transferStatus = (uint32_t) CY_SMIF_XIP_ERROR;

        Cy_SMIF_ClearInterrupt(base, SMIF_INTR_XIP_ALIGNMENT_ERROR_Msk);
    }

    else if (0U != (interruptStatus & SMIF_INTR_TX_CMD_FIFO_OVERFLOW_Msk))
    {
        /* TX CMD FIFO overflow */
        context->transferStatus = (uint32_t) CY_SMIF_CMD_ERROR;

        Cy_SMIF_ClearInterrupt(base, SMIF_INTR_TX_CMD_FIFO_OVERFLOW_Msk);
    }

    else if (0U != (interruptStatus & SMIF_INTR_TX_DATA_FIFO_OVERFLOW_Msk))
    {
        /* A TX DATA FIFO overflow */
        context->transferStatus = (uint32_t) CY_SMIF_TX_ERROR;

        Cy_SMIF_ClearInterrupt(base, SMIF_INTR_TX_DATA_FIFO_OVERFLOW_Msk);
    }

    else if (0U != (interruptStatus & SMIF_INTR_RX_DATA_FIFO_UNDERFLOW_Msk))
    {
        /* RX DATA FIFO underflow */
        context->transferStatus = (uint32_t) CY_SMIF_RX_ERROR;

        Cy_SMIF_ClearInterrupt(base, SMIF_INTR_RX_DATA_FIFO_UNDERFLOW_Msk);
    }
    else
    {
        /* Processing of errors */
    }
}


/*******************************************************************************
*  Internal SMIF in-line functions
*******************************************************************************/

/** \cond INTERNAL */

/*******************************************************************************
* Function Name: Cy_SMIF_PushTxFifo
***************************************************************************//***
*
* \internal
*
* \param baseaddr
* Holds the base address of the SMIF block registers.
*
* \param context
* Passes a configuration structure that contains the transfer parameters of the
* SMIF block.
*
* This function writes data in the TX FIFO SMIF buffer by 4, 2, or 1 bytes based
* on the residual number of bytes and the available space in the TX FIFO.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SMIF_PushTxFifo(SMIF_Type *baseaddr, cy_stc_smif_context_t *context)
{
    /* The variable that shows which is smaller: the free FIFO size or amount of bytes to be sent */
    uint32_t writeBytes;
    uint32_t freeFifoBytes;
    uint32_t buffCounter = context->txBufferCounter;
    uint8_t *buff = (uint8_t*) context->txBufferAddress;

    freeFifoBytes = CY_SMIF_TX_DATA_FIFO_STATUS_RANGE - Cy_SMIF_GetTxFifoStatus(baseaddr);
    writeBytes = (freeFifoBytes > buffCounter)? buffCounter: freeFifoBytes;

    /* Check that after a FIFO Write, no data/FIFO space remains */
    while (0U != writeBytes)
    {
        /* The first main use case for long transfers */
        if (writeBytes == CY_SMIF_EIGHT_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], true);
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[4U], true);
        }
        /* The second main use case for short transfers */
        else if(writeBytes == CY_SMIF_ONE_BYTE)
        {
#if (CY_IP_MXSMIF_VERSION>=3)
            if((context->preCmdDataRate == CY_SMIF_DDR) &&(context->preCmdWidth == CY_SMIF_WIDTH_OCTAL))
            {
                SMIF_TX_DATA_MMIO_FIFO_WR1ODD(baseaddr) = buff[0U]; 
            }
            else
            {
                SMIF_TX_DATA_MMIO_FIFO_WR1(baseaddr) = buff[0U];
            }
#else
            SMIF_TX_DATA_FIFO_WR1(baseaddr) = buff[0U];
#endif /* CY_IP_MXSMIF_VERSION */
        }
        else if(writeBytes == CY_SMIF_TWO_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR2(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], false);
        }
        else if(writeBytes == CY_SMIF_THREE_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR2(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], false);
            SMIF_TX_DATA_FIFO_WR1(baseaddr) = buff[2U];
        }
        else if(writeBytes == CY_SMIF_FOUR_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], true);
        }
        else if(writeBytes == CY_SMIF_FIVE_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], true);
            SMIF_TX_DATA_FIFO_WR1(baseaddr) = buff[4U];
        }
        else if(writeBytes == CY_SMIF_SIX_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], true);
            SMIF_TX_DATA_FIFO_WR2(baseaddr) = Cy_SMIF_PackBytesArray(&buff[4U], false);
        }
        else if(writeBytes == CY_SMIF_SEVEN_BYTES)
        {
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], true);
            SMIF_TX_DATA_FIFO_WR2(baseaddr) = Cy_SMIF_PackBytesArray(&buff[4U], false);
            SMIF_TX_DATA_FIFO_WR1(baseaddr) = buff[6U];
        }
        else /* The  future IP block with FIFO > 8*/
        {
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[0U], true);
            SMIF_TX_DATA_FIFO_WR4(baseaddr) = Cy_SMIF_PackBytesArray(&buff[4U], true);
            writeBytes = CY_SMIF_EIGHT_BYTES;
        }
        buff = &buff[writeBytes];
        buffCounter -= writeBytes;
        /* Check if we already got new data in TX_FIFO */
        freeFifoBytes = CY_SMIF_TX_DATA_FIFO_STATUS_RANGE - Cy_SMIF_GetTxFifoStatus(baseaddr);
        writeBytes = (freeFifoBytes > buffCounter)? buffCounter: freeFifoBytes;
    }

    /* Save changes in the context */
    context->txBufferAddress = buff;
    context->txBufferCounter = buffCounter;

    /* Check if all bytes are sent */
    if (0u == buffCounter)
    {
        /* Disable the TR_TX_REQ interrupt */
        Cy_SMIF_SetInterruptMask(baseaddr, Cy_SMIF_GetInterruptMask(baseaddr) & ~SMIF_INTR_TR_TX_REQ_Msk);

        context->transferStatus = (uint32_t) CY_SMIF_SEND_COMPLETE;
        if (NULL != context->txCompleteCb)
        {
            context->txCompleteCb((uint32_t) CY_SMIF_SEND_COMPLETE);
        }
    }
}


/*******************************************************************************
* Function Name: Cy_SMIF_PopRxFifo
***************************************************************************//***
*
* \internal
*
* \param baseaddr
* Holds the base address of the SMIF block registers.
*
* \param context
* Passes a configuration structure that contains the transfer parameters of the
* SMIF block.
*
* This function reads data from the RX FIFO SMIF buffer by 4, 2, or 1 bytes
* based on the data availability in the RX FIFO and amount of bytes to be
* received.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SMIF_PopRxFifo(SMIF_Type *baseaddr, cy_stc_smif_context_t *context)
{
    /* The variable that shows which is smaller: the free FIFO size or amount of bytes to be received */
    uint32_t readBytes;
    uint32_t loadedFifoBytes;
    uint32_t buffCounter = context->rxBufferCounter;
    uint8_t *buff = (uint8_t*) context->rxBufferAddress;

    loadedFifoBytes = Cy_SMIF_GetRxFifoStatus(baseaddr);
    readBytes = (loadedFifoBytes > buffCounter)? buffCounter: loadedFifoBytes;

    /* Check that after a FIFO Read, no new data is available */
    while (0U != readBytes)
    {
        if (readBytes == CY_SMIF_EIGHT_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[0U], true); 
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[4U], true);
        }
        else if(readBytes == CY_SMIF_ONE_BYTE)
        {
            buff[0U] = (uint8_t)SMIF_RX_DATA_FIFO_RD1(baseaddr);
        }
        else if(readBytes == CY_SMIF_TWO_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD2(baseaddr), &buff[0U], false); 
        }
        else if(readBytes == CY_SMIF_THREE_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD2(baseaddr), &buff[0U], false);
            buff[2U] = (uint8_t)SMIF_RX_DATA_FIFO_RD1(baseaddr);
        }
        else if(readBytes == CY_SMIF_FOUR_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[0U], true);
        }
        else if(readBytes == CY_SMIF_FIVE_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[0U], true);
            buff[4U] = (uint8_t)SMIF_RX_DATA_FIFO_RD1(baseaddr);
        }
        else if(readBytes == CY_SMIF_SIX_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[0U], true);
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD2(baseaddr), &buff[4U], false);
        }
        else if(readBytes == CY_SMIF_SEVEN_BYTES)
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[0U], true);
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD2(baseaddr), &buff[4U], false);
            buff[6U] = (uint8_t)SMIF_RX_DATA_FIFO_RD1(baseaddr);
        }
        else /* The IP block FIFO > 8*/
        {
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[0U], true);
            Cy_SMIF_UnPackByteArray(SMIF_RX_DATA_FIFO_RD4(baseaddr), &buff[4U], true);
            readBytes = CY_SMIF_EIGHT_BYTES;
        }

        buff = &buff[readBytes];
        buffCounter -= readBytes;
        /* Check if we already got new data in RX_FIFO */
        loadedFifoBytes = Cy_SMIF_GetRxFifoStatus(baseaddr);
        readBytes = (loadedFifoBytes > buffCounter)? buffCounter: loadedFifoBytes;
    }

    /* Save changes in the context */
    context->rxBufferAddress = buff;
    context->rxBufferCounter = buffCounter;

    /* Check if all bytes are received */
    if (0UL == buffCounter)
    {
        /* Disable the TR_RX_REQ interrupt */
        Cy_SMIF_SetInterruptMask(baseaddr, Cy_SMIF_GetInterruptMask(baseaddr) & ~SMIF_INTR_TR_RX_REQ_Msk);
        context->transferStatus = (uint32_t) CY_SMIF_RX_COMPLETE;
        if (NULL != context->rxCompleteCb)
        {
            context->rxCompleteCb((uint32_t) CY_SMIF_RX_COMPLETE);
        }
    }

    context->rxBufferCounter = buffCounter;
}


/*******************************************************************************
* Function Name: Cy_SMIF_PackBytesArray
***************************************************************************//***
*
* \internal
*
* This function packs 0-numBytes of the buff byte array into a 4-byte value.
*
* \param buff
* The byte array to pack.
*
* \param fourBytes
*  - True: The pack is for a 32-bit value.
*  - False: The pack is for a 16-bit value.
*
* \return
*  The 4-byte value packed from the byte array.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SMIF_PackBytesArray(uint8_t const buff[], bool fourBytes)
{
    uint32_t result = 0UL;

    result = ((uint32_t)buff[1UL] << 8UL) | (uint32_t)buff[0UL];

    if(fourBytes)
    {
        result |= ((uint32_t)buff[3UL] << 24UL) | ((uint32_t)buff[2UL] << 16UL);
    }

    return result;
}


/*******************************************************************************
* Function Name: Cy_SMIF_UnPackByteArray
***************************************************************************//***
*
* \internal
*
* This function unpacks 0-numBytes from a 4-byte value into the byte array outBuff.
*
* \param smifReg
*  The 4-byte value to unpack.
*
* \param outBuff
* The byte array to fill.
*
* \param fourBytes
*  - The True unpack is for a 32-bit value.
*  - The False unpack is for a 16-bit value.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SMIF_UnPackByteArray(uint32_t inValue, uint8_t outBuff[], bool fourBytes)
{
    outBuff[0UL] = (uint8_t)(inValue & 0xFFUL);
    outBuff[1UL] = (uint8_t)((inValue >> 8UL ) & 0xFFUL);

    if(fourBytes)
    {
        outBuff[2UL] = (uint8_t)((inValue >> 16UL) & 0xFFUL);
        outBuff[3UL] = (uint8_t)((inValue >> 24UL) & 0xFFUL);
    }
}


/*******************************************************************************
* Function Name: Cy_SMIF_TimeoutRun
****************************************************************************//**
*
* \internal
*
* This function checks if the timeout is expired. Use the Cy_SysLib_DelayUs() function for
* implementation.
*
* \param timeoutUnits
*  The pointer to the timeout. The timeout measured in microseconds is multiplied by
*  CY_SMIF_WAIT_1_UNIT.
*
* \return
* A timeout status:
*     - \ref CY_SMIF_SUCCESS - The timeout has not expired or input timeoutUnits is 0.
*     - \ref CY_SMIF_EXCEED_TIMEOUT - The timeout has expired.
*
*******************************************************************************/
__STATIC_INLINE cy_en_smif_status_t Cy_SMIF_TimeoutRun(uint32_t *timeoutUnits)
{
    cy_en_smif_status_t status = CY_SMIF_SUCCESS;
    if (*timeoutUnits > 0u)
    {
        Cy_SysLib_DelayUs(CY_SMIF_WAIT_1_UNIT);
        --(*timeoutUnits);
        status = (0u == (*timeoutUnits))? CY_SMIF_EXCEED_TIMEOUT: CY_SMIF_SUCCESS;
    }
    return status;
}


/*******************************************************************************
* Function Name: Cy_SMIF_GetDeviceBySlot
****************************************************************************//**
*
* \internal
* This function returns the address of the SMIF device registers structure by the slave
* slot number.
*
* \param base
* Holds the base address of the SMIF block registers.
*
* \param slaveSelect
* The slave device ID. This number is either CY_SMIF_SLAVE_SELECT_0 or
* CY_SMIF_SLAVE_SELECT_1 or CY_SMIF_SLAVE_SELECT_2 or CY_SMIF_SLAVE_SELECT_3
* (\ref cy_en_smif_slave_select_t). It defines the slave-select line to use
* during the transmission.
*
*******************************************************************************/
__STATIC_INLINE SMIF_DEVICE_Type volatile * Cy_SMIF_GetDeviceBySlot(SMIF_Type *base,
                                            cy_en_smif_slave_select_t slaveSelect)
{
    SMIF_DEVICE_Type volatile *device;
    /* Connect the slave to its data lines */
    switch (slaveSelect)
    {
        case CY_SMIF_SLAVE_SELECT_0:
            device = &(SMIF_DEVICE_IDX(base, 0)); 
            break;
        case CY_SMIF_SLAVE_SELECT_1:
            device = &(SMIF_DEVICE_IDX(base, 1));
            break;
        case CY_SMIF_SLAVE_SELECT_2:
            device = &(SMIF_DEVICE_IDX(base, 2));
            break;
        case CY_SMIF_SLAVE_SELECT_3:
            device = &(SMIF_DEVICE_IDX(base, 3));
            break;
        default:
            /* A user error */
            device = NULL;
            break;
    }

    return device;
}

/** \endcond */
/** \} group_smif_low_level_functions */

#if defined(__cplusplus)
}
#endif

#endif /* CY_IP_MXSMIF */

#endif /* (CY_SMIF_H) */

/** \} group_smif */


/* [] END OF FILE */