/* 2009-08-20: File added and changed by Sony Corporation */

/*
 *  File Name	    : linux/arch/arm/mach-mp200/pmu.c
 *  Function	    : pmu
 *  Release Version : Ver 1.21
 *  Release Date    : 2009/08/18
 *
 *  Copyright (C) NEC Electronics Corporation 2009
 *
 *
 *  This program is free software;you can redistribute it and/or modify it under the terms of
 *  the GNU General Public License as published by Free Softwere Foundation; either version 2
 *  of License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warrnty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with this program;
 *  If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 *  MA 02111-1307, USA.
 *
 */

#ifndef CONFIG_MP200_QR
#error CONFIG_MP200_QR not defined
#endif

char const pmu_version[] = "PMU sequencer ver1.21 and Compiled "__DATE__" "__TIME__"";
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/jiffies.h>

#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/pmu.h>
#include <asm/arch/pwc.h>
#include <asm/arch/smu.h>
#include <asm/arch/pcm_irq.h>
#include <asm/arch/cache.h>
#include <asm/arch/pm.h>
#include <asm/arch/timer.h>
#include <asm/cacheflush.h>

#ifdef CONFIG_MP200_RTC_DEV
#include <linux/rtc.h>
#endif

#include "pm_pmu.h"
#include "time.h"

#include <asm/arch/spi.h>

/* flag for debug */
/* #define IDLE_DEBUG_LOG */
/* #define DEBUG_LCD */
/* #define IDLE_DEBUG_TW1_WAKEUP */

/* #define L2_DISABLE */

/* #define L1_AUTO_ENABLE */

#ifdef DEBUG_LCD
#include <asm/arch/gpio.h>
#endif

#ifdef IDLE_DEBUG_LOG
#define DPRINTK(format,args...) printk(KERN_INFO "PMU_DEBUG: " format,##args)
#else
#define DPRINTK(format,args...)
#endif

#ifdef IDLE_DEBUG_TW1_WAKEUP

static void tw1_test_wakeup(void)
{
	disable_irq(INT_WDT1);

	outl(0x00000800,	SMU_GCLKCTRL3ENA);
	outl(0x00000800,	SMU_GCLKCTRL3);
	outl(0x00000000,	SMU_GCLKCTRL3ENA);

	outl(0x00000020,  SMU_RESETREQ1ENA);
	outl(0x00000020,  SMU_RESETREQ1);
	outl(0x00000000,  SMU_RESETREQ1ENA);

	/* WDT1:11.4688MHz (=PLL3(229.376MHz)/20) */
	outl(0x0000ffff, IO_ADDRESS(MP200_WDT1_BASE) + 0x8);   /* 5sec */
	outl(7, IO_ADDRESS(MP200_WDT1_BASE));			/* set TO_EN/TSTART/TM_EN */

	enable_irq(INT_WDT1);
	return;

}
#endif

extern void mp200_wdt_enable(void);
extern void mp200_wdt_disable(void);

static register_state_t register_state;

static unsigned int wdt_op_reg = 0;

static void (*restore_state_async_bus)(void);

static struct async_bus_state async_bus_state_cs0;
static struct async_bus_state async_bus_state_cs1;
static struct async_bus_state async_bus_state_cs2;
static struct async_bus_state async_bus_state_cs3;

#ifdef CONFIG_MP200_RTC_DEV
static long rtc_offset = 0;
extern int get_rtc_time(struct rtc_time *rtc_tm);
#endif

#ifdef CONFIG_MACH_PGPF
extern void pgpf_set_gpio_setting_suspend(void);
extern void pgpf_set_gpio_setting_resume(void);
extern void pgpf_set_wakeup_resource(void);
extern void pgpf_save_pwc_interruption_setting(void);
extern void pgpf_restore_pwc_interruption_setting(void);
#endif /* CONFIG_MACH_PGPF */

#define WDT_OP IO_ADDRESS(MP200_WDT0_BASE)

static inline int pwr_reg_write(u_char addr, u_char data)
{
	return pwc_write(addr, data, 0xff);
}

static inline int pwr_reg_read(u_char addr, u_char *data)
{
	unsigned int d;
	int ret;
	ret = pwc_read(addr, &d);
	*data = (u_char)d;
	return ret;
}

#define PDM_INT_ENA			0x00082000 /* PDMA_INT | PM0_INT */
#define	TIMER2_BASE			IO_ADDRESS(MP200_TIMER2_BASE)
#define	TIMER2_OP			(TIMER2_BASE + 0x0000)
#define	TIMER2_SET			(TIMER2_BASE + 0x0008)
#define TIMER2_RCR			(TIMER2_BASE + 0x000c)
#define	TIMER2_INT_220MS	((TIMER_CLOCK_TICK_RATE_PLL3 * 22) /100)

/*
 * INTC mask and unmask
 *
 */
int pmu_intc_mask(int mask)
{
	struct intc_state *state = &register_state.intc;

	switch (mask) {
	case PMU_INTC_MASK_SAVE_AND_MASK :
#ifdef IDLE_DEBUG_LOG
		DPRINTK("mask = PMU_INTC_MASK_SAVE_AND_MASK\n");
#endif
		state->it0_ien0 = inl(INTC_IT0_IMN0);
		state->it0_ien1 = inl(INTC_IT0_IMN1);
		state->it0_ien2 = inl(INTC_IT0_IMN2);

		outl(MASK_INTC_ALL, INTC_IT0_IDS0);
		outl(MASK_INTC_ALL, INTC_IT0_IDS1);
		outl(MASK_INTC_ALL, INTC_IT0_IDS2);

		if (mp200_sleep_while_idle) {
			outl((RESUME_INTC_1 | TI2_INT), INTC_IT0_IEN1);
			outl(PDM_INT_ENA, INTC_IT0_IEN0);
		} else {
#ifndef IDLE_DEBUG_TW1_WAKEUP
			outl(RESUME_INTC_1, INTC_IT0_IEN1);
#else
			outl((RESUME_INTC_1 | TW1_INT), INTC_IT0_IEN1);
#endif
		}

		outl(SEC_ERR_INT, INTC_IT0_IEN2);

#ifdef IDLE_DEBUG_LOG
		DPRINTK("Save:IT0_IMN0 = 0x%08x, Set:IT0_IDS0 = 0x%08x \n",
			state->it0_ien0, MASK_INTC_ALL);
		DPRINTK("Save:IT0_IMN1 = 0x%08x, Set:IT0_IDS1 = 0x%08x \n",
			state->it0_ien1, MASK_INTC_ALL);
		DPRINTK("Save:IT0_IMN2 = 0x%08x, Set:IT0_IDS2 = 0x%08x \n",
			state->it0_ien2, MASK_INTC_ALL);
		DPRINTK("unmask:IT0_IEN0 = 0x%08x\n", inl(INTC_IT0_IEN0));
		DPRINTK("Unmask:IT0_IEN1 = 0x%08x\n", RESUME_INTC_1);
		DPRINTK("Unmask:IT0_IEN2 = 0x%08x\n", RESUME_INTC_2);
#endif
		break;
	case PMU_INTC_MASK_RESTORE :
		outl(MASK_INTC_ALL, INTC_IT0_IDS0);
		outl(MASK_INTC_ALL, INTC_IT0_IDS1);
		outl(MASK_INTC_ALL, INTC_IT0_IDS2);
		outl( state->it0_ien0, INTC_IT0_IEN0);
		outl(state->it0_ien1, INTC_IT0_IEN1);
		outl(state->it0_ien2, INTC_IT0_IEN2);
#ifdef IDLE_DEBUG_LOG
		DPRINTK("Restore:IT0_IMN0 = 0x%08x\n", inl(INTC_IT0_IMN0));
		DPRINTK("Restore:IT0_IMN1 = 0x%08x\n", inl(INTC_IT0_IMN1));
		DPRINTK("Restore:IT0_IMN2 = 0x%08x\n", inl(INTC_IT0_IMN2));
#endif
		break;
	case PMU_INTC_ALLMASK :
		outl(MASK_INTC_ALL, INTC_IT0_IDS0);
		outl(MASK_INTC_ALL, INTC_IT0_IDS1);
		outl(MASK_INTC_ALL, INTC_IT0_IDS2);
		break;
	default :
		return -EINVAL;
	}

	return 0;
}

