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

📄 pm.c

📁 睡眠 LINUX 怎样进入睡眠
💻 C
字号:
/********************** BEGIN LICENSE BLOCK ************************************ * * JZ4740  mobile_tv  Project  V1.0.0 * INGENIC CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM * Copyright (c) Ingenic Semiconductor Co. Ltd 2005. All rights reserved. *  * This file, and the files included with this file, is distributed and made  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  *  * http://www.ingenic.cn  * ********************** END LICENSE BLOCK ************************************** * *  Author:  <dsqiu@ingenic.cn>  <jgao@ingenic.cn>  * *  Create:   2008-06-26, by dsqiu *             *  Maintain: 2008-06-26, by jgao *             * ******************************************************************************* */#include <bsp.h>#include <jz4740.h>#include <mipsregs.h>#include <os_api.h>//--------------------------------------------------------------------typedef struct __tag_pll_opt{	unsigned int cpuclock;   // cpu clock	int cdiv;                // cpu spec cdiv	int mdiv;                // mem div}PLL_OPT,*PPLL_OPT;//--------------------------------------------------------------------int sdram_convert(unsigned int mclock,unsigned int *sdram_freq);static void pll_convert(PPLL_OPT pllopt,unsigned int *pll_cfcr,unsigned int *pll_plcr1);static int save_reg[5];void config_source_savepower(void){	int	dwRegData;	//Set AMPEN_N output low		__gpio_port_as_output(2,27);		__gpio_clear_pin(91);	// Stop SADC	REG_SADC_ENA &= ~0x7;	// Suspend UHC, OSC and UDC in Sleep Mode.	dwRegData = REG_CPM_SCR;	dwRegData |= 1<<7;	dwRegData &= ~((1<<6)| (1<<4));	REG_CPM_SCR = dwRegData;	// Suspend Codec//	REG_ICDC_CDCCR1 = 0x001b2302;//	udelay(1000);//	REG_ICDC_CDCCR1 = 0x001b2102;	// Stop LCD	REG_LCD_STATE |= LCD_STATE_QD;	// Disable nand flash	REG_EMC_NFCSR &= ~0xff;}void save_internal_regs(void){//	save_reg[0] = REG_ICDC_CDCCR1;	save_reg[0] = REG_SADC_ENA;    save_reg[1] = REG_EMC_NFCSR;	save_reg[2] = REG_LCD_STATE;	save_reg[3] = REG_CPM_SCR;}void restore_internal_regs(void){//	REG_ICDC_CDCCR1 = save_reg[0];	REG_SADC_ENA   =  save_reg[0];	REG_EMC_NFCSR  =  save_reg[1];	REG_LCD_STATE  =  save_reg[2];	REG_CPM_SCR    =  save_reg[3];}static int jz_pm_do_hibernate(void){	printf("Put CPU into hibernate mode.\n");	serial_waitfinish();	__rtc_clear_alarm_flag();	__rtc_clear_hib_stat_all();	// __rtc_set_scratch_pattern(0x12345678);	__rtc_enable_alarm_wakeup();	__rtc_set_hrcr_val(0xfe0);	__rtc_set_hwfcr_val((0xFFFF << 4));   	__rtc_power_down();		while(1);        	return 0;}static int jz_pm_do_sleep(void){//	unsigned long imr = REG_INTC_IMR;	/* Preserve current time */	/* Mask all interrupts *///	REG_INTC_IMSR = 0xffffffff;	/* Just allow next interrupts to wakeup the system.	 * Note: modify this according to your system.	 */    save_internal_regs();    config_source_savepower();	/* Enter SLEEP mode */	REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;	REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;	//REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;	//REG_CPM_LCR |= CPM_LCR_LPM_IDLE;	__asm__(".set\tmips3\n\t"		"sync\n\t"		"wait\n\t"		"nop\n\t"		".set\tmips0");    restore_internal_regs();	/* Restore to IDLE mode */	REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;	REG_CPM_LCR |= CPM_LCR_LPM_IDLE;	/* Restore interrupts *///	REG_INTC_IMR = imr;	/* Restore current time */	return 0;}static int jz_pm_do_pllconvert(PPLL_OPT pllopt){	unsigned int cfcr, pllout,sdram_freq;	unsigned int pll_cfcr,pll_plcr1;	unsigned int t;	unsigned int dmcr;	#if 0  int div_preq[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};    if(pllin < 25000000 || pllin > 420000000)		{			printf("pll should > 25000000 and < 420000000 ! \n");			return -1;		}#endif    pll_convert(pllopt,&pll_cfcr,&pll_plcr1);    dmcr = sdram_convert(pllopt->cpuclock / pllopt->mdiv,&sdram_freq);    unsigned int olddmcr = REG_EMC_DMCR;    olddmcr &= 0xffff0000;    olddmcr |= dmcr;    t = read_c0_status();    write_c0_status(t & (~1));#if (DM==1)       dm_pre_convert();#endif       REG_CPM_CPCCR &= ~CPM_CPCCR_CE;       REG_CPM_CPCCR = pll_cfcr;       REG_EMC_RTCOR = sdram_freq;       REG_EMC_RTCNT = 0;       REG_CPM_CPCCR |= CPM_CPCCR_CE;       //udelay(1000);       //udelay(1000);              //REG_EMC_DMCR = olddmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;       write_c0_status(t);#if (DM==1)       dm_all_convert();#endif       pllout = (__cpm_get_pllm() + 2)* EXTAL_CLK / (__cpm_get_plln() + 2);       printf("pll out new: %dMHZ 0x%08x 0x%08x \n",pllout/1000000,pll_cfcr,REG_CPM_CPCCR);        return 0;}static void pll_bypass(void){	unsigned int freq;	 /* sdram convert */	sdram_convert(12000000,&freq);	REG_EMC_RTCOR = freq;	REG_EMC_RTCNT = freq;		REG_CPM_CPPCR |= CPM_CPPCR_PLLBP;	REG_CPM_CPCCR  = ((REG_CPM_CPCCR & (~0xffff)) | CPM_CPCCR_CE);	REG_CPM_CPCCR &= ~CPM_CPCCR_CE;}int sdram_convert(unsigned int mclock,unsigned int *sdram_freq){	register unsigned int ns, dmcr = 0,tmp;	printf("mclock = %d\n",mclock);	 	ns = 1000000000 / mclock;	printf("ns = %d\n",ns);		tmp = SDRAM_TRAS/ns;	if (tmp < 4) tmp = 4;	if (tmp > 11) tmp = 11;	dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);	tmp = SDRAM_RCD/ns;	if (tmp > 3) tmp = 3;	dmcr |= (tmp << EMC_DMCR_RCD_BIT);	tmp = SDRAM_TPC/ns;	if (tmp > 7) tmp = 7;	dmcr |= (tmp << EMC_DMCR_TPC_BIT);	tmp = SDRAM_TRWL/ns;	if (tmp > 3) tmp = 3;	dmcr |= (tmp << EMC_DMCR_TRWL_BIT);	tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;	if (tmp > 14) tmp = 14;	dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);	/* Set refresh registers */	tmp = SDRAM_TREF/ns;	tmp = tmp/64 + 1;	if (tmp > 0xff) tmp = 0xff;        *sdram_freq = tmp; 	//REG_EMC_RTCOR = tmp;	//REG_EMC_RTCNT = tmp;	return dmcr;}int div_preq[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};static int find_cpudiv(int div){	int i;	for(i = 0;i < sizeof(div_preq)/sizeof(div_preq[0]);i++)		if(div == div_preq[i])			return i;	return -1;}static void pll_convert(PPLL_OPT pllopt,unsigned int *pll_cfcr,unsigned int *pll_plcr1){	unsigned int cfcr, plcr1;	printf("cpuspeed  memspeed: (%dM :%dM)\n",pllopt->cpuclock / pllopt->cdiv / 1000 / 1000,pllopt->cpuclock / pllopt->mdiv / 1000 / 1000);	int cdiv = find_cpudiv(pllopt->cdiv);	#if (RELEASE==0)	if(cdiv == -1)	{		printf("error: init pll cdiv!");		return;	}	#endif		int mdiv = find_cpudiv(pllopt->mdiv);	#if (RELEASE==0)	if(mdiv == -1)	{		printf("error: init pll mdiv!");			return;		}	#endif	cfcr = REG_CPM_CPCCR;	cfcr &= ~(0xffff);  		cfcr |=  CPM_CPCCR_CLKOEN |		(cdiv << CPM_CPCCR_CDIV_BIT) | 		(mdiv << CPM_CPCCR_HDIV_BIT) | 		(mdiv << CPM_CPCCR_PDIV_BIT) |		(mdiv << CPM_CPCCR_MDIV_BIT) ;//		|(2 << CPM_CPCCR_LDIV_BIT);	/* init PLL */	*pll_cfcr= cfcr;}static void set_pll(unsigned int div,unsigned int pll){       u32 prog_entry = ((u32)set_pll / 32 - 1) * 32 ;       u32 prog_size = 1024;       u32 i;       for( i = (prog_entry);i < prog_entry + prog_size; i += 32)		__asm__ __volatile__(			"cache 0x1c, 0x00(%0)\n\t"            :			: "r" (i));	REG_CPM_CPCCR = div;//	REG_CPM_CPCCR |= CPM_CPCCR_CE;	REG_CPM_CPPCR = pll;	while (!(REG_CPM_CPPCR & CPM_CPPCR_PLLS));}/* convert pll while program is running */int jz_pm_pllconvert(PPLL_OPT pllin){	return jz_pm_do_pllconvert(pllin);}/* Put CPU to IDLE mode */void jz_pm_idle(void){	__asm__(        ".set\tmips3\n\t"        "sync\n\t"        "wait\n\t"        "nop\n\t"        "nop\n\t"		".set\tmips0"        );		//cpu_wait();}//                                  cpu speed = cpu clock / cdiv//                                  mem speed = cpu clock / mdiv//                                  cpu clock     cdiv   mdiv static PLL_OPT opt_pll[3] = {																	{CFG_CPU_SPEED,  4,     4},																	{CFG_CPU_SPEED,  2,     4},																	{CFG_CPU_SPEED,  1,     3}															};static int curLevel = 0;void pm_init(){#if (DM==1)	printf("Driver Manager \r\n");	jz_dm_init();#endif}/*    	level:    	0,1,2,3,-1;    	-1 is GetLevel;*/int jz_pm_control(int level){	printf("+jz_pm_control\r\n");	if(level != -1)	{			if(curLevel != level)		{			curLevel = level;			if(level<0 || level >3)				return -1;			if(level==3)			{				return jz_pm_sleep();			}			else			{				return jz_pm_pllconvert(&opt_pll[level]);//[level].cpuclock,opt_pll[level].div);			}	  }	}else		return curLevel;	return 0;}//--------------------------------------------------------------------typedef struct __tag_wake_type__{	void (*WakeUp)();	void (*PreWakeUp)();	unsigned int id; }WakeUpType;#define MAX_WakeUp_SOURCE 5static WakeUpType WakeUpsource[MAX_WakeUp_SOURCE] = {0};static unsigned char wcount = 0; void PM_AddWakeUp(int id,void* preWakeUp,void* WakeUp){	if(wcount < MAX_WakeUp_SOURCE)	{		WakeUpsource[wcount].id = id;		WakeUpsource[wcount].PreWakeUp = preWakeUp;		WakeUpsource[wcount].WakeUp = WakeUp;		wcount++;	}}static void PM_SetWakeUp(){	int i;	for(i = 0;i < wcount;i++)	{		if(WakeUpsource[i].PreWakeUp)		{			printf("%s->%x\n",__FUNCTION__,WakeUpsource[i].id);			WakeUpsource[i].PreWakeUp();		}	}}static void PM_WakeUp(){	int i;	for(i = 0;i < wcount;i++)	{		if(WakeUpsource[i].WakeUp)		{				printf("%s->%x\n",__FUNCTION__,WakeUpsource[i].id);			WakeUpsource[i].WakeUp();		}	}}//--------------------------------------------------------------------/* Put CPU to SLEEP mode */int jz_pm_sleep(void){	 PM_SetWakeUp();	 jz_pm_do_sleep();	 PM_WakeUp();	 return 1;}//--------------------------------------------------------------------typedef struct __tag_power_type__{	void (*pPowerDown)();	void (*pPowerUp)();	unsigned int id; }PowerType;#define MAX_Power_SOURCE 10static PowerType PowerSource[MAX_Power_SOURCE] = {0};static unsigned char w_powercount = 0;void PM_AddPowerCtrl(int id,void* ppowerdown,void* ppowerup){	if(w_powercount < MAX_Power_SOURCE)	{		PowerSource[w_powercount].id = id;		PowerSource[w_powercount].pPowerDown = ppowerdown;		PowerSource[w_powercount].pPowerUp = ppowerup;		w_powercount++;	}}static void PM_PowerDown(){	int i;	for(i = 0;i < w_powercount;i++)	{		if(PowerSource[i].pPowerDown)		{			printf("%s->%x\n",__FUNCTION__,PowerSource[i].id);			PowerSource[i].pPowerDown();		}	}}static void PM_PowerUp(){	int i;	for(i = 0;i < w_powercount;i++)	{		if(PowerSource[i].pPowerUp)		{				printf("%s->%x\n",__FUNCTION__,PowerSource[i].id);			PowerSource[i].pPowerUp();		}	}}/* Put CPU to HIBERNATE mode */int jz_pm_hibernate(void){	PM_PowerDown();	return jz_pm_do_hibernate();}

⌨️ 快捷键说明

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