/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

#ifndef _ERM_REG_H_
#define _ERM_REG_H_

/*! \brief Contains public interface to various functions related
 *         to the ERM Registers
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * the defines
 ******************************************************************************/

/* CR0 Bit Fields */
#define ERM_CR0_ENCIE1_MASK         (0x08u)
#define ERM_CR0_ENCIE1_SHIFT        (3u)
#define ERM_CR0_ENCIE1_WIDTH        (1u)
#define ERM_CR0_ESCIE1_MASK         (0x04u)
#define ERM_CR0_ESCIE1_SHIFT        (2u)
#define ERM_CR0_ESCIE1_WIDTH        (1u)
#define ERM_CR0_ENCIE0_MASK         (0x02u)
#define ERM_CR0_ENCIE0_SHIFT        (1u)
#define ERM_CR0_ENCIE0_WIDTH        (1u)
#define ERM_CR0_ESCIE0_MASK         (0x01u)
#define ERM_CR0_ESCIE0_SHIFT        (0u)
#define ERM_CR0_ESCIE0_WIDTH        (1u)

/* SR Bit Fields */
#define ERM_SR_NCE1_MASK            (0x08u)
#define ERM_SR_NCE1_SHIFT           (3u)
#define ERM_SR_NCE1_WIDTH           (1u)
#define ERM_SR_SBC1_MASK            (0x04u)
#define ERM_SR_SBC1_SHIFT           (2u)
#define ERM_SR_SBC1_WIDTH           (1u)
#define ERM_SR_NCE0_MASK            (0x02u)
#define ERM_SR_NCE0_SHIFT           (1u)
#define ERM_SR_NCE0_WIDTH           (1u)
#define ERM_SR_SBC0_MASK            (0x01u)
#define ERM_SR_SBC0_SHIFT           (0u)
#define ERM_SR_SBC0_WIDTH           (1u)

/* CH0_ST0 Bit Fields */
#define ERM_CH0_ST0_ADR0_MASK       (0xFFFFFFFFu)
#define ERM_CH0_ST0_ADR0_SHIFT      (0u)
#define ERM_CH0_ST0_ADR0_WIDTH      (32u)

/* CH0_ST1 Bit Fields */
#define ERM_CH0_ST1_SYN0_MASK       (0xFF000000u)
#define ERM_CH0_ST1_SYN0_SHIFT      (24u)
#define ERM_CH0_ST1_SYN0_WIDTH      (8u)

/* CH0_ST2 Bit Fields */
#define ERM_CH0_ST2_CORR_CNT0_MASK  (0xFFu)
#define ERM_CH0_ST2_CORR_CNT0_SHIFT (0u)
#define ERM_CH0_ST2_CORR_CNT0_WIDTH (8u)

/* CH1_ST0 Bit Fields */
#define ERM_CH1_ST0_ADR1_MASK       (0xFFFFFFFFu)
#define ERM_CH1_ST0_ADR1_SHIFT      (0u)
#define ERM_CH1_ST0_ADR1_WIDTH      (32u)

/* CH1_ST1 Bit Fields */
#define ERM_CH1_ST1_SYN1_MASK       (0xFF000000u)
#define ERM_CH1_ST1_SYN1_SHIFT      (24u)
#define ERM_CH1_ST1_SYN1_WIDTH      (8u)

/* CH1_ST2 Bit Fields */
#define ERM_CH1_ST2_CORR_CNT1_MASK  (0xFFu)
#define ERM_CH1_ST2_CORR_CNT1_SHIFT (0u)
#define ERM_CH1_ST2_CORR_CNT1_WIDTH (8u)

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

/*! \brief The definition of ERM registers
 */
typedef struct _ErmRegType_
{
    volatile uint32_t CR0;           /*!< Error report channel enable control register, offset: 0x0 */
    uint32_t          RESERVED0[3];  /*!< Reserverd block, offset: 0x4 */
    volatile uint32_t SR;            /*!< Error report channel status register, offset: 0x10 */
    uint32_t          RESERVED1[59]; /*!< Reserverd block, offset: 0x14 */
    volatile uint32_t CH0_ST0;       /*!< channel0's error address, offset: 0x100 */
    volatile uint32_t CH0_ST1;       /*!< channel0's syndrome, offset: 0x104 */
    volatile uint32_t CH0_ST2;       /*!< channel0's Correctable Error Count, offset: 0x108 */
    uint32_t          RESERVED2[1];  /*!< Reserverd block, offset: 0x10C */
    volatile uint32_t CH1_ST0;       /*!< channel1's error address, offset: 0x110 */
    volatile uint32_t CH1_ST1;       /*!< channel1's syndrome, offset: 0x114 */
    volatile uint32_t CH1_ST2;       /*!< channel1's Correctable Error Count, offset: 0x118 */
} ErmRegType;

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the function prototypes
 ******************************************************************************/

