/*!
* @file     Mcu_Pmu.c
*
* @version  1.0.0
*
* @brief    The underlying driver code of the PMU module.
*
* @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.
*/

/*
* MISRA-C:2012 compliance checks
*
*      Mcu_Pmu_c_MISRA_REF1
*          Breaks the required Rule-1.1 of MISRA 2012 guidelines,
*          The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation's translation limits
*
*      Mcu_Pmu_c_MISRA_REF2
*          Breaks the required Rule-17.7 of MISRA 2012 guidelines,
*          The value returned by a function having non-void return type shall be used
*
*/

#ifdef __cplusplus
extern "C"{
#endif

#include "Mcu.h"
#include "Mcu_Cfg.h"
#include "Std_Types.h"

#include "Mcu_PmuReg.h"
#include "Mcu_PmuTypes.h"
/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @addtogroup MCU_Driver
  * @brief MCU driver modules
  @{
*/

/** @defgroup MCU_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define MCU_PMU_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define MCU_PMU_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define MCU_PMU_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define MCU_PMU_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define MCU_PMU_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define MCU_PMU_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define MCU_PMU_SW_PATCH_VERSION                       0x00U

/**@} end of group MCU_Macros */
/*******************************************************************************
                               LOCAL FUNCTIONS
*******************************************************************************/
#define MCU_START_SEC_CODE
#include "Mcu_MemMap.h"

/** @defgroup MCU_Fuctions
  @{
*/

/*!
* @brief   Enables access to the Backup domain registers
*
* @param   None
*
* @retval  None
*/
void Mcu_Pmu_OperationPowerVoltDetector(uint32 status)
{
    if ((uint32)ENABLE == status)
    {
        REG_BIT_SET32(PMU_CTRL_REG_ADDR,PMU_CTRL_PVDEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(PMU_CTRL_REG_ADDR,PMU_CTRL_PVDEN_MASK);
    }
}


/*!
* @brief       Controls backup register access permissions
*
* @param       status          Access control state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Enables/disables write access to backup domain registers
* @note        Critical for RTC/BKP register protection during low-power modes
*/
void Mcu_Pmu_OperationBackupAccess(uint32 status)
{
    if ((uint32)ENABLE == status)
    {
        REG_BIT_SET32(PMU_CTRL_REG_ADDR,PMU_CTRL_BPWEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(PMU_CTRL_REG_ADDR,PMU_CTRL_BPWEN_MASK);
    }
}


/*!
* @brief       Configures Programmable Voltage Detector (PVD) threshold level
*
* @param       pvd             Target voltage threshold level
*
* @retval      None
*
* @note        Selects from 8 calibrated voltage thresholds (2.403V-4.457V)
* @warning     Does NOT clear previous threshold bits - may cause multiple thresholds to be active
* @note        Triggers PVD interrupt when VDD drops below selected level
*/
void Mcu_Pmu_OperationPVDLevelSelect(Mcu_Pmu_PVDSelectType pvd, uint8 high)
{
    REG_BIT_SET32(MCU_EINT_SWINTE_REG_ADDR, MCU_EINT_SWINTE_SET(16));
    REG_BIT_SET32(MCU_EINT_IMASK_REG_ADDR, MCU_EINT_IMASK_SET(16));
    
    if (high == (uint8)ENABLE)
    {
        REG_BIT_SET32(MCU_EINT_RTEN_REG_ADDR, MCU_EINT_RTEN_SET(16));
    }
    else
    {
        REG_BIT_SET32(MCU_EINT_FTEN_REG_ADDR, MCU_EINT_FTEN_SET(16));
    }
    
    switch (pvd)
    {
        case PVD_2_691V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_2_691V << PMU_CTRL_PLSEL_SHIFT);
            break;
        
        case PVD_3_005V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_3_005V << PMU_CTRL_PLSEL_SHIFT);
            break;
        
        case PVD_3_309V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_3_309V << PMU_CTRL_PLSEL_SHIFT);
            break;
        
        case PVD_3_608V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_3_608V << PMU_CTRL_PLSEL_SHIFT);
            break;
        
        case PVD_3_880V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_3_880V << PMU_CTRL_PLSEL_SHIFT);
            break;
        
        case PVD_4_197V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_4_197V << PMU_CTRL_PLSEL_SHIFT);
            break; 
        
        case PVD_4_457V :
            REG_RMW32(PMU_CTRL_REG_ADDR, PMU_CTRL_PLSEL_MASK, (uint32)PVD_4_457V << PMU_CTRL_PLSEL_SHIFT);
            break; 
        
        default:
            {
                /* nothing */
            }
            break;
    }
}


/*!
* @brief   Enters Sleep mode
*
* @param   entry :specifies if SLEEP mode in entered with WFI or WFE instruction
*                 This parameter can be one of the following values:
*                 @arg PMU_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
*                 @arg PMU_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
*
* @retval  None
*/
void Mcu_Pmu_EnterSleepMode(Mcu_Pmu_SleepEntryType entry)
{
    REG_BIT_CLEAR32(((uint32)SCB_BASE + (uint32)0x10U), (uint32)SCB_SCR_SLEEPDEEP_Msk);

    if (entry == PMU_SLEEPENTRY_WFI)
    {
        /*** @warning Mcu_Pmu_c_MISRA_REF1 '%1s' returns a value which is not being used. */
        /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
        __WFI();
    }
    else
    {
        /*** @warning Mcu_Pmu_c_MISRA_REF1 '%1s' returns a value which is not being used. */
        /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
        __SEV();
        /*** @warning Mcu_Pmu_c_MISRA_REF1 '%1s' returns a value which is not being used. */
        /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
        __WFE();
        /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
        __WFE();
    }
}

/*!
* @brief   Enters STOP mode
*
* @param   regulator: specifies the regulator state in STOP mode
*                     This parameter can be one of the following values:
*                     @arg PMU_REGULATOR_ON: STOP mode with regulator ON
*                     @arg PMU_REGULATOR_LowPower: STOP mode with regulator in low power mode
*
* @param   entry:     specifies if STOP mode in entered with WFI or WFE instruction
*                     This parameter can be one of the following values:
*                     @arg PMU_STOPENTRY_WFI: enter STOP mode with WFI instruction
*                     @arg PMU_STOPENTRY_WFE: enter STOP mode with WFE instruction
*                     @arg PMU_STOPENTRY_SLEEPONEXIT: enter STOP mode with SLEEPONEXIT instruction
*
* @retval  None
*/
void Mcu_Pmu_EnterStopMode(Mcu_Pmu_RegulatorType regulator, Mcu_Pmu_StopEntryType entry)
{
    REG_BIT_CLEAR32(PMU_CTRL_REG_ADDR,PMU_CTRL_PDDSCFG_MASK);
    
    if (PMU_REGULATOR_ON == regulator)
    {
        REG_BIT_CLEAR32(PMU_CTRL_REG_ADDR,PMU_CTRL_LPDSCFG_MASK);
    }
    else if (PMU_REGULATOR_LowPower == regulator)
    {
        REG_BIT_SET32(PMU_CTRL_REG_ADDR,PMU_CTRL_LPDSCFG_MASK);
    }
    else
    {
        /* nothing */
    }
    REG_BIT_SET32(((uint32)SCB_BASE + (uint32)0x10U), (uint32)SCB_SCR_SLEEPDEEP_Msk);

    switch (entry)
    {
        case PMU_STOPENTRY_WFI:
            /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
            __WFI();
            REG_BIT_CLEAR32(((uint32)SCB_BASE + (uint32)0x10U), (uint32)SCB_SCR_SLEEPDEEP_Msk);
            break;

        case  PMU_STOPENTRY_WFE:
            /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
            __WFE();
            /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
            __WFE();
            REG_BIT_CLEAR32(((uint32)SCB_BASE + (uint32)0x10U), (uint32)SCB_SCR_SLEEPDEEP_Msk);
            break;

        case PMU_STOPENTRY_SLEEPONEXIT:
            REG_BIT_SET32(((uint32)SCB_BASE + (uint32)0x10U), (uint32)SCB_SCR_SLEEPONEXIT_Msk);
            break;

        default:
            {
                /* nothing */
            }
            break;
    }
}

