/*
 * Copyright (c) 2021, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  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.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 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 OWNER 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.
 */

#include <ti/driverlib/dl_mcan.h>

#ifdef __MSPM0_HAS_MCAN__

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/**
 * \brief  MCAN MSG RAM BANK number for ECC AGGR.
 */
#define MCANSS_MSG_RAM_NUM (0U)

/**
 * \brief  Maximum Number of Rx Buffers.
 */
#define MCANSS_RX_BUFFER_MAX (64U)

/**
 * \brief  Maximum Number of Tx Buffers.
 */
#define MCANSS_TX_BUFFER_MAX (32U)

/**
 * \brief  Macro for standard Message ID filter.
 */
#define MCANSS_STD_ID_FILTER_SIZE_WORDS (1U)

/**
 * \brief  Macro for extended Message ID filter.
 */
#define MCANSS_EXT_ID_FILTER_SIZE_WORDS (2U)

/**
 * \brief  Macro for Tx Event FIFO element size.
 */
#define MCANSS_TX_EVENT_FIFO_SIZE_WORDS (2U)

/**
 * \brief  Macro for Interrupt Line enable mask.
 */
#define MCANSS_INTR_LINE_EN_MASK ((MCAN_ILE_EINT0_MASK | MCAN_ILE_EINT1_MASK))

/**
 * \brief  Mask and shift for Tx Buffers elements.
 */
#define MCANSS_TX_BUFFER_ELEM_ID_SHIFT (0U)
#define MCANSS_TX_BUFFER_ELEM_ID_MASK (0x1FFFFFFFU)
#define MCANSS_TX_BUFFER_ELEM_RTR_SHIFT (29U)
#define MCANSS_TX_BUFFER_ELEM_RTR_MASK (0x20000000U)
#define MCANSS_TX_BUFFER_ELEM_XTD_SHIFT (30U)
#define MCANSS_TX_BUFFER_ELEM_XTD_MASK (0x40000000U)
#define MCANSS_TX_BUFFER_ELEM_ESI_SHIFT (31U)
#define MCANSS_TX_BUFFER_ELEM_ESI_MASK (0x80000000U)
#define MCANSS_TX_BUFFER_ELEM_DLC_SHIFT (16U)
#define MCANSS_TX_BUFFER_ELEM_DLC_MASK (0x000F0000U)
#define MCANSS_TX_BUFFER_ELEM_BRS_SHIFT (20U)
#define MCANSS_TX_BUFFER_ELEM_BRS_MASK (0x00100000U)
#define MCANSS_TX_BUFFER_ELEM_FDF_SHIFT (21U)
#define MCANSS_TX_BUFFER_ELEM_FDF_MASK (0x00200000U)
#define MCANSS_TX_BUFFER_ELEM_EFC_SHIFT (23U)
#define MCANSS_TX_BUFFER_ELEM_EFC_MASK (0x00800000U)
#define MCANSS_TX_BUFFER_ELEM_MM_SHIFT (24U)
#define MCANSS_TX_BUFFER_ELEM_MM_MASK (0xFF000000U)

/**
 * \brief  Mask and shift for Rx Buffers elements.
 */
#define MCANSS_RX_BUFFER_ELEM_ID_SHIFT (0U)
#define MCANSS_RX_BUFFER_ELEM_ID_MASK (0x1FFFFFFFU)
#define MCANSS_RX_BUFFER_ELEM_RTR_SHIFT (29U)
#define MCANSS_RX_BUFFER_ELEM_RTR_MASK (0x20000000U)
#define MCANSS_RX_BUFFER_ELEM_XTD_SHIFT (30U)
#define MCANSS_RX_BUFFER_ELEM_XTD_MASK (0x40000000U)
#define MCANSS_RX_BUFFER_ELEM_ESI_SHIFT (31U)
#define MCANSS_RX_BUFFER_ELEM_ESI_MASK (0x80000000U)
#define MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT (0U)
#define MCANSS_RX_BUFFER_ELEM_RXTS_MASK (0x0000FFFFU)
#define MCANSS_RX_BUFFER_ELEM_DLC_SHIFT (16U)
#define MCANSS_RX_BUFFER_ELEM_DLC_MASK (0x000F0000U)
#define MCANSS_RX_BUFFER_ELEM_BRS_SHIFT (20U)
#define MCANSS_RX_BUFFER_ELEM_BRS_MASK (0x00100000U)
#define MCANSS_RX_BUFFER_ELEM_FDF_SHIFT (21U)
#define MCANSS_RX_BUFFER_ELEM_FDF_MASK (0x00200000U)
#define MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT (24U)
#define MCANSS_RX_BUFFER_ELEM_FIDX_MASK (0x7F000000U)
#define MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT (31U)
#define MCANSS_RX_BUFFER_ELEM_ANMF_MASK (0x80000000U)

/**
 * \brief  Mask and shift for Standard Message ID Filter Elements.
 */
#define MCANSS_STD_ID_FILTER_SFID2_SHIFT (0U)
#define MCANSS_STD_ID_FILTER_SFID2_MASK (0x000003FFU)
#define MCANSS_STD_ID_FILTER_SFID1_SHIFT (16U)
#define MCANSS_STD_ID_FILTER_SFID1_MASK (0x03FF0000U)
#define MCANSS_STD_ID_FILTER_SFEC_SHIFT (27U)
#define MCANSS_STD_ID_FILTER_SFEC_MASK (0x38000000U)
#define MCANSS_STD_ID_FILTER_SFT_SHIFT (30U)
#define MCANSS_STD_ID_FILTER_SFT_MASK (0xC0000000U)

/**
 * \brief  Extended Message ID Filter Element.
 */
#define MCANSS_EXT_ID_FILTER_EFID2_SHIFT (0U)
#define MCANSS_EXT_ID_FILTER_EFID2_MASK (0x1FFFFFFFU)
#define MCANSS_EXT_ID_FILTER_EFID1_SHIFT (0U)
#define MCANSS_EXT_ID_FILTER_EFID1_MASK (0x1FFFFFFFU)
#define MCANSS_EXT_ID_FILTER_EFEC_SHIFT (29U)
#define MCANSS_EXT_ID_FILTER_EFEC_MASK (0xE0000000U)
#define MCANSS_EXT_ID_FILTER_EFT_SHIFT (30U)
#define MCANSS_EXT_ID_FILTER_EFT_MASK (0xC0000000U)

/**
 * \brief  Mask and shift for Tx Event FIFO elements.
 */
#define MCANSS_TX_EVENT_FIFO_ELEM_ID_SHIFT (0U)
#define MCANSS_TX_EVENT_FIFO_ELEM_ID_MASK (0x1FFFFFFFU)
#define MCANSS_TX_EVENT_FIFO_ELEM_RTR_SHIFT (29U)
#define MCANSS_TX_EVENT_FIFO_ELEM_RTR_MASK (0x20000000U)
#define MCANSS_TX_EVENT_FIFO_ELEM_XTD_SHIFT (30U)
#define MCANSS_TX_EVENT_FIFO_ELEM_XTD_MASK (0x40000000U)
#define MCANSS_TX_EVENT_FIFO_ELEM_ESI_SHIFT (31U)
#define MCANSS_TX_EVENT_FIFO_ELEM_ESI_MASK (0x80000000U)

#define MCANSS_TX_EVENT_FIFO_ELEM_TXTS_SHIFT (0U)
#define MCANSS_TX_EVENT_FIFO_ELEM_TXTS_MASK (0x0000FFFFU)
#define MCANSS_TX_EVENT_FIFO_ELEM_DLC_SHIFT (16U)
#define MCANSS_TX_EVENT_FIFO_ELEM_DLC_MASK (0x000F0000U)
#define MCANSS_TX_EVENT_FIFO_ELEM_BRS_SHIFT (20U)
#define MCANSS_TX_EVENT_FIFO_ELEM_BRS_MASK (0x00100000U)
#define MCANSS_TX_EVENT_FIFO_ELEM_FDF_SHIFT (21U)
#define MCANSS_TX_EVENT_FIFO_ELEM_FDF_MASK (0x00200000U)
#define MCANSS_TX_EVENT_FIFO_ELEM_ET_SHIFT (22U)
#define MCANSS_TX_EVENT_FIFO_ELEM_ET_MASK (0x00C00000U)
#define MCANSS_TX_EVENT_FIFO_ELEM_MM_SHIFT (24U)
#define MCANSS_TX_EVENT_FIFO_ELEM_MM_MASK (0xFF000000U)

#define HW_RD_REG32(addr) (uint32_t)(HW_RD_REG32_RAW((uint32_t)(addr)))

#define HW_WR_REG32(addr, value) \
    (HW_WR_REG32_RAW((uint32_t)(addr), (uint32_t)(value)))