/*! \brief Gets the Enable Memory 1 Non-Correctable Notification
 *
 * This function gets the current Enable Memory 1 Non-Correctable Notification.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Enable Memory 1 Non-Correctable Notification
 *         - 0b : Notification of Memory 1 non-correctable error events is disabled.
 *         - 1b : Notification of Memory 1 non-correctable error events is enabled.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCr0Encie1(const ErmRegType *obj)
{
    return ((obj->CR0 & ERM_CR0_ENCIE1_MASK) >> ERM_CR0_ENCIE1_SHIFT);
}

/*! \brief Sets the Enable Memory 1 Non-Correctable Notification
 *
 * This function sets the Enable Memory 1 Non-Correctable Notification.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Enable Memory 1 Non-Correctable Notification
 *                    - 0b : Notification of Memory 1 non-correctable error events is disabled.
 *                    - 1b : Notification of Memory 1 non-correctable error events is enabled.
 */
__attribute__((always_inline)) static inline void ErmReg_SetCr0Encie1(ErmRegType *obj, uint8_t value)
{
    uint32_t tmp = obj->CR0;

    tmp &= ~ERM_CR0_ENCIE1_MASK;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_CR0_ENCIE1_SHIFT)) & ERM_CR0_ENCIE1_MASK);
    obj->CR0 = tmp;
}

/*! \brief Gets the Enable Memory 1 Single Correction Notification
 *
 * This function gets the current Enable Memory 1 Single Correction Notification.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Enable Memory 1 Single Correction Notification
 *         - 0b  : notification of Memory 1 single-bit correction events is disabled.
 *         - 1b  : notification of Memory 1 single-bit correction events is enabled.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCr0Escie1(const ErmRegType *obj)
{
    return ((obj->CR0 & ERM_CR0_ESCIE1_MASK) >> ERM_CR0_ESCIE1_SHIFT);
}

/*! \brief Sets the Enable Memory 1 Single Correction Notification
 *
 * This function sets the Enable Memory 1 Single Correction Notification.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Enable Memory 1 Single Correction Notification
 *                    - 0b  : notification of Memory 1 single-bit correction events is disabled.
 *                    - 1b  : notification of Memory 1 single-bit correction events is enabled.
 */
__attribute__((always_inline)) static inline void ErmReg_SetCr0Escie1(ErmRegType *obj, uint8_t value)
{
    uint32_t tmp = obj->CR0;

    tmp &= ~ERM_CR0_ESCIE1_MASK;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_CR0_ESCIE1_SHIFT)) & ERM_CR0_ESCIE1_MASK);
    obj->CR0 = tmp;
}

/*! \brief Gets the Enable Memory 0 Non-Correctable Notification to FHU
 *
 * This function gets the current Enable Memory 0 Non-Correctable Notification to FHU.
 * This field is initialized by hardware reset.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Enable Memory 0 Non-Correctable Notification to FHU
 *         - 0b : Notification of Memory 0 non-correctable error events is disabled.
 *         - 1b : Notification of Memory 0 non-correctable error events is enabled.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCr0Encie0(const ErmRegType *obj)
{
    return ((obj->CR0 & ERM_CR0_ENCIE0_MASK) >> ERM_CR0_ENCIE0_SHIFT);
}

/*! \brief Sets the Enable Memory 0 Non-Correctable Notification to FHU
 *
 * This function sets the Enable Memory 0 Non-Correctable Notification to FHU.
 * This field is initialized by hardware reset.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Enable Memory 0 Non-Correctable Notification to FHU
 *                    - 0b : Notification of Memory 0 non-correctable error events is disabled.
 *                    - 1b : Notification of Memory 0 non-correctable error events is enabled.
 */
