/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * 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 the copyright holder 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
 * HOLDER 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.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author$
 * $Date$
 * $RCSfile: pdwnc_hw.c,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

/** @file pdwnc_if.c
 *  pdwnc_if.c The PDWNC (Power DoWN Controller) interface
 */


//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------

#include "ir_if.h"
#include "rtc_if.h"
#include "x_pinmux.h"
#include "x_pdwnc.h"
#include "x_bim.h"
#include "x_assert.h"
#include "x_os.h"
#include "x_ckgen.h"
#include "x_timer.h"
#include "x_hal_arm.h"
#include "x_gpio.h"
#include "drvcust_if.h"
#include "pdwnc_config.h"
#include "pdwnc_debug.h"
#include "pdwnc_hw.h"
#include "pdwnc_t8032.h"
#include "pdwnc_gpio.h"
#include "pdwnc_srvad.h"
#include "pdwnc_entry.h"
#include "pdwnc_if.h"
#include "sif_if.h"
#include "eeprom_if.h"
#include "pdwnc_if.h"
#include "drv_adcset.h"
#include "ostg_if.h"
#include "drv_display.h"
#include "x_drv_cli.h"
#include "x_stl_lib.h"


#include "../net/ethernet/ether_reg.h"
#ifdef SYS_ANDROID_TV_TIF_SUPPORT
#include "mhl_if.h"
#endif
#ifndef CC_MTK_LOADER
#ifdef TIME_MEASUREMENT
#include "x_time_msrt.h"
#include "u_time_msrt_name.h"
#endif
#ifndef __USERDRV__
#if !defined(CC_DRIVER_BUILD)
#include <linux/pm.h>
#endif
#endif
#endif
#if defined(CC_MT5891) || defined(CC_MT5886) || defined(CC_MT5893) || defined(CC_MT5895)
#include "drv_mhlcom.h"
#include "x_hal_5381.h"
#ifndef CC_MTK_LOADER
#include "drv_mhl.h"
#endif
#endif

//-----------------------------------------------------------------------------
// Configuration
//-----------------------------------------------------------------------------
#ifdef CC_MTK_LOADER
//#undef x_crit_start
//#undef x_crit_end
//#define x_crit_start() 0
//#define x_crit_end(x) UNUSED(x)
#define CRIT_STATE_T UINT8
#else
#include "x_os.h"
#include "sif_if.h"
#endif
#ifndef CC_MTK_LOADER
#if(__KERNEL__) || defined(__USERDRV__)
#include "cb_data.h"
#include "mtperipheral.h"
extern INT32 _CB_PutEvent(CB_FCT_ID_T eFctId, INT32 i4TagSize, void *pvTag);
#endif
#endif

#ifdef CC_PDWNC_REBOOT_NOTIFY
#ifndef CC_MTK_LOADER
#ifdef __KERNEL__
#include <linux/reboot.h>
#include <linux/notifier.h>
#endif
#endif
#endif
#if defined(CC_ANDROID_FASTBOOT_SUPPORT) || defined(CC_ANDROID_RECOVERY_SUPPORT)
#include <linux/mmc/mtk_msdc_part.h>
#include <linux/version.h>
#endif

#ifndef CC_MTK_LOADER
#if defined(CC_S_PLATFORM)
#ifdef CONFIG_CB2_EARLYSUSPEND
extern int twoworlds_power_get_state(void);
#else
extern int pm_autosleep_state(void);
#endif
#endif
#endif

#if defined (CC_MT5895)
extern BOOL Cm4GetGaStatus(void);
#endif

//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------

#define VGAWAKEUP_VRANGE_U 0xfff
#define VGAWAKEUP_VRANGE_L 0x1c

//todo vga user check this
//Crystal is 24MHz
#define CSYNC_CONT_THU_DEFAULT   0x175//(0x01a4/9*8)
#define CSYNC_CONT_THL_DEFAULT   0xe2//(0x00ff/9*8)
#define CSYNC_CONT_THH_DEFAULT	0x16e//(0x19c/9*8)
#define VGAWAKEUP_HRANGE_U	(0x6ff)//24m/13k=1846=0x736
#define VGAWAKEUP_HRANGE_L	(0xbf)//24m/100k=240=0xf0
//this paramter is the time to try for each sync type , should bigger than V_STABLE_TH
#define VGAWAKEUP_FREERUN_CNT_TH  (0x2a0000)
#if defined(CC_S_PLATFORM) && defined(CC_PHX_CUST)
#define CC_SUPPORT_SW_WOW_GPIO
#endif

//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Static variables
//-----------------------------------------------------------------------------
#ifndef CC_MTK_LOADER
// PDWNC module sub-interrupt routine list.
static volatile x_os_isr_fct _varIntList[MAX_PDWNC_INT_ID];
#endif /* CC_MTK_LOADER */

static INT32 _gi4PDWNCInit = 0;
static UINT32 _fgPowerDownByAcCut = 0;
static UINT32 _gi4PDWNCWifiWowState = 0;


static BOOL _fgIrLedEnable = TRUE;

static BOOL _fgSuspendWakeupReasonUp = FALSE;
//static BOOL _fgWdtPreInit = FALSE;


static UINT32 _u4PowerDownEn = 0;
static UINT32 _u4PowerDownEvent = 0;
#if defined(CC_SUPPORT_STR_CORE_OFF)
UINT32 PDWNC_IsSuspend(void);
#endif

#ifdef NDEBUG
#ifdef WATCHDOG_DETECT_ENABLE
BOOL _bgWatchdogDetect = TRUE;
#endif /* WATCHDOG_DETECT_ENABLE */
#endif

// static PDWNC_FuncTbl *pgrPDWNC_Func = NULL;
#define pgrPDWNC_Func   (PDWNC_EXT_GetFunc())
#ifndef CC_MTK_LOADER
static UINT32 pdwnc_reboot_disable = 0;
void set_PDWNC_Reboot_State(int state);
#endif /* CC_MTK_LOADER */

static BOOL _fgIsSelfDiagShutDown = FALSE;
//-----------------------------------------------------------------------------
// Imported functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Static functions
//-----------------------------------------------------------------------------

#ifndef CC_MTK_LOADER
extern void _PdwncGpioIsr(UINT16 u2IntIndex);
//-----------------------------------------------------------------------------
/** _PdwncHwIsr() is the interrupt routine of PDWNC module.
 *  @param u2VctId is not used, it should be VECTOR_PDWNC.
 */
//-----------------------------------------------------------------------------
static void _PdwncHwIsr(UINT16 u2VctId)
{
    UINT16 i = 0;
    UINT32 u4Val, u4ValGpio;
    UNUSED(u2VctId);
    // Should we use this?? XXX discussion this.
    u4Val = u4IO32Read4B(PDWNC_INTSTA) & u4IO32Read4B(PDWNC_ARM_INTEN);
#ifdef CONFIG_I2C_MT53XX
    u4Val &= ~BIT(PDWNC_INTNO_SIFM);
    u4Val &= ~BIT(PDWNC_INTNO_SIFM1);
#endif
	if(u4Val)
    for (i = 0 ; i < MAX_PDWNC_INT_ID; i++)
    {
        if (u4Val & _PINT(i))
        {
            if (_varIntList[i])
            {
                _varIntList[i](i);
            }
            else
            {
                LOG(11, "PDWNC(0x%08x) interrupt %d no routine hook\n",
                    u4Val, i);
                // Still need to clear this non-hook interrupt.
            }
			vIO32Write4B(PDWNC_INTCLR, _PINT(i));
        }
    }

	u4ValGpio = u4IO32Read4B(PDWNC_EXT_INTSTA_0) & u4IO32Read4B(PDWNC_ARM_INTEN_0);
	if(u4ValGpio)
    for (i = 0 ; i < 0x20; i++)
    {
        if (u4ValGpio & _PINT(i))
        {
			//gpio interrupt always call this function
			_PdwncGpioIsr(i);
			//isr function will do clear status.
			//vIO32Write4B(PDWNC_EXTINTCLR, _PINT(i));
        }
    }
#if !(defined(CC_MT5863) || defined(CC_MT5865))
	u4ValGpio = u4IO32Read4B(PDWNC_EXT_INTSTA_1) & u4IO32Read4B(PDWNC_ARM_INTEN_1);
	if(u4ValGpio)
    for (i = 0 ; i < (TOTAL_PDWNC_GPIO_INT_NUM - 0x20); i++)
    {
        if (u4ValGpio & _PINT(i))
        {
			//gpio interrupt always call this function
			_PdwncGpioIsr(i+32);
			//isr function will do clear status.
			//vIO32Write4B(PDWNC_EXTINTCLR, _PINT(i));
        }
    }
#endif
#ifndef CC_NO_BIM_INTR
	VERIFY(BIM_ClearIrq(VECTOR_PDWNC));
#endif
}

//#define VECTOR_WDT 7
static volatile PFN_WDT_CALLBACK _afnWdtCallback[NORMAL_GPIO_NUM] = {NULL, NULL, NULL};//NORMAL_GPIO_NUM for SW gpio polling thread
static unsigned int watchdog_testcase= 0;
void PDWNC_WdtIsrTestCase(UINT32 en)
{
    watchdog_testcase = en;
}
static void PDWNC_WDT_Callback(INT32 i4Wdt)
{
    PDWNC_T8032_CMD_T rCmd;

    LOG(0, "\nPDWNC WDT%d Interrupt!\n", i4Wdt);

	if (watchdog_testcase == 3)
	{
		rCmd.u1Cmd = PDWNC_CMD_ARM8032_ENTER_DRAM_SELF_REFRESH;
		rCmd.u1SubCmd = 0;
		rCmd.au1Data[0] = rCmd.au1Data[1]= rCmd.au1Data[2] = rCmd.au1Data[3] = 0;
		PDWNC_T8032CMD_SET_CMD((rCmd.u1Cmd) | ((rCmd.u1SubCmd) << 8));
		// Signal 8032 interrupt.
		vIO32WriteFldAlign(PDWNC_ARM_INTEN, 0x1, FLD_AUX_INTEN);
	    vIO32WriteFldAlign(PDWNC_ARM_INT, 0x1, FLD_ARM_INT);
		//PDWNC_T8032Cmd(&rCmd, NULL);
	}
	else if (watchdog_testcase == 1)
	{
		#ifndef CONFIG_64BIT
		BspDumpSystemTasksState();
		#endif
	}
	LOG(0, "Dump complete, good-bye\n");
    HAL_Delay_us(10*1000);// Delay to make sure last bits get write to UART.
	//vIO32Write4B((PDWNC_WDTRST0 + (i4Wdt * 4)), 0x0fffffff);	//set reset wait time to 0 (0x0fffffff - 0x0fffffff), let watchdog reset at once
}
INT32 WDT_ISR_Reg(UINT32 u4Idx, PFN_WDT_CALLBACK pfnCallback)
{
#ifndef CC_MTK_LOADER
	if(u4Idx > 2 )
		return -1;

    if (pfnCallback != NULL)
    {
    	vIO32Write4B(PDWNC_WDTINT_EN, u4IO32Read4B(PDWNC_WDTINT_EN) | (1 << u4Idx));
        _afnWdtCallback[u4Idx] = pfnCallback;
    }
	else
	{
    	vIO32Write4B(PDWNC_WDTINT_EN, u4IO32Read4B(PDWNC_WDTINT_EN) & (~(1 << u4Idx)));
        _afnWdtCallback[u4Idx] = NULL;
	}
#endif
	return 0;
}


static void _WDTIsr(UINT16 u2VctId)
{
	UINT32 i, u4Val;
	UNUSED(u2VctId);

	u4Val = u4IO32Read4B(PDWNC_WDTINT_STA);
#if 1  //use this will cancel watchdog reboot.
	vIO32Write4B(PDWNC_WDTCTL,0x00000000);//clear watchdog flag
	vIO32Write4B(PDWNC_WDTINT_CLR, u4Val);	//use this will  clear the int and "stop watchdog reset"!!!
#ifndef CC_NO_BIM_INTR
	VERIFY(BIM_ClearIrq(VECTOR_WDT));
#endif
#endif
	if (watchdog_testcase == 2)
	{
		LOG(0, "\n watchdog_keepstate !\n");
	#ifndef __USERDRV__
		BUG();
	#endif
	}
	for(i = 0; i < 3; i++)
	{
		if(u4Val & (1 << i))
			if(_afnWdtCallback[i] != NULL)
				_afnWdtCallback[i](i);
	}

}
//#define WATCHDOG_SEC_CNT(x)  (0x0fffffffU - (x * 3000000))	//x should less than 9.48s, it is for 3M
//#define WATCHDOG_MSEC_CNT(x)  (0x0fffffffU - (((x/100) * 0x00300000)/10))

