/*!
* @file     Wdg_Hw.c
*
* @version  1.0.0
*
* @brief    This file defines Wdg register level function
*
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_01-Otc-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/

#ifdef __cplusplus
extern "C"{
#endif

#include "Wdg_Hw.h"
#include "Wdg_Reg.h"
#include "StdRegMacros.h"
#include "Mcu_RcmReg.h"

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup WDG_Driver
  * @brief WDG driver modules
  @{
*/

/** @defgroup WDG_Macros
  @{
*/
/**************************************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
**************************************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define WDG_HW_VENDOR_ID                     0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define WDG_HW_AR_RELEASE_MAJOR_VERSION      0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define WDG_HW_AR_RELEASE_MINOR_VERSION      0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define WDG_HW_AR_RELEASE_REVISION_VERSION   0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define WDG_HW_SW_MAJOR_VERSION              0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define WDG_HW_SW_MINOR_VERSION              0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define WDG_HW_SW_PATCH_VERSION              0x00U

/**@} end of group WDG_Macros */

/**************************************************************************************************
                    VERSION INFOMATION VERIFICATION
**************************************************************************************************/
/* Make sure the vendor id is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_VENDOR_ID != WDG_HW_H_VENDOR_ID)
    #error "Vendor id mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif
/* Make sure the AUTOSAR major version number is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_AR_RELEASE_MAJOR_VERSION != WDG_HW_H_AR_RELEASE_MAJOR_VERSION) 
    #error "AUTOSAR Major Version Number mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif
/* Make sure the AUTOSAR minor version number is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_AR_RELEASE_MINOR_VERSION != WDG_HW_H_AR_RELEASE_MINOR_VERSION) 
    #error "AUTOSAR Minor Version Number mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif
/* Make sure the AUTOSAR revision version number is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_AR_RELEASE_REVISION_VERSION != WDG_HW_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif
/* Make sure the software major version number is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_SW_MAJOR_VERSION != WDG_HW_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif
/* Make sure the software minor version number is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_SW_MINOR_VERSION != WDG_HW_H_SW_MINOR_VERSION) 
    #error "Software Minor Version Number mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif
/* Make sure the software patch version number is the same between Wdg_Hw.c and Wdg_Hw.h */
#if (WDG_HW_SW_PATCH_VERSION != WDG_HW_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Wdg_Hw.c and Wdg_Hw.h."
#endif

/* Make sure the vendor id is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_VENDOR_ID != WDG_REG_H_VENDOR_ID)
    #error "Vendor id mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif
/* Make sure the AUTOSAR major version number is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_AR_RELEASE_MAJOR_VERSION != WDG_REG_H_AR_RELEASE_MAJOR_VERSION) 
    #error "AUTOSAR Major Version Number mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif
/* Make sure the AUTOSAR minor version number is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_AR_RELEASE_MINOR_VERSION != WDG_REG_H_AR_RELEASE_MINOR_VERSION) 
    #error "AUTOSAR Minor Version Number mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif
/* Make sure the AUTOSAR revision version number is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_AR_RELEASE_REVISION_VERSION != WDG_REG_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif
/* Make sure the software major version number is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_SW_MAJOR_VERSION != WDG_REG_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif
/* Make sure the software minor version number is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_SW_MINOR_VERSION != WDG_REG_H_SW_MINOR_VERSION) 
    #error "Software Minor Version Number mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif
/* Make sure the software patch version number is the same between Wdg_Hw.c and Wdg_Reg.h */
#if (WDG_HW_SW_PATCH_VERSION != WDG_REG_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Wdg_Hw.c and Wdg_Reg.h."
#endif

#ifdef ENABLE_INTERMODULE_MCAL_CHECK
    /* Make sure the AUTOSAR major version number is the same between Wdg_Hw.c and StdRegMacros.h */
    #if (WDG_HW_AR_RELEASE_MAJOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MAJOR_VERSION) 
        #error "AUTOSAR Major Version Number mismatch between Wdg_Hw.c and StdRegMacros.h."
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Wdg_Hw.c and StdRegMacros.h */
    #if (WDG_HW_AR_RELEASE_MINOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MINOR_VERSION) 
        #error "AUTOSAR Minor Version Number mismatch between Wdg_Hw.c and StdRegMacros.h."
    #endif
#endif

/* Make sure the vendor id is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_VENDOR_ID != MCU_RCM_REG_H_VENDOR_ID)
    #error "Vendor id mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif
/* Make sure the AUTOSAR major version number is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_AR_RELEASE_MAJOR_VERSION != MCU_RCM_REG_H_AR_RELEASE_MAJOR_VERSION) 
    #error "AUTOSAR Major Version Number mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif
/* Make sure the AUTOSAR minor version number is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_AR_RELEASE_MINOR_VERSION != MCU_RCM_REG_H_AR_RELEASE_MINOR_VERSION) 
    #error "AUTOSAR Minor Version Number mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif
/* Make sure the AUTOSAR revision version number is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_AR_RELEASE_REVISION_VERSION != MCU_RCM_REG_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR Revision Version Number mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif
/* Make sure the software major version number is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_SW_MAJOR_VERSION != MCU_RCM_REG_H_SW_MAJOR_VERSION)
    #error "Software Major Version Number mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif
/* Make sure the software minor version number is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_SW_MINOR_VERSION != MCU_RCM_REG_H_SW_MINOR_VERSION) 
    #error "Software Minor Version Number mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif
/* Make sure the software patch version number is the same between Wdg_Hw.c and Mcu_RcmReg.h */
#if (WDG_HW_SW_PATCH_VERSION != MCU_RCM_REG_H_SW_PATCH_VERSION)
    #error "Software Patch Version Number mismatch between Wdg_Hw.c and Mcu_RcmReg.h."