#define HW_GET_FIELD(regVal, REG_FIELD) \
    (((regVal) & (uint32_t) REG_FIELD##_MASK) >> (uint32_t) REG_FIELD##_OFS)

#define HW_SET_FIELD32(regVal, REG_FIELD, fieldVal)                       \
    ((regVal) = ((regVal) & (uint32_t)(~(uint32_t) REG_FIELD##_MASK)) |   \
                ((((uint32_t)(fieldVal)) << (uint32_t) REG_FIELD##_OFS) & \
                    (uint32_t) REG_FIELD##_MASK))

#define HW_WR_FIELD32(regAddr, REG_FIELD, fieldVal)                      \
    (HW_WR_FIELD32_RAW((uint32_t)(regAddr), (uint32_t) REG_FIELD##_MASK, \
        (uint32_t) REG_FIELD##_OFS, (uint32_t)(fieldVal)))

#define HW_RD_FIELD32(regAddr, REG_FIELD)                                \
    (HW_RD_FIELD32_RAW((uint32_t)(regAddr), (uint32_t) REG_FIELD##_MASK, \
        (uint32_t) REG_FIELD##_OFS))

#define STW_SOK ((int32_t) 0)
#define STW_EFAIL (-((int32_t) 1))
#define STW_EBADARGS (-((int32_t) 2))
#define STW_EINVALID_PARAMS (-((int32_t) 3))
#define STW_ETIMEOUT (-((int32_t) 4))
#define STW_EOUT_OF_RANGE (-((int32_t) 5))
#define STW_EUNSUPPORTED_CMD (-((int32_t) 6))
#define STW_EUNSUPPORTED_OPS (-((int32_t) 7))

#define MCAN_MCAN_MSG_MEM (0x0U)

/* To fix Misra-C errors */
#ifndef TRUE
#define TRUE ((Bool) 1)
#endif
#ifndef FALSE
#define FALSE ((Bool) 0)
#endif

/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */

/**
 * \brief   This API will unblock write access to write protected registers.
 *
 * \param   mcan        Base Address of the MCAN Registers.
 *
 * \return  None.
 */
static void DL_MCAN_writeProtectedRegAccessUnlock(MCAN_Regs *mcan);

/**
 * \brief   This API will block write access to write protected registers.
 *
 * \param   mcan        Base Address of the MCAN Registers.
 *
 * \return  None.
 */
static void DL_MCAN_writeProtectedRegAccessLock(MCAN_Regs *mcan);

/**
 * \brief   This API will load the register from ECC memory bank.
 *
 * \param   mcan        Base Address of the MCAN Registers.
 * \param   regOffset       Offset of the register to read.
 *
 * \return  None.
 */
static void DL_MCAN_eccLoadRegister(MCAN_Regs *mcan, uint32_t regOffset);

/**
 * \brief   This API will read the message object from Message RAM.
 *
 * \param   mcan        Base Address of the MCAN Registers.
 * \param   elemAddr        Address of the message object.
 * \param   elem            Message Object.
 *                          Refer struct #DL_MCAN_RxBufElement.
 *
 * \return  None.
 */
static void DL_MCAN_readMsg(
    uint32_t mcan, uint32_t elemAddr, DL_MCAN_RxBufElement *elem);

/**
 * \brief   This API will write the message object to Message RAM.
 *
 * \param   mcan        Base Address of the MCAN Registers.
 * \param   elemAddr        Address of the message object.
 * \param   elem            Message Object.
 *                          Refer struct #MCAN_TXBufElement.
 *
 * \return  None.
 */
static void DL_MCAN_writeMsg(
    uint32_t mcan, uint32_t elemAddr, const DL_MCAN_TxBufElement *elem);

/**
 * \brief   This API will return payload depending on 'dlc'  field.
 *
 * \param   dlc             Data Length Code.
 *
 * \return  data size       Size of the payload.
 */
static uint32_t DL_MCAN_getDataSize(uint32_t dlc);

/**
 * \brief   This API will return message object size.
 *
 * \param   elemSize        Element Size.
 *
 * \return  message object size
 *                          Size of the message object stored in Message RAM.
 */
static uint32_t DL_MCAN_getMsgObjSize(uint32_t elemSize);

/**
 *  \brief   This function reads a 32-bit value from a hardware register
 *           and returns the value.
 *
 *  \param   addr    Address of the memory mapped hardware register.
 *
 *  \return  Unsigned 32-bit value read from a register.
 */
__STATIC_INLINE uint32_t HW_RD_REG32_RAW(uint32_t addr);

/**
 *  \brief   This function writes a 32-bit value to a hardware register.
 *
 *  \param   addr    Address of the memory mapped hardware register.
 *  \param   value   unsigned 32-bit value which has to be written to the
 *                   register.
 */
__STATIC_INLINE void HW_WR_REG32_RAW(uint32_t addr, uint32_t value);

/**
 *  \brief   This function reads a 32 bit register, modifies specific set of
 *           bits and writes back to the register.
 *
 *  \param   addr    Address of the memory mapped hardware register.
 *  \param   mask    Mask for the bit field.
 *  \param   shift   Bit field shift from LSB.
 *  \param   value   Value to be written to bit-field.
 */
__STATIC_INLINE void HW_WR_FIELD32_RAW(
    uint32_t addr, uint32_t mask, uint32_t shift, uint32_t value);

/**
 *  \brief   This function reads a 32 bit register, masks specific set of bits
 *           and the left shifted value.
 *
 *  \param   addr    Address of the memory mapped hardware register.
 *  \param   mask    Mask for the bit field.
 *  \param   shift   Bit field shift from LSB.
 *
 *  \return  Bit-field value (absolute value - shifted to LSB position)
 */
__STATIC_INLINE uint32_t HW_RD_FIELD32_RAW(
    uint32_t addr, uint32_t mask, uint32_t shift);

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

bool DL_MCAN_isReady(DL_MCAN_INSTANCE instance)
{
    return ((SYSCTL->SOCLOCK.SYSSTATUS & (uint32_t) instance) ==
            (uint32_t) instance);
}

void DL_MCAN_setClockConfig(MCAN_Regs *mcan, const DL_MCAN_ClockConfig *config)
{
    DL_Common_updateReg(&SYSCTL->SOCLOCK.GENCLKCFG,
        (uint32_t) config->clockSel, SYSCTL_GENCLKCFG_CANCLKSRC_MASK);

    mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKDIV = (uint32_t) config->divider;
}

void DL_MCAN_getClockConfig(MCAN_Regs *mcan, DL_MCAN_ClockConfig *config)
{
    uint32_t clockSource =
        (SYSCTL->SOCLOCK.GENCLKCFG & SYSCTL_GENCLKCFG_CANCLKSRC_MASK);

    config->clockSel = (DL_MCAN_FCLK)(clockSource);
}

bool DL_MCAN_isInReset(const MCAN_Regs *mcan)
{
    uint32_t reset;
    bool state;

    reset = HW_RD_FIELD32(
        &mcan->MCANSS.STAT, MCAN_TI_WRAPPER_PROCESSORS_REGS_STAT_RESET);
    if (1U == reset) {
        state = true;
    } else {
        state = false;
    }
    return state;
}

bool DL_MCAN_isFDOpEnable(const MCAN_Regs *mcan)
{
    uint32_t fdoe;
    bool state;

    fdoe = HW_RD_FIELD32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_STAT,
        MCAN_TI_WRAPPER_PROCESSORS_REGS_STAT_ENABLE_FDOE);
    if (1U == fdoe) {
        state = true;
    } else {
        state = false;
    }
    return state;
}

bool DL_MCAN_isMemInitDone(const MCAN_Regs *mcan)
{
    uint32_t memInit;
    bool state;

    memInit = HW_RD_FIELD32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_STAT,
        MCAN_TI_WRAPPER_PROCESSORS_REGS_STAT_MEM_INIT_DONE);
    if (1U == memInit) {
        state = true;
    } else {
        state = false;
    }
    return state;
}

void DL_MCAN_setOpMode(MCAN_Regs *mcan, uint32_t mode)
{
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_INIT, mode);
}

uint32_t DL_MCAN_getOpMode(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_INIT));
}

int32_t DL_MCAN_init(MCAN_Regs *mcan, const DL_MCAN_InitParams *initParams)
{
    int32_t status;
    uint32_t regVal;

    /* Configure MCAN wakeup and clock stop controls */
    regVal = HW_RD_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL);
    HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_REGS_CTRL_WAKEUPREQEN,
        initParams->wkupReqEnable);
    HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_REGS_CTRL_AUTOWAKEUP,
        initParams->autoWkupEnable);
    HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_REGS_CTRL_DBGSUSP_FREE,
        initParams->emulationEnable);

    HW_WR_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL, regVal);

    DL_MCAN_writeProtectedRegAccessUnlock(mcan);

    /* Configure MCAN mode(FD vs Classic CAN operation) and controls */
    regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_CCCR);
    HW_SET_FIELD32(regVal, MCAN_CCCR_FDOE, initParams->fdMode);
    HW_SET_FIELD32(regVal, MCAN_CCCR_BRSE, initParams->brsEnable);
    HW_SET_FIELD32(regVal, MCAN_CCCR_TXP, initParams->txpEnable);
    HW_SET_FIELD32(regVal, MCAN_CCCR_EFBI, initParams->efbi);
    HW_SET_FIELD32(regVal, MCAN_CCCR_PXHD, initParams->pxhddisable);
    HW_SET_FIELD32(regVal, MCAN_CCCR_DAR, initParams->darEnable);
    HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_CCCR, regVal);

    if ((DL_MCAN_TDCR_TDCF_MAX >= initParams->tdcConfig.tdcf) &&
        (DL_MCAN_TDCR_TDCO_MAX >= initParams->tdcConfig.tdco) &&
        (DL_MCAN_RWD_WDC_MAX >= initParams->wdcPreload)) {
        /* Configure Transceiver Delay Compensation */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TDCR, MCAN_TDCR_TDCF,
            initParams->tdcConfig.tdcf);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TDCR, MCAN_TDCR_TDCO,
            initParams->tdcConfig.tdco);
        /* Configure MSG RAM watchdog counter preload value */
        HW_WR_FIELD32(
            &mcan->MCANSS.MCAN.MCAN_RWD, MCAN_RWD_WDC, initParams->wdcPreload);
        /* Enable/Disable Transceiver Delay Compensation */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_TDC,
            initParams->tdcEnable);
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }

    DL_MCAN_writeProtectedRegAccessLock(mcan);

    return status;
}

int32_t DL_MCAN_config(
    MCAN_Regs *mcan, const DL_MCAN_ConfigParams *configParams)
{
    int32_t status;

    DL_MCAN_writeProtectedRegAccessUnlock(mcan);

    /* Configure MCAN control registers */
    HW_WR_FIELD32(
        &mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_MON, configParams->monEnable);
    HW_WR_FIELD32(
        &mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_ASM, configParams->asmEnable);
    /* Configure Global Filter */
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_RRFE,
        configParams->filterConfig.rrfe);
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_RRFS,
        configParams->filterConfig.rrfs);
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_ANFE,
        configParams->filterConfig.anfe);
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_GFC, MCAN_GFC_ANFS,
        configParams->filterConfig.anfs);

    if ((DL_MCAN_TSCC_TCP_MAX >= configParams->tsPrescalar) &&
        (DL_MCAN_TOCC_TOP_MAX >= configParams->timeoutPreload)) {
        /* Configure Time-stamp counter */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCC, MCAN_TSCC_TSS,
            configParams->tsSelect);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCC, MCAN_TSCC_TCP,
            (configParams->tsPrescalar - 1U));
        /* Configure Time-out counter */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCC, MCAN_TOCC_TOS,
            configParams->timeoutSelect);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCC, MCAN_TOCC_TOP,
            configParams->timeoutPreload);
        /* Enable Time-out counter */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCC, MCAN_TOCC_ETOC,
            configParams->timeoutCntEnable);
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }

    DL_MCAN_writeProtectedRegAccessLock(mcan);

    return status;
}

void DL_MCAN_eccConfig(
    MCAN_Regs *mcan, const DL_MCAN_ECCConfigParams *configParams)
{
    DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER
                                      .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL);
    HW_WR_FIELD32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL,
        MCAN_TI_WRAPPER_ECC_REGS_CTRL_ECC_CHECK, configParams->enableChk);
    DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER
                                      .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL);
    HW_WR_FIELD32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL,
        MCAN_TI_WRAPPER_ECC_REGS_CTRL_ECC_ENABLE, configParams->enable);
    DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER
                                      .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL);
    HW_WR_FIELD32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL,
        MCAN_TI_WRAPPER_ECC_REGS_CTRL_ENABLE_RMW, configParams->enableRdModWr);
    DL_MCAN_eccLoadRegister(mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER
                                      .PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL);
}

int32_t DL_MCAN_setBitTime(
    MCAN_Regs *mcan, const DL_MCAN_BitTimingParams *configParams)
{
    int32_t status;

    DL_MCAN_writeProtectedRegAccessUnlock(mcan);

    if ((DL_MCAN_NBTP_NSJW_MAX >= configParams->nomSynchJumpWidth) &&
        (DL_MCAN_NBTP_NTSEG2_MAX >= configParams->nomTimeSeg2) &&
        (DL_MCAN_NBTP_NTSEG1_MAX >= configParams->nomTimeSeg1) &&
        (DL_MCAN_NBTP_NBRP_MAX >= configParams->nomRatePrescalar)) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NSJW,
            configParams->nomSynchJumpWidth);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG2,
            configParams->nomTimeSeg2);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG1,
            configParams->nomTimeSeg1);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NBRP,
            configParams->nomRatePrescalar);
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }
    if (STW_SOK == status) {
        if ((DL_MCAN_DBTP_DSJW_MAX >= configParams->dataSynchJumpWidth) &&
            (DL_MCAN_DBTP_DTSEG2_MAX >= configParams->dataTimeSeg2) &&
            (DL_MCAN_DBTP_DTSEG1_MAX >= configParams->dataTimeSeg1) &&
            (DL_MCAN_DBTP_DBRP_MAX >= configParams->dataRatePrescalar)) {
            HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DSJW,
                configParams->dataSynchJumpWidth);
            HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG2,
                configParams->dataTimeSeg2);
            HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG1,
                configParams->dataTimeSeg1);
            HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DBRP,
                configParams->dataRatePrescalar);
            status = STW_SOK;
        } else {
            status = STW_EFAIL;
        }
    }

    DL_MCAN_writeProtectedRegAccessLock(mcan);
    return status;
}

int32_t DL_MCAN_msgRAMConfig(
    MCAN_Regs *mcan, const DL_MCAN_MsgRAMConfigParams *msgRAMConfigParams)
{
    int32_t status;
    uint32_t elemNum = 0U;

    DL_MCAN_writeProtectedRegAccessUnlock(mcan);

    /* Configure Message Filters section */
    if (0U != msgRAMConfigParams->lss) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_SIDFC, MCAN_SIDFC_FLSSA,
            (msgRAMConfigParams->flssa >> 2U));
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_SIDFC, MCAN_SIDFC_LSS,
            msgRAMConfigParams->lss);
    }
    if (0U != msgRAMConfigParams->lse) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDFC, MCAN_XIDFC_FLESA,
            (msgRAMConfigParams->flesa >> 2U));
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDFC, MCAN_XIDFC_LSE,
            msgRAMConfigParams->lse);
    }
    /* Configure Rx FIFO 0 section */
    if (0U != msgRAMConfigParams->rxFIFO0size) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0SA,
            (msgRAMConfigParams->rxFIFO0startAddr >> 2U));
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0S,
            msgRAMConfigParams->rxFIFO0size);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0WM,
            msgRAMConfigParams->rxFIFO0waterMark);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0OM,
            msgRAMConfigParams->rxFIFO0OpMode);
        /* Configure Rx FIFO0 elements size */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F0DS,
            msgRAMConfigParams->rxFIFO0ElemSize);
    }
    /* Configure Rx FIFO 1 section */
    if (0U != msgRAMConfigParams->rxFIFO1size) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1SA,
            (msgRAMConfigParams->rxFIFO1startAddr >> 2U));
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1S,
            msgRAMConfigParams->rxFIFO1size);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1WM,
            msgRAMConfigParams->rxFIFO1waterMark);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1OM,
            msgRAMConfigParams->rxFIFO1OpMode);
        /* Configure Rx FIFO1 elements size */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F1DS,
            msgRAMConfigParams->rxFIFO1ElemSize);
    }
    /* Configure Rx Buffer Start Address */
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXBC, MCAN_RXBC_RBSA,
        (msgRAMConfigParams->rxBufStartAddr >> 2U));
    /* Configure Rx Buffer elements size */
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_RBDS,
        msgRAMConfigParams->rxBufElemSize);
    /* Configure Tx Event FIFO section */
    if (0U != msgRAMConfigParams->txEventFIFOSize) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFSA,
            (msgRAMConfigParams->txEventFIFOStartAddr >> 2U));
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFS,
            msgRAMConfigParams->txEventFIFOSize);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFWM,
            msgRAMConfigParams->txEventFIFOWaterMark);
    }
    /* Configure Tx Buffer and FIFO/Q section */
    elemNum = msgRAMConfigParams->txBufNum + msgRAMConfigParams->txFIFOSize;
    if ((MCANSS_TX_BUFFER_MAX >= elemNum) &&
        ((0U != msgRAMConfigParams->txBufNum) ||
            (0U != msgRAMConfigParams->txFIFOSize))) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TBSA,
            (msgRAMConfigParams->txStartAddr >> 2U));
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_NDTB,
            msgRAMConfigParams->txBufNum);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TFQS,
            msgRAMConfigParams->txFIFOSize);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TFQM,
            msgRAMConfigParams->txBufMode);
        /* Configure Tx Buffer/FIFO0/FIFO1 elements size */
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXESC, MCAN_TXESC_TBDS,
            msgRAMConfigParams->txBufElemSize);
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }

    DL_MCAN_writeProtectedRegAccessLock(mcan);

    return status;
}

int32_t DL_MCAN_setExtIDAndMask(MCAN_Regs *mcan, uint32_t idMask)
{
    int32_t status;

    if (DL_MCAN_XIDAM_EIDM_MAX >= idMask) {
        DL_MCAN_writeProtectedRegAccessUnlock(mcan);

        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDAM, MCAN_XIDAM_EIDM, idMask);

        DL_MCAN_writeProtectedRegAccessLock(mcan);
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }
    return status;
}

void DL_MCAN_writeMsgRam(MCAN_Regs *mcan, uint32_t memType, uint32_t bufNum,
    const DL_MCAN_TxBufElement *elem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
    uint32_t idx = 0U, enableMod = 0U;

    if (((uint32_t) DL_MCAN_MEM_TYPE_BUF) == memType) {
        idx       = bufNum;
        enableMod = 1U;
    }
    if (((uint32_t) DL_MCAN_MEM_TYPE_FIFO) == memType) {
        idx = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXFQS, MCAN_TXFQS_TFQP);
        enableMod = 1U;
    }
    if (1U == enableMod) {
        startAddr =
            HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXBC, MCAN_TXBC_TBSA);
        elemSize =
            HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXESC, MCAN_TXESC_TBDS);
        startAddr = (uint32_t)(startAddr << 2U);
        elemSize  = DL_MCAN_getMsgObjSize(elemSize);
        elemSize *= 4U;
        elemAddr = startAddr + (elemSize * idx);
        elemAddr += MCAN_MCAN_MSG_MEM;
        DL_MCAN_writeMsg((uint32_t) mcan, elemAddr, elem);
    }
}