//#ifndef NDEBUG
void PDWNC_WatchDogIsrPreInit(void)
{
    UINT32 i;
	vIO32Write4B(PDWNC_WDTRST0, 0x0);
	vIO32Write4B(PDWNC_WDTRST1, 0x0);
	vIO32Write4B(PDWNC_WDTRST2, 0x0);
	//watchdog callback Reg
	for(i=0; i<3; i++)
	{
		if((WDT_ISR_Reg(i, PDWNC_WDT_Callback)) < 0)
		{
			LOG(0,"Reg WDT%d interrupt callback fail..\n", i);
			return;
		}
	}
	LOG(0,"Reg WDT interrupt callback successful..\n");
}
//#endif
//-----------------------------------------------------------------------------
/** _PdwncHwSetIsr() is the interrupt enable/disable routine of PDWNC module.
 *  @param fgSet TRUE to enable interrupt, otherwise disable.
 */
//-----------------------------------------------------------------------------
INT32 _PdwncHwSetIsr(BOOL fgSet)
{
    static BOOL fgCurSet = FALSE;
    INT32 i4Val;
    void (* pfnOldIsr)(UINT16);

    if (fgSet && (fgSet!=fgCurSet))
    {
    	/* enable irq. */
        fgCurSet = fgSet;
        i4Val = x_reg_isr(VECTOR_PDWNC, _PdwncHwIsr, &pfnOldIsr);
        if (i4Val != OSR_OK)
        {
            return FALSE;
        }
#ifndef CC_NO_BIM_INTR
        VERIFY(BIM_ClearIrq(VECTOR_PDWNC));
#endif

        i4Val = x_reg_isr(VECTOR_WDT, _WDTIsr, &pfnOldIsr);
        if (i4Val != OSR_OK)
        {
            return FALSE;
        }
#ifndef CC_NO_BIM_INTR
        VERIFY(BIM_ClearIrq(VECTOR_WDT));
#endif
    }
    else if (!fgSet && (fgSet!=fgCurSet))
    {
    	/* disable irq. */
        fgCurSet = fgSet;
        i4Val = x_reg_isr(VECTOR_PDWNC, NULL, &pfnOldIsr);
        if (i4Val != OSR_OK)
        {
            return FALSE;
        }

		i4Val = x_reg_isr(VECTOR_WDT, NULL, &pfnOldIsr);
		if (i4Val != OSR_OK)
		{
			return FALSE;
		}
    }
    return TRUE;
}

#ifdef CC_DC_ONOFF_TEST_ENABLE
#define SYSTEM_SHUTDOWN_DELAY       5000
#define WAKEUP_TIMER                3       // system wake up timer by RTC

static HANDLE_T _hShutdownHandle = (HANDLE_T)NULL;

static void _PDWNC_RebootHandle(void *pvArg)
{
    UINT64 u8Time;

    UNUSED(pvArg);

    x_thread_delay(SYSTEM_SHUTDOWN_DELAY);

    LOG(0, "[RebootHandle]Get time date\n");
    RTC_GetTimeDate(&u8Time);
    u8Time += WAKEUP_TIMER;
    RTC_SetAlertTime(u8Time);

    // Enable RTC wakeup
    vIO32WriteFldAlign(PDWNC_WAKEN, 0x1, FLD_RTC_WAKEN);

    LOG(0, "[RebootHandle]Enter power down\n");
    PDWNC_EnterPowerDown(WAK_IRRX | WAK_RTC, (UINT32)PDWNC_POWER_DOWN_UNKNOWN);
    return;
}
#endif

#ifdef CC_CPU_SPEED_TEST_ENABLE
#include "hw_hpcpll.h"
#define SYSTEM_SHUTDOWN_DELAY       5000 * 60 //  test time : 5 minutes

static HANDLE_T _hShutdownHandle = (HANDLE_T)NULL;

static void _PDWNC_RebootHandle(void *pvArg)
{
    UINT32 u4Clock, u4CPUPLL_FBDIV;
    UNUSED(pvArg);

    u4Clock = BSP_GetClock(SRC_CPU_CLK, NULL, NULL, NULL, NULL);
    LOG(0, "\n[RebootHandle] CPUPLL = %dHz test start !\n", u4Clock);

    x_thread_delay(SYSTEM_SHUTDOWN_DELAY);

    LOG(0, "\n[RebootHandle] CPUPLL = %dHz test pass !\n", u4Clock);
    u4CPUPLL_FBDIV = IO32ReadFldAlign(REG_HPCPLL_CFG0, FLD_RG_HPCPLL_FBDIV) + 4;
    vIO32Write4B(IO_VIRT + 0x8154, u4CPUPLL_FBDIV);
    vIO32Write4B(IO_VIRT + 0x8150, 0xFFFFFFFF);       // enable CPU speed test
    LOG(0, "[RebootHandle] Next FBDIV value of CPUPLL = %x\n", u4CPUPLL_FBDIV);

    LOG(0, "[RebootHandle] System Reboot !!\n");
    PDWNC_Reboot();
    return;
}
#endif

#endif /* CC_MTK_LOADER */

static void _PdwncSetupIRRX(UINT32 u4PowerDownEn)
{
    INT32 i4Val;
    UINT32 u4Val;

    if ((u4PowerDownEn & WAK_IRRX) == 0)
    {
        return;
    }
    i4Val = DRVCUST_InitQuery(eIrrxType, &u4Val);
    if (i4Val < 0)
    {
        u4Val = IRRX_RC5_TYPE;
    }

    // To write u4PowerDownEn for Wakeup key setting.

    //vIO32Write4B(PDWNC_WAKEN, u4PowerDownEn);

    // Configuration
    i4Val = IRRX_InitMtkIrRegSetup(u4Val);
    UNUSED(i4Val);
}
#if defined(CC_MT5863)
static void _PdwncSetupUSB(void)   //cut  off the mac and phy power of usb port2 on crax when hotboot off.
{
	UINT32 u4Val;
#if defined(CC_SUPPORT_STR_CORE_OFF)

	if(PDWNC_IsSuspend())
	{
	 LOG(0,"hotboot on usb no operation\n");
	}
	else
	{
	 LOG(0,"powerdown usb port2\n");
	 u4Val = u4IO32Read4B(PDWNC_BASE + 0xe8);   //open MAC reset
	 u4Val &= ~(1<<2);
	 vIO32Write4B(PDWNC_BASE + 0xe8, u4Val);

	u4Val = u4IO32Read4B(PDWNC_BASE + 0xe8);   //open ISO enable
	u4Val |= (0x3<<3);
	vIO32Write4B(PDWNC_BASE + 0xe8, u4Val);

	u4Val = u4IO32Read4B(PDWNC_BASE + 0xe8);   //power down MAC
	u4Val &= ~(0x3<<0);
	vIO32Write4B(PDWNC_BASE + 0xe8, u4Val);

	u4Val = u4IO32Read4B(PDWNC_BASE + 0xe8);   //power down sram
	u4Val |= (0x1<<7);
	vIO32Write4B(PDWNC_BASE + 0xe8, u4Val);

	u4Val = u4IO32Read4B(IO_VIRT + 0x5a818);   //close phy
	u4Val |= (0x1<<23);
	vIO32Write4B(IO_VIRT + 0x5a818, u4Val);
	}
#endif
}

#endif
/*static*/ void _PdwncSetupVGA(UINT32 u4PowerDownEn)
{

	if((u4PowerDownEn & WAK_VGA) == 0)
    {

        LOG(0,"Disable VGA wakeup\n");
        if(IS_IC_5895())   
        {    HAL_Delay_us(5);
            vIO32WriteFldAlign(PDWNC_VGACFG0, 0x0, FLD_RG_HSYNC_EN);
    		vIO32WriteFldAlign(PDWNC_VGACFG0, 0x0, FLD_RG_FB_AB_EN);


            vIO32WriteFldAlign(PDWNC_VGACFG1, 0x1, FLD_RG_SOGY_SINK_PWD);
            vIO32WriteFldAlign(PDWNC_VGACFG2, 0x1, FLD_RG_SOGY_SORS_PWD);
            vIO32WriteFldAlign(PDWNC_VGACFG0, 0x1, FLD_RG_SYNC_PWD);

            vIO32WriteFldMulti(PDWNC_VGACFG0, P_Fld(0,FLD_RG_SOG_EN)|P_Fld(0,FLD_RG_SOY0_EN));
            vIO32WriteFldAlign(PDWNC_VGACFG0, 0,FLD_RG_VSYNC_EN);


            HAL_Delay_us(5);
            // Turn on VGA_TESTBUF_PWD
            vIO32WriteFldAlign(PDWNC_VGACFG0, 0x1, FLD_RG_VGA_TESTBUF_PWD);
            HAL_Delay_us(5);

            // Disable VGA sync det clock
            vIO32WriteFldAlign(PDWNC_CLKPDN, 0x1, FLD_VGAPD);
            HAL_Delay_us(5);

    		vIO32WriteFldAlign(PDWNC_VGACFG0, 0x1, FLD_RG_VMUX_PWD);

    		vIO32WriteFldAlign(PDWNC_VGACFG0, 0x0, FLD_RG_AUTOBIAS_EN);//20100415, sc hwu suggestion
    		vIO32WriteFldAlign(PDWNC_PDMISC, 0x1, FLD_VGA_SYNC_DIS);//20100415, chiahsien liu suggestion
        }
        else
        {
        HAL_Delay_us(5);
        vIO32WriteFldAlign(PDWNC_VGACFG1, 0x0, FLD_RG_HSYNC_EN);
		vIO32WriteFldAlign(PDWNC_VGACFG1, 0x0, FLD_RG_FB_AB_EN);


        vIO32WriteFldAlign(PDWNC_VGACFG3, 0x1, FLD_RG_SOGY_SINK_PWD);
        vIO32WriteFldAlign(PDWNC_VGACFG3, 0x1, FLD_RG_SOGY_SORS_PWD);
        vIO32WriteFldAlign(PDWNC_VGACFG1, 0x1, FLD_RG_SYNC_PWD);

        vIO32WriteFldMulti(PDWNC_VGACFG1, P_Fld(0,FLD_RG_SOG_EN)|P_Fld(0,FLD_RG_SOY0_EN)|P_Fld(0,FLD_RG_SOY1_EN));
        vIO32WriteFldMulti(PDWNC_VGACFG1, P_Fld(0,FLD_RG_TSOGY_EN)|P_Fld(0,FLD_RG_VSYNC_EN));


        HAL_Delay_us(5);

        // Turn on VGA_TESTBUF_PWD
        vIO32WriteFldAlign(PDWNC_VGACFG2, 0x1, FLD_RG_VGA_TESTBUF_PWD);
        HAL_Delay_us(5);

        // Disable VGA sync det clock
        vIO32WriteFldAlign(PDWNC_CLKPDN, 0x1, FLD_VGAPD);
        HAL_Delay_us(5);

		vIO32WriteFldAlign(PDWNC_VGACFG0, 0x1, FLD_RG_VMUX_PWD);

		vIO32WriteFldAlign(PDWNC_VGACFG0, 0x0, FLD_RG_AUTOBIAS_EN);//20100415, sc hwu suggestion
		vIO32WriteFldAlign(PDWNC_PDMISC, 0x1, FLD_VGA_SYNC_DIS);//20100415, chiahsien liu suggestion
        }

        return;
    }

#ifndef CC_MTK_LOADER
        vDrvSYNCSlicerWakeup(1);
#endif

		// David: force enable VGA sync circuit clock 20090219
		vIO32WriteFldAlign(PDWNC_CLKPDN, 0x0, FLD_VGAPD);
		vIO32WriteFldAlign(PDWNC_PDMISC, 0x0, FLD_VGA_SYNC_DIS);
        if(IS_IC_5895())
        {
            vIO32WriteFldAlign(PDWNC_VGACFG0, 0x0, FLD_RG_SYNC_PWD);
        }
		else
        {
            vIO32WriteFldAlign(PDWNC_VGACFG1, 0x0, FLD_RG_SYNC_PWD);
        }
		vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_0_REGISTER, 0x1, FLD_AUTO_SWITCH_EN);

	 	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_0_REGISTER, VGAWAKEUP_HRANGE_U, FLD_HRANGE_U);
	 	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_0_REGISTER, VGAWAKEUP_HRANGE_L, FLD_HRANGE_L);
		HAL_Delay_us(5);
		vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_1_REGISTER, VGAWAKEUP_VRANGE_U, FLD_VRANGE_U);
		vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_1_REGISTER, VGAWAKEUP_VRANGE_L, FLD_VRANGE_L);
		HAL_Delay_us(5);


#ifdef CC_DISABLE_CSYNC_WAKEUP
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_1_REGISTER, 0x1, FLD_C_SYNC_WAK_DIS);
#endif
	HAL_Delay_us(5);
#ifdef CC_DISABLE_SOG_WAKEUP
        vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_1_REGISTER, 0x1, FLD_SOG_WAK_DIS);