/*
 * GPIO mask and unmask
 *
 */
static int pmu_gpio_mask(int flag)
{
	struct gpio_state *gpio = &register_state.gpio;
#ifndef CONFIG_MACH_PGPF 
	struct pwc_state *pwc = &register_state.pwc;
#endif  /* CONFIG_MACH_PGPF */ 

	/* GPIO/PowerIC_GPIO Interrupt Enable/Disable */
	switch (flag) {
	case MP200_PMU_CLK_FULLSPEED :
	{
		outl(MASK_GPIO_ALL, GPIO_GP_IDSL);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSH);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSHH);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSHHH);

		outl(gpio->ien0, GPIO_GP_IENL);
		outl(gpio->ien1, GPIO_GP_IENH);
		outl(gpio->ien2, GPIO_GP_IENHH);
		outl(gpio->ien3, GPIO_GP_IENHHH);

#ifndef CONFIG_MACH_PGPF 
		pwc_write(PWC_FMASK1, pwc->fmask1, MASK_GPIO_KEYSCAN);
		pwc_write(PWC_CLRFACT1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA);
		pwc_write(PWC_BMASK1, pwc->bmask1, MASK_GPIO_KEYSCAN);
		pwc_write(PWC_IOOUT1, pwc->ioout1, MASK_GPIO_KEYSCAN);
		pwc_write(PWC_FMASK2, pwc->fmask2, PWC_SD_DETECT);
		pwc_write(PWC_BMASK2, pwc->bmask2, PWC_SD_DETECT);
		pwc_write(PWC_DETMOD3H, pwc->detmod3, MASK_DETMODE3H_USBWKM);
		pwc_write(PWC_FMASK3, pwc->fmask3, MASK_USBWAKINT);
		pwc_write(PWC_BMASK3, pwc->bmask3, MASK_USBWAKINT);
#else   /* CONFIG_MACH_PGPF */ 
		pgpf_restore_pwc_interruption_setting();
#endif  /* CONFIG_MACH_PGPF */ 

#ifdef IDLE_DEBUG_LOG
		DPRINTK("GPIO_GP_IIML = 0x%08x\n", inl(GPIO_GP_IIML));
		DPRINTK("GPIO_GP_IIMH = 0x%08x\n", inl(GPIO_GP_IIMH));
		DPRINTK("GPIO_GP_IIMHH = 0x%08x\n", inl(GPIO_GP_IIMHH));
		DPRINTK("GPIO_GP_IIMHHH = 0x%08x\n", inl(GPIO_GP_IIMHHH));
#endif
		break;
	}
	case MP200_PMU_CLK_SLEEP :
	case MP200_PMU_CLK_POWERDOWN :
	{
#ifdef IDLE_DEBUG_LOG
		DPRINTK("Sleep or PowerDown\n");
#endif
		gpio->ien0 = inl(GPIO_GP_IIML);
		gpio->ien1 = inl(GPIO_GP_IIMH);
		gpio->ien2 = inl(GPIO_GP_IIMHH);
		gpio->ien3 = inl(GPIO_GP_IIMHHH);

		outl(MASK_GPIO_ALL, GPIO_GP_IDSL);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSH);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSHH);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSHHH);

		outl(GPIO_INT_PWRIC, GPIO_GP_IENL);

#ifndef CONFIG_MACH_PGPF
		pwr_reg_read(PWC_FMASK1, &pwc->fmask1);
		pwr_reg_read(PWC_BMASK1, &pwc->bmask1);
		pwr_reg_read(PWC_IOOUT1, &pwc->ioout1);

		pwr_reg_read(PWC_FMASK2, &pwc->fmask2);
		pwr_reg_read(PWC_BMASK2, &pwc->bmask2);

		pwr_reg_read(PWC_FMASK3, &pwc->fmask3);
		pwr_reg_read(PWC_BMASK3, &pwc->bmask3);
		pwr_reg_read(PWC_DETMOD3H, &pwc->detmod3);
#else   /* CONFIG_MACH_PGPF */
		pgpf_save_pwc_interruption_setting();
#endif  /* CONFIG_MACH_PGPF */

		if(flag == MP200_PMU_CLK_POWERDOWN){
			pwc_write(PWC_WAKECONT, WAKECONT_WAKEWAIT_DISABLE,
				MASK_WAKECONT_WAKEWAIT);
		}

#ifndef CONFIG_MACH_PGPF
		pwc_write(PWC_STATE1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA);
		
		pwc_write(PWC_FMASK1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA);
		pwc_write(PWC_CLRFACT1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA);
		pwc_write(PWC_BMASK1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA);
		pwc_write(PWC_IOOUT1, MASK_GPIO_RESUME_KEY, MASK_GPIO_KEYSCAN);
		pwc_write(PWC_FMASK2, DETECT_OFF, PWC_SD_DETECT);
		pwc_write(PWC_BMASK2, DETECT_OFF, PWC_SD_DETECT);

#else   /* CONFIG_MACH_PGPF */
		pgpf_set_wakeup_resource();
#endif  /* CONFIG_MACH_PGPF */

#ifdef IDLE_DEBUG_LOG
		DPRINTK("fmask1 = 0x%08x\n", pwc->fmask1);
		DPRINTK("clrfact1 = 0x%08x\n", pwc->clrfact1);
		DPRINTK("bmask1 = 0x%08x\n", pwc->bmask1);
		DPRINTK("ioout1 = 0x%08x\n", pwc->ioout1);
#endif
#if 0
		pwc_write(PWC_FMASK3, MASK_USBWAKINT, MASK_USBWAKINT);
		pwc_write(PWC_DETMOD3H, DETMODE3H_USBWKM_RISE, MASK_DETMODE3H_USBWKM);
		pwc_write(PWC_CLRFACT3, MASK_USBWAKINT, MASK_USBWAKINT);
		pwc_write(PWC_BMASK3, MASK_USBWAKINT, MASK_USBWAKINT);
#endif
#ifdef IDLE_DEBUG_LOG
		DPRINTK("save_state ien0 = 0x%08x\n", gpio->ien0);
		DPRINTK("save_state ien1 = 0x%08x\n", gpio->ien1);
		DPRINTK("save_state ien2 = 0x%08x\n", gpio->ien2);
		DPRINTK("save_state ien3 = 0x%08x\n", gpio->ien3);