int32_t DL_MCAN_TXBufAddReq(MCAN_Regs *mcan, uint32_t bufNum)
{
    int32_t status;
    uint32_t regVal;

    if (MCANSS_TX_BUFFER_MAX > bufNum) {
        regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBAR);
        regVal |= ((uint32_t) 1U << bufNum);

        /*
         * For writing to TXBAR CCE bit should be '0'. This need not be
         * reverted because for other qualified writes this is locked state
         * and can't be written.
         */
        DL_MCAN_writeProtectedRegAccessLock(mcan);
        HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBAR, regVal);

        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }
    return status;
}

void DL_MCAN_getNewDataStatus(
    const MCAN_Regs *mcan, DL_MCAN_RxNewDataStatus *newDataStatus)
{
    newDataStatus->statusLow  = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT1);
    newDataStatus->statusHigh = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT2);
}

void DL_MCAN_clearNewDataStatus(
    MCAN_Regs *mcan, const DL_MCAN_RxNewDataStatus *newDataStatus)
{
    HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT1, newDataStatus->statusLow);
    HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_NDAT2, newDataStatus->statusHigh);
}

void DL_MCAN_readMsgRam(const MCAN_Regs *mcan, uint32_t memType,
    uint32_t bufNum, uint32_t fifoNum, DL_MCAN_RxBufElement *elem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
    uint32_t enableMod = 0U, idx = 0U;

    if (((uint32_t) DL_MCAN_MEM_TYPE_BUF) == memType) {
        startAddr =
            HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXBC, MCAN_RXBC_RBSA);
        elemSize =
            HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_RBDS);
        idx       = bufNum;
        enableMod = 1U;
    }
    if (((uint32_t) DL_MCAN_MEM_TYPE_FIFO) == memType) {
        switch (fifoNum) {
            case ((uint32_t) DL_MCAN_RX_FIFO_NUM_0):
                startAddr = HW_RD_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0SA);
                elemSize = HW_RD_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F0DS);
                idx = HW_RD_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXF0S, MCAN_RXF0S_F0GI);
                enableMod = 1U;
                break;
            case ((uint32_t) DL_MCAN_RX_FIFO_NUM_1):
                startAddr = HW_RD_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1SA);
                elemSize = HW_RD_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXESC, MCAN_RXESC_F1DS);
                idx = HW_RD_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXF1S, MCAN_RXF1S_F1GI);
                enableMod = 1U;
                break;
            default:
                /* Invalid option */
                break;
        }
    }
    if (1U == enableMod) {
        startAddr = (uint32_t)(startAddr << 2U);
        elemSize  = DL_MCAN_getMsgObjSize(elemSize);
        elemSize *= 4U;
        elemAddr = startAddr + (elemSize * idx);
        elemAddr += MCAN_MCAN_MSG_MEM;
        DL_MCAN_readMsg((uint32_t) mcan, elemAddr, elem);
    }
}

void DL_MCAN_readTxEventFIFO(
    const MCAN_Regs *mcan, DL_MCAN_TxEventFIFOElement *txEventElem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
    uint32_t idx = 0U, regVal;

    startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFSA);
    elemSize  = MCANSS_TX_EVENT_FIFO_SIZE_WORDS;
    idx       = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFS, MCAN_TXEFS_EFGI);

    startAddr = (uint32_t)(startAddr << 2U);
    elemSize *= 4U;
    elemAddr = startAddr + (elemSize * idx);
    elemAddr += MCAN_MCAN_MSG_MEM;

    regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr));
    txEventElem->id =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_ID_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_ID_SHIFT);
    txEventElem->rtr =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_RTR_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_RTR_SHIFT);
    txEventElem->xtd =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_XTD_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_XTD_SHIFT);
    txEventElem->esi =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_ESI_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_ESI_SHIFT);
    elemAddr += 4U;

    regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr));

    txEventElem->txts =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_TXTS_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_TXTS_SHIFT);
    txEventElem->dlc =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_DLC_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_DLC_SHIFT);
    txEventElem->brs =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_BRS_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_BRS_SHIFT);
    txEventElem->fdf =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_FDF_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_FDF_SHIFT);
    txEventElem->et =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_ET_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_ET_SHIFT);
    txEventElem->mm =
        (uint32_t)((regVal & MCANSS_TX_EVENT_FIFO_ELEM_MM_MASK) >>
                   MCANSS_TX_EVENT_FIFO_ELEM_MM_SHIFT);
}

void DL_MCAN_addStdMsgIDFilter(MCAN_Regs *mcan, uint32_t filtNum,
    const DL_MCAN_StdMsgIDFilterElement *elem)
{
    uint32_t startAddr, elemAddr, regVal;

    startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_SIDFC, MCAN_SIDFC_FLSSA);
    startAddr = (uint32_t)(startAddr << 2U);
    elemAddr  = startAddr + (filtNum * MCANSS_STD_ID_FILTER_SIZE_WORDS * 4U);
    elemAddr += MCAN_MCAN_MSG_MEM;

    regVal = 0U;
    regVal |= (uint32_t)(elem->sfid2 << MCANSS_STD_ID_FILTER_SFID2_SHIFT);
    regVal |= (uint32_t)(elem->sfid1 << MCANSS_STD_ID_FILTER_SFID1_SHIFT);
    regVal |= (uint32_t)(elem->sfec << MCANSS_STD_ID_FILTER_SFEC_SHIFT);
    regVal |= (uint32_t)(elem->sft << MCANSS_STD_ID_FILTER_SFT_SHIFT);
    HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);
}

void DL_MCAN_addExtMsgIDFilter(MCAN_Regs *mcan, uint32_t filtNum,
    const DL_MCAN_ExtMsgIDFilterElement *elem)
{
    uint32_t startAddr, elemAddr, regVal;

    startAddr = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDFC, MCAN_XIDFC_FLESA);
    startAddr = (uint32_t)(startAddr << 2U);
    elemAddr  = startAddr + (filtNum * MCANSS_EXT_ID_FILTER_SIZE_WORDS * 4U);
    elemAddr += MCAN_MCAN_MSG_MEM;

    regVal = 0U;
    regVal |= (uint32_t)(elem->efid1 << MCANSS_EXT_ID_FILTER_EFID1_SHIFT);
    regVal |= (uint32_t)(elem->efec << MCANSS_EXT_ID_FILTER_EFEC_SHIFT);
    HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);

    elemAddr += 4U;
    regVal = 0U;
    regVal |= (uint32_t)(elem->efid2 << MCANSS_EXT_ID_FILTER_EFID2_SHIFT);
    regVal |= (uint32_t)(elem->eft << MCANSS_EXT_ID_FILTER_EFT_SHIFT);
    HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);
}

void DL_MCAN_lpbkModeEnable(MCAN_Regs *mcan, uint32_t lpbkMode, bool enable)
{
    DL_MCAN_writeProtectedRegAccessUnlock(mcan);

    if (true == enable) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_TEST, 0x1U);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_LBCK, enable);
        if (((uint32_t) DL_MCAN_LPBK_MODE_INTERNAL) == lpbkMode) {
            HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_MON, 0x1U);
        }
    } else {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_LBCK, enable);
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_TEST, 0x0U);
        if (((uint32_t) DL_MCAN_LPBK_MODE_INTERNAL) == lpbkMode) {
            HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_MON, 0x0U);
        }
    }
    DL_MCAN_writeProtectedRegAccessLock(mcan);
}

void DL_MCAN_getErrCounters(
    const MCAN_Regs *mcan, DL_MCAN_ErrCntStatus *errCounter)
{
    errCounter->canErrLogCnt =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_CEL);
    errCounter->transErrLogCnt =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_TEC);
    errCounter->recErrCnt =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_REC);
    errCounter->rpStatus =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ECR, MCAN_ECR_RP);
}

void DL_MCAN_getProtocolStatus(
    const MCAN_Regs *mcan, DL_MCAN_ProtocolStatus *protStatus)
{
    uint32_t regVal;

    regVal                    = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_PSR);
    protStatus->lastErrCode   = HW_GET_FIELD(regVal, MCAN_PSR_LEC);
    protStatus->act           = HW_GET_FIELD(regVal, MCAN_PSR_ACT);
    protStatus->errPassive    = HW_GET_FIELD(regVal, MCAN_PSR_EP);
    protStatus->warningStatus = HW_GET_FIELD(regVal, MCAN_PSR_EW);
    protStatus->busOffStatus  = HW_GET_FIELD(regVal, MCAN_PSR_BO);
    protStatus->dlec          = HW_GET_FIELD(regVal, MCAN_PSR_DLEC);
    protStatus->resi          = HW_GET_FIELD(regVal, MCAN_PSR_RESI);
    protStatus->rbrs          = HW_GET_FIELD(regVal, MCAN_PSR_RBRS);
    protStatus->rfdf          = HW_GET_FIELD(regVal, MCAN_PSR_RFDF);
    protStatus->pxe           = HW_GET_FIELD(regVal, MCAN_PSR_PXE);
    protStatus->tdcv          = HW_GET_FIELD(regVal, MCAN_PSR_TDCV);
}

void DL_MCAN_enableIntr(MCAN_Regs *mcan, uint32_t intrMask, bool enable)
{
    uint32_t regVal;

    if (true == enable) {
        regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_IE);
        regVal |= intrMask;
        HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_IE, regVal);
    } else {
        regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_IE);
        regVal &= ~intrMask;
        HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_IE, regVal);
    }
}

void DL_MCAN_selectIntrLine(
    MCAN_Regs *mcan, uint32_t intrMask, uint32_t lineNum)
{
    uint32_t regVal;

    if (((uint32_t) DL_MCAN_INTR_LINE_NUM_0) == lineNum) {
        regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILS);
        regVal &= ~intrMask;
        HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_ILS, regVal);
    } else {
        regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILS);
        regVal |= intrMask;
        HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_ILS, regVal);
    }
}

