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

📄 pm.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
字号:
#include <linux/config.h>#include <linux/init.h>#include <linux/pm.h>#include <linux/sysctl.h>#ifdef CONFIG_PROC_FS#include <linux/proc_fs.h>#endif#include <asm/hardware.h>/* * Debug macros */#undef DEBUG_PM#ifdef DEBUG_PM#define DPRINTK(args...)	printk(##args)#else#define DPRINTK(args...)#endifextern void s3c2410_cpu_suspend(void);extern void s3c2410_cpu_resume(void);#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]static u_int pwbt_num = 0;static int pwbt_edge = 0;static int pm_rtc_on = 0;intregister_wakeup_src(u_int eint_num, int edge, int rtc_on){	if (eint_num < 0 && eint_num > 23) {		return -EINVAL;	}	pwbt_num = eint_num;	pwbt_edge = edge;	pm_rtc_on = rtc_on;	return 0;}static voidsetup_wakeup_src(void){	if (pwbt_num < 4) {		EXTINT0 = (pwbt_edge << (4 * pwbt_num));		SRCPND |= (1 << pwbt_num);		INTPND |= (1 << pwbt_num);		INTMSK &= ~(1 << pwbt_num);	} else {		if (pwbt_num < 8) {			EXTINT0 = (pwbt_edge << (4 * pwbt_num));		} else if (pwbt_num < 16) {			EXTINT1 = (pwbt_edge << (4 * (pwbt_num - 8)));		} else {			EXTINT2 = (pwbt_edge << (4 * (pwbt_num - 16)));		}		EINTPEND |= (1 << pwbt_num);				EINTMASK &= ~(1 << pwbt_num);	}	if (pm_rtc_on) {		/* Enable RTC */	}}/* * List of global S3C2410 peripheral registers to preserve. * More ones like CP and general purpose register values are preserved * with the stack location in sleep.S. */enum {	SLEEP_SAVE_START = 0,	SLEEP_SAVE_INTMSK, SLEEP_SAVE_INTPND, SLEEP_SAVE_SRCPND,	SLEEP_SAVE_INTSUBMSK, SLEEP_SAVE_SUBSRCPND,	SLEEP_SAVE_INTMOD,	SLEEP_SAVE_CLKCON,	SLEEP_SAVE_UBRDIV0, SLEEP_SAVE_ULCON0, SLEEP_SAVE_UFCON0,	SLEEP_SAVE_UMCON0, SLEEP_SAVE_UCON0,	SLEEP_SAVE_GPACON, SLEEP_SAVE_GPADAT,	SLEEP_SAVE_GPBCON, SLEEP_SAVE_GPBDAT, SLEEP_SAVE_GPBUP,	SLEEP_SAVE_GPCCON, SLEEP_SAVE_GPCDAT, SLEEP_SAVE_GPCUP,	SLEEP_SAVE_GPDCON, SLEEP_SAVE_GPDDAT, SLEEP_SAVE_GPDUP,	SLEEP_SAVE_GPECON, SLEEP_SAVE_GPEDAT, SLEEP_SAVE_GPEUP,	SLEEP_SAVE_GPFCON, SLEEP_SAVE_GPFDAT, SLEEP_SAVE_GPFUP,	SLEEP_SAVE_GPGCON, SLEEP_SAVE_GPGDAT, SLEEP_SAVE_GPGUP,	SLEEP_SAVE_MISCCR, SLEEP_SAVE_DCLKCON,	SLEEP_SAVE_EXTINT0, SLEEP_SAVE_EXTINT1, SLEEP_SAVE_EXTINT2,	SLEEP_SAVE_EINTFLT0, SLEEP_SAVE_EINTFLT1, SLEEP_SAVE_EINTFLT2, 	SLEEP_SAVE_EINTFLT3, SLEEP_SAVE_EINTMASK,	SLEEP_SAVE_TCFG0, SLEEP_SAVE_TCFG1, SLEEP_SAVE_TCNTB4,	SLEEP_SAVE_TCON,	SLEEP_SAVE_SIZE};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;}unsigned long sleep_phys_sp(void *sp) {	return virt_to_phys(sp);}#ifdef CONFIG_SYSCTL/* * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than * linux/sysctl.h * * This means our interface here won't survice long - it needs a new * interface. Quick hact to et this working - use sysctl id 9999. */#warning ACPI broke the kernel, this interface needs to be fixed up.#define CTL_ACPI 9999#define ACPI_S1_SLP_TYP	19/* * Send us to sleep. */static intsysctl_pm_do_suspend(void){	int ret;	ret = pm_send_all(PM_SUSPEND, (void *)3);	if (ret == 0) {		ret = pm_do_suspend();		pm_send_all(PM_RESUME, (void *)0);	}	return ret;}static struct ctl_table pm_table[] ={	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},	{0}};static struct ctl_table pm_dir_table[] ={	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},	{0}};#endif#ifdef CONFIG_PROC_FSstatic intpminfo_proc_output(char *buf){	char *p;	struct pm_dev *dev;	p = buf;	p += sprintf(p, "type \t\t id \t\t stat \t prev_state \n");	p += sprintf(p, "----------------------------------------------\n");	dev = NULL;	while ((dev = pm_find(PM_UNKNOWN_DEV, dev)) != NULL) {		switch (dev->type) {		case PM_SYS_DEV:			p += sprintf(p, "PM_SYS_DEV \t ");			break;		case PM_PCI_DEV:			p += sprintf(p, "PM_PCI_DEV \t ");			break;		case PM_USB_DEV:			p += sprintf(p, "PM_USB_DEV \t ");			break;		case PM_SCSI_DEV:			p += sprintf(p, "PM_SCSI_DEV \t ");			break;		case PM_ISA_DEV:			p += sprintf(p, "PM_ISA_DEV \t ");			break;		case PM_MTD_DEV:			p += sprintf(p, "PM_MTD_DEV \t ");			break;		case PM_ILLUMINATION_DEV:			p += sprintf(p, "PM_ILLUMINATION_DEV \t ");			break;		case PM_USER_DEV:			p += sprintf(p, "PM_USER_DEV \t ");			break;		case PM_DEBUG_DEV:			p += sprintf(p, "PM_DEBUG_DEV \t ");			break;		case PM_GP_DEV:			p += sprintf(p, "PM_GP_DEV \t ");			break;		default:			p += sprintf(p, "PM_UNKONWN_DEV \t ");			break;		}		switch (dev->id) {		case PM_SYS_KBC:			p += sprintf(p, "PM_SYS_KBC \t ");			break;		case PM_SYS_COM:			p += sprintf(p, "PM_SYS_COM \t ");			break;		case PM_SYS_IRDA:			p += sprintf(p, "PM_SYS_IRDA \t ");			break;		case PM_SYS_FDC:			p += sprintf(p, "PM_SYS_FDC \t ");			break;		case PM_SYS_VGA:			p += sprintf(p, "PM_SYS_VGA \t ");			break;		case PM_SYS_PCMCIA:			p += sprintf(p, "PM_SYS_PCMCIA \t ");			break;		case PM_USER_LCD:			p += sprintf(p, "PM_USER_LCD \t ");			break;		case PM_USER_LIGHT:			p += sprintf(p, "PM_USER_LIGHT \t ");			break;		case PM_USER_INPUT:			p += sprintf(p, "PM_USER_INPUT \t ");			break;		case PM_DEBUG_0:			p += sprintf(p, "PM_DEBUG_0 \t ");			break;		case PM_DEBUG_1:			p += sprintf(p, "PM_DEBUG_1 \t ");			break;		case PM_DEBUG_2:			p += sprintf(p, "PM_DEBUG_2 \t ");			break;		case PM_SYS_MISC:			p += sprintf(p, "PM_SYS_MISC \t ");			break;		default:			p += sprintf(p, "PM_UNKONWN_DEV \t ");			break;		}		p += sprintf(p, "%d \t %d\n", (int)dev->state, (int)dev->prev_state);	}	return p - buf;}static intpminfo_read_proc(char *page, char **start, off_t off,                 int count, int *eof, void *data){	int len = pminfo_proc_output(page);	if (len <= off+count) *eof = 1;	*start = page + off;	len -= off;	if (len > count) len = count;	if (len < 0) len = 0;	return len;}#endif/* * Initialize power interface */static int __initpm_init(void){#ifdef CONFIG_SYSCTL	register_sysctl_table(pm_dir_table, 1);#endif    #ifdef CONFIG_PROC_FS	create_proc_read_entry("pminfo", 0, 0, pminfo_read_proc, NULL);#endif	return 0;}__initcall(pm_init);

⌨️ 快捷键说明

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