/*!
* @brief   Enters STANDBY mode
*
* @param   None
*
* @retval  None
*/
void Mcu_Pmu_EnterStandbyMode(void)
{
    REG_BIT_SET32(PMU_CTRL_REG_ADDR,PMU_CTRL_PDDSCFG_MASK);
    
    REG_BIT_SET32(((uint32)SCB_BASE + (uint32)0x10U), (uint32)SCB_SCR_SLEEPDEEP_Msk);
    /*** @warning Mcu_Pmu_c_MISRA_REF2 No function declaration. Implicit declaration inserted: 'extern int %1s(); */
    __WFI();
}

/*!
* @brief   Clears the PWR's pending flags
*
* @param   flag: specifies the flag to clear
*                This parameter can be one of the following values:
*                @arg PMU_FLAG_WUPF: Wake Up flag
*                @arg PMU_FLAG_STDBYF: StandBy flag
*
* @retval  None
*/
void Mcu_Pmu_ClearStatusFlag(Mcu_Pmu_FlagType flag)
{
    if (flag == PMU_FLAG_WAKEUP)
    {
        REG_BIT_SET32(PMU_CTRL_REG_ADDR,PMU_CTRL_WUFLGCLR_MASK);
    }
    else if (flag == PMU_FLAG_STANDBY)
    {
        REG_BIT_SET32(PMU_CTRL_REG_ADDR,PMU_CTRL_SBFLGCLR_MASK);
    }
    else
    {
        /* nothing */
    }
}


FUNC(uint8, MCU_CODE) Mcu_Pmu_ReadPvdFlag(void)
{
    uint8 returnVal = BIT_RESET;

    if (((REG_BIT_GET32(PMU_CSTS_REG_ADDR, PMU_CSTS_PVDOFLG_MASK)) >> PMU_CSTS_PVDOFLG_SHIFT) == (uint32)BIT_SET)
    {
        returnVal = BIT_SET;
    }
    else
    {
        /* nothing */
    }
    return returnVal;
}

FUNC(uint8, ICU_CODE) Mcu_Eint_ReadIntFlag(void)
{
    uint8 status = BIT_RESET;
    uint32 enablestatus = 0;

    enablestatus = REG_BIT_GET32(MCU_EINT_IMASK_REG_ADDR, MCU_EINT_PVD_MASK);

    if(REG_BIT_GET32(MCU_EINT_IPEND_REG_ADDR, MCU_EINT_PVD_MASK) == (uint32)BIT_RESET)
    {
        status = BIT_RESET;
    }
    else if(enablestatus == (uint32)BIT_RESET)
    {
        status = BIT_RESET;
    }
    else
    {
        status = BIT_SET;
    }

    return status;
}

FUNC(void, ICU_CODE)  Mcu_Eint_ClearIntFlag(void)
{
    REG_WRITE32(MCU_EINT_IPEND_REG_ADDR, MCU_EINT_PVD_MASK);
}
/*******************************************************************************
                              GLOBAL FUNCTION
*******************************************************************************/
/*!
* @brief         Used to initialize the Pmu driver
*
* @param[in]     PmuPtr:    Pointer to configuration structure.
*
* @retval        void
*
* @note          None
*/
FUNC(void, MCU_CODE) Mcu_Pmu_Init(const Mcu_Pmu_CfgType * PmuPtr)
{
    Mcu_Pmu_OperationBackupAccess(PmuPtr->rtcEnable);
    Mcu_Pmu_OperationPowerVoltDetector(PmuPtr->powerEnable);
    Mcu_Pmu_OperationPVDLevelSelect(PmuPtr->pvdSelect,PmuPtr->PVDHigh);
}

/**@} end of group MCU_Fuctions */

#define MCU_STOP_SEC_CODE
#include "Mcu_MemMap.h"

#ifdef __cplusplus
}
#endif

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