#endif
		break;
	}
	case MP200_PMU_CLK_POWEROFF:
	{
		outl(MASK_GPIO_ALL, GPIO_GP_IDSL);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSH);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSHH);
		outl(MASK_GPIO_ALL, GPIO_GP_IDSHHH);
		break;
	}
	default:
		return -EINVAL;
	}
	return 0;
}

/*
 * REGGP3(for eMMC/SD) power control
 *
 */
static int pmu_emmc_pw_ctrl(int power)
{
	struct chg_state *state = &register_state.chg;

	switch (power) {
	case PMU_EMMC_POWER_OFF :
#ifdef IDLE_DEBUG_LOG
		DPRINTK("power = PMU_EMMC_POWER_OFF\n");
#endif
		state->pinsel_g80  = inl(CHG_PINSEL_G80);
		state->pinsel_g112 = inl(CHG_PINSEL_G112);
		outl((state->pinsel_g80 & ~CHG_PIN_G80_SD0SD2), CHG_PINSEL_G80);
		outl(CHG_PIN_G112_GIO, CHG_PINSEL_G112);
#ifdef IDLE_DEBUG_LOG
		DPRINTK("Save:CHG_PINSEL_G80  = 0x%08x -> 0x%08x\n", state->pinsel_g80, inl(CHG_PINSEL_G80));
		DPRINTK("Save:CHG_PINSEL_G112 = 0x%08x -> 0x%08x\n", state->pinsel_g112, inl(CHG_PINSEL_G112));
#endif
		pwc_write(PWC_PSCNT2, PWC_POWER_OFF, PWC_REGGP3);
		break;
	case PMU_EMMC_POWER_ON :
#ifdef IDLE_DEBUG_LOG
		DPRINTK("power = PMU_EMMC_POWER_ON\n");
#endif
		pwc_write(PWC_PSCNT2, PWC_POWER_ON, PWC_REGGP3);
		outl(state->pinsel_g80,  CHG_PINSEL_G80);
		outl(state->pinsel_g112, CHG_PINSEL_G112);
#ifdef IDLE_DEBUG_LOG
		DPRINTK("Restore:CHG_PINSEL_G80  = 0x%08x\n", inl(CHG_PINSEL_G80));
		DPRINTK("Restore:CHG_PINSEL_G112 = 0x%08x\n", inl(CHG_PINSEL_G112));
#endif
		break;
	default :
		return -EINVAL;
	}

	return 0;
}

/*
 * Set PMU Command Sequence
 *
 */