uint32_t DL_MCAN_getIntrLineSelectStatus(const MCAN_Regs *mcan)
{
    return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILS));
}

void DL_MCAN_enableIntrLine(MCAN_Regs *mcan, uint32_t lineNum, bool enable)
{
    uint32_t regVal;

    lineNum &= MCANSS_INTR_LINE_EN_MASK;
    regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_ILE);
    regVal &= ~((uint32_t) 0x1U << lineNum);
    regVal |= ((uint32_t) enable << lineNum);
    HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_ILE, regVal);
}

uint32_t DL_MCAN_getIntrStatus(const MCAN_Regs *mcan)
{
    return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_IR));
}

void DL_MCAN_clearIntrStatus(
    MCAN_Regs *mcan, uint32_t intrMask, DL_MCAN_INTR_SRC_MCAN eoi)
{
    HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_IR, intrMask);
    HW_WR_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_EOI,
        (uint32_t) eoi);
}

void DL_MCAN_getHighPriorityMsgStatus(
    const MCAN_Regs *mcan, DL_MCAN_HighPriorityMsgInfo *hpm)
{
    hpm->bufIdx = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_BIDX);
    hpm->msi    = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_MSI);
    hpm->filterIdx =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_FIDX);
    hpm->filterList =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_HPMS, MCAN_HPMS_FLST);
}

void DL_MCAN_getRxFIFOStatus(
    const MCAN_Regs *mcan, DL_MCAN_RxFIFOStatus *fifoStatus)
{
    uint32_t regVal;

    switch (fifoStatus->num) {
        case ((uint32_t) DL_MCAN_RX_FIFO_NUM_0):
            regVal               = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_RXF0S);
            fifoStatus->fillLvl  = HW_GET_FIELD(regVal, MCAN_RXF0S_F0FL);
            fifoStatus->getIdx   = HW_GET_FIELD(regVal, MCAN_RXF0S_F0GI);
            fifoStatus->putIdx   = HW_GET_FIELD(regVal, MCAN_RXF0S_F0PI);
            fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_RXF0S_F0F);
            fifoStatus->msgLost  = HW_GET_FIELD(regVal, MCAN_RXF0S_RF0L);
            break;
        case ((uint32_t) DL_MCAN_RX_FIFO_NUM_1):
            regVal               = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_RXF1S);
            fifoStatus->fillLvl  = HW_GET_FIELD(regVal, MCAN_RXF1S_F1FL);
            fifoStatus->getIdx   = HW_GET_FIELD(regVal, MCAN_RXF1S_F1GI);
            fifoStatus->putIdx   = HW_GET_FIELD(regVal, MCAN_RXF1S_F1PI);
            fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_RXF1S_F1F);
            fifoStatus->msgLost  = HW_GET_FIELD(regVal, MCAN_RXF1S_RF1L);
            break;
        default:
            /* Invalid option */
            break;
    }
}

int32_t DL_MCAN_writeRxFIFOAck(MCAN_Regs *mcan, uint32_t fifoNum, uint32_t idx)
{
    int32_t status;
    uint32_t size;

    switch (fifoNum) {
        case ((uint32_t) DL_MCAN_RX_FIFO_NUM_0):
            size =
                HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF0C, MCAN_RXF0C_F0S);
            if (size >= idx) {
                HW_WR_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXF0A, MCAN_RXF0A_F0AI, idx);
                status = STW_SOK;
            } else {
                status = STW_EFAIL;
            }
            break;
        case ((uint32_t) DL_MCAN_RX_FIFO_NUM_1):
            size =
                HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_RXF1C, MCAN_RXF1C_F1S);
            if (size >= idx) {
                HW_WR_FIELD32(
                    &mcan->MCANSS.MCAN.MCAN_RXF1A, MCAN_RXF1A_F1AI, idx);
                status = STW_SOK;
            } else {
                status = STW_EFAIL;
            }
            break;
        default:
            status = STW_EFAIL;
            break;
    }

    return status;
}

void DL_MCAN_getTxFIFOQueStatus(
    const MCAN_Regs *mcan, DL_MCAN_TxFIFOStatus *fifoStatus)
{
    uint32_t regVal;

    regVal               = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXFQS);
    fifoStatus->freeLvl  = HW_GET_FIELD(regVal, MCAN_TXFQS_TFFL);
    fifoStatus->getIdx   = HW_GET_FIELD(regVal, MCAN_TXFQS_TFGI);
    fifoStatus->putIdx   = HW_GET_FIELD(regVal, MCAN_TXFQS_TFQP);
    fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_TXFQS_TFQF);
}

uint32_t DL_MCAN_getTxBufReqPend(const MCAN_Regs *mcan)
{
    return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBRP));
}

int32_t DL_MCAN_txBufCancellationReq(MCAN_Regs *mcan, uint32_t buffNum)
{
    int32_t status;
    uint32_t regVal;

    if (MCANSS_TX_BUFFER_MAX > buffNum) {
        regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCR);
        regVal |= ((uint32_t) 1U << buffNum);

        /*
         * For writing to TXBCR CCE bit should be '0'. This need not be
         * reverted because for other qualified writes this is locked state
         * and can't be written.
         */
        DL_MCAN_writeProtectedRegAccessLock(mcan);
        HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCR, regVal);

        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }
    return status;
}

uint32_t DL_MCAN_getTxBufTransmissionStatus(const MCAN_Regs *mcan)
{
    return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTO));
}

uint32_t DL_MCAN_txBufCancellationStatus(const MCAN_Regs *mcan)
{
    return (HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCF));
}

int32_t DL_MCAN_TXBufTransIntrEnable(
    MCAN_Regs *mcan, uint32_t bufNum, bool enable)
{
    int32_t status;
    uint32_t regVal;

    if (MCANSS_TX_BUFFER_MAX > bufNum) {
        if (true == enable) {
            regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE);
            regVal |= ((uint32_t) 1U << bufNum);
            HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE, regVal);
        } else {
            regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE);
            regVal &= ~((uint32_t) 0x1U << bufNum);
            HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBTIE, regVal);
        }
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }
    return status;
}

int32_t DL_MCAN_getTxBufCancellationIntrEnable(
    const MCAN_Regs *mcan, uint32_t bufNum, bool enable)
{
    int32_t status;
    uint32_t regVal;

    if (MCANSS_TX_BUFFER_MAX > bufNum) {
        if (true == enable) {
            regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE);
            regVal |= ((uint32_t) 0x1U << bufNum);
            HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE, regVal);
        } else {
            regVal = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE);
            regVal &= ~((uint32_t) 0x1U << bufNum);
            HW_WR_REG32(&mcan->MCANSS.MCAN.MCAN_TXBCIE, regVal);
        }
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }
    return status;
}

void DL_MCAN_getTxEventFIFOStatus(
    const MCAN_Regs *mcan, DL_MCAN_TxEventFIFOStatus *fifoStatus)
{
    uint32_t regVal;

    regVal               = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_TXEFS);
    fifoStatus->fillLvl  = HW_GET_FIELD(regVal, MCAN_TXEFS_EFFL);
    fifoStatus->getIdx   = HW_GET_FIELD(regVal, MCAN_TXEFS_EFGI);
    fifoStatus->putIdx   = HW_GET_FIELD(regVal, MCAN_TXEFS_EFPI);
    fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_TXEFS_EFF);
    fifoStatus->eleLost  = HW_GET_FIELD(regVal, MCAN_TXEFS_TEFL);
}

void DL_MCAN_addClockStopRequest(MCAN_Regs *mcan, bool enable)
{
    if (true == enable) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSR, 0x1U);
    } else {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSR, 0x0U);
    }
}

int32_t DL_MCAN_writeTxEventFIFOAck(MCAN_Regs *mcan, uint32_t idx)
{
    int32_t status;
    uint32_t size;

    size = HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFC, MCAN_TXEFC_EFS);

    if (size >= idx) {
        HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TXEFA, MCAN_TXEFA_EFAI, idx);
        status = STW_SOK;
    } else {
        status = STW_EFAIL;
    }

    return status;
}

void DL_MCAN_eccForceError(
    MCAN_Regs *mcan, const DL_MCAN_ECCErrForceParams *eccErr)
{
    uint32_t regVal;

    if ((eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC)) ||
        (eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED))) {
        DL_MCAN_eccLoadRegister(
            mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                      .MCANERR_ERR_CTRL1);
        regVal = HW_RD_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                                  .MCANERR_ERR_CTRL1);
        HW_SET_FIELD32(regVal, MCAN_ERR_CTRL1_ECC_ROW, eccErr->rowNum);
        HW_WR_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                         .MCANERR_ERR_CTRL1,
            regVal);
        DL_MCAN_eccLoadRegister(
            mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                      .MCANERR_ERR_CTRL2);
        regVal = HW_RD_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                                  .MCANERR_ERR_CTRL2);
        HW_SET_FIELD32(regVal, MCAN_ERR_CTRL2_ECC_BIT1, eccErr->bit1);
        HW_SET_FIELD32(regVal, MCAN_ERR_CTRL2_ECC_BIT2, eccErr->bit2);
        HW_WR_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                         .MCANERR_ERR_CTRL2,
            regVal);
        DL_MCAN_eccLoadRegister(
            mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                      .MCANERR_CTRL);
        regVal = HW_RD_REG32(
            &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL);
        HW_SET_FIELD32(regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_FORCE_N_ROW,
            eccErr->errForce);
        HW_SET_FIELD32(
            regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_ERROR_ONCE, eccErr->errOnce);
        if (eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC)) {
            HW_SET_FIELD32(
                regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_FORCE_SEC, 0x1U);
        } else {
            /* eccErr->errType == ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED) */
            HW_SET_FIELD32(
                regVal, MCAN_TI_WRAPPER_ECC_REGS_CTRL_FORCE_DED, 0x1U);
        }
        HW_WR_REG32(
            &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL,
            regVal);
        DL_MCAN_eccLoadRegister(
            mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                      .MCANERR_CTRL);
    }
}