__attribute__((always_inline)) static inline void ErmReg_SetCr0Encie0(ErmRegType *obj, uint8_t value)
{
    uint32_t tmp = obj->CR0;

    tmp &= ~ERM_CR0_ENCIE0_MASK;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_CR0_ENCIE0_SHIFT)) & ERM_CR0_ENCIE0_MASK);
    obj->CR0 = tmp;
}

/*! \brief Gets the Enable Memory 0 Single Correction Notification to FHU
 *
 * This function gets the current Enable Memory 0 Single Correction Notification to FHU.
 * This field is initialized by hardware reset.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Enable Memory 0 Single Correction Notification to FHU
 *         - 0b  : notification of Memory 0 single-bit correction events is disabled.
 *         - 1b  : notification of Memory 0 single-bit correction events is enabled.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCr0Escie0(const ErmRegType *obj)
{
    return ((obj->CR0 & ERM_CR0_ESCIE0_MASK) >> ERM_CR0_ESCIE0_SHIFT);
}

/*! \brief Sets the Enable Memory 0 Single Correction Notification to FHU
 *
 * This function sets the Enable Memory 0 Single Correction Notification to FHU.
 * This field is initialized by hardware reset.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Enable Memory 0 Single Correction Notification to FHU
 *                    - 0b  : notification of Memory 0 single-bit correction events is disabled.
 *                    - 1b  : notification of Memory 0 single-bit correction events is enabled.
 */
__attribute__((always_inline)) static inline void ErmReg_SetCr0Escie0(ErmRegType *obj, uint8_t value)
{
    uint32_t tmp = obj->CR0;

    tmp &= ~ERM_CR0_ESCIE0_MASK;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_CR0_ESCIE0_SHIFT)) & ERM_CR0_ESCIE0_MASK);
    obj->CR0 = tmp;
}

/*! \brief Gets the Memory 1 Non-Correctable Error Event
 *
 * This function gets the current Memory 1 Non-Correctable Error Event.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory 1 Non-Correctable Error Event
 *         - 0b : No non-correctable error event on Memory 1 detected.
 *         - 1b : Non-correctable error event on Memory 1 detected.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetSrNce1(const ErmRegType *obj)
{
    return ((obj->SR & ERM_SR_NCE1_MASK) >> ERM_SR_NCE1_SHIFT);
}

/*! \brief Sets the Memory 1 Non-Correctable Error Event
 *
 * This function sets the Memory 1 Non-Correctable Error Event.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Memory 1 Non-Correctable Error Event
 *                    - 0b : No non-correctable error event on Memory 1 detected.
 *                    - 1b : Non-correctable error event on Memory 1 detected.
 */
__attribute__((always_inline)) static inline void ErmReg_SetSrNce1(ErmRegType *obj, uint8_t value)
{
    /* Clear the affected bit-field and write '0' to the w1c bits to avoid side-effects */
    uint32_t tmp = 0;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_SR_NCE1_SHIFT)) & ERM_SR_NCE1_MASK);
    obj->SR = tmp;
}

/*! \brief Gets the Memory 1 Single-Bit Correction Event
 *
 * This function gets the current Memory 1 Single-Bit Correction Event.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory 1 Single-Bit Correction Event
 *         - 0b : No single-bit correction event on Memory 1 detected.
 *         - 1b : Single-bit correction event on Memory 1 detected.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetSrSbc1(const ErmRegType *obj)
{
    return ((obj->SR & ERM_SR_SBC1_MASK) >> ERM_SR_SBC1_SHIFT);
}

/*! \brief Sets the Memory 1 Single-Bit Correction Event
 *
 * This function sets the Memory 1 Single-Bit Correction Event.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Memory 1 Single-Bit Correction Event
 *                    - 0b : No single-bit correction event on Memory 1 detected.
 *                    - 1b : Single-bit correction event on Memory 1 detected.
 */
__attribute__((always_inline)) static inline void ErmReg_SetSrSbc1(ErmRegType *obj, uint8_t value)
{
    /* Clear the affected bit-field and write '0' to the w1c bits to avoid side-effects */
    uint32_t tmp = 0;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_SR_SBC1_SHIFT)) & ERM_SR_SBC1_MASK);
    obj->SR = tmp;
}

