//*****************************************************************************
//
//! @file am_hal_iom.h
//!
//! @brief Functions for interfacing with IO Master serial (SPI/I2C) modules.
//!
//! @addtogroup iom4_4b IOM - IO Master (SPI/I2C)
//! @ingroup apollo4b_hal
//! @{

//*****************************************************************************

//*****************************************************************************
//
// Copyright (c) 2024, Ambiq Micro, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision ambiqvos_r4.5-fdfa8cf6a4 of the AmbiqSuite Development Package.
//
//*****************************************************************************

#ifndef AM_HAL_IOM_H
#define AM_HAL_IOM_H

#include "am_mcu_apollo.h"

//*****************************************************************************
//
//! CMSIS-Style macro for handling a variable IOM module number.
//
//*****************************************************************************
#define IOMn(n) ((IOM0_Type*)(IOM0_BASE + (n * (IOM1_BASE - IOM0_BASE))))

//
//! Maximum time to wait for hardware to finish a blocking transaction
//! This is an escape to allow for bailing out in case of faulty peripheral
//! (e.g. a device pulling the I2C clock low)
//
#define AM_HAL_IOM_MAX_BLOCKING_WAIT    500000 // 0.5 sec

//
//! Size guideline for allocation of application supploed buffers
//
#define AM_HAL_IOM_CQ_ENTRY_SIZE               (24 * sizeof(uint32_t))
#define AM_HAL_IOM_HIPRIO_ENTRY_SIZE           (8 * sizeof(uint32_t))

#define AM_HAL_IOM_SC_CLEAR(flag)              ((flag) << 16)
#define AM_HAL_IOM_SC_SET(flag)                ((flag))

//
//! For IOM - Need to Clear the flag for unpausing
//
#define AM_HAL_IOM_SC_UNPAUSE(flag)            AM_HAL_IOM_SC_CLEAR(flag)
#define AM_HAL_IOM_SC_PAUSE(flag)              AM_HAL_IOM_SC_SET(flag)

//
//! Use this macro to directly control the flags
//
#define AM_HAL_IOM_SETCLR(iom, scVal)           \
do {                                        \
  IOMn((iom))->CQSETCLEAR = (scVal);      \
} while (0);

//
//! Flags 5, 7 & 6 are reserved by HAL
//
#define AM_HAL_IOM_PAUSE_FLAG_RESV             (IOM0_CQPAUSEEN_CQPEN_SWFLAGEN7 | IOM0_CQPAUSEEN_CQPEN_SWFLAGEN6 | IOM0_CQPAUSEEN_CQPEN_SWFLAGEN5)
#define AM_HAL_IOM_SC_RESV_MASK                (AM_HAL_IOM_PAUSE_FLAG_RESV | (AM_HAL_IOM_PAUSE_FLAG_RESV << 8) | (AM_HAL_IOM_PAUSE_FLAG_RESV << 16))

// We use SWFLAGEN7 to control SW pausing Command Queue - default unPause
// We use SWFLAGEN6 to pause on the sequece loopback - default Pause
#define AM_HAL_IOM_PAUSE_FLAG_IDX      (_VAL2FLD(IOM0_CQPAUSEEN_CQPEN, IOM0_CQPAUSEEN_CQPEN_IDXEQ))
#define AM_HAL_IOM_PAUSE_FLAG_CQ       (_VAL2FLD(IOM0_CQPAUSEEN_CQPEN, IOM0_CQPAUSEEN_CQPEN_SWFLAGEN7))
#define AM_HAL_IOM_PAUSE_FLAG_SEQLOOP  (_VAL2FLD(IOM0_CQPAUSEEN_CQPEN, IOM0_CQPAUSEEN_CQPEN_SWFLAGEN6))
#define AM_HAL_IOM_PAUSE_FLAG_BLOCK    (_VAL2FLD(IOM0_CQPAUSEEN_CQPEN, IOM0_CQPAUSEEN_CQPEN_SWFLAGEN5))

