⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			left = CHECK_CHUNKSIZE;		ptr = phys_to_virt(addr);		if (in_region(ptr, left, crcs, crc_size)) {			DBG("skipping %08lx, has crc block in\n", addr);			goto skip_check;		}		if (in_region(ptr, left, save_at, 32*4 )) {			DBG("skipping %08lx, has save block in\n", addr);			goto skip_check;		}		/* calculate and check the checksum */		calc = crc32_le(~0, ptr, left);		if (calc != *val) {			printk(KERN_ERR PFX "Restore CRC error at "			       "%08lx (%08x vs %08x)\n", addr, calc, *val);			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",			    addr, calc, *val);		}	skip_check:		val++;	}	return val;}/* s3c2410_pm_check_restore * * check the CRCs after the restore event and free the memory used * to hold them*/static void s3c2410_pm_check_restore(void){	if (crcs != NULL) {		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);		kfree(crcs);		crcs = NULL;	}}#else#define s3c2410_pm_check_prepare() do { } while(0)#define s3c2410_pm_check_restore() do { } while(0)#define s3c2410_pm_check_store()   do { } while(0)#endif/* helper functions to save and restore register state */void s3c2410_pm_do_save(struct sleep_save *ptr, int count){	for (; count > 0; count--, ptr++) {		ptr->val = __raw_readl(ptr->reg);		DBG("saved %p value %08lx\n", ptr->reg, ptr->val);	}}/* s3c2410_pm_do_restore * * restore the system from the given list of saved registers * * Note, we do not use DBG() in here, as the system may not have * restore the UARTs state yet*/void s3c2410_pm_do_restore(struct sleep_save *ptr, int count){	for (; count > 0; count--, ptr++) {		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",		       ptr->reg, ptr->val, __raw_readl(ptr->reg));		__raw_writel(ptr->val, ptr->reg);	}}/* s3c2410_pm_do_restore_core * * similar to s3c2410_pm_do_restore_core * * WARNING: Do not put any debug in here that may effect memory or use * peripherals, as things may be changing!*/static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count){	for (; count > 0; count--, ptr++) {		__raw_writel(ptr->val, ptr->reg);	}}/* s3c2410_pm_show_resume_irqs * * print any IRQs asserted at resume time (ie, we woke from)*/static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,					unsigned long mask){	int i;	which &= ~mask;	for (i = 0; i <= 31; i++) {		if ((which) & (1L<<i)) {			DBG("IRQ %d asserted at resume\n", start+i);		}	}}/* s3c2410_pm_check_resume_pin * * check to see if the pin is configured correctly for sleep mode, and * make any necessary adjustments if it is not*/static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs){	unsigned long irqstate;	unsigned long pinstate;	int irq = s3c2410_gpio_getirq(pin);	if (irqoffs < 4)		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);	else		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);	pinstate = s3c2410_gpio_getcfg(pin);	pinstate >>= S3C2410_GPIO_OFFSET(pin)*2;	if (!irqstate) {		if (pinstate == 0x02)			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);	} else {		if (pinstate == 0x02) {			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);			s3c2410_gpio_cfgpin(pin, 0x00);		}	}}/* s3c2410_pm_configure_extint * * configure all external interrupt pins*/static void s3c2410_pm_configure_extint(void){	int pin;	/* for each of the external interrupts (EINT0..EINT15) we	 * need to check wether it is an external interrupt source,	 * and then configure it as an input if it is not	*/	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);	}	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);	}}#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))/* s3c2410_pm_enter * * central control for sleep/resume process*/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();	/* send the cpu to sleep... */	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */	s3c2410_cpu_suspend(regs_save);	/* restore the cpu state */	cpu_init();	/* 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;}/* * Called after processes are frozen, but before we shut down devices. */static int s3c2410_pm_prepare(suspend_state_t state){	return 0;}/* * Called after devices are re-setup, but before processes are thawed. */static int s3c2410_pm_finish(suspend_state_t state){	return 0;}/* * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. */static struct pm_ops s3c2410_pm_ops = {	.pm_disk_mode	= PM_DISK_FIRMWARE,	.prepare	= s3c2410_pm_prepare,	.enter		= s3c2410_pm_enter,	.finish		= s3c2410_pm_finish,};/* s3c2410_pm_init * * Attach the power management functions. This should be called * from the board specific initialisation if the board supports * it.*/int __init s3c2410_pm_init(void){	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");	pm_set_ops(&s3c2410_pm_ops);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -