/*
 * PXA910 Power Management Routines
 *
 * This software program is licensed subject to the GNU General Public License
 * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
 *
 * (C) Copyright 2009 Marvell International Ltd.
 * All Rights Reserved
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/suspend.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/cputype.h>
#include <mach/addr-map.h>
#include <mach/pm-pxa910.h>
#include <mach/regs-icu.h>
#include <mach/irqs.h>

int pxa910_set_wake(struct irq_data *data, unsigned int on)
{
	int irq = data->irq;
	struct irq_desc *desc = irq_to_desc(data->irq);
	uint32_t awucrm = 0, apcr = 0;

	if (unlikely(irq >= nr_irqs)) {
		pr_err("IRQ nubmers are out of boundary!\n");
		return -EINVAL;
	}

	if (on) {
		if (desc->action)
			desc->action->flags |= IRQF_NO_SUSPEND;
	} else {
		if (desc->action)
			desc->action->flags &= ~IRQF_NO_SUSPEND;
	}

	/* setting wakeup sources */
	switch (irq) {
	/* wakeup line 2 */
	case IRQ_PXA910_AP_GPIO:
		awucrm = MPMU_AWUCRM_WAKEUP(2);
		apcr |= MPMU_APCR_SLPWP2;
		break;
	/* wakeup line 3 */
	case IRQ_PXA910_KEYPAD:
		awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS;
		apcr |= MPMU_APCR_SLPWP3;
		break;
	case IRQ_PXA910_ROTARY:
		awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY;
		apcr |= MPMU_APCR_SLPWP3;
		break;
	case IRQ_PXA910_TRACKBALL:
		awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL;
		apcr |= MPMU_APCR_SLPWP3;
		break;
	/* wakeup line 4 */
	case IRQ_PXA910_AP1_TIMER1:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	case IRQ_PXA910_AP1_TIMER2:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	case IRQ_PXA910_AP1_TIMER3:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	case IRQ_PXA910_AP2_TIMER1:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	case IRQ_PXA910_AP2_TIMER2:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	case IRQ_PXA910_AP2_TIMER3:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	case IRQ_PXA910_RTC_ALARM:
		awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM;
		apcr |= MPMU_APCR_SLPWP4;
		break;
	/* wakeup line 5 */
	case IRQ_PXA910_USB1:
	case IRQ_PXA910_USB2:
		awucrm = MPMU_AWUCRM_WAKEUP(5);
		apcr |= MPMU_APCR_SLPWP5;
		break;
	/* wakeup line 6 */
	case IRQ_PXA910_MMC:
		awucrm = MPMU_AWUCRM_WAKEUP(6)
			| MPMU_AWUCRM_SDH1
			| MPMU_AWUCRM_SDH2;
		apcr |= MPMU_APCR_SLPWP6;
		break;
	/* wakeup line 7 */
	case IRQ_PXA910_PMIC_INT:
		awucrm = MPMU_AWUCRM_WAKEUP(7);
		apcr |= MPMU_APCR_SLPWP7;
		break;
	default:
		if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) {
			awucrm = MPMU_AWUCRM_WAKEUP(2);
			apcr |= MPMU_APCR_SLPWP2;
		} else
			printk(KERN_ERR "Error: no defined wake up source irq: %d\n",
				irq);
	}

	if (on) {
		if (awucrm) {
			awucrm |= __raw_readl(MPMU_AWUCRM);
			__raw_writel(awucrm, MPMU_AWUCRM);
		}
		if (apcr) {
			apcr = ~apcr & __raw_readl(MPMU_APCR);
			__raw_writel(apcr, MPMU_APCR);
		}
	} else {
		if (awucrm) {
			awucrm = ~awucrm & __raw_readl(MPMU_AWUCRM);
			__raw_writel(awucrm, MPMU_AWUCRM);
		}
		if (apcr) {
			apcr |= __raw_readl(MPMU_APCR);
			__raw_writel(apcr, MPMU_APCR);
		}
	}
	return 0;
}