void DL_MCAN_eccGetErrorStatus(MCAN_Regs *mcan, DL_MCAN_ECCErrStatus *eccErr)
{
    uint32_t regVal;

    DL_MCAN_eccLoadRegister(
        mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                  .MCANERR_ERR_STAT1);
    regVal = HW_RD_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_STAT1);
    eccErr->secErr = HW_GET_FIELD(regVal, MCAN_ERR_STAT1_ECC_SEC);
    eccErr->dedErr = HW_GET_FIELD(regVal, MCAN_ERR_STAT1_ECC_DED);
    eccErr->bit1   = HW_GET_FIELD(regVal, MCAN_ERR_STAT1_ECC_BIT1);
    DL_MCAN_eccLoadRegister(
        mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                  .MCANERR_ERR_STAT2);
    regVal = HW_RD_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_STAT2);
    eccErr->row = HW_GET_FIELD(regVal, MCAN_ERR_STAT2_ECC_ROW);
}

void DL_MCAN_eccClearErrorStatus(MCAN_Regs *mcan, uint32_t errType)
{
    DL_MCAN_eccLoadRegister(
        mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                  .MCANERR_ERR_STAT1);
    switch (errType) {
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC):
            HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                               .MCANERR_ERR_STAT1,
                MCAN_ERR_STAT1_ECC_SEC, 0x1U);
            break;
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED):
            HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                               .MCANERR_ERR_STAT1,
                MCAN_ERR_STAT1_ECC_DED, 0x1U);
            break;
        default:
            /* Invalid option */
            break;
    }
    DL_MCAN_eccLoadRegister(
        mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                  .MCANERR_ERR_STAT1);
}

void DL_MCAN_eccWriteEOI(MCAN_Regs *mcan, uint32_t errType)
{
    switch (errType) {
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC):
            HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                               .MCANERR_SEC_EOI,
                MCAN_SEC_EOI_EOI_WR, 0x1U);
            break;
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED):
            HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                               .MCANERR_DED_EOI,
                MCAN_DED_EOI_EOI_WR, 0x1U);
            break;
        default:
            /* Invalid option */
            break;
    }
}

void DL_MCAN_eccEnableIntr(MCAN_Regs *mcan, uint32_t errType, bool enable)
{
    if (true == enable) {
        switch (errType) {
            case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC):
                HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                                   .MCANERR_SEC_ENABLE_SET,
                    MCAN_SEC_ENABLE_SET_MSGMEM_ENABLE_SET, 0x1U);
                break;
            case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED):
                HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                                   .MCANERR_DED_ENABLE_SET,
                    MCAN_DED_ENABLE_SET_MSGMEM_ENABLE_SET, 0x1U);
                break;
            default:
                /* Invalid option */
                break;
        }
    } else {
        switch (errType) {
            case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC):
                HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                                   .MCANERR_SEC_ENABLE_CLR,
                    MCAN_SEC_ENABLE_CLR_MSGMEM_ENABLE_CLR, 0x1U);
                break;
            case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED):
                HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                                   .MCANERR_DED_ENABLE_CLR,
                    MCAN_DED_ENABLE_CLR_MSGMEM_ENABLE_CLR, 0x1U);
                break;
            default:
                /* Invalid option */
                break;
        }
    }
}

uint32_t DL_MCAN_eccGetIntrStatus(const MCAN_Regs *mcan, uint32_t errType)
{
    uint32_t retVal = 0U;

    switch (errType) {
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC):
            retVal = HW_RD_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS
                                        .MCAN_ECC_REGS.MCANERR_SEC_STATUS,
                MCAN_SEC_STATUS_MSGMEM_PEND);
            break;
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED):
            retVal = HW_RD_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS
                                        .MCAN_ECC_REGS.MCANERR_DED_STATUS,
                MCAN_DED_STATUS_MSGMEM_PEND);
            break;
        default:
            retVal = 0U;
            break;
    }
    return retVal;
}

void DL_MCAN_eccClearIntrStatus(MCAN_Regs *mcan, uint32_t errType)
{
    switch (errType) {
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_SEC):
            HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                               .MCANERR_SEC_STATUS,
                MCAN_SEC_STATUS_MSGMEM_PEND, 0x1U);
            break;
        case ((uint32_t) DL_MCAN_ECC_ERR_TYPE_DED):
            HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                               .MCANERR_DED_STATUS,
                MCAN_DED_STATUS_MSGMEM_PEND, 0x1U);
            break;
        default:
            break;
    }
}

void DL_MCAN_extTSCounterConfig(MCAN_Regs *mcan, uint32_t prescalar)
{
    HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS
                       .MCANSS_EXT_TS_PRESCALER,
        MCAN_EXT_TS_PRESCALER_PRESCALER, prescalar);
}

void DL_MCAN_extTSCounterEnable(MCAN_Regs *mcan, bool enable)
{
    HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL,
        MCAN_TI_WRAPPER_REGS_CTRL_EXT_TS_CNTR_EN, enable);
}

void DL_MCAN_extTSEnableIntr(MCAN_Regs *mcan, bool enable)
{
    if (true == enable) {
        HW_WR_FIELD32(
            &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IE,
            MCAN_TI_WRAPPER_PROCESSORS_REGS_IE_EXT_TS_CNTR_OVFL, 1U);
    } else {
        HW_WR_FIELD32(
            &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IECS,
            MCAN_IECS_EXT_TS_CNTR_OVFL, 1U);
    }
}

void DL_MCAN_extTSWriteEOI(MCAN_Regs *mcan)
{
    HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_EOI,
        MCAN_EOI_EOI, 0x1U);
}

uint32_t DL_MCAN_extTSGetUnservicedIntrCount(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS
                               .MCANSS_EXT_TS_UNSERVICED_INTR_CNTR,
        MCAN_EXT_TS_UNSERVICED_INTR_CNTR_EXT_TS_INTR_CNTR));
}

/* ========================================================================== */
/*                          Advance Functions                                 */
/* ========================================================================== */

void DL_MCAN_getRevisionId(const MCAN_Regs *mcan, DL_MCAN_RevisionId *revId)
{
    uint32_t regVal;

    regVal = HW_RD_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_PID);
    revId->minor  = HW_GET_FIELD(regVal, MCAN_PID_MINOR);
    revId->major  = HW_GET_FIELD(regVal, MCAN_PID_MAJOR);
    revId->modId  = HW_GET_FIELD(regVal, MCAN_PID_MODULE_ID);
    revId->scheme = HW_GET_FIELD(regVal, MCAN_PID_SCHEME);

    regVal         = HW_RD_REG32(&mcan->MCANSS.MCAN.MCAN_CREL);
    revId->day     = HW_GET_FIELD(regVal, MCAN_CREL_DAY);
    revId->mon     = HW_GET_FIELD(regVal, MCAN_CREL_MON);
    revId->year    = HW_GET_FIELD(regVal, MCAN_CREL_YEAR);
    revId->subStep = HW_GET_FIELD(regVal, MCAN_CREL_SUBSTEP);
    revId->step    = HW_GET_FIELD(regVal, MCAN_CREL_STEP);
    revId->rel     = HW_GET_FIELD(regVal, MCAN_CREL_REL);
}

uint32_t DL_MCAN_getClockStopAck(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSR));
}

void DL_MCAN_extTSSetRawStatus(MCAN_Regs *mcan)
{
    HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IRS,
        MCAN_IRS_EXT_TS_CNTR_OVFL, 1U);
}

void DL_MCAN_extTSClearRawStatus(MCAN_Regs *mcan)
{
    HW_WR_FIELD32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_ICS,
        MCAN_ICS_EXT_TS_CNTR_OVFL, 1U);
}

uint32_t DL_MCAN_getRxPinState(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_RX));
}

void DL_MCAN_setTxPinState(MCAN_Regs *mcan, uint32_t state)
{
    DL_MCAN_writeProtectedRegAccessUnlock(mcan);

    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_TEST, 0x1U);
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_TX, state);

    DL_MCAN_writeProtectedRegAccessLock(mcan);
}

uint32_t DL_MCAN_getTxPinState(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TEST, MCAN_TEST_TX));
}

uint32_t DL_MCAN_getTSCounterVal(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCV, MCAN_TSCV_TSC));
}

uint32_t DL_MCAN_getClkStopAck(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CSA));
}

void DL_MCAN_getBitTime(
    const MCAN_Regs *mcan, DL_MCAN_BitTimingParams *configParams)
{
    configParams->nomSynchJumpWidth =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NSJW);
    configParams->nomTimeSeg2 =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG2);
    configParams->nomTimeSeg1 =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NTSEG1);
    configParams->nomRatePrescalar =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_NBTP, MCAN_NBTP_NBRP);

    configParams->dataSynchJumpWidth =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DSJW);
    configParams->dataTimeSeg2 =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG2);
    configParams->dataTimeSeg1 =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DTSEG1);
    configParams->dataRatePrescalar =
        HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_DBTP, MCAN_DBTP_DBRP);
}

void DL_MCAN_resetTSCounter(MCAN_Regs *mcan)
{
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_TSCV, MCAN_TSCV_TSC, 0x0U);
}