#endif

/**************************************************************************************************
                    GLOBAL CONSTANTS COLLECTION
**************************************************************************************************/
#define WDG_START_SEC_CONST_32
#include "Wdg_MemMap.h"

/** @defgroup WDG_Variable
  @{
*/

/** The base address array of the IWDT */
CONST(uint32, WDG_CONST) IWDT_BASEADDR[1] =
{
    IWDT0_BASEADDR
};

/**@} end of group WDG_Variable */

#define WDG_STOP_SEC_CONST_32
#include "Wdg_MemMap.h"


#define WDG_START_SEC_VAR_INIT_UNSPECIFIED
#include "Wdg_MemMap.h"

/** @defgroup WDG_Variable
  @{
*/

/** Variable used to store wdg reconfigurat status */
static VAR(boolean, WDG_VAR) g_RecfgStatus[WDG_INSTANCES_SUPPORT_NUMBER] = {TRUE};

/**@} end of group WDG_Variable */

#define WDG_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Wdg_MemMap.h"


#ifdef WDG_RUN_AREA_ROM
#define WDG_START_SEC_CODE
#else
#define WDG_START_SEC_RAMCODE
#endif
#include "Wdg_MemMap.h"

#if (WDG_INTERNAL_DIRECT == WDG_IMPLEMENTATION_TYPE)

/** @defgroup WDG_Fuctions
  @{
*/

/**************************************************************************************************
                    GLOBAL FUNCTION
**************************************************************************************************/
/*!
* @brief           This function used to check hardware settings on lower level.
*
* @param[in]       pWdgHWCfgPtr      Pointer to specific mode parameter struct.
*                  wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK.
*/
FUNC(Std_ReturnType, WDG_CODE) Wdg_Hw_CheckWindowCfg
                              (P2CONST(Wdg_ModeParamterType, AUTOMATIC, WDG_APPL_CONST) pWdgHWCfgPtr,
                                 CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(Std_ReturnType, AUTOMATIC) checkResult = (Std_ReturnType)E_OK;

    (void)wdgInstanceId;

    if(
        /* checkResult is E_NOT_OK if the configuration pointer is NULL */
        (NULL_PTR == pWdgHWCfgPtr) ||
        /* checkResult is E_NOT_OK if the timeout value is small than window value */
        (
          (TRUE == pWdgHWCfgPtr->wdgWindowEn) &&
          (pWdgHWCfgPtr->wdgModeTimeout < pWdgHWCfgPtr->wdgModeWindow)
        )
      )
    {
        checkResult = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        /* do nothing */
    }

    return checkResult;
}

