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

📄 pm.c

📁 the attached file is the power mangement for MP201
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (mp200_sleep_mode == PM_SLEEP_MODE_NONE) {		switch (state) {		case PM_SUSPEND_STANDBY:			sleep_mode = PM_SLEEP_MODE_S1;			break;		case PM_SUSPEND_MEM:			sleep_mode = PM_SLEEP_MODE_S3;			break;		default:			return;		}	} else {		sleep_mode = mp200_sleep_mode;	}	printk(KERN_INFO "PM: mp200/%x is entering sleep now ...\n",	       system_rev);	local_irq_disable();	local_fiq_disable();#ifdef CONFIG_MP200_RTC	/*	 * lets figure out the offset of the RTC to our system time.	 */	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	mp200_pm_intc_mask(PM_INTC_MASK_SAVE_AND_MASK, &intc_state);	timer_set_clock(TIMER_SUSPEND);	/* if clock is not 12MHz, then make the clock 12MHz */	pll_mode = mp200_pm_get_pll();	if(pll_mode != MP200_PLL_12MHZ) {		mp200_pm_full_to_eco();	}	mp200_pm_do_suspend(sleep_mode);	mp200_pm_do_resume();	if(pll_mode == MP200_PLL_12MHZ) {		mp200_pm_full_to_eco();	}	else {		mp200_pm_eco_to_full(pll_mode);	}	mp200_pm_update_lpj();	timer_set_clock(TIMER_RESUME);	mp200_pm_intc_mask(PM_INTC_MASK_RESTORE, &intc_state);#ifdef CONFIG_MP200_RTC	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	local_fiq_enable();	local_irq_enable();	printk(KERN_INFO "PM: mp200/%x is re-starting from sleep...\n",	       system_rev);}static voidmp200_pm_set_poweroff_regs(void){	unsigned int n = 0;	/* power OFF */	n += SET_PMU_CMDS(n, pmu_cmds_power_off);	if (n >= PMU_CMD_BUF_RAM_SIZE) {		printk(KERN_INFO "%s(): PMU command length over. (%d word)\n",			__FUNCTION__, n);	}	/* setting pmu regs. */	/* power off sequence start address */	outl(0, PMU_PC);	/* disable watch dog timer */	outl(PMU_WDT_DISABLE, PMU_WDT_COUNT_EN);	/* set watch dog timer limit count */	outl(PMU_WDT_MAX_COUNT, PMU_WDT_COUNT_LMT);}static voidmp200_pm_do_poweroff(void){	unsigned int wfi_reg = 0;	unsigned int regval;	/* LCD panel off */	pwc_write(PWC_IOOUT2, 0x0, MASK_GPIO_LCDPANEL);	/* setting pmu registers for poweroff */	mp200_pm_set_poweroff_regs();	/* disable interrupt */	outl(MASK_INTC_ALL, intc[0].ids);	outl(MASK_INTC_ALL, intc[1].ids);#if 1	/* mwi APB clock control off */	outl(inl(SMU_APBCLKCTRL) & ~(0x00040000), SMU_APBCLKCTRL);#endif	/* disable uwire int */	outl(MWI_ENCLR, MWI_INTENCLR);	/* start PMU */	outl(PMU_START_SET, PMU_START);	/* wait for pmu_start */	do {		regval = inl(PMU_START);	} while (regval != PMU_START_SET);	/* save PEn regs and wait for interrupt */	__asm__ __volatile__ (" mcr   p15, 0, %0, c7, c0, 4"::"r" (wfi_reg));	/*	 * PEn status moves to WFI, pmu command start at that time.	 * after warm boot handler done, pc return here	 */	regval = inl(PMU_START);	if ((regval & PMU_START_SET) == PMU_START_SET) {		outl(0, PMU_START);		printk(KERN_INFO "%s(): PMU not run.\n", __FUNCTION__);	}}void mp200_pm_power_off(void){	unsigned long irq_flags;	/* int mask */	local_irq_save(irq_flags);	/* noneed? */	timer_set_clock(TIMER_SUSPEND);	/* if clock is not 12MHz, then make the clock 12MHz */	if (mp200_pm_get_pll() != MP200_PLL_12MHZ) {		mp200_pm_full_to_eco();	}	/* poweroff setting function*/	mp200_pm_do_poweroff();	printk(KERN_INFO "%s(): AFTER PMU POWER OFF.\n", __FUNCTION__);	/* int unmask */	local_irq_restore(irq_flags);     /* not call */}void mp200_pm_cache_clean(void){	flush_cache_all();}static int mp200_pm_prepare(suspend_state_t state){	switch (state) {	case PM_SUSPEND_STANDBY:	case PM_SUSPEND_MEM:		break;	case PM_SUSPEND_DISK:		return -ENOTSUPP;	default:		return -EINVAL;	}	return 0;}static int mp200_pm_enter(suspend_state_t state){	switch (state) {	case PM_SUSPEND_STANDBY:	case PM_SUSPEND_MEM:		mp200_pm_suspend(state);		break;	case PM_SUSPEND_DISK:		return -ENOTSUPP;	default:		return -EINVAL;	}	return 0;}static int mp200_pm_finish(suspend_state_t state){	return 0;}static struct pm_ops mp200_pm_ops = {	.pm_disk_mode = 0,	.prepare = mp200_pm_prepare,	.enter = mp200_pm_enter,	.finish = mp200_pm_finish,};int mp200_pm_sleep(unsigned int mode){	suspend_state_t state;	int ret;	switch (mode) {	case PM_SLEEP_MODE_S1:	case PM_SLEEP_MODE_S2:		state = PM_SUSPEND_STANDBY;		break;	case PM_SLEEP_MODE_S3:		state = PM_SUSPEND_MEM;		break;	default:		return -EINVAL;	}	mp200_sleep_mode = mode;	ret = pm_suspend(state);	mp200_sleep_mode = PM_SLEEP_MODE_NONE;	return ret;}#ifdef CONFIG_PROC_FS/* * Writing to /proc/pm puts the CPU in sleep mode */static ssize_t mp200_pm_write_proc(struct file *file, const char *buffer,				   size_t count, loff_t * ppos){	char *buf;	char *tok;	char *s;	char *str;	char *whitespace = " \t\r\n";	int ret = 0;	if (current->uid != 0) {		return -EPERM;	}	if (count == 0) {		return 0;	}	buf = kmalloc(count + 1, GFP_KERNEL);	if (buf == NULL) {		ret = -ENOMEM;		goto exit_2;	}	if (copy_from_user(buf, buffer, count) != 0) {		ret = -EFAULT;		goto exit_1;	}	buf[count] = '\0';	s = buf + strspn(buf, whitespace);	tok = strsep(&s, whitespace);	str = "M248";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("248MHz...\n");		ret = mp200_pm_set_pll(MP200_PLL_248MHZ);		goto exit_1;	}	str = "M164";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("164MHz...\n");		ret = mp200_pm_set_pll(MP200_PLL_164MHZ);		goto exit_1;	}	str = "M124";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("124MHz...\n");		ret = mp200_pm_set_pll(MP200_PLL_124MHZ);		goto exit_1;	}	str = "M83";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("83MHz...\n");		ret = mp200_pm_set_pll(MP200_PLL_83MHZ);		goto exit_1;	}	str = "M50";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("50MHz...\n");		ret = mp200_pm_set_pll(MP200_PLL_50MHZ);		goto exit_1;	}	str = "M12";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("12MHz(OSC)...\n");		ret = mp200_pm_set_pll(MP200_PLL_12MHZ);		goto exit_1;	}	str = "S1";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		ret = mp200_pm_sleep(PM_SLEEP_MODE_S1);		goto exit_1;	}	str = "S2";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		ret = mp200_pm_sleep(PM_SLEEP_MODE_S2);		goto exit_1;	}	str = "S3";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		ret = mp200_pm_sleep(PM_SLEEP_MODE_S3);		goto exit_1;	}	str = "PD";	if (strnicmp(tok, str, strlen(str) + 1) == 0) {		printk("MP201 PowerDown...\n");		mp200_pm_power_off();		goto exit_1;	}	ret = -EINVAL;      exit_1:	kfree(buf);      exit_2:	if (ret == 0) {		return count;	}	return ret;}static int mp200_pm_read_proc(char *page, char **start, off_t off, int count,			      int *eof, void *data){#ifdef PM_DEBUG_REG	printk("** SMU registers dump ** \n");	printk("SMU_SMU_RESET_STATE = 0x%08x \n", inl(SMU_SMU_RESET_STATE));	printk("SMU_PLLSEL          = 0x%08x \n", inl(SMU_PLLSEL));	printk("SMU_PLLSEL2         = 0x%08x \n", inl(SMU_PLLSEL2));	printk("SMU_LPLL_CTRL1      = 0x%08x \n", inl(SMU_LPLL_CTRL1));	printk("SMU_LPLL_CTRL2      = 0x%08x \n", inl(SMU_LPLL_CTRL2));	printk("SMU_HPLL_CTRL1      = 0x%08x \n", inl(SMU_HPLL_CTRL1));	printk("SMU_HPLL_CTRL2      = 0x%08x \n", inl(SMU_HPLL_CTRL2));	printk("SMU_HPLL_CTRL3      = 0x%08x \n", inl(SMU_HPLL_CTRL3));	printk("SMU_HPLL_CTRL4      = 0x%08x \n", inl(SMU_HPLL_CTRL4));	printk("SMU_CLK_DOMAIN_DIV  = 0x%08x \n", inl(SMU_CLK_DOMAIN_DIV));	printk("SMU_OSC_CTRL        = 0x%08x \n", inl(SMU_OSC_CTRL));	printk("SMU_AUTO_FRQ_CHANGE = 0x%08x \n", inl(SMU_AUTO_FRQ_CHANGE));	printk("** FIF registers dump ** \n");	printk("FIF_SDRCONFIGA      = 0x%08x \n", inl(FIF_SDRCONFIGA));	printk("FIF_SDRCONFIGB      = 0x%08x \n", inl(FIF_SDRCONFIGB));	printk("\n");	printk("loops_per_jiffy     = 0x%08x \n", (unsigned int)loops_per_jiffy);#endif /* PM_DEBUG_REG */	return 0;}#endif				/* CONFIG_PROC_FS */extern void (*mp200_change_pll_on_sram) (struct pll_param *);extern void (*mp200_change_osc_on_sram) (void);static int __init mp200_pm_init(void){#ifdef CONFIG_PROC_FS	struct proc_dir_entry *entry;#endif#ifdef PM_POWERIC_ES_SWITCH	unsigned int reg = 0;#endif	printk(KERN_INFO "Starting pm.\n");#ifdef PM_POWERIC_ES_SWITCH	if(pwc_read(PWC_LSIVER, &reg) < 0) {		return -EIO;	}	printk(KERN_INFO " RW5T735 LSIVER [%02x]\n", reg);	if(reg <= PWC_LSIVER_ES1_1) {		lsiver_old = 1; /* ES1.1 or less */	}#endif /* PM_POWERIC_ES_SWITCH */	pm_idle = mp200_pm_idle;	/*	 * copy to SRAM	 */	if (warmboot_handler_size > (HANDLER_SIZE - 4)) {		printk(KERN_INFO "warmboot handler size over. 0x%x\n",		       warmboot_handler_size);		return -ENOMEM;	}	/* copy warm boot handler to SRAM S/W virtual area */	memcpy((void *)WARMBOOT_ADDR, warmboot_handler, warmboot_handler_size);	mp200_change_pll_on_sram = 	    (void (*)(struct pll_param *))(WARMBOOT_ADDR +	    ((unsigned int)mp200_change_pll - (unsigned int)warmboot_handler));	mp200_change_osc_on_sram = 	    (void (*)(void))(WARMBOOT_ADDR +	    ((unsigned int)mp200_change_osc - (unsigned int)warmboot_handler));#ifdef PM_DEBUG_REG	printk("mp200_change_pll_on_sram = 0x%08x \n",		(unsigned int)mp200_change_pll_on_sram);	printk("mp200_change_osc_on_sram = 0x%08x \n",		(unsigned int)mp200_change_osc_on_sram);#endif /* PM_DEBUG_REG */	pm_set_ops(&mp200_pm_ops);#ifdef CONFIG_PROC_FS	entry = create_proc_read_entry("pm", S_IWUSR | S_IRUGO, NULL,				       mp200_pm_read_proc, 0);	if (entry == NULL) {		return -ENOENT;	}	entry->write_proc = (write_proc_t *) mp200_pm_write_proc;#endif	/*	 * set irq type of button (rising edge)	 */	set_irq_type(INT_PWC_GPIO_KEY_DATA0, IRQT_RISING);	set_irq_type(INT_PWC_GPIO_KEY_DATA1, IRQT_HIGH);	set_irq_type(INT_PWC_GPIO_KEY_DATA2, IRQT_RISING);	set_irq_type(INT_PWC_GPIO_KEY_DATA3, IRQT_RISING);		/* button (GPIO0-4) chattering On */	pwc_write(PWC_STATE1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA);	/* USBWAK chattering Off */#ifdef PM_POWERIC_ES_SWITCH	if(lsiver_old == 0) {		pwc_write(PWC_STATE3, 0x00, MASK_USBWAKINT);	}#else	pwc_write(PWC_STATE3, 0x00, MASK_USBWAKINT);#endif /* !PM_POWERIC_ES_SWITCH */	pm_power_off = mp200_pm_power_off;	return 0;}__initcall(mp200_pm_init);EXPORT_SYMBOL(mp200_pm_sleep);

⌨️ 快捷键说明

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