uint32_t DL_MCAN_getTOCounterVal(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_TOCV, MCAN_TOCV_TOC));
}

void DL_MCAN_eccAggrGetRevisionId(
    const MCAN_Regs *mcan, DL_MCAN_ECCAggrRevisionId *revId)
{
    uint32_t regVal;

    regVal = HW_RD_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_REV);
    revId->minor  = HW_GET_FIELD(regVal, MCAN_REV_REVMIN);
    revId->major  = HW_GET_FIELD(regVal, MCAN_REV_REVMAJ);
    revId->modId  = HW_GET_FIELD(regVal, MCAN_REV_MODULE_ID);
    revId->scheme = HW_GET_FIELD(regVal, MCAN_REV_SCHEME);
}

void DL_MCAN_eccWrapGetRevisionId(
    MCAN_Regs *mcan, DL_MCAN_ECCWrapRevisionId *revId)
{
    uint32_t regVal;

    DL_MCAN_eccLoadRegister(
        mcan, (uint32_t) &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                  .MCANERR_WRAP_REV);
    regVal = HW_RD_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_WRAP_REV);
    revId->minor  = HW_GET_FIELD(regVal, MCAN_WRAP_REV_REVMIN);
    revId->major  = HW_GET_FIELD(regVal, MCAN_WRAP_REV_REVMAJ);
    revId->modId  = HW_GET_FIELD(regVal, MCAN_WRAP_REV_MODULE_ID);
    revId->scheme = HW_GET_FIELD(regVal, MCAN_WRAP_REV_SCHEME);
}

bool DL_MCAN_extTSIsIntrEnable(const MCAN_Regs *mcan)
{
    bool status;

    if (1U == HW_RD_FIELD32(
                  &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IES,
                  MCAN_IES_EXT_TS_CNTR_OVFL)) {
        status = true;
    } else {
        status = false;
    }

    return status;
}

uint32_t DL_MCAN_getEndianVal(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_ENDN, MCAN_ENDN_ETV));
}

uint32_t DL_MCAN_getExtIDANDMask(const MCAN_Regs *mcan)
{
    return (HW_RD_FIELD32(&mcan->MCANSS.MCAN.MCAN_XIDAM, MCAN_XIDAM_EIDM));
}

/* ========================================================================== */
/*                          Internal Functions                                */
/* ========================================================================== */

static void DL_MCAN_writeProtectedRegAccessUnlock(MCAN_Regs *mcan)
{
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CCE, 0x1U);
}

static void DL_MCAN_writeProtectedRegAccessLock(MCAN_Regs *mcan)
{
    HW_WR_FIELD32(&mcan->MCANSS.MCAN.MCAN_CCCR, MCAN_CCCR_CCE, 0x0U);
}

static void DL_MCAN_eccLoadRegister(MCAN_Regs *mcan, uint32_t regOffset)
{
    uint32_t regVal = 0U, offset;

    offset = regOffset & 0xFFU;
    regVal |= ((uint32_t) MCANSS_MSG_RAM_NUM << MCAN_VECTOR_ECC_VECTOR_OFS);
    regVal |= (offset << MCAN_VECTOR_RD_SVBUS_ADDRESS_OFS);
    regVal |= ((uint32_t) 1U << MCAN_VECTOR_RD_SVBUS_OFS);
    HW_WR_REG32(
        &mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_VECTOR,
        regVal);
    while (MCAN_VECTOR_RD_SVBUS_DONE_MASK !=
           (HW_RD_REG32(&mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS
                             .MCANERR_VECTOR) &
               MCAN_VECTOR_RD_SVBUS_DONE_MASK)) {
    }
}

static void DL_MCAN_readMsg(
    uint32_t mcan, uint32_t elemAddr, DL_MCAN_RxBufElement *elem)
{
    uint32_t regVal = 0U, loopCnt = 0U;

    regVal    = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr));
    elem->id  = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_ID_MASK) >>
                          MCANSS_RX_BUFFER_ELEM_ID_SHIFT);
    elem->rtr = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_RTR_MASK) >>
                           MCANSS_RX_BUFFER_ELEM_RTR_SHIFT);
    elem->xtd = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_XTD_MASK) >>
                           MCANSS_RX_BUFFER_ELEM_XTD_SHIFT);
    elem->esi = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_ESI_MASK) >>
                           MCANSS_RX_BUFFER_ELEM_ESI_SHIFT);

    elemAddr += 4U;
    regVal     = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr));
    elem->rxts = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_RXTS_MASK) >>
                            MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT);
    elem->dlc  = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_DLC_MASK) >>
                           MCANSS_RX_BUFFER_ELEM_DLC_SHIFT);
    elem->brs  = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_BRS_MASK) >>
                           MCANSS_RX_BUFFER_ELEM_BRS_SHIFT);
    elem->fdf  = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_FDF_MASK) >>
                           MCANSS_RX_BUFFER_ELEM_FDF_SHIFT);
    elem->fidx = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_FIDX_MASK) >>
                            MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT);
    elem->anmf = (uint32_t)((regVal & MCANSS_RX_BUFFER_ELEM_ANMF_MASK) >>
                            MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT);
    elemAddr += 4U;

    loopCnt = 0U;
    /* Reading words from message RAM and forming payload bytes out of it */
    while ((4U <= (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) &&
           (0U != (DL_MCAN_getDataSize(elem->dlc) - loopCnt))) {
        regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr));
        elem->data[loopCnt]        = (uint16_t)(regVal & 0x000000FFU);
        elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U);
        elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U);
        elem->data[(loopCnt + 3U)] = (uint16_t)((regVal & 0xFF000000U) >> 24U);
        elemAddr += 4U;
        loopCnt += 4U;
    }
    /* Reading remaining bytes from message RAM */
    if (0U < (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) {
        regVal = HW_RD_REG32(((uint32_t) mcan + (uint32_t) elemAddr));
        elem->data[loopCnt]        = (uint16_t)(regVal & 0x000000FFU);
        elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U);
        elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U);
    }
}

static void DL_MCAN_writeMsg(
    uint32_t mcan, uint32_t elemAddr, const DL_MCAN_TxBufElement *elem)
{
    uint32_t regVal = 0, loopCnt = 0U;

    regVal = 0U;
    regVal |= (((uint32_t)(elem->id << MCANSS_TX_BUFFER_ELEM_ID_SHIFT)) |
               ((uint32_t)(elem->rtr << MCANSS_TX_BUFFER_ELEM_RTR_SHIFT)) |
               ((uint32_t)(elem->xtd << MCANSS_TX_BUFFER_ELEM_XTD_SHIFT)) |
               ((uint32_t)(elem->esi << MCANSS_TX_BUFFER_ELEM_ESI_SHIFT)));
    HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);
    elemAddr += 4U;

    regVal = 0U;
    regVal |= ((uint32_t)(elem->dlc << MCANSS_TX_BUFFER_ELEM_DLC_SHIFT)) |
              ((uint32_t)(elem->brs << MCANSS_TX_BUFFER_ELEM_BRS_SHIFT)) |
              ((uint32_t)(elem->fdf << MCANSS_TX_BUFFER_ELEM_FDF_SHIFT)) |
              ((uint32_t)(elem->efc << MCANSS_TX_BUFFER_ELEM_EFC_SHIFT)) |
              ((uint32_t)(elem->mm << MCANSS_TX_BUFFER_ELEM_MM_SHIFT));
    HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);
    elemAddr += 4U;

    loopCnt = 0U;
    /* Framing words out of the payload bytes and writing it to message RAM */
    while ((4U <= (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) &&
           (0U != (DL_MCAN_getDataSize(elem->dlc) - loopCnt))) {
        regVal = 0U;
        regVal |= ((uint32_t) elem->data[loopCnt] |
                   ((uint32_t) elem->data[(loopCnt + 1U)] << 8U) |
                   ((uint32_t) elem->data[(loopCnt + 2U)] << 16U) |
                   ((uint32_t) elem->data[(loopCnt + 3U)] << 24U));
        HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);
        elemAddr += 4U;
        loopCnt += 4U;
    }
    /* Framing a word out of remaining payload bytes and writing it to
     * message RAM */
    if (0U < (DL_MCAN_getDataSize(elem->dlc) - loopCnt)) {
        regVal = 0U;
        regVal |= ((uint32_t) elem->data[loopCnt] |
                   ((uint32_t) elem->data[(loopCnt + 1U)] << 8U) |
                   ((uint32_t) elem->data[(loopCnt + 2U)] << 16U) |
                   ((uint32_t) elem->data[(loopCnt + 3U)] << 24U));
        HW_WR_REG32(((uint32_t) mcan + (uint32_t) elemAddr), regVal);
    }
}

static uint32_t DL_MCAN_getDataSize(uint32_t dlc)
{
    uint32_t dataSize[16] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
    return (dataSize[dlc]);
}

static uint32_t DL_MCAN_getMsgObjSize(uint32_t elemSize)
{
    uint32_t objSize[8] = {4, 5, 6, 7, 8, 10, 14, 18};
    return (objSize[elemSize]);
}

__STATIC_INLINE uint32_t HW_RD_REG32_RAW(uint32_t addr)
{
    uint32_t regVal = *(volatile uint32_t *) addr;
    return (regVal);
}

__STATIC_INLINE void HW_WR_REG32_RAW(uint32_t addr, uint32_t value)
{
    *(volatile uint32_t *) addr = value;
    return;
}

__STATIC_INLINE void HW_WR_FIELD32_RAW(
    uint32_t addr, uint32_t mask, uint32_t shift, uint32_t value)
{
    uint32_t regVal = *(volatile uint32_t *) addr;
    regVal &= (~mask);
    regVal |= (value << shift) & mask;
    *(volatile uint32_t *) addr = regVal;
    return;
}
__STATIC_INLINE uint32_t HW_RD_FIELD32_RAW(
    uint32_t addr, uint32_t mask, uint32_t shift)
{
    uint32_t regVal = *(volatile uint32_t *) addr;
    regVal          = (regVal & mask) >> shift;
    return (regVal);
}

bool DL_MCAN_saveConfiguration(
    const MCAN_Regs *mcan, DL_MCAN_backupConfig *ptr)
{
    bool saveState = !ptr->backupRdy;
    if (saveState) {
        /* Clock configuration */
        ptr->clkDivConf = mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKDIV;
        ptr->clkConf    = mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKCTL;
        ptr->clkEnConf  = mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKEN;

        /* Interrupt Configuration */
        ptr->txBuffTxIntConf   = mcan->MCANSS.MCAN.MCAN_TXBTIE;
        ptr->txBuffCancIntConf = mcan->MCANSS.MCAN.MCAN_TXBCIE;
        ptr->intLnSelConf      = mcan->MCANSS.MCAN.MCAN_ILS;
        ptr->intLnEnableConf   = mcan->MCANSS.MCAN.MCAN_ILE;
        ptr->ssIntEnConf =
            mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IE;
        ptr->intEnConf    = mcan->MCANSS.MCAN.MCAN_IE;
        ptr->intEvnt0Conf = mcan->MCANSS.TI_WRAPPER.MSP.CPU_INT.IMASK;

        /* MCAN configuration */
        ptr->ctrlConf        = mcan->MCANSS.MCAN.MCAN_CCCR;
        ptr->nomBitTimeConf  = mcan->MCANSS.MCAN.MCAN_NBTP;
        ptr->dataBitTimeConf = mcan->MCANSS.MCAN.MCAN_DBTP;
        ptr->timeCntConf     = mcan->MCANSS.MCAN.MCAN_TSCC;
        ptr->timeCntVal      = mcan->MCANSS.MCAN.MCAN_TSCV;
        ptr->timeOutConf     = mcan->MCANSS.MCAN.MCAN_TOCC;
        ptr->timeOutCntVal   = mcan->MCANSS.MCAN.MCAN_TOCV;
        ptr->txDelCompConf   = mcan->MCANSS.MCAN.MCAN_TDCR;
        ptr->globFiltIDConf  = mcan->MCANSS.MCAN.MCAN_GFC;
        ptr->stdFiltIDConf   = mcan->MCANSS.MCAN.MCAN_SIDFC;
        ptr->exFiltIDConf    = mcan->MCANSS.MCAN.MCAN_XIDFC;
        ptr->exFiltIDMsk     = mcan->MCANSS.MCAN.MCAN_XIDAM;
        ptr->rxFIFO0Conf     = mcan->MCANSS.MCAN.MCAN_RXF0C;
        ptr->rxBuffConf      = mcan->MCANSS.MCAN.MCAN_RXBC;
        ptr->rxFIFO1Conf     = mcan->MCANSS.MCAN.MCAN_RXF1C;
        ptr->rxDataSize      = mcan->MCANSS.MCAN.MCAN_RXESC;
        ptr->txBuffConf      = mcan->MCANSS.MCAN.MCAN_TXBC;
        ptr->txDataSize      = mcan->MCANSS.MCAN.MCAN_TXESC;
        ptr->txEvntFIFOConf  = mcan->MCANSS.MCAN.MCAN_TXEFC;
        ptr->ssCtrlConf =
            mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL;
        ptr->preSclConf = mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS
                              .MCANSS_EXT_TS_PRESCALER;
        ptr->edcVecConf =
            mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_VECTOR;
        ptr->edcConf2 =
            mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL;
        ptr->edcConf1 =
            mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL1;
        ptr->edcConf0 =
            mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL2;
        ptr->ramWDConf = mcan->MCANSS.MCAN.MCAN_RWD;
        ptr->testConf  = mcan->MCANSS.MCAN.MCAN_TEST;
        ptr->backupRdy = true;
    }
    return saveState;
}

bool DL_MCAN_restoreConfiguration(MCAN_Regs *mcan, DL_MCAN_backupConfig *ptr)
{
    bool stateRestored = ptr->backupRdy;
    bool cceState;
    bool initState;
    if (stateRestored) {
        ptr->backupRdy = false;

        /**
         * Stores actual state of Configuration Change Enable. CCE will be set
         * during restore operation and will configure CCE actual state at the
         * end.
         */
        cceState =
            ((ptr->ctrlConf & MCAN_CCCR_CCE_MASK) == MCAN_CCCR_CCE_MASK);
        initState =
            ((ptr->ctrlConf & MCAN_CCCR_INIT_MASK) == MCAN_CCCR_INIT_MASK);

        /**
         * MCAN configuration only overwrittring CCE configuration since INIT
         * reset value is 0x1. CCE and INIT must be set to 0x1 to allow
         * reconfiguration of MCAN.
         */
        mcan->MCANSS.MCAN.MCAN_CCCR  = (ptr->ctrlConf |= MCAN_CCCR_CCE_MASK);
        mcan->MCANSS.MCAN.MCAN_NBTP  = ptr->nomBitTimeConf;
        mcan->MCANSS.MCAN.MCAN_DBTP  = ptr->dataBitTimeConf;
        mcan->MCANSS.MCAN.MCAN_TSCC  = ptr->timeCntConf;
        mcan->MCANSS.MCAN.MCAN_TSCV  = ptr->timeCntVal;
        mcan->MCANSS.MCAN.MCAN_TOCC  = ptr->timeOutConf;
        mcan->MCANSS.MCAN.MCAN_TOCV  = ptr->timeOutCntVal;
        mcan->MCANSS.MCAN.MCAN_TDCR  = ptr->txDelCompConf;
        mcan->MCANSS.MCAN.MCAN_GFC   = ptr->globFiltIDConf;
        mcan->MCANSS.MCAN.MCAN_SIDFC = ptr->stdFiltIDConf;
        mcan->MCANSS.MCAN.MCAN_XIDFC = ptr->exFiltIDConf;
        mcan->MCANSS.MCAN.MCAN_XIDAM = ptr->exFiltIDMsk;
        mcan->MCANSS.MCAN.MCAN_RXF0C = ptr->rxFIFO0Conf;
        mcan->MCANSS.MCAN.MCAN_RXBC  = ptr->rxBuffConf;
        mcan->MCANSS.MCAN.MCAN_RXF1C = ptr->rxFIFO1Conf;
        mcan->MCANSS.MCAN.MCAN_RXESC = ptr->rxDataSize;
        mcan->MCANSS.MCAN.MCAN_TXBC  = ptr->txBuffConf;
        mcan->MCANSS.MCAN.MCAN_TXESC = ptr->txDataSize;
        mcan->MCANSS.MCAN.MCAN_TXEFC = ptr->txEvntFIFOConf;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_CTRL =
            ptr->ssCtrlConf;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS
            .MCANSS_EXT_TS_PRESCALER = ptr->preSclConf;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_VECTOR =
            ptr->edcVecConf;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_CTRL =
            ptr->edcConf2;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL1 =
            ptr->edcConf1;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCAN_ECC_REGS.MCANERR_ERR_CTRL2 =
            ptr->edcConf0;
        mcan->MCANSS.MCAN.MCAN_RWD  = ptr->ramWDConf;
        mcan->MCANSS.MCAN.MCAN_TEST = ptr->testConf;

        /* Clock configuration */
        mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKDIV = ptr->clkDivConf;
        mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKCTL = ptr->clkConf;
        mcan->MCANSS.TI_WRAPPER.MSP.MCANSS_CLKEN  = ptr->clkEnConf;

        /* Interrupt Configuration */
        mcan->MCANSS.MCAN.MCAN_TXBTIE = ptr->txBuffTxIntConf;
        mcan->MCANSS.MCAN.MCAN_TXBCIE = ptr->txBuffCancIntConf;
        mcan->MCANSS.MCAN.MCAN_ILS    = ptr->intLnSelConf;
        mcan->MCANSS.MCAN.MCAN_ILE    = ptr->intLnEnableConf;
        mcan->MCANSS.TI_WRAPPER.PROCESSORS.MCANSS_REGS.MCANSS_IE =
            ptr->ssIntEnConf;
        mcan->MCANSS.MCAN.MCAN_IE                 = ptr->intEnConf;
        mcan->MCANSS.TI_WRAPPER.MSP.CPU_INT.IMASK = ptr->intEvnt0Conf;

        /* Restores MCAN configuration change state */
        if (false == cceState) {
            DL_Common_updateReg(
                &mcan->MCANSS.MCAN.MCAN_CCCR, 0, MCAN_CCCR_CCE_MASK);
        } else {
            DL_Common_updateReg(&mcan->MCANSS.MCAN.MCAN_CCCR,
                MCAN_CCCR_CCE_MASK, MCAN_CCCR_CCE_MASK);
        }

        /* Restores MCAN intialization status */
        if (false == initState) {
            DL_Common_updateReg(
                &mcan->MCANSS.MCAN.MCAN_CCCR, 0, MCAN_CCCR_INIT_MASK);
        } else {
            DL_Common_updateReg(&mcan->MCANSS.MCAN.MCAN_CCCR,
                MCAN_CCCR_INIT_MASK, MCAN_CCCR_INIT_MASK);
        }
    }

    return stateRestored;
}

#endif /* __MSPM0_HAS_MCAN__ */
