📄 pm.c
字号:
static const unsigned int pmu_cmds_power_off[] = {/* SDR Pull Down */ PMU_CMD_REG_WRITE(SMU_PULLCTL_SDR, SMU_PULLCTL_SDR_PDOWN),/* SDR Floating */ PMU_CMD_REG_WRITE(SMU_PCTL_SDR, SMU_PCTL_SDR_FLOATING),/* SET MWI_SCLK_DIV for OSC */ PMU_CMD_REG_WRITE(SMU_MWI_SCLK_DIV, SMU_MWI_DIV_OSC_VAL ),/* L0 power OFF */ PMU_CMD_REG_WRITE(SMU_GCLKCTRL1_ENA, MASK_SMU_MWI_GCK), PMU_CMD_REG_WRITE(SMU_GCLKCTRL1, SMU_GCK_ON), PMU_CMD_REG_WRITE(MWI_INTFFCLR, MWI_FFCLR), PMU_CMD_REG_WRITE(MWI_CONT, MWI_CONT_PWC_A8_D8_TX_OFF), PMU_CMD_REG_WRITE(MWI_CONT, MWI_CONT_PWC_A8_D8_TX), PMU_CMD_REG_WRITE(MWI_TXQA, (GPIOCORE_PWC_REGA << 24)), PMU_CMD_REG_WRITE(MWI_TXQ, (PWC_REGA_L0_OFF_ECO_PS << 24)), PMU_CMD_REG_WRITE(MWI_INTENSET, MWI_ENSET), PMU_CMD_MWI_WRITE(MWI_START, MWI_START_FLAG), PMU_CMD_REG_WRITE(MWI_INTFFCLR, MWI_FFCLR), PMU_CMD_REG_WRITE(MWI_CONT, MWI_CONT_PWC_A8_D8_TX_OFF),/* Clock -> RTC */ PMU_CMD_REG_WRITE(SMU_PLLSEL, SMU_PLLSEL_RTC ),/* disable OSC */ PMU_CMD_REG_WRITE(SMU_OSC_CTRL, SMU_OSC_ENA_DISABLE ),/* PMU_END */ PMU_CMD_PMU_END(),};static const struct intc_t intc[] = { { .ien = VA_INTC + MP200_INTC_IT0_IEN0, .ids = VA_INTC + MP200_INTC_IT0_IDS0, .imn = VA_INTC + MP200_INTC_IT0_IMN0, }, { .ien = VA_INTC + MP200_INTC_IT0_IEN1, .ids = VA_INTC + MP200_INTC_IT0_IDS1, .imn = VA_INTC + MP200_INTC_IT0_IMN1, },};static struct { unsigned int ia; unsigned int imn;} gpio_state;static struct { unsigned int ioout1; unsigned int fmask1; unsigned int bmask1; unsigned int fmask3; unsigned int bmask3; unsigned int detmod3;} pwc_state;#if ENABLE_FRAMECACHEstatic struct { unsigned int fif_fcctrl; unsigned int fif_frameaaddr; unsigned int fif_framebaddr; unsigned int fif_framesize; unsigned int fif_fcbaseaddr;} fif_state;#endif /* ENABLE_FRAMECACHE */static struct { unsigned int smu_ahbclkctrl0; unsigned int smu_ahbclkctrl1; unsigned int smu_apbclkctrl; unsigned int smu_clkctrl;} clkctrl_state;static struct { unsigned int smu_gio_int_clk_sel;} smu_state;#ifdef CONFIG_MP201_RSTRESUMEstatic struct { unsigned int smu_gclkctrl0; unsigned int smu_gclkctrl1; unsigned int smu_gclkctrl2;} clock_state;static struct { unsigned int smu_resetreq1a; unsigned int smu_resetreq1b; unsigned int smu_resetreqdsp;} reset_state;#endif#ifdef CONFIG_MP200_WATCHDOGstatic unsigned int smu_wdt_int_reset;#endifstatic unsigned int mp200_sleep_mode = PM_SLEEP_MODE_NONE;/* * Let's power down on idle, but only if we are really * idle, because once we start down the path of * going idle we continue to do idle even if we get * a clock tick interrupt . . */static void mp200_pm_idle(void){ local_irq_disable(); local_fiq_disable(); if (need_resched() == 0) { cpu_do_idle(); } local_fiq_enable(); local_irq_enable();}static int mp200_pm_set_pmu_cmds(unsigned int cnt, const unsigned int data[], int size){ int i; for (i = 0; i < size; i++) { outl(data[i], PMU_CMD_BUF_RAM + (cnt + i) * sizeof(unsigned int)); } return i;}/* * mp200_pm_set_pmu_regs(unsigned int mode) */static void mp200_pm_set_pmu_regs(unsigned int mode){ unsigned int pow_on_pc; unsigned int n = 0; /* setting pmu command */ switch(mode){ case PM_SLEEP_MODE_S1: n += SET_PMU_CMDS(n, pmu_cmds_s1_suspend); break; case PM_SLEEP_MODE_S2: n += SET_PMU_CMDS(n, pmu_cmds_s2_suspend); break; case PM_SLEEP_MODE_S3:#ifdef PM_POWERIC_ES_SWITCH if(lsiver_old) n += SET_PMU_CMDS(n, pmu_cmds_s3_suspend_es1_1); else n += SET_PMU_CMDS(n, pmu_cmds_s3_suspend);#else n += SET_PMU_CMDS(n, pmu_cmds_s3_suspend);#endif /* PM_POWERIC_ES_SWITCH */ break; } pow_on_pc = n; switch(mode){ case PM_SLEEP_MODE_S1: n += SET_PMU_CMDS(n, pmu_cmds_s1_resume); break; case PM_SLEEP_MODE_S2: n += SET_PMU_CMDS(n, pmu_cmds_s2_resume); break; case PM_SLEEP_MODE_S3:#ifdef PM_POWERIC_ES_SWITCH if(lsiver_old) n += SET_PMU_CMDS(n, pmu_cmds_s3_resume_es1_1); else n += SET_PMU_CMDS(n, pmu_cmds_s3_resume);#else n += SET_PMU_CMDS(n, pmu_cmds_s3_resume);#endif /* PM_POWERIC_ES_SWITCH */ break; } 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); /* power on sequence start address */ outl(pow_on_pc, PMU_POWER_ON_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 int mp200_pm_intc_mask(int mask, struct intc_state *state){ if (state == 0) { return -EINVAL; } switch (mask) { case PM_INTC_MASK_SAVE_AND_MASK: state->mask0 = inl(intc[0].imn); state->mask1 = inl(intc[1].imn); outl(MASK_INTC_ALL, intc[0].ids); outl(MASK_INTC_ALL, intc[1].ids); break; case PM_INTC_MASK_RESTORE: outl(MASK_INTC_ALL, intc[0].ids); outl(MASK_INTC_ALL, intc[1].ids); outl(state->mask0, intc[0].ien); outl(state->mask1, intc[1].ien); break; default: return -EINVAL; } return 0;}static void mp200_pm_save_state(unsigned int mode){ /* save GPIO state */ gpio_state.imn = inl(VA_GIO + GPIO0_IMN); gpio_state.ia = inl(VA_GIO + GPIO0_IA); /* save PWC state */ pwc_read(PWC_FMASK1, &pwc_state.fmask1); pwc_read(PWC_BMASK1, &pwc_state.bmask1); pwc_read(PWC_IOOUT1, &pwc_state.ioout1);#ifdef PM_POWERIC_ES_SWITCH if(lsiver_old == 0) { pwc_read(PWC_FMASK3, &pwc_state.fmask3); pwc_read(PWC_BMASK3, &pwc_state.bmask3); pwc_read(PWC_DETMOD3H, &pwc_state.detmod3); }#else pwc_read(PWC_FMASK3, &pwc_state.fmask3); pwc_read(PWC_BMASK3, &pwc_state.bmask3); pwc_read(PWC_DETMOD3H, &pwc_state.detmod3);#endif /* !PM_POWERIC_ES_SWITCH */#if ENABLE_FRAMECACHE /* save FIFO state */ fif_state.fif_frameaaddr = inl(FIF_FRAMEAADDR); fif_state.fif_framebaddr = inl(FIF_FRAMEBADDR); fif_state.fif_framesize = inl(FIF_FRAMESIZE); fif_state.fif_fcbaseaddr = inl(FIF_FCBASEADDR); fif_state.fif_fcctrl = inl(FIF_FCCTRL);#endif /* ENABLE_FRAMECACHE */#ifdef CONFIG_MP201_RSTRESUME /* save clockgate status */ clock_state.smu_gclkctrl0 = inl(SMU_GCLKCTRL0); clock_state.smu_gclkctrl1 = inl(SMU_GCLKCTRL1); clock_state.smu_gclkctrl2 = inl(SMU_GCLKCTRL2); /* save reset status */ reset_state.smu_resetreq1a = inl(SMU_RESETREQ1A); reset_state.smu_resetreq1b = inl(SMU_RESETREQ1B); reset_state.smu_resetreqdsp = inl(SMU_RESETREQDSP);#endif#ifdef CONFIG_MP200_WATCHDOG /* save SMU wdt int reset state */ smu_wdt_int_reset = inl(SMU_WDT_INT_RESET); /* SMU wdt int reset : enable TW0 */ outl(SMU_TW0_RSTREQ, SMU_WDT_INT_RESET);#endif /* SMU other state */ smu_state.smu_gio_int_clk_sel = inl(SMU_GIO_INT_CLK_SEL); /* gio int use RTC */ outl(SMU_GIO_INT_CLK_RTC, SMU_GIO_INT_CLK_SEL); /* save SMU clkctrl state */ clkctrl_state.smu_ahbclkctrl0 = inl(SMU_AHBCLKCTRL0); clkctrl_state.smu_ahbclkctrl1 = inl(SMU_AHBCLKCTRL1); clkctrl_state.smu_apbclkctrl = inl(SMU_APBCLKCTRL); clkctrl_state.smu_clkctrl = inl(SMU_CLKCTRL); return;}static void mp200_pm_restore_state(void){#ifdef CONFIG_MP201_RSTRESUME /* restore clockgate status */ outl(clock_state.smu_gclkctrl0, SMU_GCLKCTRL0_ENA); outl(clock_state.smu_gclkctrl0, SMU_GCLKCTRL0); outl(0, SMU_GCLKCTRL0_ENA); outl(clock_state.smu_gclkctrl1, SMU_GCLKCTRL1_ENA); outl(clock_state.smu_gclkctrl1, SMU_GCLKCTRL1 ); outl(0, SMU_GCLKCTRL1_ENA); outl(clock_state.smu_gclkctrl2, SMU_GCLKCTRL2_ENA); outl(clock_state.smu_gclkctrl2, SMU_GCLKCTRL2 ); outl(0, SMU_GCLKCTRL2_ENA); /* resotre reset status */ outl(reset_state.smu_resetreq1a, SMU_RESETREQ1A_ENA) outl(reset_state.smu_resetreq1a, SMU_RESETREQ1A); outl(0, SMU_RESETREQ1A_ENA); outl(reset_state.smu_resetreq1b, SMU_RESETREQ1B_ENA outl(reset_state.smu_resetreq1b, SMU_RESETREQ1B); outl(0, SMU_RESETREQ1B_ENA); outl(reset_state.smu_resetreqdsp, SMU_RESETREQDSP_ENA); outl(reset_state.smu_resetreqdsp, SMU_RESETREQDSP); outl(0, SMU_RESETREQDSP_ENA);#endif /* SMU clkctrl : PB0LP,PB1LP off */ outl(inl(SMU_AHBCLKCTRL1) & ~(SMU_CLKCTRL_PB0LP | SMU_CLKCTRL_PB1LP), SMU_AHBCLKCTRL1); /* restore SMU clkctrl state */ outl(clkctrl_state.smu_clkctrl, SMU_CLKCTRL); outl(clkctrl_state.smu_apbclkctrl, SMU_APBCLKCTRL); outl(clkctrl_state.smu_ahbclkctrl1, SMU_AHBCLKCTRL1); outl(clkctrl_state.smu_ahbclkctrl0, SMU_AHBCLKCTRL0); /* SMU other state */ outl(smu_state.smu_gio_int_clk_sel, SMU_GIO_INT_CLK_SEL);#ifdef CONFIG_MP200_WATCHDOG /* restore SMU wdt int reset state */ outl(smu_wdt_int_reset, SMU_WDT_INT_RESET);#endif#if ENABLE_FRAMECACHE /* restore FIFO state */ outl(fif_state.fif_frameaaddr, FIF_FRAMEAADDR); outl(fif_state.fif_framebaddr, FIF_FRAMEBADDR); outl(fif_state.fif_framesize, FIF_FRAMESIZE); outl(fif_state.fif_fcbaseaddr, FIF_FCBASEADDR); outl(fif_state.fif_fcctrl, FIF_FCCTRL);#endif /* ENABLE_FRAMECACHE */ /* uWire state : enable */ mp200_pm_set_uwire_clock(); /* restore PWC state */ pwc_write(PWC_FMASK1, pwc_state.fmask1, MASK_GPIO_KEYSCAN); pwc_write(PWC_CLRFACT1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA); pwc_write(PWC_BMASK1, pwc_state.bmask1, MASK_GPIO_KEYSCAN); pwc_write(PWC_IOOUT1, pwc_state.ioout1, MASK_GPIO_KEYSCAN); /* USBWAKE INT state */#ifdef PM_POWERIC_ES_SWITCH if(lsiver_old == 0) { pwc_write(PWC_DETMOD3H, pwc_state.detmod3, MASK_DETMODE3H_USBWKM); pwc_write(PWC_FMASK3, pwc_state.fmask3, MASK_USBWAKINT); pwc_write(PWC_BMASK3, pwc_state.bmask3, MASK_USBWAKINT); }#else pwc_write(PWC_DETMOD3H, pwc_state.detmod3, MASK_DETMODE3H_USBWKM); pwc_write(PWC_FMASK3, pwc_state.fmask3, MASK_USBWAKINT); pwc_write(PWC_BMASK3, pwc_state.bmask3, MASK_USBWAKINT);#endif /* !PM_POWERIC_ES_SWITCH */ /* restore GPIO state */ outl(gpio_state.ia, VA_GIO + GPIO0_IA); outl(MASK_GPIO_ALL, VA_GIO + GPIO0_IME); outl(~gpio_state.imn, VA_GIO + GPIO0_IMN); return;}/* * mp200_pm_do_suspend(unsigned int mode) */static void mp200_pm_do_suspend(unsigned int mode){ unsigned int sus_add; unsigned int regval; void (*suspend_on_sram) (void); mp200_pm_save_state(mode); /* on SRAM mp200_cpu_suspend() */ sus_add = (unsigned int)mp200_cpu_suspend - (unsigned int)warmboot_handler; suspend_on_sram = (void (*)(void))(WARMBOOT_ADDR + sus_add); /* WAKEWAIT disable */ if (mode == PM_SLEEP_MODE_S3) { pwc_write(PWC_WAKECONT, WAKECONT_WAKEWAIT_DISABLE, MASK_WAKECONT_WAKEWAIT); } /* open key interrupt mask */ /* PWC */ pwc_write(PWC_FMASK1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA); pwc_write(PWC_CLRFACT1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA); pwc_write(PWC_BMASK1, MASK_GPIO_KEYDATA, MASK_GPIO_KEYDATA); pwc_write(PWC_IOOUT1, MASK_GPIO_RESUME_KEY, MASK_GPIO_KEYSCAN); /* USB WAKINT enable */#ifdef PM_POWERIC_ES_SWITCH if(lsiver_old == 0) { pwc_write(PWC_FMASK3, MASK_USBWAKINT, MASK_USBWAKINT); pwc_write(PWC_DETMOD3H, DETMODE3H_USBWKM_RISE, MASK_DETMODE3H_USBWKM); pwc_write(PWC_CLRFACT3, MASK_USBWAKINT, MASK_USBWAKINT); pwc_write(PWC_BMASK3, MASK_USBWAKINT, MASK_USBWAKINT); }#else pwc_write(PWC_FMASK3, MASK_USBWAKINT, MASK_USBWAKINT); pwc_write(PWC_DETMOD3H, DETMODE3H_USBWKM_RISE, MASK_DETMODE3H_USBWKM); pwc_write(PWC_CLRFACT3, MASK_USBWAKINT, MASK_USBWAKINT); pwc_write(PWC_BMASK3, MASK_USBWAKINT, MASK_USBWAKINT);#endif /* !PM_POWERIC_ES_SWITCH */ /* GPIO */ outl(MASK_GPIO_ALL, VA_GIO + GPIO0_IME); outl((inl(VA_GIO + GPIO0_IA) | MASK_GPIO_RESUME), VA_GIO + GPIO0_IA); outl(MASK_GPIO_RESUME, VA_GIO + GPIO0_IR); outl(MASK_GPIO_RESUME, VA_GIO + GPIO0_IMN); /* setting pmu registers */ mp200_pm_set_pmu_regs(mode); outl(SMU_RESET_STATE_WARM, SMU_SMU_RESET_STATE); /* 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 */ suspend_on_sram(); /* * 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__); }}/* * mp200_pm_do_resume() */static void mp200_pm_do_resume(void){ outl(SMU_RESET_STATE_CLR, SMU_SMU_RESET_STATE); mp200_pm_restore_state();}static void mp200_pm_suspend(suspend_state_t state){ struct intc_state intc_state; unsigned int sleep_mode; unsigned int pll_mode; #ifdef CONFIG_MP200_RTC struct rtc_time rt; long rtc_offset; unsigned long mkt; extern void get_rtc_time(struct rtc_time *);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -