Ejemplo n.º 1
0
static int s3c2410_pm_enter(suspend_state_t state)
{
	unsigned long regs_save[16];
	unsigned long tmp;

	/* ensure the debug is initialised (if enabled) */

	s3c2410_pm_debug_init();

	DBG("s3c2410_pm_enter(%d)\n", state);

	if (state != PM_SUSPEND_MEM) {
		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
		return -EINVAL;
	}

	/* check if we have anything to wake-up with... bad things seem
	 * to happen if you suspend with no wakeup (system will often
	 * require a full power-cycle)
	*/

	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
		printk(KERN_ERR PFX "Aborting sleep\n");
		return -EINVAL;
	}

	/* prepare check area if configured */

	s3c2410_pm_check_prepare();

	/* store the physical address of the register recovery block */

	s3c2410_sleep_save_phys = virt_to_phys(regs_save);

	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);

	/* ensure at least GESTATUS3 has the resume address */

	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);

	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));

	/* save all necessary core registers not covered by the drivers */

	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));

	/* set the irq configuration for wake */

	s3c2410_pm_configure_extint();

	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
	    s3c_irqwake_intmask, s3c_irqwake_eintmask);

	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);

	/* ack any outstanding external interrupts before we go to sleep */

	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);

	/* flush cache back to ram */

	arm920_flush_kern_cache_all();

	s3c2410_pm_check_store();

	// need to make some form of time-delta

	/* send the cpu to sleep... */

	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */

	s3c2410_cpu_suspend(regs_save);

	/* unset the return-from-sleep flag, to ensure reset */

	tmp = __raw_readl(S3C2410_GSTATUS2);
	tmp &= S3C2410_GSTATUS2_OFFRESET;
	__raw_writel(tmp, S3C2410_GSTATUS2);

	/* restore the system state */

	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));

	s3c2410_pm_debug_init();

	/* check what irq (if any) restored the system */

	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
	    __raw_readl(S3C2410_SRCPND),
	    __raw_readl(S3C2410_EINTPEND));

	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
				    s3c_irqwake_intmask);

	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
				    s3c_irqwake_eintmask);

	DBG("post sleep, preparing to return\n");

	s3c2410_pm_check_restore();

	/* ok, let's return from sleep */

	DBG("S3C2410 PM Resume (post-restore)\n");
	return 0;
}
Ejemplo n.º 2
0
Archivo: pm.c Proyecto: hugh712/Jollen
int pm_do_suspend(void)
{
	unsigned long sleep_save[SLEEP_SAVE_SIZE];

	DPRINTK("I am pm_do_suspend\n");

	cli();


	/* save vital registers */
	SAVE(UBRDIV0);
	SAVE(ULCON0);
	SAVE(UFCON0);
	SAVE(UMCON0);
	SAVE(UCON0);

	SAVE(GPACON); SAVE(GPADAT);
	SAVE(GPBCON); SAVE(GPBDAT); SAVE(GPBUP);
	SAVE(GPCCON); SAVE(GPCDAT); SAVE(GPCUP);
	SAVE(GPDCON); SAVE(GPDDAT); SAVE(GPDUP);
	SAVE(GPECON); SAVE(GPEDAT); SAVE(GPEUP);
	SAVE(GPFCON); SAVE(GPFDAT); SAVE(GPFUP);
	SAVE(GPGCON); SAVE(GPGDAT); SAVE(GPGUP);

	SAVE(MISCCR); SAVE(DCLKCON);
	SAVE(EXTINT0); SAVE(EXTINT1); SAVE(EXTINT2);
	SAVE(EINTFLT0); SAVE(EINTFLT1); SAVE(EINTFLT2); SAVE(EINTFLT3);
	SAVE(EINTMASK);

	SAVE(INTMOD); SAVE(INTMSK); SAVE(INTSUBMSK);


	SAVE(TCFG0); SAVE(TCNTB4); SAVE(TCON);

	/* temporary.. */
	GPFDAT |= 0xf0;  
	GPGDAT &= ~(1 << 4);

	PMCTL1 |= (USBSPD1 | USBSPD0);
	PMCTL1 |= (0x3);

	/* Clear previous reset status */
	PMST = (PMST_HWR | PMST_WDR | PMST_SMR);

	/* set resume return address */
	PMSR0 = virt_to_phys(s3c2410_cpu_resume);

	setup_wakeup_src();

	/* go zzz */
	s3c2410_cpu_suspend();

	/* ensure not to come back here if it wasn't intended */
	PMSR0 = 0;

	PMCTL1 &= ~(USBSPD1 | USBSPD0);

	RESTORE(TCFG0);
	RESTORE(TCNTB4);
	TCON = (TCON_4_AUTO | TCON_4_UPDATE | COUNT_4_OFF);
	TCON = (TCON_4_AUTO | COUNT_4_ON);



	/* restore registers */
	RESTORE(GPACON); RESTORE(GPADAT);
	RESTORE(GPBCON); RESTORE(GPBDAT); RESTORE(GPBUP);
	RESTORE(GPCCON); RESTORE(GPCDAT); RESTORE(GPCUP);
	RESTORE(GPDCON); RESTORE(GPDDAT); RESTORE(GPDUP);
	RESTORE(GPECON); RESTORE(GPEDAT); RESTORE(GPEUP);
	RESTORE(GPFCON); RESTORE(GPFDAT); RESTORE(GPFUP);
	RESTORE(GPGCON); RESTORE(GPGDAT); RESTORE(GPGUP);

	RESTORE(MISCCR); RESTORE(DCLKCON);
	RESTORE(EXTINT0); RESTORE(EXTINT1); RESTORE(EXTINT2);
	RESTORE(EINTFLT0); RESTORE(EINTFLT1); RESTORE(EINTFLT2); RESTORE(EINTFLT3);
	RESTORE(EINTMASK);

	RESTORE(INTMOD); RESTORE(INTMSK); RESTORE(INTSUBMSK);

	/* Clear interrupts */
	EINTPEND = EINTPEND;
	LCDSRCPND = LCDSRCPND;
	LCDINTPND = LCDINTPND;
	SUBSRCPND = SUBSRCPND;
	SRCPND = SRCPND;
	INTPND = INTPND;


	/* temporary.. reset UART */
	RESTORE(ULCON0); RESTORE(UCON0); RESTORE(UFCON0);
	RESTORE(UMCON0); RESTORE(UBRDIV0);
	GPFCON &= ~(0xff00);
	GPFCON |= 0x5500;
	GPFUP |= 0xf0;
	GPFDAT &= ~(0xf0);  
	GPFDAT |= 0xa0;



	sti();

	DPRINTK("¾ß½Ã²Ù·Õ\n");

	DPRINTK("I am still alive\n");

	return 0;
}