static void pmu_set_command_sequence(unsigned int sleep_flag)
{
	unsigned tmp_pc;
	unsigned int* pmu_cmd_adr;

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_MAIN);

	/******************************************************************/
	/********** PowerOffSequence (Sleep/DeepSleep/PowerOff) ***********/
	/******************************************************************/
	/* M-1 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_POWERSW_ENA, 0x000fff05, pmu_cmd_adr);
	/* M-2 */
	PMU_CMD_RWM(ASMU_MACRO, SMU_CMD_QR_ENA, 0x00000002, 0x00000002, pmu_cmd_adr);
	PMU_CMD_QR_WAIT(PMU_QR_WAIT_BACKUP, pmu_cmd_adr);
	/* M-3 */
	PMU_CMD_INT_MASK(PMU_INT_MASK, pmu_cmd_adr);
	/* M-5 */
	PMU_CMD_REG_WRITE(CHG_MACRO, CHG_CMD_CHG_L1_HOLD, 0x00000001, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(CHG_MACRO, CHG_CMD_CHG_L1_HOLD, 0x00000003, pmu_cmd_adr);

	/* M-6 */ 
	if( (sleep_flag & MP200_PMU_CLK_MASK) != MP200_PMU_CLK_POWEROFF ){
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_STATE8, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000003, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
	}
	else {
		PMU_CMD_SUBROUTINE_START(PMU_PC_MEMC_DEEP_POWERDOWN, pmu_cmd_adr);
	}

	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_IO_L0_LM_BUZ, 0x00000000, pmu_cmd_adr);
	PMU_CMD_SUBROUTINE_START(PMU_PC_MEMC1, pmu_cmd_adr);
	PMU_CMD_SUBROUTINE_START(PMU_PC_L1POWEROFF, pmu_cmd_adr);
	PMU_CMD_SUBROUTINE_START(PMU_PC_L2POWEROFF, pmu_cmd_adr);

	/* M-7 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_MEMC_HAND_SHAKE_FAKE, 0x00000001, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ2ENA, 0x0000000a, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ2, 0x00000000, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ2ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);

	/* M-8 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000005, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);

	/* M-9 */
	tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
	PMU_CMD_REG_READ(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_AND(0x00000f00, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_CMP2(0x00000500, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
	/* M-10 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000006, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
	/* M-11 */
	tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
	PMU_CMD_REG_READ(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_AND(0x00000f00, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_CMP2(0x00000600, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
	/* M-12 */
	if((sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_POWERDOWN) {
		PMU_CMD_AJUMP(PMU_PC_POWERDOWN , pmu_cmd_adr);
	}
	else if( (sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_POWEROFF ) {
		PMU_CMD_AJUMP(PMU_PC_POWEROFF , pmu_cmd_adr);
	} else {
		PMU_CMD_AJUMP(PMU_PC_SLEEP , pmu_cmd_adr);
	}

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_SLEEP);
	/***************************/
	/********** Sleep **********/
	/***************************/
	if((sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_SLEEP) {
		/* SLP-1 */
		PMU_CMD_WDT_STOP(pmu_cmd_adr);
		/* SLP-2 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000007, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
		/* SLP-3 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_PLL1CTRL1, 0x000000ff, pmu_cmd_adr);
		/* SLP-4 */
		PMU_CMD_CYCLE_WAIT(0x1b0, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
		/* SLP-5 Wait INTC */
		PMU_CMD_TRIG_WAIT(1, PMU_TRIG_INT, pmu_cmd_adr);
		/* SLP-6 */
		PMU_CMD_WDT_RESTART(pmu_cmd_adr);
		/* SLP-7 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000000, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
		/* SLP-8 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_PLL1CTRL1, 0x00000000, pmu_cmd_adr);
		/* SLP-9 */
		PMU_CMD_AJUMP(PMU_PC_POWER_ON_SEQUENCE, pmu_cmd_adr);
	}

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_POWERDOWN);
	/***************************/
	/******** PowerDown ********/
	/***************************/
	if((sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_POWERDOWN) {
		/* PWRDWN-1 */
		PMU_CMD_SUBROUTINE_START(PMU_PC_SPI_ENABLE, pmu_cmd_adr);
		/* PWRDWN-2 */
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_TX_DATA, 0x00006e03, pmu_cmd_adr);
		PMU_CMD_SP0_WRITE(SPI_CMD_SPx_CONTROL, 0x00000009, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
		/* PWRDWN-3 */
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_TX_DATA, 0x00009202, pmu_cmd_adr);
		PMU_CMD_SP0_WRITE(SPI_CMD_SPx_CONTROL, 0x00000009, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
		/* PWRDWN-4 */
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_TX_DATA, 0x00000aa3, pmu_cmd_adr);
		PMU_CMD_SP0_WRITE(SPI_CMD_SPx_CONTROL, 0x00000009, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
		/* PWRDWN-5 */
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_TX_DATA, 0x0000021d, pmu_cmd_adr);
		PMU_CMD_SP0_WRITE(SPI_CMD_SPx_CONTROL, 0x00000009, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
		/* PWRDWN-6 */
		PMU_CMD_SUBROUTINE_START(PMU_PC_SPI_DISABLE, pmu_cmd_adr);
		/* PWRDWN-7 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_AUTO_MODE_EN, 0x00020100, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* PWRDWN-8 */
		PMU_CMD_WDT_STOP(pmu_cmd_adr);
		/* PWRDWN-9 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000008, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
		/* PWRDWN-10 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_PLL3CTRL1, 0x000000ff, pmu_cmd_adr);
		/* PWRDWN-11 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_PLL1CTRL1, 0x000000ff, pmu_cmd_adr);
		/* PWRDWN-12 */
		PMU_CMD_TRIG_WAIT(1, PMU_TRIG_INT, pmu_cmd_adr);
		/* PWRDWN-13 */
		PMU_CMD_WDT_RESTART(pmu_cmd_adr);
		/* PWRDWN-14 */
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
		/* PWRDWN-15 */
		PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_AUTO_MODE_EN, 0x00000000, pmu_cmd_adr);
		/* PWRDWN-16 */
		PMU_CMD_SUBROUTINE_START(PMU_PC_SPI_ENABLE, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_TX_DATA, 0x00009200, pmu_cmd_adr);
		PMU_CMD_SP0_WRITE(SPI_CMD_SPx_CONTROL, 0x00000009, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
		PMU_CMD_SUBROUTINE_START(PMU_PC_SPI_DISABLE, pmu_cmd_adr);
		/* PWRDWN-17 */
		PMU_CMD_AJUMP(PMU_PC_POWER_ON_SEQUENCE, pmu_cmd_adr);
	}

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_POWEROFF);
	/***************************/
	/******** POWEROFF *********/
	/***************************/
	if((sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_POWEROFF) {
		/* PWOFF-1 */
		PMU_CMD_SUBROUTINE_START(PMU_PC_SPI_ENABLE, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_TX_DATA, 0x0000021c, pmu_cmd_adr);
		PMU_CMD_SP0_WRITE(SPI_CMD_SPx_CONTROL, 0x00000009, pmu_cmd_adr);
		PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
		PMU_CMD_SUBROUTINE_START(PMU_PC_SPI_DISABLE, pmu_cmd_adr);
		/* PWOFF-2 */
		PMU_CMD_INTWAIT(pmu_cmd_adr)
	}

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_POWER_ON_SEQUENCE);
	/***************************/
	/**** Power On Sequence ****/
	/***************************/
	/* PWRON-1 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000005, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
	/* PWRON-2 */
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);

	/* PWRON-3*/
	PMU_CMD_SUBROUTINE_START(PMU_PC_L2POWERON, pmu_cmd_adr);
	PMU_CMD_SUBROUTINE_START(PMU_PC_L1POWERON, pmu_cmd_adr);

	/* PWRON-4 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ0ENA, 0xbffeef3f, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ1ENA, 0x7feb3fff, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ2ENA, 0x0000167f, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ3ENA, 0x0000001c, pmu_cmd_adr);

	/* PWRON-5 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_MEMC_HAND_SHAKE_FAKE, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(CHG_MACRO, CHG_CMD_CHG_L1_HOLD, 0x00000001, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x2b0, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);

	/* PWRON-6 */
	tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
	PMU_CMD_REG_READ(ASMU_MACRO, SMU_CMD_POWERSW_STATUS, PMU_REGA, pmu_cmd_adr);
	PMU_CMD_AND(0x00000001, PMU_REGA, pmu_cmd_adr);
	PMU_CMD_CMP2(0x00000001, PMU_REGA, pmu_cmd_adr);
	PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
	/* PWRON-7 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL0ENA, 0x760ffce3, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL0, 0x760ffce3, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL0ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL1ENA, 0xffffdff7, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL1, 0xffffdff7, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL1ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL2ENA, 0x67ff79fe, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL2, 0x67ff79fe, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL2ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3ENA, 0xfff87fff, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3, 0xfff87fff, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL4ENA, 0x000003e0, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL4, 0x000003e0, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL4ENA, 0x00000000, pmu_cmd_adr);
	/* PWRON-8 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ0, register_state.smu.resetreq0, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ1, register_state.smu.resetreq1, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ2, register_state.smu.resetreq2, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ3, register_state.smu.resetreq3, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ0ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ1ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ2ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_RESETREQ3ENA, 0x00000000, pmu_cmd_adr);
	/* PWRON-9 */
	PMU_CMD_SUBROUTINE_START(PMU_PC_MEMC2, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x0000009b, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_IO_L0_LM_BUZ, 0x00000101, pmu_cmd_adr);
	/* PWRON-11 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_CLK_MODE_SEL, 0x00000001, pmu_cmd_adr);
	PMU_CMD_NOP(pmu_cmd_adr);
	if((sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_POWERDOWN) {
		PMU_CMD_SMU_READY_WAIT(PMU_HIGH_LEVEL, pmu_cmd_adr);
	} else {
		PMU_CMD_NOP(pmu_cmd_adr);
	}

	/* PWRON-12 */
	PMU_CMD_AJUMP(PMU_PC_POWER_ON_PC, pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_POWER_ON_PC);
	/***************************/
	/******* Power On PC *******/
	/***************************/
	/* PWRON_PC-1 */
	PMU_CMD_REG_READ(ASMU_MACRO, SMU_CMD_QR_ENA, PMU_REGA, pmu_cmd_adr);
	PMU_CMD_AND(0x00000100, PMU_REGA, pmu_cmd_adr);
	PMU_CMD_CMP2(0x00000100, PMU_REGA, pmu_cmd_adr);
	tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
	PMU_CMD_BRANCH((tmp_pc + 0x10), PMU_BNE, pmu_cmd_adr);
	PMU_CMD_RWM(ASMU_MACRO, SMU_CMD_QR_ENA, 0x00000002, 0x00000002, pmu_cmd_adr);
	/* PWRON_PC-2 */
	PMU_CMD_ARMINT_MASK(PMU_INT_UNMASK, pmu_cmd_adr);
	/* PWRON_PC-3 */
	PMU_CMD_QR_WAIT(PMU_QR_WAIT_RESTORE, pmu_cmd_adr);
	/* PWRON_PC-4 */
	PMU_CMD_RWM(ASMU_MACRO, SMU_CMD_QR_ENA, 0x00000100, 0x00000100, pmu_cmd_adr);

	PMU_CMD_PMU_END(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_SPI_ENABLE);
	/***************************/
	/******** SPI Enable *******/
	/***************************/
	/* SPIEN-1 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3ENA, 0x00600000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3, 0x00600000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_FFCLR, 0x000000ff, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_ENSET, 0x000000ff, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_MODE, 0x00000f00, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(SPI0_MACRO, SPI_CMD_SPx_POL, SPI_POL_SP0_CS0, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_DIVSP0SCLK, 0x00000190, pmu_cmd_adr);
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_SPI_DISABLE);
	/***************************/
	/******** SPI Disable ******/
	/***************************/
	/* SPIDIS-1 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3ENA, 0x00600000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_GCLKCTRL3ENA, 0x00000000, pmu_cmd_adr);
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_L2POWEROFF);
	/******************************/
	/******** L2OFF_Sequence ******/
	/******************************/
#ifndef L2_DISABLE
	/* L2OFF-1 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_LOG2SW_ACTRLEN, 0x00000100, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x000000FF, pmu_cmd_adr);
#endif
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_L2POWERON);
	/******************************/
	/******** L2ON_Sequence *******/
	/******************************/
#ifndef L2_DISABLE
	/* L2ON-1 */
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x0000007F, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x0000003F, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x0000001F, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x0000000F, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x00000007, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x00000003, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x00000001, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x00000000, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0010, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L2_POWERSW, 0x00010100, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_LOG2SW_ACTRLEN, 0x00000000, pmu_cmd_adr);
#endif
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_MEMC1);
	/*******************************/
	/******** MEMC1_Sequence *******/
	/*******************************/
	/* MEMC1_SEQ1 */
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_CACHE_MODE, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0000), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DEGFUN, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0004), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_REQSCH, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x000c), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGF, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0010), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGA1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0014), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGA2, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0018), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x001c), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR2, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0020), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR3, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0024), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGT1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0028), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGT2, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x002c), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0030), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_MEMC2);
	/*******************************/
	/******** MEMC2_Sequence *******/
	/*******************************/
	/* MEMC2_SEQ1 */
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0000), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_CACHE_MODE, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0004), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DEGFUN, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x000c), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_REQSCH, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0010), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGF, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0014), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGA1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0018), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGA2, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x001c), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0020), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR2, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0024), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR3, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0028), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGT1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x002c), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGT2, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_READ(PMU_MACRO, (PMU_PC_USE_MEMC + 0x0030), PMU_REGB, pmu_cmd_adr);
	PMU_CMD_REG_WRITE2(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC1, PMU_REGB, pmu_cmd_adr);
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_L1POWEROFF);
	/***********************************/
	/******** PMU_PC_L1POWEROFF ********/
	/***********************************/
	/* L1OFF-1 */