#endif
	HAL_Delay_us(5);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_3_REGISTER, /*0x06*/0xF, FLD_H_DIFF_TH);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_3_REGISTER, 0x02, FLD_V_STABLE_TH);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_3_REGISTER, 0x80, FLD_H_STABLE_TH);
	HAL_Delay_us(5);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_4_REGISTER, 0x3f, FLD_V_DIFF_TH);
	HAL_Delay_us(5);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_5_REGISTER, (CSYNC_CONT_THL_DEFAULT & 0xff), FLD_CSYNC_CONT_THL);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_5_REGISTER, (CSYNC_CONT_THL_DEFAULT >> 8), FLD_CYSNC_CT_THL);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_5_REGISTER, (CSYNC_CONT_THU_DEFAULT & 0xff), FLD_CSYNC_CONT_THU);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_5_REGISTER, (CSYNC_CONT_THU_DEFAULT >> 8), FLD_CSYNC_CT_THU);
	 HAL_Delay_us(5);

	vIO32WriteFldMulti(PDWNC_VGA_WAKE_UP_CONTROL_6_REGISTER, P_Fld(0, FLD_HLEN_USE_VMASKX)| P_Fld(0x208, FLD_VMASK_S)| P_Fld(0xA, FLD_VMASK_E));

	HAL_Delay_us(5);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_7_REGISTER, (CSYNC_CONT_THH_DEFAULT & 0xff), FLD_CSYNC_CONT_SLICE_THH);
	HAL_Delay_us(5);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_8_REGISTER, (CSYNC_CONT_THH_DEFAULT >> 8), FLD_CSYNC_CONT_THH);
	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_8_REGISTER, VGAWAKEUP_FREERUN_CNT_TH, FLD_FREERUN_CNT_TH);

	vIO32WriteFldAlign(PDWNC_VGA_WAKE_UP_CONTROL_8_REGISTER, 1, FLD_FREERUN_CNT_UNLOCK);


	LOG(0," set vga pdwnc module\n");
}

#ifndef CC_MTK_LOADER
static void _PdwncSetupRTC(UINT32* pu4PowerDownEn)
{
    UINT32 u4RtcHw;
    ASSERT(pu4PowerDownEn != NULL);

    if ((*pu4PowerDownEn & WAK_RTC) == 0)
    {
        return;
    }
    if(DRVCUST_OptQuery(eRtcHw, &u4RtcHw) != 0)
    {
        return;
    }
    if(u4RtcHw == (INT32)RTC_INTERNAL)
    {
    }
    else
    {
        RTC_SetWakeup((UINT32 *)pu4PowerDownEn);
    }

}
#endif /* CC_MTK_LOADER */


//-----------------------------------------------------------------------------
/* _PDWNC_SetupStrapping() to setup the PDWNC Gpio interrupt callback function, type,
 *      and state.
 *  @param i4Gpio should be between 0~7.
 *  @param eType should be one of enum GPIO_TYPE.
 *  @param pfnCallback the callback function.
 *  @retval 0 successful, -1 failed.
 */
//-----------------------------------------------------------------------------
void _PDWNC_SetupStrapping(void)
{
    return;
}

//-----------------------------------------------------------------------------
/* PDWNC_ReadWakeupReason() to read the wakeup reason
 *
 *  @param u4Pdstat  register 0/1.
 *  @retval   u4Status0/u4Status1.
 */
//-----------------------------------------------------------------------------
UINT32 _PDWNC_ReadWakeupStatus(UINT32 u4Pdstat)
{
    if(u4Pdstat == 1)
	{
		return u4IO32Read4B(PDWNC_PDSTAT1);
	}else{
		return u4IO32Read4B(PDWNC_PDSTAT0);
	}
}

//-----------------------------------------------------------------------------
/* PDWNC_ReadWatchDogStatus() to read watchdog reset status
 *
 *  @param u1ErrorCode  Error code
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
UINT32 _PDWNC_ReadWatchDogStatus(void)
{
    return (u4IO32Read4B(PDWNC_WDTCTL) & FLD_WDTALL_RST);
}

#ifndef CC_MTK_LOADER
#if defined(NDEBUG) & defined(WATCHDOG_DETECT_ENABLE)
//-----------------------------------------------------------------------------
/* _PDWNC_SetWatchDogDetectState() to disable/enable the watchdog detect function
 *
 *  @param u1Enable     the option of enable/disable watchdog detect function
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
UINT32 _PDWNC_SetWatchDogDetectState(BOOL u1Enable)
{
    CRIT_STATE_T rCritState;

    rCritState = x_crit_start();
    _bgWatchdogDetect = u1Enable;
    x_crit_end(rCritState);

    return 0;
}

//-----------------------------------------------------------------------------
/* _PDWNC_ReadWatchDogDetectStatus() to read the state of watchdog detection
 *
 *  @param  void
 *  @retval   0		    Disable.
 *  @retval   1		    Enable.
 */
//-----------------------------------------------------------------------------
UINT32 _PDWNC_ReadWatchDogDetectStatus(void)
{
    UINT32 u4Status;
    CRIT_STATE_T rCritState;

    rCritState = x_crit_start();
    u4Status = (UINT32)_bgWatchdogDetect;
    x_crit_end(rCritState);

    return (u4Status);
}
#endif /* defined(NDEBUG) & defined(WATCHDOG_DETECT_ENABLE) */
#endif /* CC_MTK_LOADER */

//-----------------------------------------------------------------------------
/* _PDWNC_SetupEthernetWakeup() to set ethernet wakeup
 *
 */
//-----------------------------------------------------------------------------
void _PDWNC_SetupEthernetWakeup(UINT32 *pu4PowerDownEn)
{
    UINT32 u4Val;
	UINT32 u4Pol,u4Gpio;
    UINT32 MACADDRESS_H;
    UINT32 MACADDRESS_L;
    UINT32 count;
#if defined(CC_MT5863) || defined(CC_MT5886) || defined(CC_MT5893) || defined(CC_MT5895)
    UINT32 max_delays;
#endif
#ifndef	CC_WOL_WOWL_DEFAULT_ON
    DTVCFG_T    rDtvCfg;
    INT32       i4_ret;
#endif

#ifndef	CC_WOL_WOWL_DEFAULT_ON
#if defined(CC_S_PLATFORM) && defined(CC_PHX_CUST)
#ifdef 	CC_SUPPORT_SW_WOW_GPIO
		PDWNC_T8032_CMD_T rCmd;

		rCmd.u1Cmd = PDWNC_CMD_ARM8032_SW_WOW_GPIO;
		rCmd.au1Data[0] = rCmd.au1Data[1]= rCmd.au1Data[2] = rCmd.au1Data[3] = 0;
		PDWNC_T8032Cmd(&rCmd, NULL);
#endif
#endif

    i4_ret = EEPDTV_GetCfg(&rDtvCfg);

    ASSERT(i4_ret==0);
    if (i4_ret!=0)
    {
        LOG(0, "_PDWNC_SetupEthernetWakeup: DTV EEPROM read failure.\n");
        LOG(0, "%s(%d) DTV EEPROM read failure.\n", __FILE__, __LINE__);
        return;
    }
    if(rDtvCfg.u1Flags3 & (UINT8)DTVCFG_FLAG3_WAKEUP_ON_LAN )
#endif
    {
        LOG(0,"_PDWNC_SetupEthernetWakeup(WOL)!!\n\n");
#if defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || defined(CC_MT5895)
#if defined(CC_SUPPORT_STR_CORE_OFF)
		if (PDWNC_IsSuspend())
		{
			/* hotboot on flow, just wol setting in star driver */
			LOG(0,"\nstar: _PDWNC_SetupEthernetWakeup,wol on,hotboot on\n");
		}
		else
#endif
#endif
		{
		#if defined(CC_MT5895)
		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CTL);
		u4Val &= ~(1<<10);
		vIO32Write4B(PDWNC_ETH_PWR_CTL, u4Val);
		#else
		u4Val = u4IO32Read4B(ETHERNET_BASE + ETH_UP_CFG);
		u4Val &= ~CPUCK_BY_8032;
		vIO32Write4B(ETHERNET_BASE + ETH_UP_CFG, u4Val);
		#endif
		LOG(0,"MAC register switch to arm\n");

		MACADDRESS_H = u4IO32Read4B(ETHERNET_BASE + RW_MY_MAC_H);
        MACADDRESS_L = u4IO32Read4B(ETHERNET_BASE + RW_MY_MAC_L);
        if((0 == MACADDRESS_H) && (0 == MACADDRESS_L))
        {
            MACADDRESS_H = 0x0000000C;
            MACADDRESS_L = 0xE7060000;
        }
#if 0
        u4Val = u4IO32Read4B(CKGEN_BASE + 0x1C0);
        u4Val &= ~(0x1 << 25);
        vIO32Write4B(CKGEN_BASE + 0x1C0, u4Val);
        HAL_Delay_us(50);
        u4Val |= 0x1 << 25;
        vIO32Write4B(CKGEN_BASE + 0x1C0, u4Val);

        HAL_Delay_us(50);
#endif

#if defined(CC_MT5891)
		if (IS_IC_5891_ES1())
#endif
		{
        #ifndef CC_MT5895
        u4Val = u4IO32Read4B(ETHERNET_BASE + RW_ETHSYS_CONFIG);
        u4Val |= INT_PHY_SEL;
        vIO32Write4B(ETHERNET_BASE + RW_ETHSYS_CONFIG, u4Val);

        u4Val = u4IO32Read4B(ETHERNET_BASE + RW_SW_RESET_CONTROL);
        u4Val |= PHY_RSTN;
        vIO32Write4B(ETHERNET_BASE + RW_SW_RESET_CONTROL, u4Val);
        #endif
        HAL_Delay_us(50);
		}

        vIO32Write4B(ETHERNET_BASE + RW_MY_MAC_H, MACADDRESS_H);
        vIO32Write4B(ETHERNET_BASE + RW_MY_MAC_L, MACADDRESS_L);

		u4Val = u4IO32Read4B(ETHERNET_BASE + RW_MAC_CFG);
        u4Val |= WOL;
        vIO32Write4B(ETHERNET_BASE + RW_MAC_CFG, u4Val);

        count = 0;
        u4Val = u4IO32Read4B(ETHERNET_BASE + RW_MAC_CFG);
        while ((u4Val & NIC_PD_READY) == 0x0)
        {
            count++;

            if (count >= MAX_NICPDRDY_RETRY)
            {
                LOG(0,"_PDWNC_SetupEthernetWakeup(WOL) NIC Not Ready!\n");
                break;
            }
        }

        u4Val = u4IO32Read4B(ETHERNET_BASE + RW_INT_MASK);
        u4Val &= ~(MAGIC_PAK_REC_INT_MASK);
        vIO32Write4B(ETHERNET_BASE + RW_INT_MASK, u4Val);

        u4Val = u4IO32Read4B(PDWNC_PDMISC);
        u4Val |= (1<<29);    // ethernet wakeup enable
        vIO32Write4B(PDWNC_PDMISC, u4Val);

        u4Val = u4IO32Read4B(PDWNC_T8032_INTEN);
        u4Val |= (1<<29);    // ethernet interrupt 8032 enable
        vIO32Write4B(PDWNC_T8032_INTEN, u4Val);
                #ifndef CC_MT5895
		u4Val = u4IO32Read4B(ETHERNET_BASE + ETH_UP_CFG);
		u4Val |= CPUCK_BY_8032;
		vIO32Write4B(ETHERNET_BASE + ETH_UP_CFG, u4Val);
                #endif
		}
    }
#ifndef	CC_WOL_WOWL_DEFAULT_ON
	else
	{
		#if defined(CC_MT5895)
		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CTL);
		u4Val &= ~(1<<10);
		vIO32Write4B(PDWNC_ETH_PWR_CTL, u4Val);
		#else
		u4Val = u4IO32Read4B(ETHERNET_BASE + ETH_UP_CFG);
		u4Val &= ~CPUCK_BY_8032;
		vIO32Write4B(ETHERNET_BASE + ETH_UP_CFG, u4Val);
		#endif
		LOG(0,"wol off, MAC register switch to arm\n");

		u4Val = u4IO32Read4B(PDWNC_PDMISC);
		u4Val &= ~(1<<29);	  // ethernet wakeup disable
		vIO32Write4B(PDWNC_PDMISC, u4Val);

		u4Val = u4IO32Read4B(PDWNC_T8032_INTEN);
		u4Val &= ~(1<<29);	  // ethernet pdwn reset disable.
		vIO32Write4B(PDWNC_T8032_INTEN, u4Val);

#if defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || (CC_MT5895)
#if defined(CC_SUPPORT_STR_CORE_OFF)
	if (PDWNC_IsSuspend())
	{
		/* hotboot on flow, just do in star driver */
		LOG(0,"\nstar: _PDWNC_SetupEthernetWakeup, wol off, hotboot on\n");
	}
	else