void pxa910_pm_enter_lowpower_mode(int state)
{
	uint32_t idle_cfg, apcr;

	idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
	apcr = __raw_readl(MPMU_APCR);

	apcr &= ~(MPMU_APCR_DDRCORSD | MPMU_APCR_APBSD | MPMU_APCR_AXISD
		| MPMU_APCR_VCTCXOSD | MPMU_APCR_STBYEN);
	idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_IDLE
		| APMU_MOH_IDLE_CFG_MOH_PWRDWN);

	switch (state) {
	case POWER_MODE_UDR:
		/* only shutdown APB in UDR */
		apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD;
		/* fall through */
	case POWER_MODE_SYS_SLEEP:
		apcr |= MPMU_APCR_SLPEN;		/* set the SLPEN bit */
		apcr |= MPMU_APCR_VCTCXOSD;		/* set VCTCXOSD */
		/* fall through */
	case POWER_MODE_APPS_SLEEP:
		apcr |= MPMU_APCR_DDRCORSD;		/* set DDRCORSD */
		/* fall through */
	case POWER_MODE_APPS_IDLE:
		apcr |= MPMU_APCR_AXISD;		/* set AXISDD bit */
		/* fall through */
	case POWER_MODE_CORE_EXTIDLE:
		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_IDLE;
		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN;
		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
			| APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
		/* fall through */
	case POWER_MODE_CORE_INTIDLE:
		break;
	}

	/* program the memory controller hardware sleep type and auto wakeup */
	idle_cfg |= APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ;
	idle_cfg |= APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN;
	__raw_writel(0x0, APMU_MC_HW_SLP_TYPE);		/* auto refresh */

	/* set DSPSD, DTCMSD, BBSD, MSASLPEN */
	apcr |= MPMU_APCR_DSPSD | MPMU_APCR_DTCMSD | MPMU_APCR_BBSD
		| MPMU_APCR_MSASLPEN;

	/*always set SLEPEN bit mainly for MSA*/
	apcr |= MPMU_APCR_SLPEN;

	/* finally write the registers back */
	__raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
	__raw_writel(apcr, MPMU_APCR);

}

static int pxa910_pm_enter(suspend_state_t state)
{
	unsigned int idle_cfg, reg = 0;

	/*pmic thread not completed,exit;otherwise system can't be waked up*/
	reg = __raw_readl(ICU_INT_CONF(IRQ_PXA910_PMIC_INT));
	if ((reg & 0x3) == 0)
		return -EAGAIN;

	idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
	idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN
		| APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN;
	__raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);

	/* disable L2 */
	outer_disable();
	/* wait for l2 idle */
	while (!(readl(CIU_REG(0x8)) & (1 << 16)))
		udelay(1);

	cpu_do_idle();

	/* enable L2 */
	outer_resume();
	/* wait for l2 idle */
	while (!(readl(CIU_REG(0x8)) & (1 << 16)))
		udelay(1);

	idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
	idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_PWRDWN
		| APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN);
	__raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);

	return 0;
}

/*
 * Called after processes are frozen, but before we shut down devices.
 */
static int pxa910_pm_prepare(void)
{
	pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR);
	return 0;
}

/*
 * Called after devices are re-setup, but before processes are thawed.
 */
static void pxa910_pm_finish(void)
{
	pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
}

static int pxa910_pm_valid(suspend_state_t state)
{
	return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
}

static const struct platform_suspend_ops pxa910_pm_ops = {
	.valid		= pxa910_pm_valid,
	.prepare	= pxa910_pm_prepare,
	.enter		= pxa910_pm_enter,
	.finish		= pxa910_pm_finish,
};

static int __init pxa910_pm_init(void)
{
	uint32_t awucrm = 0;

	if (!cpu_is_pxa910())
		return -EIO;

	suspend_set_ops(&pxa910_pm_ops);

	/* Set the following bits for MMP3 playback with VCTXO on */
	__raw_writel(__raw_readl(APMU_SQU_CLK_GATE_CTRL) | (1 << 30),
		APMU_SQU_CLK_GATE_CTRL);
	__raw_writel(__raw_readl(MPMU_FCCR) | (1 << 28), MPMU_FCCR);

	awucrm |= MPMU_AWUCRM_AP_ASYNC_INT | MPMU_AWUCRM_AP_FULL_IDLE;
	__raw_writel(awucrm, MPMU_AWUCRM);

	return 0;
}

late_initcall(pxa910_pm_init);