#ifndef L1_AUTO_ENABLE
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_BUZ, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_BUZ2, 0x00000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000F0F, pmu_cmd_adr);
#else
	PMU_CMD_RWM(ASMU_MACRO, SMU_CMD_POWERSW_ACTRL_EN, 0x00000002, 0x00000002, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_LOG1SW_ACTRL, 0x00000000, pmu_cmd_adr);
#endif
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_L1POWERON);
	/***********************************/
	/******** PMU_PC_L1POWERON *********/
	/***********************************/
	/* L1ON-1 */
#ifndef L1_AUTO_ENABLE
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000F07, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000F03, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000F01, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000F00, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000700, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000300, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000100, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_POWERSW, 0x00000000, pmu_cmd_adr);
	PMU_CMD_CYCLE_WAIT(0x0050, PMU_WAIT_INT_CONTINUE, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_ASMU_BGCTRL, 0x01000000, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_BUZ, 0x00001111, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_L1_BUZ2, 0x00000011, pmu_cmd_adr);
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_ASMU_BGCTRL, 0x00000000, pmu_cmd_adr);
#else
	PMU_CMD_REG_WRITE(ASMU_MACRO, SMU_CMD_LOG1SW_ACTRL, 0x00005301, pmu_cmd_adr)
	PMU_CMD_RWM(ASMU_MACRO, SMU_CMD_POWERSW_ACTRL_EN, 0x00000000, 0x00000002, pmu_cmd_adr);