// By default - we Pause CQ for no more entries, or force pause from SW
#define AM_HAL_IOM_PAUSE_DEFAULT       AM_HAL_IOM_PAUSE_FLAG_IDX
#define AM_HAL_IOM_CQP_PAUSE_DEFAULT   (AM_HAL_IOM_PAUSE_FLAG_IDX | AM_HAL_IOM_PAUSE_FLAG_CQ)

//*****************************************************************************
//
//! IOM Specific status codes
//
//*****************************************************************************
typedef enum
{
    //
    //! Error in hardware command issued or illegal access by SW
    //
    AM_HAL_IOM_ERR_INVALID_OPER = AM_HAL_STATUS_MODULE_SPECIFIC_START,

    //
    //! Loss of I2C multi-master arbitration
    //
    AM_HAL_IOM_ERR_I2C_ARB,

    //
    //! I2C NAK
    //
    AM_HAL_IOM_ERR_I2C_NAK,
}
am_hal_iom_err_e;

//*****************************************************************************
//
//! @name General defines
//! @{
//
//*****************************************************************************
#define AM_HAL_IOM_FIFO_SIZE_MAX        32
#define AM_HAL_IOM_MAX_OFFSETSIZE       5
#define AM_HAL_IOM_MAX_TXNSIZE_SPI      4095
#define AM_HAL_IOM_MAX_TXNSIZE_I2C      4095
#define AM_HAL_IOM_MAX_CS_SPI           4
//! @}

//*****************************************************************************
//
//! @name enumeration types for the IOM.
//! @{
//
//*****************************************************************************

//
//! IOM mode enumerations
//
typedef enum
{
    AM_HAL_IOM_SPI_MODE,
    AM_HAL_IOM_I2C_MODE,
    AM_HAL_IOM_NUM_MODES
}
am_hal_iom_mode_e;

//
//! Transmit or receive enumerations.
//! Make these enums consistent with the IOM CMD register values.
//
typedef enum
{
    AM_HAL_IOM_TX,
    AM_HAL_IOM_RX,
    AM_HAL_IOM_FULLDUPLEX,
}
am_hal_iom_dir_e;

//
//! Enumerate the SPI modes.  Note that these are arranged per the ordering of
//! SPHA (bit1) and SPOL (bit0) in the IOM.MSPICFG register.
//
typedef enum
{
    AM_HAL_IOM_SPI_MODE_0,                  // CPOL = 0; CPHA = 0
    AM_HAL_IOM_SPI_MODE_2,                  // CPOL = 1; CPHA = 0
    AM_HAL_IOM_SPI_MODE_1,                  // CPOL = 0; CPHA = 1
    AM_HAL_IOM_SPI_MODE_3,                  // CPOL = 1; CPHA = 1
}
am_hal_iom_spi_mode_e;
//! @}

#ifdef __cplusplus
extern "C"
{
#endif

//*****************************************************************************
//
//! @brief Transfer callback function prototype
//
//*****************************************************************************
typedef void (*am_hal_iom_callback_t)(void *pCallbackCtxt, uint32_t transactionStatus);

//
//*****************************************************************************
//
//! @brief Configuration structure for the IOM.
//
//*****************************************************************************
typedef struct
{
    //
    //! Select the interface mode, SPI or I2C
    //
    am_hal_iom_mode_e eInterfaceMode;

    //
    //! Select the interface clock frequency
    //
    uint32_t ui32ClockFreq;

    //
    //! Select the SPI clock mode (polarity/phase). Ignored for I2C operation.
    //
    am_hal_iom_spi_mode_e eSpiMode;

    //
    //! Non-Blocking transaction memory configuration
    //! Set length and pointer to Transfer Control Buffer.
    //! Length is in 4 byte multiples
    //
    uint32_t *pNBTxnBuf;
    uint32_t ui32NBTxnBufLength;
}
am_hal_iom_config_t;

//*****************************************************************************
//
//! Configuration structure for an individual SPI device.
//
//*****************************************************************************
typedef struct
{
    //
    //! IOM module to use for communicating with this device.
    //
    uint32_t ui32Module;

    //
    //! Chip select signal that should be used for this device.
    //
    uint32_t ui32ChipSelect;

    //
    //! Additional options that will ALWAYS be ORed into the command word.
    //
    uint32_t ui32Options;
}
am_hal_iom_spi_device_t;

//*****************************************************************************
//
//! Configuration structure for an individual I2C device.
//
//*****************************************************************************
typedef struct
{
    //
    //! IOM module to use for communicating with this device.
    //
    uint32_t ui32Module;

    //
    //! I2C address associated with this device.
    //
    uint32_t ui32BusAddress;

    //
    //! Additional options that will ALWAYS be ORed into the command word.
    //
    uint32_t ui32Options;
}
am_hal_iom_i2c_device_t;

//*****************************************************************************
//
//! @brief Status structure for the IOM.
//
//*****************************************************************************
typedef struct
{
    //
    //! IOM status.
    //
    bool     bStatIdle;
    bool     bStatCmdAct;
    bool     bStatErr;

    //
    //! DMA status
    //! One of:
    //!     AM_HAL_IOM_STATUS_DMA_IN_PROGRESS
    //!     AM_HAL_IOM_STATUS_XFER_COMPLETE
    //!     AM_HAL_IOM_STATUS_DMAERR
    //
    uint32_t ui32DmaStat;

    uint32_t ui32MaxTransactions;
    uint32_t ui32NumPendTransactions;
}
am_hal_iom_status_t;

//*****************************************************************************
//
//! IOM transfer structure
//
//*****************************************************************************
typedef struct
{
    union
    {
        //
        //! Chip enable (chip select) for this transaction on this device.
        //
        uint32_t ui32SpiChipSelect;
        uint32_t ui32I2CDevAddr;
    }
    uPeerInfo;

    //
    //! Instruction length (0 - 5).
    //
    uint32_t ui32InstrLen;

    //
    //! Device Instruction (aka Command). Often used as the offset.
    //
    uint64_t ui64Instr;

    //
    //! Number of bytes to transfer
    //
    uint32_t ui32NumBytes;

    //
    //! Transfer Direction (Transmit/Receive)
    //
    am_hal_iom_dir_e eDirection;

    //
    //! Buffer
    //
    uint32_t *pui32TxBuffer;
    uint32_t *pui32RxBuffer;

    //
    // Continue - holds the SPI or I2C bus for multiple transactions.
    //
    bool     bContinue;

    //
    //! Repeat Count
    //
    uint8_t  ui8RepeatCount;  // Deprecated - Not suppoprted

    //
    //! DMA: Priority 0 = Low (best effort); 1 = High (service immediately)
    //
    uint8_t  ui8Priority;

    //
    //! Command Queue Advanced control on gating conditions for transaction to start
    //
    uint32_t ui32PauseCondition;
    //
    //! Command Queue Advanced Post-Transaction status setting
    //
    uint32_t ui32StatusSetClr;

}
am_hal_iom_transfer_t;

//*****************************************************************************
//
//! IOM Sequence End
//
//*****************************************************************************
typedef struct
{
    //
    //! Looping Sequence
    //
    bool                        bLoop;

    //
    //! Command Queue Transaction Gating
    //
    uint32_t                    ui32PauseCondition;

    //
    //! Command Queue Post-Transaction status setting
    //
    uint32_t                    ui32StatusSetClr;
}
am_hal_iom_seq_end_t;

//*****************************************************************************
//
//! IOM High Priority Config
//
//*****************************************************************************
typedef struct
{
    //
    //! Buffer provided to store the high priority transaction context
    //
    uint8_t                     *pBuf;

    //
    //! Size of buffer in bytes
    //
    uint32_t                    size;
}
am_hal_iom_hiprio_cfg_t;

#define AM_HAL_IOM_DCX_INVALID  0xFF

//
//! IOM DCX config
//
typedef struct
{

    //
    //! CS for which this configuration applies
    //
    uint8_t cs;

    //
    //! alternate CS line used for DCX - AM_HAL_IOM_DCX_INVALID indicates DCX is not used
    //
    uint8_t dcx;
}
am_hal_iom_dcx_cfg_t;

//*****************************************************************************
//
//! IOM Command Queue
//
//*****************************************************************************
typedef struct
{
    //
    //! Command Queue Advanced control on gating conditions for transaction to start
    //
    uint32_t ui32PauseCondition;

    //
    //! Command Queue Advanced Post-Transaction status setting
    //
    uint32_t ui32StatusSetClr;

    //
    //! Raw Command Queue Entry list.
    //
    am_hal_cmdq_entry_t *pCQEntry;

    //
    //! Number of Command Queue Entries in the list.
    //
    uint32_t numEntries;

    //
    //! Callback function to call at entry completion.
    //
    am_hal_iom_callback_t pfnCallback;

    //
    //! Callback context
    //
    void *pCallbackCtxt;

    //
    //! Jump back address
    //
    uint32_t *pJmpAddr;
}
am_hal_iom_cq_raw_t;

//*****************************************************************************
//
//! IOM Request
//
//*****************************************************************************
typedef enum
{
    //! Used to set/clear 8 CQ Pause flags - reserved flags are defined as AM_HAL_IOM_PAUSE_FLAG_RESV
    //! Pass uint32_t as pArgs
    AM_HAL_IOM_REQ_FLAG_SETCLR = 0,
    //! Pass uint32_t as pArgs
    AM_HAL_IOM_REQ_SPI_LSB,
    //! Pass uint32_t as pArgs
    AM_HAL_IOM_REQ_RESV1,
    //! Pass uint32_t as pArgs
    AM_HAL_IOM_REQ_SPI_RDTHRESH,
    //! Pass uint32_t as pArgs
    AM_HAL_IOM_REQ_SPI_WRTHRESH,
    //! Pass uint32_t as pArgs
    AM_HAL_IOM_REQ_LINK_MSPI,
    //! Pause the CQ gracefully
    //! pArgs N/A
    AM_HAL_IOM_REQ_PAUSE,
    //! Unpause the CQ
    // pArgs N/A
    AM_HAL_IOM_REQ_UNPAUSE,
    //! Get in and out of Sequence Mode - which allows building a sequence, which either runs once, or repeats
    //! Pass in bool as pArgs - true/false
    AM_HAL_IOM_REQ_SET_SEQMODE,
    //! pArgs N/A
    AM_HAL_IOM_REQ_SEQ_END,
    //! Initialize configuration for high priority transactions
    //! These transactions take precedence over existing CQ transactions
    //! Pass am_hal_iom_hiprio_cfg_t * as pArgs
    AM_HAL_IOM_REQ_INIT_HIPRIO,
    //! Create a block of transactions which are not paused in between
    //! pArgs N/A
    AM_HAL_IOM_REQ_START_BLOCK,
    //! pArgs N/A
    AM_HAL_IOM_REQ_END_BLOCK,
    //! Control the DCX line
    //! Pass am_hal_iom_dcx_cfg_t * as pArgs
    AM_HAL_IOM_REQ_SET_DCX,
    //! Raw CQ transaction
    //! Pass am_hal_iom_cq_raw_t * as pArgs
    AM_HAL_IOM_REQ_CQ_RAW,
    AM_HAL_IOM_REQ_MAX
}
am_hal_iom_request_e;

#define am_hal_iom_buffer(A)            \
union                                   \
  {                                     \
    uint32_t words[(A + 3) >> 2];       \
      uint8_t bytes[A];                 \
  }

//*****************************************************************************
//
//! @name IOM Clock Frequencies
//! @{
//! Macro definitions for common SPI and I2C clock frequencies.
//!
//! These macros may be used with the ui32ClockFrequency member of the
//! am_hal_iom_config_t structure to set the clock frequency of the serial
//! interfaces.
//!
//! This list of frequencies is not exhaustive by any means. If your desired
//! frequency is not in this list, simply set ui32ClockFrequency to the
//! desired frequency (in Hz) when calling am_hal_iom_config().
//
//*****************************************************************************
#define AM_HAL_IOM_48MHZ    48000000
#define AM_HAL_IOM_24MHZ    24000000
#define AM_HAL_IOM_16MHZ    16000000
#define AM_HAL_IOM_12MHZ    12000000
#define AM_HAL_IOM_8MHZ      8000000
#define AM_HAL_IOM_6MHZ      6000000
#define AM_HAL_IOM_4MHZ      4000000
#define AM_HAL_IOM_3MHZ      3000000
#define AM_HAL_IOM_2MHZ      2000000
#define AM_HAL_IOM_1_5MHZ    1500000
#define AM_HAL_IOM_1MHZ      1000000
#define AM_HAL_IOM_750KHZ     750000
#define AM_HAL_IOM_500KHZ     500000
#define AM_HAL_IOM_400KHZ     400000
#define AM_HAL_IOM_375KHZ     375000
#define AM_HAL_IOM_250KHZ     250000
#define AM_HAL_IOM_125KHZ     125000
#define AM_HAL_IOM_100KHZ     100000
#define AM_HAL_IOM_50KHZ       50000
#define AM_HAL_IOM_10KHZ       10000
//! @}

//
//! Max Frequency supported in HAL
//
#define AM_HAL_IOM_MAX_FREQ AM_HAL_IOM_48MHZ

//*****************************************************************************
//
//! @name IOM Interrupts
//! @{
//
//*****************************************************************************
#define AM_HAL_IOM_INT_CQERR            IOM0_INTEN_CQERR_Msk        //!< Error during command queue operations
#define AM_HAL_IOM_INT_CQUPD            IOM0_INTEN_CQUPD_Msk        //!< Command queue operation  performed a register write with the register address bit 0 set to 1.
#define AM_HAL_IOM_INT_CQPAUSED         IOM0_INTEN_CQPAUSED_Msk     //!< Command queue operation paused
#define AM_HAL_IOM_INT_DERR             IOM0_INTEN_DERR_Msk         //!< DMA error received
#define AM_HAL_IOM_INT_DCMP             IOM0_INTEN_DCMP_Msk         //!< DMA transfer complete
#define AM_HAL_IOM_INT_ARB              IOM0_INTEN_ARB_Msk          //!< Arbitration loss
#define AM_HAL_IOM_INT_STOP             IOM0_INTEN_STOP_Msk         //!< STOP command
#define AM_HAL_IOM_INT_START            IOM0_INTEN_START_Msk        //!< START command
#define AM_HAL_IOM_INT_ICMD             IOM0_INTEN_ICMD_Msk         //!< ILLEGAL command
#define AM_HAL_IOM_INT_IACC             IOM0_INTEN_IACC_Msk         //!< Illegal FIFO access
#define AM_HAL_IOM_INT_NAK              IOM0_INTEN_NAK_Msk          //!< I2C NAK
#define AM_HAL_IOM_INT_FOVFL            IOM0_INTEN_FOVFL_Msk        //!< Write FIFO overflow
#define AM_HAL_IOM_INT_FUNDFL           IOM0_INTEN_FUNDFL_Msk       //!< Read FIFO underflow
#define AM_HAL_IOM_INT_THR              IOM0_INTEN_THR_Msk          //!< FIFO threshold interrupt
#define AM_HAL_IOM_INT_CMDCMP           IOM0_INTEN_CMDCMP_Msk       //!< Command complete

#define AM_HAL_IOM_INT_SWERR            (AM_HAL_IOM_INT_ICMD | AM_HAL_IOM_INT_IACC | AM_HAL_IOM_INT_FOVFL | AM_HAL_IOM_INT_FUNDFL)
#define AM_HAL_IOM_INT_I2CARBERR        (AM_HAL_IOM_INT_ARB)
#define AM_HAL_IOM_INT_INTERR           (AM_HAL_IOM_INT_CQERR | AM_HAL_IOM_INT_DERR)
#define AM_HAL_IOM_INT_ALL              0xFFFFFFFF

//
//! Unsuccessful end of a transaction results in one more more of the following
//
#define AM_HAL_IOM_INT_ERR          (AM_HAL_IOM_INT_SWERR | AM_HAL_IOM_INT_I2CARBERR | AM_HAL_IOM_INT_INTERR | AM_HAL_IOM_INT_NAK)
//! @}

//*****************************************************************************
//
//! @brief IOM initialization function
//!
//! @param ui32Module   - module instance.
//! @param ppHandle     - returns the handle for the module instance.
//!
//! This function accepts a module instance, allocates the interface and then
//! returns a handle to be used by the remaining interface functions.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_initialize(uint32_t ui32Module, void **ppHandle);

//*****************************************************************************
//
//! @brief IOM configuration function
//!
//! @param pHandle      - handle for the IOM.
//! @param psConfig      - pointer to the IOM specific configuration.
//!
//! This function configures the interface settings for the IO Master.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_configure(void *pHandle,
                                     const am_hal_iom_config_t *psConfig);