/*!
* @brief           This function initialize the wdg module on register level.
*
* @param[in]       pWdgHWCfgPtr      Pointer to specific mode parameter struct.
*                  wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          (uint32)value
*/
FUNC(uint32, WDG_CODE) Wdg_Hw_Init
                       (P2CONST(Wdg_ModeParamterType, AUTOMATIC, WDG_APPL_CONST) pWdgHWCfgPtr,
                          CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    VAR(uint32, AUTOMATIC) gptTickCalculate = 0U;
#if (STD_ON == WDG_USE_GPT)
    CONST(uint16, WDG_CONST) divisors[7] = { 4, 8, 16, 32, 64, 128, 256 };
#endif
#if (STD_ON == WDG_DEM_ERROR_DETECT)
    VAR(volatile uint32, AUTOMATIC) recfgTimeout = (uint32)WDG_RECONFIGURE_FLAG_TIMEOUT;
#endif

    SuspendAllInterrupts();

    if(TRUE == pWdgHWCfgPtr->wdgRecfgEn)
    {
        g_RecfgStatus[wdgInstanceId] = TRUE;
    }
    else
    {
        g_RecfgStatus[wdgInstanceId] = FALSE;
    }

    if(0U != REG_BIT_GET32(RCM_CSTS_REG_ADDR, RCM_CSTS_IWDTRSTFLG_MASK))
    {
        REG_BIT_SET32(RCM_CSTS_REG_ADDR, RCM_CSTS_RSTFLGCLR_MASK);
    }
    else
    {
        /* do nothing */
    }

    if(TRUE == pWdgHWCfgPtr->wdgWindowEn)
    {
        /* Enable wdg */
        REG_WRITE32(IWDT_KEY_REG_ADDR(wdgInstanceId), (uint32)WDG_KEY_ENABLE);
        /* Unlock the register, so than can reconfiguration wdg */
        REG_WRITE32(IWDT_KEY_REG_ADDR(wdgInstanceId), (uint32)WDG_KEY_ACCESS);
        /* Set IWDT_PSC register */
        REG_WRITE32(IWDT_PSC_REG_ADDR(wdgInstanceId), (uint32)(pWdgHWCfgPtr->psc));
        /* Set IWDT_CNTRLD register */
        REG_WRITE32(IWDT_CNTRLD_REG_ADDR(wdgInstanceId), (pWdgHWCfgPtr->wdgModeTimeout));
        /* Make sure the register is in an idle state */
        while(0U != REG_READ32(IWDT_STS_REG_ADDR(wdgInstanceId)))
        {
            /* do nothing */
        }
        /* Set IWDT_WIN register */
        REG_WRITE32(IWDT_WIN_REG_ADDR(wdgInstanceId), (pWdgHWCfgPtr->wdgModeWindow));
    }
    else
    {
        /* Unlock the register, so than can reconfiguration wdg */
        REG_WRITE32(IWDT_KEY_REG_ADDR(wdgInstanceId), (uint32)WDG_KEY_ACCESS);
        /* Set IWDT_PSC register */
        REG_WRITE32(IWDT_PSC_REG_ADDR(wdgInstanceId), (uint32)(pWdgHWCfgPtr->psc));
        /* Set IWDT_CNTRLD register */
        REG_WRITE32(IWDT_CNTRLD_REG_ADDR(wdgInstanceId), (pWdgHWCfgPtr->wdgModeTimeout));
        /* refresh wdg */
        REG_WRITE32(IWDT_KEY_REG_ADDR(wdgInstanceId), (uint32)WDG_KEY_REFRESH);
        /* Enable wdg */
        REG_WRITE32(IWDT_KEY_REG_ADDR(wdgInstanceId), (uint32)WDG_KEY_ENABLE);
    }

    ResumeAllInterrupts();

#if (STD_ON == WDG_DEM_ERROR_DETECT)
    /* Check if reconfiguration was success */
    while ((recfgTimeout > 0UL) && (0U != REG_READ32(IWDT_STS_REG_ADDR(wdgInstanceId))))
    {
        recfgTimeout = recfgTimeout - 1U;
    }

    if (0UL == recfgTimeout)
    {
        if((uint32)STD_ON == g_wdgETimeout.state)
        {
            (void) Dem_SetEventStatus((Dem_EventIdType)g_wdgETimeout.id, DEM_EVENT_STATUS_FAILED);
        }
        else
        {
            /* do nothing */
        }
    }
    else
    {
        /* do nothing */
    }
#endif

#if (STD_ON == WDG_USE_GPT)
    if(TRUE == pWdgHWCfgPtr->wdgWindowEn)
    {
        gptTickCalculate = (uint32)(((pWdgHWCfgPtr->wdgModeTimeout + 1U) * (divisors[pWdgHWCfgPtr->psc])) - 
                                   (((pWdgHWCfgPtr->wdgModeWindow  + 1U) * (divisors[pWdgHWCfgPtr->psc])) >> 1U));
    }
    else
    {
        gptTickCalculate = (uint32)(((pWdgHWCfgPtr->wdgModeTimeout + 1U) * (divisors[pWdgHWCfgPtr->psc])) >> 1U);
    }
#else
        gptTickCalculate = 0U;
#endif

    return gptTickCalculate;
}

/*!
* @brief           This function used to check whether wdg mode can be updated.
*
* @param[in]       wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          E_OK / E_NOT_OK.
*/
#ifdef WDG_CHECK_CONFIG_REFRESH
#if (STD_ON == WDG_CHECK_CONFIG_REFRESH)
FUNC(Std_ReturnType, WDG_CODE) Wdg_Hw_CheckReconfig(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    return ((Std_ReturnType)(((boolean)FALSE == g_RecfgStatus[wdgInstanceId]) ? E_NOT_OK : E_OK));
}
#endif
#endif

/*!
* @brief           This function will clear WDT_CNT value.
*
* @param[in]       wdgInstanceId     wdg specific instance.
* @param[out]      None
* @param[in,out]   None
*
* @retval          None
*/
FUNC(void, WDG_CODE) Wdg_Hw_ReloadCounter(CONST(Wdg_InstanceType, WDG_CONST) wdgInstanceId)
{
    SuspendAllInterrupts();
    REG_WRITE32(IWDT_KEY_REG_ADDR(wdgInstanceId), (uint32)WDG_KEY_REFRESH);
    ResumeAllInterrupts();
}

#endif

/**@} end of group WDG_Fuctions */

#ifdef WDG_RUN_AREA_ROM
#define WDG_STOP_SEC_CODE
#else
#define WDG_STOP_SEC_RAMCODE
#endif
#include "Wdg_MemMap.h"

#ifdef __cplusplus
}
#endif

/**@} end of group WDG_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