/*! \brief Gets the Memory 0 Non-Correctable Error Event
 *
 * This function gets the current Memory 0 Non-Correctable Error Event.
 * Write 1 to clear this field. This write also clears the corresponding interrupt notification,
 * if CR0[ENCIE0] is enabled.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory 0 Non-Correctable Error Event
 *         - 0b : No non-correctable error event on Memory 0 detected.
 *         - 1b : Non-correctable error event on Memory 0 detected.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetSrNce0(const ErmRegType *obj)
{
    return ((obj->SR & ERM_SR_NCE0_MASK) >> ERM_SR_NCE0_SHIFT);
}

/*! \brief Sets the Memory 0 Non-Correctable Error Event
 *
 * This function sets the Memory 0 Non-Correctable Error Event.
 * Write 1 to clear this field. This write also clears the corresponding interrupt notification,
 * if CR0[ENCIE0] is enabled.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Memory 0 Non-Correctable Error Event
 *                    - 0b : No non-correctable error event on Memory 0 detected.
 *                    - 1b : Non-correctable error event on Memory 0 detected.
 */
__attribute__((always_inline)) static inline void ErmReg_SetSrNce0(ErmRegType *obj, uint8_t value)
{
    /* Clear the affected bit-field and write '0' to the w1c bits to avoid side-effects */
    uint32_t tmp = 0;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_SR_NCE0_SHIFT)) & ERM_SR_NCE0_MASK);
    obj->SR = tmp;
}

/*! \brief Gets the Memory 0 Single-Bit Correction Event
 *
 * This function gets the current Memory 0 Single-Bit Correction Event.
 * Write 1 to clear this field. This write also clears the corresponding interrupt notification,
 * if CR0[ESCIE0] is enabled.
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory 0 Single-Bit Correction Event
 *         - 0b : No single-bit correction event on Memory 0 detected.
 *         - 1b : Single-bit correction event on Memory 0 detected.
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetSrSbc0(const ErmRegType *obj)
{
    return ((obj->SR & ERM_SR_SBC0_MASK) >> ERM_SR_SBC0_SHIFT);
}

/*! \brief Sets the Memory 0 Single-Bit Correction Event
 *
 * This function sets the Memory 0 Single-Bit Correction Event.
 * Write 1 to clear this field. This write also clears the corresponding interrupt notification,
 * if CR0[ESCIE0] is enabled.
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Memory 0 Single-Bit Correction Event
 *                    - 0b : No single-bit correction event on Memory 0 detected.
 *                    - 1b : Single-bit correction event on Memory 0 detected.
 */
__attribute__((always_inline)) static inline void ErmReg_SetSrSbc0(ErmRegType *obj, uint8_t value)
{
    /* Clear the affected bit-field and write '0' to the w1c bits to avoid side-effects */
    uint32_t tmp = 0;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_SR_SBC0_SHIFT)) & ERM_SR_SBC0_MASK);
    obj->SR = tmp;
}

/*! \brief Gets the Memory 0 Error Address
 *
 * This function gets the current Memory 0 Error Address.
 * This field contains the faulting system address of the last recorded ECC event on Memory 0
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory 0 Error Address
 */
__attribute__((always_inline)) static inline uint32_t ErmReg_GetCh0St0Adr0(const ErmRegType *obj)
{
    return ((obj->CH0_ST0 & ERM_CH0_ST0_ADR0_MASK) >> ERM_CH0_ST0_ADR0_SHIFT);
}