//*****************************************************************************
//
//! @brief IOM enable function
//!
//! @param pHandle      - handle for the interface.
//!
//! This function enables the IOM for operation.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_enable(void *pHandle);

//*****************************************************************************
//
//! @brief IOM disable function
//!
//! @param pHandle      - handle for the interface.
//!
//! This function disables the IOMaster from operation.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_disable(void *pHandle);

//*****************************************************************************
//
//! @brief IOM control function
//!
//! @param pHandle      - handle for the IOM.
//! @param eReq         - device specific special request code.
//! @param pArgs - Pointer to arguments for Control Switch Case
//!
//! This function allows advanced settings
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_control(void *pHandle, am_hal_iom_request_e eReq, void *pArgs);

//*****************************************************************************
//
//! @brief IOM status function
//!
//! @param pHandle      - handle for the interface.
//! @param psStatus     - pointer to an interface specific structure used to
//!                       return the status of the interface.
//!
//! This function returns the current status of the interface.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_status_get(void *pHandle, am_hal_iom_status_t *psStatus);

//*****************************************************************************
//
//! @brief IOM enable interrupts function
//!
//! @param pHandle      - handle for the interface.
//! @param ui32IntMask  - interface specific interrupt mask.
//!
//! This function enables the specific indicated interrupts.
//!
//! The following are valid enable bits, any of which can be ORed together.
//!   AM_REG_IOM_INTEN_CQERR_M      // Error during command queue operations
//!   AM_REG_IOM_INTEN_CQCMP_M      // Command queue operation complete
//!   AM_REG_IOM_INTEN_DERR_M       // DMA error received
//!   AM_REG_IOM_INTEN_DCMP_M       // DMA transfer complete
//!   AM_REG_IOM_INTEN_ARB_M        // Arbitration loss
//!   AM_REG_IOM_INTEN_STOP_M       // STOP command
//!   AM_REG_IOM_INTEN_START_M      // START command
//!   AM_REG_IOM_INTEN_ICMD         // ILLEGAL command
//!   AM_REG_IOM_INTEN_IACC_M       // Illegal FIFO access
//!   AM_REG_IOM_INTEN_NAK_M        // I2C NAK
//!   AM_REG_IOM_INTEN_FOVFL_M      // Write FIFO overflow
//!   AM_REG_IOM_INTEN_FUNDFL_M     // Read FIFO underflow
//!   AM_REG_IOM_INTEN_THR_M        // FIFO threshold interrupt
//!   AM_REG_IOM_INTEN_CMDCMP_M     // Command complete
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_interrupt_enable(void *pHandle, uint32_t ui32IntMask);