#endif
#endif
	{
		#if defined(CC_MT5863) || defined(CC_MT5886) || defined(CC_MT5893) || defined(CC_MT5895)
		LOG(0,"\nstar:mtcmos poweroff eth\n");

		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CTL);
		u4Val &= ~(1<<0);
		vIO32Write4B(PDWNC_ETH_PWR_CTL, u4Val);

		x_thread_delay(1);
		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CTL);
		u4Val |= (1<<2);
		vIO32Write4B(PDWNC_ETH_PWR_CTL, u4Val);

		x_thread_delay(1);
		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CTL);
		u4Val |= (1<<1);
		vIO32Write4B(PDWNC_ETH_PWR_CTL, u4Val);

		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CTL);
		u4Val |= (0x1F<<4);
		vIO32Write4B(PDWNC_ETH_PWR_CTL, u4Val);

		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CHAIN_CTL);
		#if defined(CC_MT5895)
		u4Val &= ~(1<<1);
		#else
		u4Val &= ~(1<<0);
		#endif
		vIO32Write4B(PDWNC_ETH_PWR_CHAIN_CTL, u4Val);

		max_delays = 10;
		#if defined(CC_MT5895)
		while((((u4IO32Read4B(PDWNC_ETH_PWR_CHAIN_CTL)>>3) & 0x1) != 0x0) && max_delays--)
				x_thread_delay(1);
		#else
		while((((u4IO32Read4B(PDWNC_ETH_PWR_CHAIN_CTL)>>2) & 0x1) != 0x0) && max_delays--)
				x_thread_delay(1);
		#endif

		u4Val = u4IO32Read4B(PDWNC_ETH_PWR_CHAIN_CTL);
		#if defined(CC_MT5895)
		u4Val &= ~(1<<0);
		#else
		u4Val &= ~(1<<1);
		#endif
		vIO32Write4B(PDWNC_ETH_PWR_CHAIN_CTL, u4Val);

		max_delays = 10;
		#if defined(CC_MT5895)
		while((((u4IO32Read4B(PDWNC_ETH_PWR_CHAIN_CTL)>>2) & 0x1) != 0x0) && max_delays--)
				x_thread_delay(1);
		#else
		while((((u4IO32Read4B(PDWNC_ETH_PWR_CHAIN_CTL)>>3) & 0x1) != 0x0) && max_delays--)
				x_thread_delay(1);
		#endif

		#if defined(CC_MT5895)
		u4Val = u4IO32Read4B(PDWNC_XPLL_CFG2);
		u4Val |= (0x1<<2);
		vIO32Write4B(PDWNC_XPLL_CFG2, u4Val);

		u4Val = u4IO32Read4B(PDWNC_XPLL_CFG2);
		u4Val &= ~(0x1<<3);
		vIO32Write4B(PDWNC_XPLL_CFG2, u4Val);
		#endif

		#if defined(CC_MT5863)
		u4Val = u4IO32Read4B(PDWNC_XPLL_CFG2);
		u4Val |= (0x1<<2);
		vIO32Write4B(PDWNC_XPLL_CFG2, u4Val);

		u4Val = u4IO32Read4B(PDWNC_XPLL_CFG2);
		u4Val &= ~(0x1<<3);
		vIO32Write4B(PDWNC_XPLL_CFG2, u4Val);

		u4Val = u4IO32Read4B(PDWNC_XPLL_CFG2);
		u4Val |= (0x1<<0);
		vIO32Write4B(PDWNC_XPLL_CFG2, u4Val);

		u4Val = u4IO32Read4B(PDWNC_XPLL_CFG1);
		u4Val &= ~(0x1<<2);
		vIO32Write4B(PDWNC_XPLL_CFG1, u4Val);
		#endif
		#endif
		#if !defined(CC_S_PLATFORM)
		#if defined(CC_MT5891)
		if (IS_IC_5891_ES1()) {
			//todo
		} else {
			//ETH_AFE_PWD2 to 1,reset phy when wakeup
			u4Val = u4IO32Read4B(ETHERNET_BASE + 0x314);
			u4Val |= 1<<11;
			vIO32Write4B(ETHERNET_BASE + 0x308, u4Val);

			// CKEN: REG_CLK_PDCFG2
			u4Val = u4IO32Read4B(CKGEN_BASE + 0x1c8);
			u4Val &= ~(3<<25);
			vIO32Write4B(CKGEN_BASE + 0x1c8, u4Val);

			// CKRST: REG_CLK_PDCFG0
			u4Val = u4IO32Read4B(CKGEN_BASE + 0x1c0);
			u4Val &= ~(3<<25);
			vIO32Write4B(CKGEN_BASE + 0x1c0, u4Val);

			// sel pd_rstb for config ethernet CG enable
			u4Val = u4IO32Read4B(PDWNC_BASE + 0x8);
			u4Val |= (1<<29);
			vIO32Write4B(PDWNC_BASE + 0x8, u4Val);

			// for off clk and reset mac&phy
			u4Val = u4IO32Read4B(ETHERNET_BASE + 0x308);
			u4Val &= ~(0x7fff);
			u4Val |= 0x80;
			vIO32Write4B(ETHERNET_BASE + 0x308, u4Val);

			// for AD_PL_REFCLK select test_clk0
			u4Val = u4IO32Read4B(ETHERNET_BASE + 0x314);
			u4Val |= 1<<16;
			vIO32Write4B(ETHERNET_BASE + 0x314, u4Val);

			// for	power down ether sram
			u4Val = u4IO32Read4B(PDWNC_BASE + 0x14);
			u4Val |= 0x1f<<16;
			vIO32Write4B(PDWNC_BASE + 0x14, u4Val);
		}
		#endif
		#endif
	}
	}
#endif

#ifndef	CC_WOL_WOWL_DEFAULT_ON
#ifdef CC_ANDROID_TWO_WORLDS
	if((rDtvCfg.u1Flags4 & (UINT8)DTVCFG_FLAG4_WAKEUP_ON_WLAN ) && (_gi4PDWNCWifiWowState == 1) )
#else
	if((rDtvCfg.u1Flags4 & (UINT8)DTVCFG_FLAG4_WAKEUP_ON_WLAN ))
#endif
#endif
	{
	    LOG(0,"_PDWNC_SetupEthernetWakeup(WOWL) _gi4PDWNCWifiWowState=%d !!\n\n",_gi4PDWNCWifiWowState);
		if(DRVCUST_InitQuery(eWakeupOnWLanGpio, (UINT32 *)&u4Gpio) < 0)
		{
			return;
		}
		if(DRVCUST_InitQuery(eWakeupOnWLanPol, (UINT32 *)&u4Pol) < 0)
		{
			return;
		}
#if defined(CC_S_PLATFORM) && defined(CC_PHX_CUST)
#ifdef	CC_SUPPORT_SW_WOW_GPIO
		rCmd.u1Cmd = PDWNC_CMD_ARM8032_SW_WOW_GPIO;
		rCmd.au1Data[0] = 1;
		rCmd.au1Data[1]= u4Gpio;
		rCmd.au1Data[2] = u4Pol;
		rCmd.au1Data[3] = 0;
		PDWNC_T8032Cmd(&rCmd, NULL);
#else
		PDWNC_SetupGpioWakeup(u4Gpio,TRUE,(BOOL)u4Pol,FALSE);
#endif
#else
		#ifdef CC_SUPPORT_SHUT_DOWN_ECO
		if(PDWNC_IsSuspend())
		{
			LOG(0,"[Sony power] only hot boot will enable WIFI wakeup.\n");
			PDWNC_SetupGpioWakeup(u4Gpio,TRUE,(BOOL)u4Pol,FALSE);
		}
		#else
		PDWNC_SetupGpioWakeup(u4Gpio,TRUE,(BOOL)u4Pol,FALSE);
		#endif
#endif
	}
}
//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------
UINT32 PDWNC_SetWifiWowState (UINT32 u4WifiWowState)
{
    _gi4PDWNCWifiWowState = u4WifiWowState;
    LOG(0, "baohe test _gi4PDWNCWifiWowState=%d ,u4WifiWowState=%d \n",
    _gi4PDWNCWifiWowState,u4WifiWowState);
    return 0;
}

//-----------------------------------------------------------------------------
/* PDWNC_WriteErrorCode() to write the current error code to EEPROM & uP
 *
 *  @param u1ErrorCode  Error code
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
INT32 PDWNC_WriteErrorCode(UINT8 u1ErrorCode)
{
    VERIFY(pgrPDWNC_Func);
    VERIFY(pgrPDWNC_Func->pfnWriteErrorCode);
    pgrPDWNC_Func->pfnWriteErrorCode(u1ErrorCode);
    return 0;
}

//-----------------------------------------------------------------------------
/* PDWNC_SetQueryRtcYear() to query RTC year register value
 *
 *  @param u1ErrorCode  Error code
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
UINT8 PDWNC_SetQueryRtcYear(const UINT8 *pu1Year)
{
#ifdef CC_FPGA
    return *pu1Year;
#else
    if (pu1Year)
    {
        vIO32WriteFldAlign(PDWNC_PROT, 0x87, FLD_PROT);
        vIO32WriteFldAlign(PDWNC_PROT, 0x78, FLD_PROT);
        vIO32Write4B(PDWNC_YEAR, (UINT32)(*pu1Year));
        vIO32WriteFldAlign(PDWNC_PROT, 0x0, FLD_PROT);
    }
    return(u4IO32Read4B(PDWNC_YEAR));
#endif
}

//-----------------------------------------------------------------------------
/* PDWNC_ReadWakeupReason() to read the wakeup reason
 *
 *  @param u1ErrorCode  Error code
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
UINT32 u4WakeupReason;
UINT32 PDWNC_ReadWakeupReason(void)
{
	static BOOL fgHasRead = FALSE;
	if(_fgSuspendWakeupReasonUp)//wakeup from suspend
	{
		fgHasRead = FALSE;
	}
	if(fgHasRead)
	{
		return (u4WakeupReason);
	}
    VERIFY(pgrPDWNC_Func);
    VERIFY(pgrPDWNC_Func->pfnReadWakeupReason);
    pgrPDWNC_Func->pfnReadWakeupReason(&u4WakeupReason);
    if((_fgSuspendWakeupReasonUp == TRUE) && (u4WakeupReason == PDWNC_WAKE_UP_REASON_AC_POWER))
	{
		u4WakeupReason = PDWNC_WAKE_UP_REASON_UNKNOWN;
	}
	fgHasRead = TRUE;
	_fgSuspendWakeupReasonUp = FALSE;
    return (u4WakeupReason);
}


//-----------------------------------------------------------------------------
/* PDWNC_PowerDownByAcCut()
 *
 *  @param u1ErrorCode  Error code
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
UINT32 PDWNC_PowerDownByAcCut(void)
{
	if(PDWNC_ReadWakeupReason() == PDWNC_WAKE_UP_REASON_AC_POWER)
	{
		return 1;
	}
	else
		return 0;

}

#ifndef CC_MTK_LOADER
#ifdef CC_PDWNC_REBOOT_NOTIFY
static HANDLE_T _StandbyLock = NULL_HANDLE;
void wait_for_unlock_standby (void)
{
    INT32 i4Ret;
    i4Ret = x_sema_lock_timeout(_StandbyLock, 10000);
    if (i4Ret != OSR_OK)
    {
        LOG(0, "wait_for_unlock_standby() timeout !!!\n");
    }
}
void unlock_standby(void)
{
    x_sema_unlock(_StandbyLock);
}

extern unsigned int isAndroidRecoveryMode(void);
static int pdwnc_reboot_notify(struct notifier_block* nb, unsigned long event, void *unused)
{
    static int reboot_event_handled = 0;
    MTPDWNC_STANDBY_NOTIFY_T t_cb_info;
    char* cmd = unused;
    #if defined(CC_S_PLATFORM)
    #if defined(CC_ARIB) //for 8KSHV power off
    PFN_GPIO_POWERSET_EXT_DEC_MODEL_FUNC pfnPowerSetExtDecModelFunc = NULL;
    #endif /* CC_ARIB */
    #if defined(CC_OX_CUST) || defined(CC_WK_CUST) || defined(CC_HK_CUST) || defined(CC_CP_CUST)
    UINT32 u4PowerDownEvent;
    DTVCFG_T    rDtvCfg;
    INT32       i4_ret;
    #if defined(CC_S_PLATFORM)
    UINT8 tState;
    #endif
    LOG(0,KERN_EMERG "pdwnc_reboot_notify-0: %s,event = 0x%lx \n", cmd,event);
    i4_ret = EEPDTV_GetCfg(&rDtvCfg);
    #else
    LOG(0,KERN_EMERG "pdwnc_reboot_notify-0: %s,event = 0x%lx \n", cmd,event);
    #endif
    #else
    LOG(0,KERN_EMERG "pdwnc_reboot_notify-0: %s,event = 0x%lx \n", cmd,event);
    #endif
    if (!reboot_event_handled)
    {
#ifdef CC_ANDROID_REBOOT
        if(event == SYS_RESTART)
        {
            #ifdef CC_ANDROID_FASTBOOT_SUPPORT
            if(cmd && !x_memcmp(cmd, "bootloader", 10))
            {
                int u4Val = msdc_partwrite_byname("misc",512,sizeof("fastboot"),(void *)"fastboot");
                if(u4Val == -1)
                LOG(0,"\n writer misc partition failed \n");
            }
            #endif
            #ifdef CC_ANDROID_RECOVERY_SUPPORT
            if(cmd && !x_memcmp(cmd, "recovery", 8))
            {
                int u4Val = msdc_partwrite_byname("misc",0,sizeof("boot-recovery"),(void *)"boot-recovery");
                if(u4Val == -1)
                LOG(0,"\n writer misc partition for recovery failed \n");
            }
            #endif
        }
#endif
        /* only do this once */
        reboot_event_handled = 1;
        t_cb_info.u4Block = TRUE;
        if (t_cb_info.u4Block)
        {
        #if defined(CC_S_PLATFORM) && defined(CC_ARIB) //for 8KSHV power off
            if(DRVCUST_InitQueryUptr(eGpioPowerSetExtDecModelfunc, (UPTR *)&pfnPowerSetExtDecModelFunc) == 0)
            {
                LOG(0,"[LBH] CustomPowerOff: Power OFF processing\n");
                UNUSED(pfnPowerSetExtDecModelFunc(FALSE));
            }
        #endif /* CC_S_PLATFORM && CC_ARIB */
            #if 0
            if (cmd && *cmd != '\0')
            {
                LOG(0,KERN_EMERG "pdwnc_reboot_notify-1: %s\n", cmd);
                if (!x_strcmp(cmd, "recovery"))
                {
                    return NOTIFY_DONE;
                }
            }
            #endif
            if (isAndroidRecoveryMode())
            {
                #if defined(CC_S_PLATFORM)
                #if defined(CC_OX_CUST) || defined(CC_WK_CUST) || defined(CC_HK_CUST) || defined(CC_CP_CUST)
                if(rDtvCfg.u1Flags4 & (UINT8)DTVCFG_FLAG4_QUIET_HOT_BOOT )
                {
                    //rDtvCfg.u1Flags &= (UINT8)(~(DTVCFG_FLAG_USB_UPGRADE_ON));
                    //rDtvCfg.u1Flags2 |= (DTVCFG_FLAG2_UPGRADE_GO);
                    //EEPDTV_SetCfg(&rDtvCfg);//change to use new DTVCFG API
                    EEPDTV_SetCfg_New(EEPDTV_DTVCFG_FLAGS, (UINT8)DTVCFG_FLAG_USB_UPGRADE_ON, (UINT8)0);
                    EEPDTV_SetCfg_New(EEPDTV_DTVCFG_FLAGS2, (UINT8)DTVCFG_FLAG2_UPGRADE_GO, (UINT8)DTVCFG_FLAG2_UPGRADE_GO);
                    EEPDTV_GetCfg(&rDtvCfg);
                    if(((rDtvCfg.u1Flags & DTVCFG_FLAG_USB_UPGRADE_ON) != 0) || ((rDtvCfg.u1Flags2 & DTVCFG_FLAG2_UPGRADE_GO) != DTVCFG_FLAG2_UPGRADE_GO))
                    {
                        LOG(0,KERN_EMERG "[DTV_CFG] DTVCFG_FLAG_USB_UPGRADE_ON or DTVCFG_FLAG2_UPGRADE_GO  %s(L:%d) ERROR!!!\n", __FUNCTION__, __LINE__);
                    }
                    u4PowerDownEvent = 0x50;
                    PDWNC_EnterPowerState(u4PowerDownEvent);
                }
                #endif
                #endif
                LOG(0,KERN_EMERG "pdwnc_reboot_notify: isAndroidRecoveryMode\n");
                return NOTIFY_DONE;
            }
            if(event == SYS_RESTART)
            {
                t_cb_info.u4Arg2= MTPDWNC_REBOOT;
#if defined(CC_S_PLATFORM)
#ifdef CONFIG_CB2_EARLYSUSPEND
                tState = twoworlds_power_get_state();
#else
                tState = pm_autosleep_state();
#endif
                printk(KERN_EMERG "pm_autosleep_state: %d\n", tState);
        #ifdef CC_QHB_UPGRADE_SUPPORT
                if(cmd && !x_memcmp(cmd, "reboot", 6))
                {
                    LOG(0,KERN_EMERG "[zzuu]pdwnc_reboot_notify: shell reboot.\n");  //need to confirm
                    if(tState == 0 /*PM_SUSPEND_ON*/)
                    {
                    printk(KERN_EMERG "Force disable QHB.\n");
                    PDWNC_EnterPowerState(0x200);
                }
                }
                else
                {
                    if(tState == 0 /*PM_SUSPEND_ON*/)
                    {
                        printk(KERN_EMERG "Force disable QHB.\n");
                        PDWNC_EnterPowerState(0x200);
                        }
                        LOG(0,KERN_EMERG "[zzuu]pdwnc_reboot_notify: in fact not shell reboot.\n");
                    }
        #else
                if(tState == 0 /*PM_SUSPEND_ON*/)
                {
                    printk(KERN_EMERG "Force disable QHB.\n");
                    PDWNC_EnterPowerState(0x200);
                }
        #endif
 #endif
            }
            else if((event == SYS_POWER_OFF) || (event == SYS_HALT))
            {
                //t_cb_info.u4Arg2= MTPDWNC_STANDBY;
                UNUSED(PDWNC_EnterPowerDown(_u4PowerDownEn,_u4PowerDownEvent));
            }
            _CB_PutEvent(CB_DRV_PDWNC_STANDBY_NFY, sizeof(MTPDWNC_STANDBY_NOTIFY_T), &t_cb_info);
            LOG(0,KERN_EMERG "pdwnc_reboot_notify: wait-1\n");
            wait_for_unlock_standby();
            LOG(0,KERN_EMERG "pdwnc_reboot_notify: wait-2\n");
        }
    }
    return NOTIFY_DONE;
}

static struct notifier_block pdwnc_notifier = {
    .notifier_call  = pdwnc_reboot_notify,
    .next           = NULL,
    .priority       = 0,
};
#endif
#endif
//-----------------------------------------------------------------------------
/* PDWNC_Init() to initialize PDWNC driver
 *
 *  @param u1ErrorCode  Error code
 *  @retval   0		    SUCCESS.
 *  @retval   1		    FAIL.
 */
//-----------------------------------------------------------------------------
INT32 PDWNC_Init(void)
{
    UINT32 u4Val;
    PFN_GPIO_POWER_FUNC pfnPowerOnFunc = NULL;
    if (_gi4PDWNCInit)
    {
        return 0;
    }
    _gi4PDWNCInit = 1;
	LOG(0,"PDWNC_Init\n");
#if !defined(CC_MTK_LOADER) &&  !defined(CONFIG_TV_DRV_VFY)
    // If use internal T8032, need to initialize something...
    if(DRVCUST_InitGetUptr(eT8032uPOffset) != 0)
    {
        // Let ARM control other engine after loading image
        // Note this should happen before _PDWNC_InitGpio to avoid interrupt before interrupt status/clear could be access
		vIO32Write4B(PDWNC_INTCLR, 0xffffffff);
        // Install T8032 ISR
        VERIFY(_PDWNC_RegT8032Isr() == PDWNC_OK);

        // Install GPIO ISR
        VERIFY(_PDWNC_InitGpio() == 0);

        u4Val = PDWNC_ReadWakeupReason();
        if((u4Val != PDWNC_WAKE_UP_REASON_AC_POWER) && (u4Val != PDWNC_WAKE_UP_REASON_WATCHDOG))
        {
            LOG(5, "T8032 init wakeup case app stage...\n");
            VERIFY(_PDWNC_SetT8032(PDWNC_T8032_SET_NORMAL) == 0);
        }
        else
        {
            LOG(5, "T8032 init AC on/off case app stage...\n");
            VERIFY(_PDWNC_SetT8032(PDWNC_T8032_SET_NORMAL) == 0);
        }
    }
    else
    {
        LOG(0, "T8032 is disabled...\n");
    }
#else
	vIO32Write4B(PDWNC_ARM_INTEN,0x00000000); //clean pdwnc interrupt enable bit.
	vIO32Write4B(PDWNC_WAKEN,0x00000000); //just clean wakeup enable bit, for MT5890(Oryx),wangliang.wang,20140830.
	vIO32Write4B(PDWNC_WAKEN1,0x00000000);
    u4Val = PDWNC_ReadWakeupReason();
    if(u4Val == PDWNC_WAKE_UP_REASON_AC_POWER)
    {
#if !defined(CC_MT5886)
        UINT8 u1Year = 0xff;
        // To indicate it is last cut off by A/C
        VERIFY(PDWNC_SetQueryRtcYear(&u1Year) == u1Year);
#endif
    }
#endif /* CC_MTK_LOADER */

    if (DRVCUST_InitQueryUptr(eGpioPowerOnFunc, (UPTR *)&pfnPowerOnFunc) == 0)
    {
        pfnPowerOnFunc();
    }

    _fgPowerDownByAcCut = (PDWNC_SetQueryRtcYear(NULL)==0xff);


    PDWNC_InitServoADC();

	// Set reset value to some registers.
	//vIO32Write4B(PDWNC_VGACFG0, 0xe8884c88);// SYNC slicer current reduction

	vIO32WriteFldAlign(PDWNC_VGACFG0, 0x0, FLD_RG_VMUX_PWD);

	vIO32WriteFldAlign(PDWNC_VGACFG0, 0x1, FLD_RG_AUTOBIAS_EN);//20100415, sc hwu suggestion
	vIO32WriteFldAlign(PDWNC_PDMISC, 0x0, FLD_VGA_SYNC_DIS);//20100415, chiahsien liu suggestion
	vIO32WriteFldAlign(PDWNC_PRST, 0x1, FLD_PRST_EN); //Power reset enable.
#ifdef CC_DISABLE_SOG_WAKEUP
    vIO32WriteFldAlign(PDWNC_VGACFG1, 1, FLD_RG_SOG_EN);
    vIO32WriteFldAlign(PDWNC_VGACFG1, 0, FLD_RG_SYNC_PWD);
#endif

#ifndef CC_MTK_LOADER
    // Do the external power down function
    VERIFY(pgrPDWNC_Func->pfnInit);
    pgrPDWNC_Func->pfnInit();

#ifdef CC_PDWNC_REBOOT_NOTIFY
    // register reboot notifier
    if (_StandbyLock == NULL_HANDLE)
    {
	VERIFY(x_sema_create(&_StandbyLock, X_SEMA_TYPE_BINARY,
		    X_SEMA_STATE_LOCK) == OSR_OK);
    }
    LOG(0,KERN_EMERG "register_reboot_notifier: pdwnc_notifier\n");
    register_reboot_notifier(&pdwnc_notifier);
#endif
#endif /* CC_MTK_LOADER */
    #ifdef CC_QHB_UPGRADE_SUPPORT
    #ifdef  CC_MTK_LOADER
	vIO32WriteFldAlign(PDWNC_ARM_INTEN, 1, FLD_IR_INTEN);
    #endif
    #endif
    return 0;
}

#ifndef CC_MTK_LOADER
//-----------------------------------------------------------------------------
/** PDWNC_RegIsr() is to hook the sub-interrupt routine of PDWNC module.
 *  @param u2IntNo the interrupt number at PDWNC module.
 *  @param pfnIsr the hooked function to register, NULL to disable.
 *  @param ppfnOld the old hooked function.
 *  @retval PDWNC_OK: Succeed
 *  @retval PDWNC_FAIL: Fail
 */
//-----------------------------------------------------------------------------
INT32 PDWNC_RegIsr(UINT16 u2IntNo, x_os_isr_fct pfnIsr, x_os_isr_fct *ppfnOld)
{
    UINT32 u4Val, u4State;

    VERIFY(PDWNC_Init()==0);

    if(u2IntNo > (MAX_PDWNC_INT_ID - 1))
    {
        return PDWNC_FAIL;
    }

    if (ppfnOld != NULL)
    {
        *ppfnOld = _varIntList[u2IntNo];
    }

    if (pfnIsr == NULL)
    {
        u4Val = u4IO32Read4B(PDWNC_ARM_INTEN);
        u4Val &= ~(_PINT(u2IntNo));
        if (u4Val==0)
        {
            VERIFY(_PdwncHwSetIsr(FALSE));
        }
#ifndef CC_MTK_LOADER
        u4State = HalCriticalStart();
#endif
        vIO32Write4B(PDWNC_ARM_INTEN, u4Val);
#ifndef CC_MTK_LOADER
        HalCriticalEnd(u4State);
#endif
        _varIntList[u2IntNo] = pfnIsr;
    }
    else
    {

  		_varIntList[u2IntNo] = pfnIsr;
	    u4Val = u4IO32Read4B(PDWNC_ARM_INTEN);
        u4Val |= (_PINT(u2IntNo));
#ifndef CC_MTK_LOADER
        u4State = HalCriticalStart();
#endif
        VERIFY(_PdwncHwSetIsr(TRUE));
        vIO32Write4B(PDWNC_ARM_INTEN, u4Val);
#ifndef CC_MTK_LOADER
        HalCriticalEnd(u4State);
#endif
    }
    return PDWNC_OK;
}

//-----------------------------------------------------------------------------
/** PDWNC_ClearInt() to clear the interrupt flag in PDWNC status
 *  PDWNC_ClearInt() do bit clear on REG_RW_PDWNC_INTCLR register and the \n
 *  value of REG_RO_PDWNC_INTST will change, too.  If the REG_RO_PDWNC_INTST
 *  is 0, the interrupt status bit of PDWNC on BIM IRQST will be cleared, too.
 *  @param u2IntNo the sub-interrupt number of PDWNC
 *  @retval TRUE: Succeed
 *  @retval FALSE: Fail
 */
//-----------------------------------------------------------------------------
BOOL PDWNC_ClearInt(UINT16 u2IntNo)
{
    UINT32 u4Int, u4State;

    if (u2IntNo > (MAX_PDWNC_INT_ID - 1))//MAX_PINT_ID)
    {
        return FALSE;
    }

    u4Int = _PINT(u2IntNo);
#ifndef CC_MTK_LOADER
    u4State = HalCriticalStart();
#endif
          vIO32Write4B(PDWNC_INTCLR, u4Int);
#ifndef CC_MTK_LOADER
    HalCriticalEnd(u4State);
#endif
    return TRUE;
}
#endif /* CC_MTK_LOADER */

#ifndef CC_MTK_LOADER
void set_PDWNC_Reboot_State(int state) 
{
	pdwnc_reboot_disable = state;
}
#endif /* CC_MTK_LOADER */


//-----------------------------------------------------------------------------
/** PDWNC_Reboot() Reboot the system
 */
//-----------------------------------------------------------------------------
void PDWNC_Reboot()
{
    _PDWNC_SetupStrapping();
	#ifndef CC_MTK_LOADER
#ifdef CONFIG_LOCKUP_DETECTOR_ADD_LOG
    show_cmdline(NULL);
#endif
    dump_stack();
    if (pdwnc_reboot_disable) {
	 Printf("Disabled PDWNC_Reboot\n");
	 while (1) { }
    }
	#endif
    LOG(0, "\n                                       ");
    vIO32WriteFldAlign(PDWNC_WDTCTL,0xFF,FLD_WDT0E);//	use watchdog 0 trigger wakeup.
    vIO32Write4B(PDWNC_WDTRST0,0x0fffffff);
    vIO32Write4B(PDWNC_WDT0,0x7fffffff);//vIO32Write4B(PDWNC_WDT0,0x0fff0000);

    while (1) { }
}

//-----------------------------------------------------------------------------
/** PDWNC_Reboot1() Reboot the system
 */
//-----------------------------------------------------------------------------
void PDWNC_Reboot1()
{
    _PDWNC_SetupStrapping();
	#ifndef CC_MTK_LOADER
#ifdef CONFIG_LOCKUP_DETECTOR_ADD_LOG
    show_cmdline(NULL);
#endif
    dump_stack();
    if (pdwnc_reboot_disable) {
        Printf("Disabled PDWNC_Reboot1\n");
        while (1) { }
    }
    #endif
    LOG(0, " PDWNC_Reboot1 \n                                       ");
    vIO32Write4B(PDWNC_WDTCTL, (u4IO32Read4B(PDWNC_WDTCTL) & 0x00ffffff) | 0x100);//	vIO32WriteFldAlign(PDWNC_WDTCTL, 0x1, FLD_WDT0E);
    vIO32Write4B(PDWNC_WDTRST1,0x0fffffff);
    vIO32Write4B(PDWNC_WDT1,0x7fffffff);//vIO32Write4B(PDWNC_WDT0,0x0fff0000);

    while (1) { }
}

//-----------------------------------------------------------------------------
/** PDWNC_Reboot2() Reboot the system
 */
//-----------------------------------------------------------------------------
void PDWNC_Reboot2()
{
    _PDWNC_SetupStrapping();
#ifndef CC_MTK_LOADER
#ifdef CONFIG_LOCKUP_DETECTOR_ADD_LOG
    show_cmdline(NULL);
#endif
    dump_stack();
    if (pdwnc_reboot_disable) {
        Printf("Disabled PDWNC_Reboot2\n");
        while (1) { }
    }
#endif
    LOG(0, " PDWNC_Reboot2 \n                                       ");
    vIO32WriteFldAlign(PDWNC_WDTCTL, 0xFF, FLD_WDT2E);//	use watchdog 2 trigger wakeup.
    vIO32Write4B(PDWNC_WDTRST2, 0x0fffffff);
    vIO32Write4B(PDWNC_WDT2, 0x7fffffff);//vIO32Write4B(PDWNC_WDT2,0x0fff0000);

    while (1) { }
}

#define PDWNC_WDTxE(X) ((X==0)?FLD_WDT0E:((X==1)?FLD_WDT1E:FLD_WDT2E))
void PDWNC_WatchDogEnDis(UINT32 u4WdtCh ,BOOL fgEnable)
{
	if(u4WdtCh == 0 || u4WdtCh == 1 || u4WdtCh == 2)
	{
		if(fgEnable == TRUE)
		{
			vIO32WriteFldAlign(PDWNC_WDTCTL,0xFF,PDWNC_WDTxE(u4WdtCh));
		}else
		{
			vIO32WriteFldAlign(PDWNC_WDTCTL,0x00,PDWNC_WDTxE(u4WdtCh));
		}
	}
}

//-----------------------------------------------------------------------------
/** PDWNC_IsWakeupByPowerButton() to check wakeup status is Power key pad.
 *  @retval 0 not wakeup by power key pad, 1 wakeup by power key pad.
 */
