/**
 * @file hv_cal_Watchdog.c
 * @brief wdg driver chip abstract layer file.
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2023-06-05
 * @copyright Copyright(c),2023-6, Hiview Software. All rights reserved.
 * </table>
 */

#include "hv_vos_Comm.h"
#include "hv_chip_Config.h"
#include "hv_cal_Watchdog.h"

HV_CAL_WDG_EARLY_INTERRUPT_FN g_fEarlyInterruptFn;

/** wdg interrupt
 *  @param uiIrqNum intrrupte number
 *  @retval HV_VOS_ISR_HANDLED
 */
HV_VOS_ISR_RESULT_E Hv_Cal_WDG_IRQHandler(UINT32 uiIrqNum, void *pArg)
{
    HV_UNUSED(uiIrqNum);
    HV_UNUSED(pArg);

    HV_R32_DECL_VAR();

    UINT32 uiStatus = HV_R32(SYS_REG_SH5_TOP0_REGR_SH5_MEM_RO_FIELD3);

    /* clear all the status */
    HV_W32(SYS_REG_SH5_TOP0_REGR_SH5_MEM_RO_FIELD3, 0);
    /* early wakeup interrupt status at 1/4 value of regw_wdg_cnt */
    if ((uiStatus & 0x1) == 1)
    {
        if (g_fEarlyInterruptFn != NULL)
        {
            g_fEarlyInterruptFn();
        }
    }

    return HV_VOS_ISR_HANDLED;
}

/**
 * @brief Reload the counter register.
 */
void Hv_Cal_WDG_Feed(UINT32 uiTimeoutMs)
{
    /* set wdt timeout */
    HV_W32(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED5, uiTimeoutMs);
    /* wdt reload */
    HV_W32_FIELD(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED7, reg_sh5_wdg_reload_en, 1);
    HV_W32_FIELD(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED7, reg_sh5_wdg_reload_en, 0);
    return;
}

/**
 * @brief WDG Enable
 */
void Hv_Cal_WDG_Enable(void)
{
    UINT32 uiVal = HV_R32(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED4);

    /* count enable */
    uiVal |= 0x00000001;
    /* wdg reset enable to reset whole system */
    uiVal |= 0x00000008;

    /* set count period 1ms from APB_CLK */
    HV_W32(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED6, (HV_CHIP_CLK_APB / 1000));

    /* start the wdt */
    HV_W32(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED4, uiVal);
    return;
}

 /**
 * @brief WDG Disable
 */
void Hv_Cal_WDG_Disable(void)
{
    /* clear the wdg ctrl */
    HV_W32(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED4, 0);
    return;
}

 /**
 * @brief WDG Cleanup
 */
void Hv_Cal_WDG_Cleanup(void)
{
    Hv_Cal_WDG_Disable();
    Hv_Vos_MaskIrq(HV_CHIP_IRQ_WDG);
    Hv_Vos_DetachIsr(HV_CHIP_IRQ_WDG, Hv_Cal_WDG_IRQHandler);
    g_fEarlyInterruptFn = NULL;
    return;
}

/**
 * @brief set early wakeup calback.
 */
void Hv_Cal_WDG_SetEarlyWakeup(HV_CAL_WDG_EARLY_INTERRUPT_FN fEarlyInterruptFn)
{
    if (fEarlyInterruptFn != NULL)
    {
        g_fEarlyInterruptFn = fEarlyInterruptFn;
        /* early wakeup interrupt enable at 1/4 value of regw_wdg_cnt */
        HV_W32(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED4, 0x2);
        Hv_Vos_AttachIsr(HV_CHIP_IRQ_WDG, Hv_Cal_WDG_IRQHandler, NULL);
        Hv_Vos_UnmaskIrq(HV_CHIP_IRQ_WDG);
    }
	else
	{
        Hv_Vos_MaskIrq(HV_CHIP_IRQ_WDG);
        Hv_Vos_DetachIsr(HV_CHIP_IRQ_WDG, Hv_Cal_WDG_IRQHandler);
        g_fEarlyInterruptFn = NULL;
	}

    return;
}