/*! \brief Gets the Memory n Syndrome
 *
 * This function gets the current Memory n Syndrome.
 * This field contains the ECC syndrome associated with the last recorded ECC event on Memory n
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory n Syndrome
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCh0St1Syn0(const ErmRegType *obj)
{
    return ((obj->CH0_ST1 & ERM_CH0_ST1_SYN0_MASK) >> ERM_CH0_ST1_SYN0_SHIFT);
}

/*! \brief Gets the Memory n Correctable Error Count
 *
 * This function gets the current Memory n Correctable Error Count.
 * For each correctable error event, the ERM increments this field's error count value
 * until the counter reaches its maximum value FFh.
 * COUNT field description can be updated as required.
 * COUNT value will stop once it reaches maximum value FFh and will not wrap even if error occurs.
 * Read this field to determine the correctable error count value so far.
 * Write all zeros to this field to reset the counter. Writing non-zero (or partial zero) values has no effect
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory n Correctable Error Count
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCh0St2CorrCnt0(const ErmRegType *obj)
{
    return ((obj->CH0_ST2 & ERM_CH0_ST2_CORR_CNT0_MASK) >> ERM_CH0_ST2_CORR_CNT0_SHIFT);
}

/*! \brief Sets the Memory n Correctable Error Count
 *
 * This function sets the Memory n Correctable Error Count.
 * For each correctable error event, the ERM increments this field's error count value
 * until the counter reaches its maximum value FFh.
 * COUNT field description can be updated as required.
 * COUNT value will stop once it reaches maximum value FFh and will not wrap even if error occurs.
 * Read this field to determine the correctable error count value so far.
 * Write all zeros to this field to reset the counter. Writing non-zero (or partial zero) values has no effect
 *
 * \param[in] obj : pointer to ERM register instance
 * \param[in] value : the value of Memory n Correctable Error Count
 */
__attribute__((always_inline)) static inline void ErmReg_SetCh0St2CorrCnt0(ErmRegType *obj, uint8_t value)
{
    uint32_t tmp = obj->CH0_ST2;

    tmp &= ~ERM_CH0_ST2_CORR_CNT0_MASK;
    tmp |= (((uint32_t)(((uint32_t)(value)) << ERM_CH0_ST2_CORR_CNT0_SHIFT)) & ERM_CH0_ST2_CORR_CNT0_MASK);
    obj->CH0_ST2 = tmp;
}

/*! \brief Gets the Memory 1 Error Address
 *
 * This function gets the current Memory 1 Error Address.
 * This field contains the faulting system address of the last recorded ECC event on Memory 1
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory 1 Error Address
 */
__attribute__((always_inline)) static inline uint32_t ErmReg_GetCh1St0Adr1(const ErmRegType *obj)
{
    return ((obj->CH1_ST0 & ERM_CH1_ST0_ADR1_MASK) >> ERM_CH1_ST0_ADR1_SHIFT);
}

/*! \brief Gets the Memory n Syndrome
 *
 * This function gets the current Memory n Syndrome.
 * This field contains the ECC syndrome associated with the last recorded ECC event on Memory 1
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory n Syndrome
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCh1St1Syn1(const ErmRegType *obj)
{
    return ((obj->CH1_ST1 & ERM_CH1_ST1_SYN1_MASK) >> ERM_CH1_ST1_SYN1_SHIFT);
}

/*! \brief Gets the Memory n Correctable Error Count
 *
 * This function gets the current Memory n Correctable Error Count.
 * For each correctable error event, the ERM increments this field's error count value
 * until the counter reaches its maximum value FFh.
 * COUNT value will stop once it reaches maximum value FFh and will not wrap even if error occurs.
 * Read this field to determine the correctable error count value so far.
 * Write all zeros to this field to reset the counter.
 * Writing non-zero (or partial zero) values has no effect
 *
 * \param[in] obj : pointer to ERM register instance
 * \return Memory n Correctable Error Count
 */
__attribute__((always_inline)) static inline uint8_t ErmReg_GetCh1St2CorrCnt1(const ErmRegType *obj)
{
    return ((obj->CH1_ST2 & ERM_CH1_ST2_CORR_CNT1_MASK) >> ERM_CH1_ST2_CORR_CNT1_SHIFT);
}

/*! \brief Sets the Memory n Correctable Error Count
 *
 * This function sets the Memory n Correctable Error Count.
 * For each correctable error event, the ERM increments this field's error count value
 * until the counter reaches its maximum value FFh.
 * COUNT value will stop once it reaches maximum value FFh and will not wrap even if error occurs.
 * Read this field to determine the correctable error count value so far.
 * Write all zeros to this field to reset the counter.
 * Writing non-zero (or partial zero) values has no effect
 *
 * \param[in] obj : pointer to ERM register instance
 */
__attribute__((always_inline)) static inline void ErmReg_SetCh1St2CorrCnt1(ErmRegType *obj)
{
    obj->CH1_ST2 = 0;
}

#ifdef __cplusplus
}
#endif /* extern "C" */

#endif /* _ERM_REG_H_ */