//-----------------------------------------------------------------------------
UINT32 PDWNC_IsWakeupByPowerButton(void)
{
    INT32 i;
    UINT32 u4Val, u4Servo, u4DkBit;
    SGL_GPIO_T   *prSingleGpioKeyList = NULL;
    SGL_SERVO_T  *prSingleServoKeyList = NULL;

    // For compatible with both main chip servoADC & mcm servoADC
    _PDWNC_ReadServoADCWakeupStatus(&u4Val);
    i = DRVCUST_InitQueryUptr(eSingleServoKeyList, (UPTR *)&prSingleServoKeyList);
	u4DkBit = DRVCUST_InitGet(eKeyPadWakeupBit);
    if (i==0)
    {
        while ((prSingleServoKeyList) &&
            (prSingleServoKeyList[i].u4Key != 0) &&
            (prSingleServoKeyList[i].u4Key != DKBIT_NONE))
        {
            if (prSingleServoKeyList[i].u4Key && u4DkBit)
            {
                u4Servo = prSingleServoKeyList[i].u4Servo;
                // In case of old style servo ADC numbering
                if(u4Servo >= ADIN0)
                {
                    u4Servo -= ADIN0;
                }
                if (u4Servo > 31)
                {
                    return 0;
                }
                if (u4Val & SRVAD_WAKEN(WAK_SRVADX(u4Servo)))
                //if (u4Val & PDWNC_SRVAD_WAKEN(PDWNC_WAK_SRVADX(u4Servo)))
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            i++;
        }
    }
	//u4Val = (_PDWNC_ReadWakeupStatus(0) & ~(0xff << 20)) | u4Servo;
    i = DRVCUST_InitQueryUptr(eSingleGpioKeyList, (UPTR *)&prSingleGpioKeyList);
    if (i == 0)
    {
        while ((prSingleGpioKeyList) &&
            (prSingleGpioKeyList[i].u4Key != 0) &&
            (prSingleGpioKeyList[i].u4Key != DKBIT_NONE))
        {
            if (prSingleGpioKeyList[i].u4Key == DKBIT_POWER)
            {
                //u4Gpio = prSingleGpioKeyList[i].u4Gpio - OPCTRL(0);
				if(!PDWNC_GetWakeupGpioNum(&u4Val))
				{
					if (prSingleGpioKeyList[i].u4Gpio == u4Val)
	                {
	                    return 1;
	                }else{
	                    return 0;
	                }
				}else{
					return 0;
				}
            }
            i++;
        }
    }
    return 0;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void PDWNC_WatchDogReboot(void)
{
	LOG(0, "%s.\n", __FUNCTION__);
	//if(u4IO32Read4B(PDWNC_WDTCTL))
	if (IO32ReadFldAlign(PDWNC_WDTCTL, FLD_WDT0E)
		|| IO32ReadFldAlign(PDWNC_WDTCTL, FLD_WDT1E)
		|| IO32ReadFldAlign(PDWNC_WDTCTL, FLD_WDT2E))
	{
		PDWNC_Reboot();
	}
}

//-----------------------------------------------------------------------------
/** PDWNC_CreateWatchDogThread() to enable watch dog and set watch dog thread.
 */
//-----------------------------------------------------------------------------
void PDWNC_CreateWatchDogThread(void)
{
#ifndef CC_MTK_LOADER
	//if(_fgWdtPreInit)
	//{
	//	PDWNC_WatchDogPreInit();
	//}
    VERIFY(pgrPDWNC_Func);
    VERIFY(pgrPDWNC_Func->pfnWatchDogInit);
    pgrPDWNC_Func->pfnWatchDogInit();

    VERIFY(pgrPDWNC_Func->pfnErrorHandleInit);
    pgrPDWNC_Func->pfnErrorHandleInit();
#endif /* CC_MTK_LOADER */
}

//-----------------------------------------------------------------------------
/** PDWNC_IrLedCheck() to check ir blinking option
 */
//-----------------------------------------------------------------------------
void PDWNC_IrLedCheck(INT32 fgOn)
{
    static HAL_TIME_T rPrevTime = { 0, 0 };
    static INT32 fgPrev = 1;
    static INT32 fgInit = 0;
    static PFN_GPIO_LEDCTRL_FUNC pfnLedCtrlFunc = NULL;
    HAL_TIME_T rTime, rDelta;

    if (!fgInit)
    {
        UNUSED(DRVCUST_InitQueryUptr(eGpioLedCtrlFunc, (UPTR *)&pfnLedCtrlFunc));
        fgInit = 1;
    }

    if (!_fgIrLedEnable && DRVCUST_InitGet(eIrrxFlagBlinking))
    {
        if (DRVCUST_InitGet(eSupportDarkLed))
        {
            pfnLedCtrlFunc(eLedDarkLed);
        }
        else
        {
            pfnLedCtrlFunc(eLedIrOff);
        }
        return;
    }

    if (DRVCUST_InitGet(eIrrxFlagBlinking))
    {
        HAL_GetTime(&rTime);
        HAL_GetDeltaTime(&rDelta, &rPrevTime, &rTime);

        if ((fgOn) && (!fgPrev) && ((rDelta.u4Seconds > 0) || (rDelta.u4Micros > 50000)))
        {
            pfnLedCtrlFunc(eLedIrOn);
            fgPrev = 1;
            HAL_GetTime(&rPrevTime);
        }
        else if ((!fgOn) && (fgPrev) && ((rDelta.u4Seconds > 0) || (rDelta.u4Micros > 100000)))
        {
            if (DRVCUST_InitGet(eSupportDarkLed))
            {
                pfnLedCtrlFunc(eLedDarkLed);
            }
            else
            {
                pfnLedCtrlFunc(eLedIrOff);
            }
            fgPrev = 0;
            HAL_GetTime(&rPrevTime);
        }
    }
}

//-----------------------------------------------------------------------------
/** PDWNC_IrLedCheck() to check ir blinking option
 */
//-----------------------------------------------------------------------------
void PDWNC_EnableIrLed(BOOL fgEnable)
{
    _fgIrLedEnable = fgEnable;
}

#ifndef CC_MT5895
//#ifdef CBUS_DRIVER_VERIFY
static void _PDWNC_SetupCbus(BOOL fgEnable)
{
#if defined(CC_MT5863)
    vIO32Write4B(PDWNC_CBUS_LINK_0D, 0x00000000);// 00000000 close all interrupt when enter standby because crax 8032 will dont clear interrupt.for cr 784034.
    //vCbus_CableIntMskSet(CABLE_CON_INTMSK_EN);//
#elif defined(CC_MT5895)
    LOG(0,"MT5895 do not support MHL , no need to set Cbus"\n);
#else
    PDWNC_T8032_CMD_T rCmd;
#if !defined(CONFIG_TV_DRV_VFY)
#if defined(CC_MT5891) ||defined(CC_MT5886)
#ifndef CC_MTK_LOADER
    if(fgMHL3ComGetCdSense())
    {
        vMHL3ComSetEx1K(FALSE);
        vMHL3ComSetCbusImpedance1K();
        vMHL3SetVbusOutput(1);
    }
#endif
#endif
#endif

    rCmd.u1Cmd = PDWNC_CMD_ARMT8032_CTRL_CBUS; //Notify T8032 start/stop control CEC
    rCmd.u1SubCmd = 0;

    if(fgEnable)
    {
        rCmd.au1Data[0] = 1; //T8032 mhl charge enable
    }
    else
    {
        rCmd.au1Data[0] = 0; //T8032 mhl charge disable
    }
#ifdef SYS_MHL_SUPPORT
#ifdef SYS_ANDROID_TV_TIF_SUPPORT
#ifndef CC_MTK_LOADER
    rCmd.au1Data[1] = (drvMhlStandbyNeedCharge())?1:0;
#endif
#endif
#endif
    (void)PDWNC_T8032Cmd(&rCmd, NULL);
#endif
}
#endif

#if defined(CC_SUPPORT_STR_CORE_OFF)
// for WDT
static UINT32 u4WDTSuspendRegister;
void WDT_pm_suspend(void)
{
	u4WDTSuspendRegister = u4IO32Read4B(PDWNC_WDTCTL);
	if((u4WDTSuspendRegister & 0x00FFFFFF) == 0)
	{
		vIO32WriteFldAlign(PDWNC_CONCFG1,1,FLD_RG_DIS_HOTBOOT_WDT);
		vIO32WriteFldAlign(PDWNC_CONCFG1,1,FLD_RG_DIS_SUSPEND_WDT);
	}
}

void WDT_pm_resume(void)
{
	vIO32Write4B(PDWNC_WDT0,0);
	vIO32Write4B(PDWNC_WDT1,0);
	vIO32Write4B(PDWNC_WDT2,0);
	vIO32Write4B(PDWNC_WDTCTL,u4WDTSuspendRegister);
}

static UINT32 SysSuspendMode=0;
//static UINT8  SysSuspendDelay=0;

#if !defined(CC_MTK_LOADER)
#ifdef CC_STR_ONOFF_TEST_ENABLE
static HANDLE_T _hTestOnOffHandle = (HANDLE_T)NULL;

#if defined(CC_MTK_AUTO_TEST) || defined(TIME_MEASUREMENT)
UINT32 enableSTROnOffTest = 0;  //no need power down automatically.
#else
UINT32 enableSTROnOffTest = 1;
#endif

#endif
#ifndef PDWNC_RESUME_METHOD

#ifdef CC_ANDROID_TWO_WORLDS
#define PDWNC_RESUME_METHOD 0x1    //By Application control
#else
#define PDWNC_RESUME_METHOD 0x0
#endif

#endif

#if defined(ANDROID)
static HANDLE_T _hResumeHandle = (HANDLE_T)NULL;
UINT32 u4PDWNC_TestWakelock = PDWNC_RESUME_METHOD;
static void _PDWNC_AWAKE_PMS(void)
{
    IRRC_WAKKEY_T pWakeupKey;

    if (u4PDWNC_TestWakelock == 0)
    {
        IRRX_SendMtkIr(DRVCUST_InitGet(ePdwncResumeHandleKey)); // trigger a user-activity via a fixed-key
    }
    else
    {
        if (u4PDWNC_TestWakelock & 0x02)
        {
            UINT32 u4Reason = PDWNC_ReadWakeupReason();
            if (u4Reason != PDWNC_WAKE_UP_REASON_RTC)
            {
                if (u4Reason == PDWNC_WAKE_UP_REASON_IRRC)
                {
                    IRRX_QueryWakeupKey(&pWakeupKey);
                    IRRX_SendMtkIr(pWakeupKey.u4WakeupKey);
                    LOG(0,"(yjdbg) IRRX_SendMtkIr.1: 0x%x\n", pWakeupKey.u4WakeupKey);
                }
                else
                {
                    IRRX_SendMtkIr(DRVCUST_InitGet(ePdwncResumeHandleKey)); // trigger a user-activity via a fixed-key
                    LOG(0,"(yjdbg) IRRX_SendMtkIr.2: 0x%lx\n", BTN_POWER);
                }
            }
        }
    }

}

static void _PDWNC_ResumeHandle(void *pvArg)
{
    x_thread_delay(300); // delay 300ms until driver/kernel is finished
    LOG(0, "_PDWNC_ResumeHandle\n");
    _PDWNC_AWAKE_PMS();
}
#endif

#ifdef CC_STR_ONOFF_TEST_ENABLE
// refer to _PDWNC_RebootHandle implementation
#define SYSTEM_SUSPEND_DELAY        20000
#define WAKEUP_TIMER                10       // system wake up timer by RTC

#if defined(CC_MTK_AUTO_TEST) || defined(TIME_MEASUREMENT)
UINT32 _u4PDWNC_TestOnOFF = 1;  //default enable it to resume automatically.
#else
UINT32 _u4PDWNC_TestOnOFF = 0;
#endif

static void _PDWNC_TestOnOFF(void *pvArg)
{
    x_thread_delay(SYSTEM_SUSPEND_DELAY);

    IRRX_SendMtkIr(BTN_MENU); // trigger a user-activity
    x_thread_delay(5000);
    IRRX_SendMtkIr(BTN_MENU); // trigger a user-activity
    x_thread_delay(5000);
    IRRX_SendMtkIr(BTN_POWER); // trigger a user-activity

    _u4PDWNC_TestOnOFF = 1;

    return;
}
#endif
void PDWNC_Resume(void)
{
    LOG(0,"resume reason: %d ,  %X .\n", PDWNC_ReadWakeupReason(), u4IO32Read4B(PDWNC_IRCFGL));
    VERIFY(_PDWNC_SetT8032(PDWNC_T8032_SET_NORMAL) == 0);
    PDWNC_SetSuspendMode(FALSE);
	// Do the external power resume for customize setting
    VERIFY(pgrPDWNC_Func);
    VERIFY(pgrPDWNC_Func->pfnPowerResume);
    pgrPDWNC_Func->pfnPowerResume();
#if defined(ANDROID)
    if (u4PDWNC_TestWakelock == 0)
    {
		_PDWNC_AWAKE_PMS();
		UNUSED(x_thread_create(&_hResumeHandle, "ResumeHandle", 0x800, 100, _PDWNC_ResumeHandle, 0, NULL));
    }
    else
    {
		if (u4PDWNC_TestWakelock & 0x01)
		{
			MTPDWNC_RESUME_REASON_T t_cb_info;
		    t_cb_info.u4Reason = PDWNC_ReadWakeupReason();
		    t_cb_info.u4Other = 0xA5A5A5A5;
		    _CB_PutEvent(CB_DRV_PDWNC_RESUME_NFY, sizeof(MTPDWNC_RESUME_REASON_T), &t_cb_info);
		}
		if (u4PDWNC_TestWakelock & 0x02)
		{
		    _PDWNC_AWAKE_PMS();
		}
    }
#endif
#ifdef CC_STR_ONOFF_TEST_ENABLE
    if (enableSTROnOffTest)
        UNUSED(x_thread_create(&_hTestOnOffHandle, "TestOnOffHandle", 0x800, 100, _PDWNC_TestOnOFF, 0, NULL));
#endif

	vIO32Write4B(PDWNC_WAKEN, 0x00000000); //just clean wakeup enable bit,for MT5890(Oryx),wangliang.wang,20140830.
	vIO32Write4B(PDWNC_WAKEN1,0x00000000);
}
#endif

void PDWNC_SetSuspendMode(UINT32 SuspendMode)
{
    SysSuspendMode = SuspendMode;
}

UINT32 PDWNC_IsSuspend(void)
{
    return SysSuspendMode;
}

UINT32 PDWNC_IsWakeupFromSuspend(void)
{
    return IO32ReadFldAlign(PDWNC_CONCFG1,FLD_RG_DMSUS_RESERVED);
}
//-----------------------------------------------------------------------------
/** PDWNC_EnterSuspend() Enter Suspend mode.
 */
//-----------------------------------------------------------------------------
UINT32 PDWNC_EnterSuspend(void)
{
    //PFN_GPIO_POWEROFF_FUNC pfnPowerOffFunc = NULL;
    //UINT32 u4Val, i, u4WtdCtrl, u4IRQEN, u4FIQEN;
    //UINT32 u4PowerDownEn = WAK_RTC | WAK_IRRX | WAK_VGA ;
    //UINT32 u4PowerDownEvent = u4SuspendEn;

#ifndef CC_MTK_LOADER
	_fgSuspendWakeupReasonUp = TRUE;
	#if defined(CC_SUPPORT_STR_CORE_OFF)
		IRRX_SuspendClrWakeupKeyFg();
	#endif
    //LOG(0, "PDWNC_EnterSuspend\n");
	_u4PowerDownEn = _u4PowerDownEn | WAK_IRRX;
#ifdef CC_STR_ONOFF_TEST_ENABLE
	if (_u4PDWNC_TestOnOFF == 1)
	{
	    UINT64 u8Time;

	    _u4PowerDownEn |= WAK_RTC;

	    RTC_GetTimeDate(&u8Time);
	    u8Time += WAKEUP_TIMER;
	    RTC_SetAlertTime(u8Time);

	    // Enable RTC wakeup
	    vIO32WriteFldAlign(PDWNC_WAKEN, 0x1, FLD_RTC_WAKEN);
	}
#endif
	LOG(0, "PDWNC_EnterSuspend(0x%x,0x%x) .\n",_u4PowerDownEn,_u4PowerDownEvent);

	PDWNC_SetSuspendMode(TRUE);
    
#if defined(CC_MT5895)
    vIO32WriteFldAlign(PDWNC_RESRV4, 0x1, FLD_RG_HOTBOOT_FLOW_CTRL);
    if(Cm4GetGaStatus())
    {
        LOG(0, "CM4 GA is enable.\n");
        vIO32WriteFldAlign(PDWNC_RESRV4, 0x1, FLD_RG_CM4_GA_STATUS);
    }
    else
    {
        LOG(0, "CM4 GA is diable.\n");
        vIO32WriteFldAlign(PDWNC_RESRV4, 0x0, FLD_RG_CM4_GA_STATUS);
    }
#endif // defined(CC_MT5895)

#ifdef CC_BT_GPIO_WAKEUP
	//disable gpio intr
	_BTGpioIntrEnable(FALSE);
#endif // CC_BT_GPIO_WAKEUP

	return PDWNC_EnterPowerDown(_u4PowerDownEn,_u4PowerDownEvent);
#else // CC_MTK_LOADER
    return 0;
#endif // CC_MTK_LOADER
}
#endif

static void _PdwncSetupCEC(void)
{
	UINT32 u4Val;
	UINT32 u4Val2,u4Val3;
	INT32 i4Val;
	UINT8 au1Data[6] = {0};
	PDWNC_T8032_CMD_T rCmd;
#ifdef CC_CUST_CEC_CONFIG_SUPPORT
    BOOL fgCecEnable = TRUE;
    {
        // CEC configuration.
        PFN_CEC_CONFIG_QUERY_FUNC pfnQueryCECEnableFunc;

        pfnQueryCECEnableFunc =
            (PFN_CEC_CONFIG_QUERY_FUNC)(DRVCUST_InitGetUptr(eLoaderCECConfigQueryFunc));

        if (pfnQueryCECEnableFunc != NULL)
        {
            fgCecEnable = pfnQueryCECEnableFunc();
        }
    }

	if (!fgCecEnable)
	{
		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_SET_T8032_CTL_CEC; //Notify T8032 start/stop control CEC
		rCmd.u1SubCmd = 0;
		rCmd.au1Data[0] = 0;	//T8032 stop control CEC.
		PDWNC_T8032Cmd(&rCmd, NULL);
		return;
	}
#endif /* CC_CUST_CEC_CONFIG_SUPPORT */

	// Write CEC configuration to uP
	if((DRVCUST_InitGetUptr(eT8032uPOffset) != 0) && ((u4Val = DRVCUST_InitGet(eEepromCECMenuLanguageOffset)) != 0x0) &&
	((DRVCUST_InitGet(eEepromCECEnableOffset)) == 0x00) && ((DRVCUST_InitGet(eEepromCECOneTouchPlayEnableOffset)) == 0x00))
	{
		i4Val = EEPROM_Read(u4Val, (UPTR)au1Data, 6);
		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_SET_MENU_LANGUAGE;
		rCmd.u1SubCmd = 0;
		x_memset(rCmd.au1Data,0,sizeof(rCmd.au1Data));
		x_memcpy(rCmd.au1Data, au1Data, 4);
		PDWNC_T8032Cmd(&rCmd, NULL);

		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_ENABLE_CEC;
		x_memset(rCmd.au1Data,0,sizeof(rCmd.au1Data));
		x_memcpy(rCmd.au1Data, &au1Data[4], 1);
		PDWNC_T8032Cmd(&rCmd, NULL);

		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_ENABLE_ONE_TOUCH_PLAY;
		x_memset(rCmd.au1Data,0,sizeof(rCmd.au1Data));
		x_memcpy(rCmd.au1Data, &au1Data[5], 1);
		PDWNC_T8032Cmd(&rCmd, NULL);
		UNUSED(i4Val);
	}
	else if((DRVCUST_InitGetUptr(eT8032uPOffset) != 0) && ((u4Val = DRVCUST_InitGet(eEepromCECMenuLanguageOffset)) != 0x0) &&
	((u4Val2 = DRVCUST_InitGet(eEepromCECEnableOffset)) != 0x00) && ((u4Val3 = DRVCUST_InitGet(eEepromCECOneTouchPlayEnableOffset)) != 0x00))
	{
		i4Val = EEPROM_Read(u4Val, (UPTR)au1Data, 4);
		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_SET_MENU_LANGUAGE;
		rCmd.u1SubCmd = 0;
		x_memset(rCmd.au1Data,0,sizeof(rCmd.au1Data));
		x_memcpy(rCmd.au1Data, au1Data, 4);
		PDWNC_T8032Cmd(&rCmd, NULL);

		i4Val = EEPROM_Read(u4Val2, (UPTR)au1Data, 1);
		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_ENABLE_CEC;
		x_memset(rCmd.au1Data,0,sizeof(rCmd.au1Data));
		x_memcpy(rCmd.au1Data, au1Data, 1);
		PDWNC_T8032Cmd(&rCmd, NULL);

		i4Val = EEPROM_Read(u4Val3, (UPTR)au1Data, 1);
		rCmd.u1Cmd = PDWNC_CMD_ARMT8032_ENABLE_ONE_TOUCH_PLAY;
		x_memset(rCmd.au1Data,0,sizeof(rCmd.au1Data));
		x_memcpy(rCmd.au1Data, au1Data, 1);
		PDWNC_T8032Cmd(&rCmd, NULL);
		UNUSED(i4Val);
	}

	rCmd.u1Cmd = PDWNC_CMD_ARMT8032_SET_T8032_CTL_CEC; //Notify T8032 start/stop control CEC
	rCmd.u1SubCmd = 0;
	rCmd.au1Data[0] = 1;	//T8032 control CEC
	PDWNC_T8032Cmd(&rCmd, NULL);
}

//-----------------------------------------------------------------------------
/** PDWNC_RequestSuspendEvent() Request Suspend mode Event .
 */
//-----------------------------------------------------------------------------
#ifndef CC_MTK_LOADER
extern UINT32 _fgNetFlixTgWak;

#if defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || defined(CC_MT5865) || defined(CC_MT5895)
extern void star_support_wol(BOOL is_support);
#endif
#endif

UINT32 PDWNC_RequestSuspendEvent(UINT32 u4SuspendEn, UINT32 u4SuspendEvent)
{
#ifndef CC_MTK_LOADER
#if defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || defined(CC_MT5865) || defined(CC_MT5895)
	#ifndef	CC_WOL_WOWL_DEFAULT_ON
				DTVCFG_T	rDtvCfg;
	#endif
	INT32		i4_ret;
#endif
#endif

#if defined(CC_SUPPORT_STR_CORE_OFF)
	_u4PowerDownEn = u4SuspendEn;
	_u4PowerDownEvent = u4SuspendEvent;
	//LOG(0, "PDWNC_RequestSuspendEvent(%x,%x) .\n",u4SuspendEn,u4SuspendEvent);
	vIO32WriteFldAlign(PDWNC_PDSTCLR, 0x1, FLD_STCLR);
	//clear watchdog flag
    vIO32Write4B(PDWNC_WDTCTL,u4IO32Read4B(PDWNC_WDTCTL));
	_fgSuspendWakeupReasonUp = TRUE;
#endif
	#ifndef CC_MTK_LOADER
	_fgNetFlixTgWak = 1;
	#endif

#ifndef CC_MTK_LOADER
#if defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || defined(CC_MT5865) || defined(CC_MT5895)
	#ifndef	CC_WOL_WOWL_DEFAULT_ON
		i4_ret = EEPDTV_GetCfg(&rDtvCfg);
		ASSERT(i4_ret==0);
		if (i4_ret!=0)
		{
			LOG(0, "PDWNC_RequestSuspendEvent: DTV EEPROM read failure.\n");
			LOG(0, "%s(%d) DTV EEPROM read failure.\n", __FILE__, __LINE__);
			return 0;
		}
		if(rDtvCfg.u1Flags3 & (UINT8)DTVCFG_FLAG3_WAKEUP_ON_LAN )
	#endif
		{
			/* use flag to callback with star driver */
			LOG(0,"\nstar: PDWNC_RequestSuspendEvent, wol on\n");
			star_support_wol(TRUE);
		}
	#ifndef CC_WOL_WOWL_DEFAULT_ON
		else
		{
			LOG(0,"\nstar: PDWNC_RequestSuspendEvent, wol off\n");
			star_support_wol(FALSE);
		}
	#endif
#endif
#endif
	return 0;
}

#ifndef CC_MTK_LOADER
UINT32 PDWNC_RequestPowerDownEvent(UINT32 u4PowerDownEn, UINT32 u4PowerDownEvent)
{
    LOG(0,"%s(%d), 0x%08X, 0x%08X .\n",__FUNCTION__, __LINE__,u4PowerDownEn,u4PowerDownEvent);
    _u4PowerDownEn = u4PowerDownEn;
    _u4PowerDownEvent = u4PowerDownEvent;

    return 0;
}
#endif
//-----------------------------------------------------------------------------
/** PDWNC_EnterPowerDown() Enter Power Down mode.
 */
//-----------------------------------------------------------------------------
#ifndef CC_MTK_LOADER
static INT32 (*_fPDWNC_PowerDown_f)(void) = 0;
void RegisterPdwncCallback(INT32 (*f)(void))
{
	_fPDWNC_PowerDown_f = f;
}
#endif
UINT32 PDWNC_EnterPowerDown(UINT32 u4PowerDownEn, UINT32 u4PowerDownEvent)
{
    PFN_GPIO_POWEROFF_FUNC pfnPowerOffFunc = NULL;
	PFN_GPIO_POWEROFF_SELFDIAG_SHUTDOWN_FUNC pfnPowerOffSelfDiagShutDownFunc = NULL;
    INT32 i4Gpio;
    UINT32 u4Cnt;

#ifndef CC_MTK_LOADER
    if (_fPDWNC_PowerDown_f
        #if defined(CC_SUPPORT_STR_CORE_OFF)
        && (PDWNC_IsSuspend() == 0)
        #endif
        )
    {
        LOG(0, "PowerDown Notify others: _fPDWNC_PowerDown_f 0x%x, event 0x%x, f %p\n", u4PowerDownEn, u4PowerDownEvent, _fPDWNC_PowerDown_f);
        _fPDWNC_PowerDown_f();
    }
#endif
    _PdwncSetupCEC();
#ifndef CC_MT5895
    _PDWNC_SetupCbus(1);
#endif
    // GPIO wakeup setup
    _PDWNC_SetupGPIO(&u4PowerDownEn);
    // ServoADC wakeup setup
    _PDWNC_SetupServoADC(&u4PowerDownEn);
    // IRRX wakeup setup
    _PdwncSetupIRRX(u4PowerDownEn);
    // VGA wakeup setup
    _PdwncSetupVGA(u4PowerDownEn);
	//USB pdwnc Setup
#if defined(CC_MT5863)
    _PdwncSetupUSB();  //cut off usb port2 power on crax
#endif

#ifndef CC_MTK_LOADER
    // RTC wakeup setup
    _PdwncSetupRTC(&u4PowerDownEn);
#endif /* CC_MTK_LOADER */
	//CC_PDWNC_SUPPORT_WOL is defined in the .cfg file of sysbuild directory
    LOG(0,"support WOL                         \n");
#if !defined(CONFIG_TV_DRV_VFY)
    _PDWNC_SetupEthernetWakeup(&u4PowerDownEn);
#endif
    // Do customization
    if (DRVCUST_InitQueryUptr(eGpioPowerOffFunc, (UPTR *)&pfnPowerOffFunc) == 0)
    {
        pfnPowerOffFunc(u4PowerDownEn);
		if(_fgIsSelfDiagShutDown)
        {
            if (DRVCUST_InitQueryUptr(eGpioPowerOffSelfDiagShutDownfunc, (UPTR *)&pfnPowerOffSelfDiagShutDownFunc) == 0)
            {
                pfnPowerOffSelfDiagShutDownFunc();
            }
            _fgIsSelfDiagShutDown = FALSE;
        }
    }
    if(DRVCUST_InitGet(eFlagMt8292GpioSupport))
    {
        INT32 i4Val = 0;
        // If customization option does not set 8292 reset, it must be polled by H/W
        i4Gpio = (INT32)DRVCUST_InitGet(eMt8292ResetGpio);
        if(i4Gpio != -1)//if(i4Gpio != (INT32)0xFFFFFFFF)
        {
            VERIFY(GPIO_Output(i4Gpio, &i4Val) == 0);
        }
        UNUSED(i4Val);
    }

    if (DRVCUST_InitGet(ePdwncPolarity))
    {
        vIO32WriteFldAlign(PDWNC_PDMISC, 0x1, FLD_PDWN_POL);
    }
    else
    {
        vIO32WriteFldAlign(PDWNC_PDMISC, 0x0, FLD_PDWN_POL);
    }
#ifndef CC_MTK_LOADER
#ifdef TIME_MEASUREMENT
    TMS_DIFF_EX(TMS_FLAG_POWER_OFF,TMS_IR_POWER_OFF,"@DRV power off");
    TMS_END_EX(TMS_FLAG_POWER_OFF,TMS_IR_POWER_OFF,"@DRV power off");
#endif
#endif
    //clear watchdog flag
    vIO32Write4B(PDWNC_WDTCTL,0x7000000);
    vIO32WriteFldAlign(PDWNC_CONCFG1,0,FLD_RG_DMSUS_RESERVED);
#if defined(CC_MT5891) || defined(CC_MT5886)
	vIO32WriteFldAlign(PDWNC_RESRV5,0x0,FLD_RG_WDT_DRAMSR);
#endif
    // Setup Power Down
    LOG(0, "Standby                         \n");
    // SerWaitTxBufClear();
    //for the case of logo standby, T8032 may be hang by CEC driver at this monent...
    if(DRVCUST_InitGetUptr(eT8032uPOffset) != 0)
    {
        u4Cnt = 0;
        while(IS_XDATA_AT_ARM() && (u4Cnt < 3))
        {
            x_thread_delay(100);
            u4Cnt++;
        }
        if(u4Cnt == 3)
        {
            LOG(0, "Warning T8032 is still hang...\n");
        }
    }

    // Do the external power down for customize setting
    VERIFY(pgrPDWNC_Func);
    VERIFY(pgrPDWNC_Func->pfnPowerDown);
    pgrPDWNC_Func->pfnPowerDown(u4PowerDownEvent, &u4PowerDownEn);

    // Enable wakeup devices
    vIO32Write4B(PDWNC_WAKEN, (u4IO32Read4B(PDWNC_WAKEN) | u4PowerDownEn));
	LOG(0, "PDWNC_EnterPowerDown(0x%x,0x%x) \n",u4IO32Read4B(PDWNC_WAKEN),u4PowerDownEvent);
#if defined(CC_MT5893)
	if(IS_IC_5893_ES1())
        {
		vIO32Write4B(PDWNC_TOUT_RSTCNT,0x6DDD00);
		LOG(0,"workaround for husky es1 power ready tout time 300ms\n");
	}
#endif
    PDWNC_SetupPowerDown();

    return 0;
}

//-----------------------------------------------------------------------------
/** PDWNC_EnterPowerState() to enter semi power state (Will not actually power down the system).
 */
//-----------------------------------------------------------------------------
UINT32 PDWNC_EnterPowerState(UINT32 u4PowerDownEvent)
{
    UINT32 u4State, u4NextState;
	#ifndef CC_MTK_LOADER
	LOG(0,"PDWNC_EnterPowerState : STATE_CHAGNE_MASK : 0x%x, PowerEvent :%d .\n",
	        (u4PowerDownEvent & PDWNC_POWER_STATE_CHAGNE_MASK), (u4PowerDownEvent & PDWNC_POWER_STATE_EVENT_MASK));
	if(u4PowerDownEvent == 4)
    {
		_fgNetFlixTgWak = 0;
    }
	#endif
    // Do the external power down for customize setting
    VERIFY(pgrPDWNC_Func);
    if (pgrPDWNC_Func->pfnGetCurrentState &&
        pgrPDWNC_Func->pfnDetermineNextState)
    {
        pgrPDWNC_Func->pfnGetCurrentState(&u4State);
        pgrPDWNC_Func->pfnDetermineNextState(u4State, u4PowerDownEvent, &u4NextState, NULL, NULL);
        pgrPDWNC_Func->pfnEnterNextState(u4NextState);
    }
    return 0;
}
BOOL PDWNC_SetupFpWakeup(BOOL *pfgEnable)
{
    static BOOL fgFpEnable = TRUE;
    if (pfgEnable)
    {
        fgFpEnable = *pfgEnable;
    }
    return fgFpEnable;
}

#ifndef CC_MTK_LOADER
void PDWNC_CreateDCOnOffTestThread(void)
{
    #if defined(CC_DC_ONOFF_TEST_ENABLE) || defined(CC_CPU_SPEED_TEST_ENABLE)
    // Start DC on/off stress test
    UNUSED(x_thread_create(&_hShutdownHandle, "ShutdownHandle", 0x800, 100, _PDWNC_RebootHandle, 0, NULL));
    #else
    return;
    #endif
}
#endif /* CC_MTK_LOADER */

void PDWNC_PrepareShutdown(void)
{
    _fgIsSelfDiagShutDown = TRUE;
}