//*****************************************************************************
//
//! @brief IOM disable interrupts function
//!
//! @param pHandle      - handle for the interface.
//! @param ui32IntMask  - interface specific interrupt mask.
//!
//! This function disables the specified interrupts.
//!
//! @return status      - generic or interface specific status.
//!
//! The following are valid disable bits, any of which can be ORed together.
//!   AM_REG_IOM_INTEN_CQERR_M      // Error during command queue operations
//!   AM_REG_IOM_INTEN_CQCMP_M      // Command queue operation complete
//!   AM_REG_IOM_INTEN_DERR_M       // DMA error received
//!   AM_REG_IOM_INTEN_DCMP_M       // DMA transfer complete
//!   AM_REG_IOM_INTEN_ARB_M        // Arbitration loss
//!   AM_REG_IOM_INTEN_STOP_M       // STOP command
//!   AM_REG_IOM_INTEN_START_M      // START command
//!   AM_REG_IOM_INTEN_ICMD         // ILLEGAL command
//!   AM_REG_IOM_INTEN_IACC_M       // Illegal FIFO access
//!   AM_REG_IOM_INTEN_NAK_M        // I2C NAK
//!   AM_REG_IOM_INTEN_FOVFL_M      // Write FIFO overflow
//!   AM_REG_IOM_INTEN_FUNDFL_M     // Read FIFO underflow
//!   AM_REG_IOM_INTEN_THR_M        // FIFO threshold interrupt
//!   AM_REG_IOM_INTEN_CMDCMP_M     // Command complete
//
//*****************************************************************************
extern uint32_t am_hal_iom_interrupt_disable(void *pHandle, uint32_t ui32IntMask);