#endif
	PMU_CMD_RFS(pmu_cmd_adr);

	pmu_cmd_adr = (unsigned int*)PMU_PC_TO_VIRADDR(PMU_PC_MEMC_DEEP_POWERDOWN);
	/**************************************/
	/********* MEMC_DEEP_POWERDOWN ********/
	/**************************************/
	if((sleep_flag & MP200_PMU_CLK_MASK) == MP200_PMU_CLK_POWEROFF) {
		/* MEMC DPD-0 auto power down:disable*/
		PMU_CMD_RWM(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR3, 0x00000000, 0x00000101, pmu_cmd_adr); 
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);

		/* MEMC_DPD-1 Auto-SREF,Auto-CBR:disable*/ 
		PMU_CMD_RWM(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGR2, 0x00000000, 0x00000303, pmu_cmd_adr); 
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);

		/*CMD CLEAR*/
		/* ready */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x000000c0, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000000, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);


		/* MEMC_DPD-2 all bank precharge*/
		PMU_CMD_RWM(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC1, 0x00000400, 0x00000400, pmu_cmd_adr); 
		/* ready */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x00000099, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000009, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);

		/*CMD CLEAR*/
		/* ready */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x000000c0, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000000, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);

		/* MEMC_DPD-3 CKE*/
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		/* ready */
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x0000009d, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x0000000d, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);

		/*CMD CLEAR*/
		/* ready */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x000000c0, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000000, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		
		/* MEMC_DPD-5 Deep Power Down */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		/* ready */
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x0000009c, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x0000000c, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* check state */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_STATE8, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000007, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);

		/*CMD CLEAR*/
		/* ready */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000300, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		/* write */
		PMU_CMD_REG_WRITE(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, 0x000000c0, pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		PMU_CMD_NOP(pmu_cmd_adr);
		/* read */
		tmp_pc = PMU_VIRADDR_TO_PC((unsigned int)pmu_cmd_adr);
		PMU_CMD_REG_READ(MEMC_MACRO, MEMC_CMD_MEMC_DDR_CONFIGC2, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_AND(0x0000000f, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_CMP2(0x00000000, PMU_REGB, pmu_cmd_adr);
		PMU_CMD_BRANCH(tmp_pc, PMU_BNE, pmu_cmd_adr);
		
		PMU_CMD_RFS(pmu_cmd_adr);
	}

	return;
}

/*
 * pmu_set_regs(unsigned int sleep_flag)
 *
 */
static void pmu_set_regs(unsigned int sleep_flag)
{
	unsigned int regval;

	/* pmu command sequence set */
	pmu_set_command_sequence(sleep_flag);

	/* pmu_pc and pmu_wdt set */
	outl(PMU_PC_MAIN, PMU_PC);

	/* This doesn't use */
	outl(PMU_PC_POWER_ON_SEQUENCE, PMU_POWER_ON_PC);

	outl(PMU_WDT_ENABLE, PMU_WDT_COUNT_EN);
	outl(PMU_WDT_MAX_COUNT, PMU_WDT_COUNT_LMT);

	/* pmu start */
	outl(PMU_START_SET, PMU_START);
	do {
		regval = inl(PMU_START);
	} while ((regval & PMU_START_SET) != PMU_START_SET);

#ifdef IDLE_DEBUG_LOG
	DPRINTK("PMU_PC           =0x%08x \n", inl(PMU_PC));
	DPRINTK("PMU_POWER_ON_PC  =0x%08x \n", inl(PMU_POWER_ON_PC));
	DPRINTK("PMU_WDT_COUNT_EN =0x%08x \n", inl(PMU_WDT_COUNT_EN));
	DPRINTK("PMU_WDT_COUNT_LMT=0x%08x \n", inl(PMU_WDT_COUNT_LMT));
	DPRINTK("PMU_START        =0x%08x \n", inl(PMU_START));
#endif
}

static void pmu_save_state(void)
{
	/* SMU state save */
	register_state.smu.resetreq0   = inl(SMU_RESETREQ0);
	register_state.smu.resetreq1   = inl(SMU_RESETREQ1);
	register_state.smu.resetreq2   = inl(SMU_RESETREQ2);
	register_state.smu.resetreq3   = inl(SMU_RESETREQ3);
	register_state.smu.clkctrl	   = inl(SMU_CLKCTRL);
	register_state.smu.clkctrl1	   = inl(SMU_CLKCTRL1);
	register_state.smu.gclkctrl0	   = inl(SMU_GCLKCTRL0);
	register_state.smu.gclkctrl1	   = inl(SMU_GCLKCTRL1);
	register_state.smu.gclkctrl2	   = inl(SMU_GCLKCTRL2);
	register_state.smu.gclkctrl3	   = inl(SMU_GCLKCTRL3);
	register_state.smu.gclkctrl4	   = inl(SMU_GCLKCTRL4);
	register_state.smu.auto_frq_change = inl(SMU_AUTO_FRQ_CHANGE);
	register_state.memc.configr2	   = inl(MEMC_DDR_CONFIGR2);

#ifdef IDLE_DEBUG_LOG
	DPRINTK("SMU_AHBCLKCTRL0   =0x%08x\n", inl(SMU_AHBCLKCTRL0));
	DPRINTK("SMU_AHBCLKCTRL1   =0x%08x\n", inl(SMU_AHBCLKCTRL1));
	DPRINTK("SMU_APBCLKCTRL0   =0x%08x\n", inl(SMU_APBCLKCTRL0));
	DPRINTK("SMU_APBCLKCTRL1   =0x%08x\n", inl(SMU_APBCLKCTRL1));
	DPRINTK("SMU_RESETREQ0   =0x%08x\n", register_state.smu.resetreq0);
	DPRINTK("SMU_RESETREQ1   =0x%08x\n", register_state.smu.resetreq1);
	DPRINTK("SMU_RESETREQ2   =0x%08x\n", register_state.smu.resetreq2);
	DPRINTK("SMU_RESETREQ3   =0x%08x\n", register_state.smu.resetreq3);
	DPRINTK("SMU_CLKCTRL         =0x%08x\n", register_state.smu.clkctrl);
	DPRINTK("SMU_CLKCTRL1         =0x%08x\n", register_state.smu.clkctrl1);
	DPRINTK("SMU_GCLKCTRL0       =0x%08x\n", register_state.smu.gclkctrl0);
	DPRINTK("SMU_GCLKCTRL1       =0x%08x\n", register_state.smu.gclkctrl1);
	DPRINTK("SMU_GCLKCTRL2       =0x%08x\n", register_state.smu.gclkctrl2);
	DPRINTK("SMU_GCLKCTRL3       =0x%08x\n", register_state.smu.gclkctrl3);
	DPRINTK("SMU_GCLKCTRL4       =0x%08x\n", register_state.smu.gclkctrl4);
	DPRINTK("SMU_AUTO_FRQ_CHANGE =0x%08x\n", register_state.smu.auto_frq_change);
	DPRINTK("MEMC_DDR_CONFIGR2 = 0x%08x\n", inl(MEMC_DDR_CONFIGR2));
#endif
}

static void pmu_restore_state(void)
{
	outl(register_state.memc.configr2,	 MEMC_DDR_CONFIGR2);
	outl(register_state.smu.auto_frq_change, SMU_AUTO_FRQ_CHANGE);
	outl(register_state.smu.clkctrl,	 SMU_CLKCTRL);
	outl(register_state.smu.clkctrl1,	 SMU_CLKCTRL1);
	outl(SMU_ENA_ALL,			 SMU_GCLKCTRL0ENA);
	outl(register_state.smu.gclkctrl0,	 SMU_GCLKCTRL0);
	outl(SMU_ENA_CLEAR,			 SMU_GCLKCTRL0ENA);
	outl(SMU_ENA_ALL,			 SMU_GCLKCTRL1ENA);
	outl(register_state.smu.gclkctrl1,	 SMU_GCLKCTRL1);
	outl(SMU_ENA_CLEAR,			 SMU_GCLKCTRL1ENA);
	outl(SMU_ENA_ALL,			 SMU_GCLKCTRL2ENA);
	outl(register_state.smu.gclkctrl2,	 SMU_GCLKCTRL2);
	outl(SMU_ENA_CLEAR,			 SMU_GCLKCTRL2ENA);
	outl(SMU_ENA_ALL,			 SMU_GCLKCTRL3ENA);
	outl(register_state.smu.gclkctrl3,	 SMU_GCLKCTRL3);
	outl(SMU_ENA_CLEAR,			 SMU_GCLKCTRL3ENA);
	outl(SMU_ENA_ALL,			 SMU_GCLKCTRL4ENA);
	outl(register_state.smu.gclkctrl4,	 SMU_GCLKCTRL4);
	outl(SMU_ENA_CLEAR,			 SMU_GCLKCTRL4ENA);

#ifdef IDLE_DEBUG_LOG
	DPRINTK("MEMC_DDR_CONFIGR2 = 0x%08x\n", inl(MEMC_DDR_CONFIGR2));
	DPRINTK("SMU_AHBCLKCTRL0   =0x%08x\n", inl(SMU_AHBCLKCTRL0));
	DPRINTK("SMU_AHBCLKCTRL1   =0x%08x\n", inl(SMU_AHBCLKCTRL1));
	DPRINTK("SMU_APBCLKCTRL0   =0x%08x\n", inl(SMU_APBCLKCTRL0));
	DPRINTK("SMU_APBCLKCTRL1   =0x%08x\n", inl(SMU_APBCLKCTRL1));
	DPRINTK("SMU_RESETREQ0   =0x%08x\n", inl(SMU_RESETREQ0));
	DPRINTK("SMU_RESETREQ1   =0x%08x\n", inl(SMU_RESETREQ1));
	DPRINTK("SMU_RESETREQ2   =0x%08x\n", inl(SMU_RESETREQ2));
	DPRINTK("SMU_RESETREQ3   =0x%08x\n", inl(SMU_RESETREQ3));
	DPRINTK("SMU_CLKCTRL         =0x%08x\n", inl(SMU_CLKCTRL));
	DPRINTK("SMU_CLKCTRL1         =0x%08x\n", inl(SMU_CLKCTRL1));
	DPRINTK("SMU_GCLKCTRL0       =0x%08x\n", inl(SMU_GCLKCTRL0));
	DPRINTK("SMU_GCLKCTRL1       =0x%08x\n", inl(SMU_GCLKCTRL1));
	DPRINTK("SMU_GCLKCTRL2       =0x%08x\n", inl(SMU_GCLKCTRL2));
	DPRINTK("SMU_GCLKCTRL3       =0x%08x\n", inl(SMU_GCLKCTRL3));
	DPRINTK("SMU_GCLKCTRL4       =0x%08x\n", inl(SMU_GCLKCTRL4));
	DPRINTK("SMU_AUTO_FRQ_CHANGE =0x%08x\n", inl(SMU_AUTO_FRQ_CHANGE));
#endif

}

/*
 * Wait for Interrupt
 *
 */
void mp200_cpu_do_idle(unsigned int pmu_boot)
{
	unsigned long val;

	outl(0x00530101, SMU_QR_ENA); /* PMU BOOT */

	val = (inl(SMU_POWERSW_ENA) & ~0x000fff00);
	val |= 0x000fff00;
	outl(val, SMU_POWERSW_ENA);

#ifdef IDLE_DEBUG_LOG
	DPRINTK("SMU_QR_ENA =0x%08x\n", inl(SMU_QR_ENA));
#endif

	/* WFI */
	cpu_do_idle();

	/* Clear PMU boot bit */
	if (inl(PMU_START)) {
		outl(0x00000000, PMU_START);
	}
	return;
}

/*
 * Restore Async Bus Register.
 * This function is copied onto RAM.
 */
static void restore_state_async_bus_func(void)
{
	outl(async_bus_state_cs0.base_addr ,AB0_CS0BASEADD);
	outl(async_bus_state_cs0.bitcomp ,AB0_CS0BITCOMP);
	outl(async_bus_state_cs0.waitctrl ,AB0_CS0WAITCTRL);
	outl(async_bus_state_cs0.waitctrl_w ,AB0_CS0WAITCTRL_W);
	outl(async_bus_state_cs0.readctrl ,AB0_CS0READCTRL);
	outl(async_bus_state_cs0.control ,AB0_CS0CONTROL);

	outl(async_bus_state_cs1.base_addr ,AB0_CS1BASEADD);
	outl(async_bus_state_cs1.bitcomp ,AB0_CS1BITCOMP);
	outl(async_bus_state_cs1.waitctrl ,AB0_CS1WAITCTRL);
	outl(async_bus_state_cs1.waitctrl_w ,AB0_CS1WAITCTRL_W);
	outl(async_bus_state_cs1.readctrl ,AB0_CS1READCTRL);
	outl(async_bus_state_cs1.control ,AB0_CS1CONTROL);

	outl(async_bus_state_cs2.base_addr ,AB0_CS2BASEADD);
	outl(async_bus_state_cs2.bitcomp ,AB0_CS2BITCOMP);
	outl(async_bus_state_cs2.waitctrl ,AB0_CS2WAITCTRL);
	outl(async_bus_state_cs2.waitctrl_w ,AB0_CS2WAITCTRL_W);
	outl(async_bus_state_cs2.readctrl ,AB0_CS2READCTRL);
	outl(async_bus_state_cs2.control ,AB0_CS2CONTROL);

	outl(async_bus_state_cs3.base_addr ,AB0_CS3BASEADD);
	outl(async_bus_state_cs3.bitcomp ,AB0_CS3BITCOMP);
	outl(async_bus_state_cs3.waitctrl ,AB0_CS3WAITCTRL);
	outl(async_bus_state_cs3.waitctrl_w ,AB0_CS3WAITCTRL_W);
	outl(async_bus_state_cs3.readctrl ,AB0_CS3READCTRL);
	outl(async_bus_state_cs3.control ,AB0_CS3CONTROL);

	outl(0x00000009 ,AB0_FLASHCOMSET);
}

/* Dummy function */
static void restore_state_async_bus_after_func(void){};

/*
 * Save Async Bus Register.
 *
 */
static void save_state_async_bus(void)
{
	async_bus_state_cs0.base_addr = inl(AB0_CS0BASEADD);
	async_bus_state_cs0.bitcomp = inl(AB0_CS0BITCOMP);
	async_bus_state_cs0.waitctrl = inl(AB0_CS0WAITCTRL);
	async_bus_state_cs0.waitctrl_w = inl(AB0_CS0WAITCTRL_W);
	async_bus_state_cs0.readctrl = inl(AB0_CS0READCTRL);
	async_bus_state_cs0.control = inl(AB0_CS0CONTROL);

	async_bus_state_cs1.base_addr = inl(AB0_CS1BASEADD);
	async_bus_state_cs1.bitcomp = inl(AB0_CS1BITCOMP);
	async_bus_state_cs1.waitctrl = inl(AB0_CS1WAITCTRL);
	async_bus_state_cs1.waitctrl_w = inl(AB0_CS1WAITCTRL_W);
	async_bus_state_cs1.readctrl = inl(AB0_CS1READCTRL);
	async_bus_state_cs1.control = inl(AB0_CS1CONTROL);

	async_bus_state_cs2.base_addr = inl(AB0_CS2BASEADD);
	async_bus_state_cs2.bitcomp = inl(AB0_CS2BITCOMP);
	async_bus_state_cs2.waitctrl = inl(AB0_CS2WAITCTRL);
	async_bus_state_cs2.waitctrl_w = inl(AB0_CS2WAITCTRL_W);
	async_bus_state_cs2.readctrl = inl(AB0_CS2READCTRL);
	async_bus_state_cs2.control = inl(AB0_CS2CONTROL);

	async_bus_state_cs3.base_addr = inl(AB0_CS3BASEADD);
	async_bus_state_cs3.bitcomp = inl(AB0_CS3BITCOMP);
	async_bus_state_cs3.waitctrl = inl(AB0_CS3WAITCTRL);
	async_bus_state_cs3.waitctrl_w = inl(AB0_CS3WAITCTRL_W);
	async_bus_state_cs3.readctrl = inl(AB0_CS3READCTRL);
	async_bus_state_cs3.control = inl(AB0_CS3CONTROL);
}

static int tm2_int_ct = 0;

/*
 * pmu_do_suspend()
 *
 */
static void pmu_do_suspend(unsigned int sleep_flag)
{
#ifdef CONFIG_MP200_RTC_DEV
	struct rtc_time rt;
	unsigned long mkt;
#endif

	extern void pm_change_normalA(void);

	/* INTC Disable */
	pmu_intc_mask(PMU_INTC_MASK_SAVE_AND_MASK);

	if (!mp200_sleep_while_idle) {
#ifdef CONFIG_MP200_RTC_DEV
		memset(&rt, 0, sizeof(struct rtc_time));
		get_rtc_time(&rt);
		mkt = mktime(rt.tm_year + 1900, rt.tm_mon + 1, rt.tm_mday, rt.tm_hour,
			     rt.tm_min, rt.tm_sec);
		rtc_offset = (long)(xtime.tv_sec - mkt);
#endif
		timer_set_clock(TIMER_SUSPEND);
		/* Disable GPIO Interrupt & Set PWC Resume Interrupt */
		pmu_gpio_mask(sleep_flag & MP200_PMU_CLK_MASK);
		/* eMMC/SD power off */
		pmu_emmc_pw_ctrl(PMU_EMMC_POWER_OFF);
	} else {
		timer_set_clock(TIMER_SUSPEND_PDMA);
		mp200_pmu_open_clockgate(MP200_CLOCKGATE_TI2_TIN);
		tm2_int_ct = 0;
		writel(0x0, TIMER2_RCR);
		writel(0x7, TIMER2_OP);
	}

	/* save registers */
	pmu_save_state();

	/* NORMALA mode */
	pm_change_normalA();

	/* PMU registers setting and boot */
	pmu_set_regs(sleep_flag);

	/* WDT stop */
	wdt_op_reg = inl(WDT_OP);
	if (wdt_op_reg & 0x1) { /* TM_EN */
#ifdef IDLE_DEBUG_LOG
		DPRINTK("disable WDT\n");
#endif
		mp200_wdt_disable();
	}

	/* Auto Frq Change Disable */
	outl(inl(SMU_AUTO_FRQ_CHANGE) & ~0x00000001, SMU_AUTO_FRQ_CHANGE);

	/* SPI SCLK Clock Ctrl Off */
	outl(inl(SMU_CLKCTRL) & ~(SMU_CLKCTRL_SP0SCLKLP | SMU_CLKCTRL_SP1SCLKLP | SMU_CLKCTRL_SP2SCLKLP), SMU_CLKCTRL);

#ifdef IDLE_DEBUG_LOG
	DPRINTK("SMU_CLKCTRL         =0x%08x\n", inl(SMU_CLKCTRL));
	DPRINTK("SMU_AUTO_FRQ_CHANGE =0x%08x\n", inl(SMU_AUTO_FRQ_CHANGE));
#endif

#ifdef IDLE_DEBUG_TW1_WAKEUP
	tw1_test_wakeup();
#endif

	/* Auto Self Reflesh enable by PM */
	outl((inl(MEMC_DDR_CONFIGR2) & ~0x000000FC) | 0x0000001E , MEMC_DDR_CONFIGR2);

#ifdef CONFIG_MACH_PGPF
	pgpf_set_gpio_setting_suspend();
#endif

	/* QR Boot & WFI */
	mp200_cpu_do_idle(MP200_PMU_BOOT);

#ifdef CONFIG_MACH_PGPF
	pgpf_set_gpio_setting_resume();
#endif

	return;
}

/*
 * pmu_do_resume()
 *
 */
static void pmu_do_resume(void)
{
#ifdef CONFIG_MP200_RTC_DEV
	struct rtc_time rt;
	unsigned long mkt;
#endif

#ifdef IDLE_DEBUG_LOG
	DPRINTK("resume start... \n");
#endif

	restore_state_async_bus();

	/* restore registers */
	pmu_restore_state();

	if (!mp200_sleep_while_idle) {
		/* eMMC/SD power on */
		pmu_emmc_pw_ctrl(PMU_EMMC_POWER_ON);
		/* Restore GPIO/PWC Interrupt */
		pmu_gpio_mask(MP200_PMU_CLK_FULLSPEED);
	}
	
	/* INTC restore */
	pmu_intc_mask(PMU_INTC_MASK_RESTORE);

	timer_set_clock_parm(TIMER_FULLSPEED);
	if (!mp200_sleep_while_idle) {
#ifdef CONFIG_MP200_RTC_DEV
		get_rtc_time(&rt);
		mkt = mktime(rt.tm_year + 1900, rt.tm_mon + 1, rt.tm_mday, rt.tm_hour,
			     rt.tm_min, rt.tm_sec);
		xtime.tv_sec = mkt + rtc_offset;
#endif
		timer_set_clock(TIMER_RESUME);
	} else {
		unsigned int tim;
		uint64_t nsecs;

		tim = readl(TIMER2_RCR);
		writel(0x0, TIMER2_OP);
		mp200_pmu_close_clockgate(MP200_CLOCKGATE_TI2_TIN);
		if( readl(INTC_IT0_RAW1) & TI2_INT ) {
			tim += TIMER2_INT_220MS;
		}
		nsecs = (uint64_t) tim * 1000000000ULL;
		
		do_div(nsecs, TIMER_CLOCK_TICK_RATE_PLL3);
		if (((uint64_t)xtime.tv_nsec + (uint64_t)nsecs) >= 1000000000ULL) {
			xtime.tv_sec++;
			xtime.tv_nsec = nsecs - (1000000000ULL - xtime.tv_nsec);
		} else {
			xtime.tv_nsec += nsecs;
		}
		nsecs *= HZ;
		do_div(nsecs, (1000 * USEC_PER_SEC));
		jiffies_64 += nsecs;
		timer_set_clock(TIMER_RESUME_PDMA);
	}

	/* WDT start */
	if (wdt_op_reg & 0x1) {
		mp200_wdt_enable();
	}
}

static irqreturn_t mp200_tm_interrupt( int irq, void *dev_id )
{
	tm2_int_ct ++;
	
	mp200_pm_pdma_suspend_disable();
	
	DPRINTK("** TI2_INTERRUPT %d **\n", tm2_int_ct);

	return IRQ_HANDLED;
}

/*
 * mp200_pmu_sleep(unsigned int flag)
 */
int mp200_pmu_sleep(unsigned int sleep_flag)
{
#ifdef IDLE_DEBUG_LOG
	DPRINTK("mp200_pmu_sleep.. sleep_flag=0x%x \n", sleep_flag);
#endif

	/* suspend */
	pmu_do_suspend(sleep_flag);
	pmu_do_resume();

	return 0;
}

int mp200_pm_do_poweroff(void)
{
	unsigned int regval;

	/* setting pmu registers for poweroff */
	pmu_set_regs(MP200_PMU_CLK_POWEROFF);

	/* GPIO/Begonia Disable */
	pmu_gpio_mask(MP200_PMU_CLK_POWEROFF);

	/* INTC Disable */
	pmu_intc_mask(PMU_INTC_ALLMASK);

	/* start PMU */
	outl(PMU_START_SET, PMU_START);

	/* wait for pmu_start */
	do {
		regval = inl(PMU_START);
	} while (regval != PMU_START_SET);

	/* QR Boot & WFI */
	mp200_cpu_do_idle(MP200_PMU_BOOT);

	return 0;
}

/*
 * init
 *
 */
int __init mp200_pmu_init(void)
{
	void *saddr;
	void *daddr;
	size_t len;
	unsigned int start;
	unsigned int end;
	int ret, port;

	saddr = (void *) restore_state_async_bus_func;

	start = (unsigned int)restore_state_async_bus_func;
	end = (unsigned int)restore_state_async_bus_after_func;

	len = end - start;

#ifdef IDLE_DEBUG_LOG
	DPRINTK("len = %d\n",len);
#endif

	daddr = kmalloc(len, GFP_KERNEL);
	if (daddr == NULL) {
		return -ENOMEM;
	}

	memcpy(daddr, saddr, len);

	restore_state_async_bus = (void (*))daddr;

	save_state_async_bus();

	flush_cache_all();

	printk(KERN_INFO "Starting pmu. \n");

	mp200_pmu_open_clockgate(MP200_CLOCKGATE_TI2_TIN);
	__raw_writel( (TIMER2_INT_220MS - 1), TIMER2_SET );
	mp200_pmu_close_clockgate(MP200_CLOCKGATE_TI2_TIN);

	ret = request_irq( INT_TIMER2, &mp200_tm_interrupt, 0, "TI2_interrupt", NULL );
	if(ret != 0){
		printk("error request_irq = %d\n",ret);
		return ret;
	}
	
#ifndef CONFIG_MACH_PGPF
	/* P88-P91:SD0_DATA1-3/SD0_CKI */
	for(port=GPIO_P88; port<=GPIO_P91; port++) {
		gpio_direction_output(port, GPIO_OUTPUT_LOW);
	}
#endif /* CONFIG_MACH_PGPF */
	/* P93:SD2_CKI */
	gpio_direction_output(GPIO_P93, GPIO_OUTPUT_LOW);
	/* P112-P117:SD2_CKO/SD2_CMD/SD2_DATA0-3 */
	for(port=GPIO_P112; port<=GPIO_P117; port++) {
		gpio_direction_output(port, GPIO_OUTPUT_LOW);
	}

	return 0;
}

__initcall(mp200_pmu_init);