//*****************************************************************************
//
//! @brief IOM get interrupt status
//!
//! @param pHandle        - handle for the interface.
//! @param bEnabledOnly   - determines whether disabled interrupts are included
//!                         in the status.
//! @param pui32IntStatus - pointer to a uint32_t to return the interrupt status
//!
//! This function returns the interrupt status for the given peripheral.
//!
//! The following are valid status bits.
//!   AM_REG_IOM_INTSTAT_CQERR_M    // Error during command queue operations
//!   AM_REG_IOM_INTSTAT_CQCMP_M    // Command queue operation complete
//!   AM_REG_IOM_INTSTAT_DERR_M     // DMA error received
//!   AM_REG_IOM_INTSTAT_DCMP_M     // DMA transfer complete
//!   AM_REG_IOM_INTSTAT_ARB_M      // Arbitration loss
//!   AM_REG_IOM_INTSTAT_STOP_M     // STOP command
//!   AM_REG_IOM_INTSTAT_START_M    // START command
//!   AM_REG_IOM_INTSTAT_ICMD       // ILLEGAL command
//!   AM_REG_IOM_INTSTAT_IACC_M     // Illegal FIFO access
//!   AM_REG_IOM_INTSTAT_NAK_M      // I2C NAK
//!   AM_REG_IOM_INTSTAT_FOVFL_M    // Write FIFO overflow
//!   AM_REG_IOM_INTSTAT_FUNDFL_M   // Read FIFO underflow
//!   AM_REG_IOM_INTSTAT_THR_M      // FIFO threshold interrupt
//!   AM_REG_IOM_INTSTAT_CMDCMP_M   // Command complete
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_interrupt_status_get(void *pHandle, bool bEnabledOnly,
                                                uint32_t *pui32IntStatus);

//*****************************************************************************
//
//! @brief IOM interrupt clear
//!
//! @param pHandle      - handle for the interface.
//! @param ui32IntMask  - interface specific interrupt mask.
//!
//! This function clears the interrupts for the given peripheral.
//!
//! The following are valid clear bits, any of which can be ORed together.
//!   AM_REG_IOM_INTCLR_CQERR_M     // Error during command queue operations
//!   AM_REG_IOM_INTCLR_CQCMP_M     // Command queue operation complete
//!   AM_REG_IOM_INTCLR_DERR_M      // DMA error received
//!   AM_REG_IOM_INTCLR_DCMP_M      // DMA transfer complete
//!   AM_REG_IOM_INTCLR_ARB_M       // Arbitration loss
//!   AM_REG_IOM_INTCLR_STOP_M      // STOP command
//!   AM_REG_IOM_INTCLR_START_M     // START command
//!   AM_REG_IOM_INTCLR_ICMD        // ILLEGAL command
//!   AM_REG_IOM_INTCLR_IACC_M      // Illegal FIFO access
//!   AM_REG_IOM_INTCLR_NAK_M       // I2C NAK
//!   AM_REG_IOM_INTCLR_FOVFL_M     // Write FIFO overflow
//!   AM_REG_IOM_INTCLR_FUNDFL_M    // Read FIFO underflow
//!   AM_REG_IOM_INTCLR_THR_M       // FIFO threshold interrupt
//!   AM_REG_IOM_INTCLR_CMDCMP_M    // Command complete
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_interrupt_clear(void *pHandle, uint32_t ui32IntMask);

//*****************************************************************************
//
//! @brief IOM interrupt service routine
//!
//! @param pHandle      - handle for the interface.
//! @param ui32IntMask  - interface specific interrupt mask indicating
//!                       interrupts to be serviced
//!
//! This function is designed to be called from within the user defined ISR
//! (am_iom_isr) in order to service the non-blocking, queued, or DMA processing
//! for a given module instance.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_interrupt_service(void *pHandle, uint32_t ui32IntMask);

//*****************************************************************************
//
//! @brief IOM power control function
//!
//! @param pHandle      - handle for the interface.
//! @param ePowerState  - the desired power state to move the peripheral to.
//! @param retainState  - flag (if true) to save/restore perhipheral state upon
//!                       power state change.
//!
//! This function updates the peripheral to a given power state.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_power_ctrl(void *pHandle,
                                         am_hal_sysctrl_power_state_e ePowerState,
                                         bool retainState);

//*****************************************************************************
//
//! @brief IOM blocking transfer function
//!
//! @param pHandle      - handle for the interface.
//! @param psTransaction - pointer to the transaction control structure.
//!
//! This function performs a transaction on the IOM in PIO mode.  It handles
//! half duplex transactions only (TX or RX).
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_blocking_transfer(void *pHandle,
                                             am_hal_iom_transfer_t *psTransaction);

//*****************************************************************************
//
//! @brief IOM non-blocking transfer function
//!
//! @param pHandle      - handle for the interface.
//! @param psTransaction - pointer to the uniform transaction control structure.
//! @param pfnCallback  - pointer the callback function to be executed when
//!                       transaction is complete can be set to NULL).
//! @param pCallbackCtxt- context registered which is passed on to the callback
//!                       function
//!
//! This function performs a transaction on the interface.  It handles both full
//! and half duplex transactions.  The callback is executed when the transaction
//! is complete.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
extern uint32_t am_hal_iom_nonblocking_transfer(void *pHandle,
                                                am_hal_iom_transfer_t *psTransaction,
                                                am_hal_iom_callback_t pfnCallback,
                                                void *pCallbackCtxt);

//*****************************************************************************
//
//! @brief IOM uninitialize function
//!
//! @param pHandle      - returns the handle for the module instance.
//!
//! This function accepts a handle to the initialized interface and returns
//! the peripheral instance to a known uninitialized state.
//!
//! @return status      - generic or interface specific status.
//
//*****************************************************************************
//
// Uninitialize the interface and return the handle to a known state.
//
extern uint32_t am_hal_iom_uninitialize(void *pHandle);

//*****************************************************************************
//
//! @brief Perform a Full Duplex transaction to a selected SPI interface
//!
//! @param pHandle              - handle for the interface.
//! @param psTransaction         - pointer to the uniform transaction control structure.
//!
//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
//! This means that you will need to byte-pack the \e pui32TxData array with the
//! data you intend to send over the interface. One easy way to do this is to
//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
//! put your actual data into the array. If there are not enough bytes in your
//! desired message to completely fill the last 32-bit word, you may pad that
//! last word with bytes of any value. The IOM hardware will only read the
//! first \e ui32NumBytes in the \e pui32TxData array.
//!
//! @return HAL status of the operation.
//
//*****************************************************************************
extern uint32_t am_hal_iom_spi_blocking_fullduplex(void *pHandle,
                                                   am_hal_iom_transfer_t *psTransaction);

//*****************************************************************************
//
//! @brief IOM High Priority transfer function
//!
//! @param pHandle       - the handle for the IOM instance
//! @param psTransaction - pointer to the transfer control structure.
//! @param pfnCallback   - pointer the callback function to be executed when
//!                        transfer is complete.
//! @param pCallbackCtxt - pointer to a context to be passed to the callback
//!                        function.
//!
//! This function performs injection of a "high priority" transaction into the
//! IOM processing when ongoing Command Queue (CQ) operations are active.  The
//! function pauses the CQ, manually schedules a DMA operation, then restarts
//! the CQ.
//!
//! @return status       - generic or interface specific status.
//
//*****************************************************************************
uint32_t am_hal_iom_highprio_transfer(void *pHandle,
                                      am_hal_iom_transfer_t *psTransaction,
                                      am_hal_iom_callback_t pfnCallback,
                                      void *pCallbackCtxt);

#ifdef __cplusplus
}
#endif

#endif // AM_HAL_IOM_H

//*****************************************************************************
//
// End Doxygen group.
//! @}
//
//*****************************************************************************

