📄 pm.c
字号:
REG_CPM_RSTR &= ~(CPM_RSTR_HR | CPM_RSTR_WR | CPM_RSTR_SR); /* Set resume return address */ REG_CPM_SPR = PHYS(jz_cpu_resume); /* Before sleeping, calculate and save a checksum */ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) checksum += sleep_save[i]; sleep_save[SLEEP_SAVE_CKSUM] = checksum; /* *** go zzz *** */ jz_cpu_suspend(); /* after sleeping, validate the checksum */ checksum = 0; for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) checksum += sleep_save[i]; /* if invalid, display message and wait for a hardware reset */ if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { /** Add platform-specific message display codes here **/ while (1); } /* Ensure not to come back here if it wasn't intended */ REG_CPM_SPR = 0; /* Restore registers */ RESTORE(GPIO_GPDR0, 32); RESTORE(GPIO_GPDR1, 32); RESTORE(GPIO_GPDR2, 32); RESTORE(GPIO_GPDR3, 32); RESTORE(GPIO_GPDIR0, 32); RESTORE(GPIO_GPDIR1, 32); RESTORE(GPIO_GPDIR2, 32); RESTORE(GPIO_GPDIR3, 32); RESTORE(GPIO_GPODR0, 32); RESTORE(GPIO_GPODR1, 32); RESTORE(GPIO_GPODR2, 32); RESTORE(GPIO_GPODR3, 32); RESTORE(GPIO_GPPUR0, 32); RESTORE(GPIO_GPPUR1, 32); RESTORE(GPIO_GPPUR2, 32); RESTORE(GPIO_GPPUR3, 32); RESTORE(GPIO_GPALR0, 32); RESTORE(GPIO_GPALR1, 32); RESTORE(GPIO_GPALR2, 32); RESTORE(GPIO_GPALR3, 32); RESTORE(GPIO_GPAUR0, 32); RESTORE(GPIO_GPAUR1, 32); RESTORE(GPIO_GPAUR2, 32); RESTORE(GPIO_GPAUR3, 32); RESTORE(GPIO_GPIDLR0, 32);RESTORE(GPIO_GPIDLR1, 32);RESTORE(GPIO_GPIDLR2, 32); RESTORE(GPIO_GPIDLR3, 32); RESTORE(GPIO_GPIDUR0, 32);RESTORE(GPIO_GPIDUR1, 32);RESTORE(GPIO_GPIDUR2, 32); RESTORE(GPIO_GPIDUR3, 32); RESTORE(GPIO_GPIER0, 32); RESTORE(GPIO_GPIER1, 32); RESTORE(GPIO_GPIER2, 32); RESTORE(GPIO_GPIER3, 32); RESTORE(GPIO_GPIMR0, 32); RESTORE(GPIO_GPIMR1, 32); RESTORE(GPIO_GPIMR2, 32); RESTORE(GPIO_GPIMR3, 32); RESTORE(GPIO_GPFR0, 32); RESTORE(GPIO_GPFR1, 32); RESTORE(GPIO_GPFR2, 32); RESTORE(GPIO_GPFR3, 32); RESTORE(HARB_HAPOR, 32); RESTORE(HARB_HMCTR, 32); RESTORE(HARB_HMLTR, 32); RESTORE(OST_TCNT0, 32); RESTORE(OST_TCNT1, 32); RESTORE(OST_TCNT2, 32); RESTORE(OST_TRDR0, 32); RESTORE(OST_TRDR1, 32); RESTORE(OST_TRDR2, 32); RESTORE(OST_TCSR0, 16); RESTORE(OST_TCSR1, 16); RESTORE(OST_TCSR2, 16); RESTORE(OST_TER, 8); RESTORE(DMAC_DMACR, 32); RESTORE(DMAC_DSAR0, 32); RESTORE(DMAC_DSAR1, 32); RESTORE(DMAC_DSAR2, 32); RESTORE(DMAC_DSAR3, 32); RESTORE(DMAC_DSAR4, 32); RESTORE(DMAC_DSAR5, 32); RESTORE(DMAC_DSAR6, 32); RESTORE(DMAC_DSAR7, 32); RESTORE(DMAC_DDAR0, 32); RESTORE(DMAC_DDAR1, 32); RESTORE(DMAC_DDAR2, 32); RESTORE(DMAC_DDAR3, 32); RESTORE(DMAC_DDAR4, 32); RESTORE(DMAC_DDAR5, 32); RESTORE(DMAC_DDAR6, 32); RESTORE(DMAC_DDAR7, 32); RESTORE(DMAC_DTCR0, 32); RESTORE(DMAC_DTCR1, 32); RESTORE(DMAC_DTCR2, 32); RESTORE(DMAC_DTCR3, 32); RESTORE(DMAC_DTCR4, 32); RESTORE(DMAC_DTCR5, 32); RESTORE(DMAC_DTCR6, 32); RESTORE(DMAC_DTCR7, 32); RESTORE(DMAC_DRSR0, 32); RESTORE(DMAC_DRSR1, 32); RESTORE(DMAC_DRSR2, 32); RESTORE(DMAC_DRSR3, 32); RESTORE(DMAC_DRSR4, 32); RESTORE(DMAC_DRSR5, 32); RESTORE(DMAC_DRSR6, 32); RESTORE(DMAC_DRSR7, 32); RESTORE(DMAC_DCCSR0, 32); RESTORE(DMAC_DCCSR1, 32); RESTORE(DMAC_DCCSR2, 32); RESTORE(DMAC_DCCSR3, 32); RESTORE(DMAC_DCCSR4, 32); RESTORE(DMAC_DCCSR5, 32); RESTORE(DMAC_DCCSR6, 32); RESTORE(DMAC_DCCSR7, 32); RESTORE(INTC_IMR, 32); /* * Temporary solution. This won't be necessary once * we move jz support into the serial driver. * Restore the on-chip UART. */ /* FIFO control reg, write-only */ REG8(UART0_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; REG8(UART1_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; REG8(UART2_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; REG8(UART3_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; REG8(UART0_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ RESTORE(UART0_DLLR, 8); RESTORE(UART0_DLHR, 8); REG8(UART0_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ RESTORE(UART0_IER, 8); RESTORE(UART0_MCR, 8); RESTORE(UART0_SPR, 8); RESTORE(UART0_LCR, 8); REG8(UART1_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ RESTORE(UART1_DLLR, 8); RESTORE(UART1_DLHR, 8); REG8(UART1_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ RESTORE(UART1_IER, 8); RESTORE(UART1_MCR, 8); RESTORE(UART1_SPR, 8); RESTORE(UART1_LCR, 8); REG8(UART2_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ RESTORE(UART2_DLLR, 8); RESTORE(UART2_DLHR, 8); REG8(UART2_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ RESTORE(UART2_IER, 8); RESTORE(UART2_MCR, 8); RESTORE(UART2_SPR, 8); RESTORE(UART2_LCR, 8); REG8(UART3_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ RESTORE(UART3_DLLR, 8); RESTORE(UART3_DLHR, 8); REG8(UART3_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ RESTORE(UART3_IER, 8); RESTORE(UART3_MCR, 8); RESTORE(UART3_SPR, 8); RESTORE(UART3_LCR, 8); REG_CPM_OCR &= ~CPM_OCR_SUSPEND_PHY0; /* resume USB PHY 0 */ REG_CPM_OCR &= ~CPM_OCR_SUSPEND_PHY1; /* resume USB PHY 1 */ REG_CPM_OCR &= ~CPM_OCR_EXT_RTC_CLK; /* reuse internal RTC clock (3686400/128=28.8KHz) */}//=======================================================================//// Global Routines////=======================================================================/********************************************************************************* Name: void pm_cpu_clock(void)** Function: Change the CPU clock during programs are running.** We just allow to change the four clocks: ICLK, SCLK, MCLK, PCLK.** Other clocks such as LCD_CLK, LCD_PIXEL_CLK are unchanged.**** Note 1: We are assuming that the boot clocks are the max values, then** other program calls this function to scale down the four clocks.** PLL output frequency does not change in this implementation.**** Note 2: The four divisors must be confirmed to the constraint conditions** as mentioned in the section << Clock and Power Management>> of** the jz4730 spec.**** Note 3: Valid values for xxx_div have: 1, 2, 3, 4, 6, 8, 12, 16, 24, 32.**** PLL_OUT_FREQ = 3686400 * <NF> / (<NR> * <NO>) -- PLL clock** ICLK = PLL_OUT_FREQ / <ICLK_DIV> -- CPU clock** SCLK = PLL_OUT_FREQ / <SCLK_DIV> -- System bus clock** MCLK = PLL_OUT_FREQ / <MCLK_DIV> -- External memory clock** PCLK = PLL_OUT_FREQ / <PCLK_DIV> -- Peripheral bus clock*********************************************************************************/void pm_cpu_clock(int iclk_div, int sclk_div, int mclk_div, int pclk_div){ int div2val[] = {-1, 0, 1, 2, 3, -1, 4, -1, 5, -1, -1, -1, 6, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, 9}; unsigned int cfcr; unsigned int cur_mclk_val, new_mclk_val, new_rtcor_val; unsigned int tmp = 0, wait = PLL_WAIT_500NS; static int first = 1; if (first) { first = 0; boot_rtcor_val = REG_EMC_RTCOR; boot_mclk_val = __cpm_get_mclk(); } /* * Calc the new value of CFCR register */ cfcr = REG_CPM_CFCR; /* current value of CFCR register */ cfcr &= ~(CPM_CFCR_IFR_MASK | CPM_CFCR_SFR_MASK | CPM_CFCR_MFR_MASK | CPM_CFCR_PFR_MASK); cfcr |= (div2val[iclk_div] << CPM_CFCR_IFR_BIT) | (div2val[sclk_div] << CPM_CFCR_SFR_BIT) | (div2val[mclk_div] << CPM_CFCR_MFR_BIT) | (div2val[pclk_div] << CPM_CFCR_PFR_BIT); cfcr |= CPM_CFCR_UPE; /* update immediately */ /* * Update some SDRAM parameters. * Here we need to update the refresh constant. */ cur_mclk_val = __cpm_get_mclk(); new_mclk_val = __cpm_get_pllout() / mclk_div; new_rtcor_val = boot_rtcor_val * new_mclk_val / boot_mclk_val; if (new_rtcor_val < 1) new_rtcor_val = 1; if (new_rtcor_val > 255) new_rtcor_val = 255; /* * Stop module clocks here .. */ __cpm_stop_aic(1); __cpm_stop_aic(2); /* We're going SLOWER: first update RTCOR value * before changing the frequency. */ if (new_mclk_val < cur_mclk_val) { REG_EMC_RTCOR = new_rtcor_val; REG_EMC_RTCNT = new_rtcor_val; } /* update register to change the clocks. * align this code to a cache line. */ __asm__ __volatile__( ".set noreorder\n\t" ".align 5\n" "sw %1,0(%0)\n\t" "li %3,0\n\t" "1:\n\t" "bne %3,%2,1b\n\t" "addi %3, 1\n\t" "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" ".set reorder\n\t" : : "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp)); /* We're going FASTER, so update RTCOR * after changing the frequency */ if (new_mclk_val > cur_mclk_val) { REG_EMC_RTCOR = new_rtcor_val; REG_EMC_RTCNT = new_rtcor_val; } /* * Restart module clocks here .. */ __cpm_start_aic(1); __cpm_start_aic(2);#if 0 printf("freqs: cpu_clk=%dMHz sys_clk=%dMHz mem_clk=%dMHz per_clk=%dMHz\n", __cpm_get_iclk()/1000000, __cpm_get_sclk()/1000000, __cpm_get_mclk()/1000000, __cpm_get_pclk()/1000000);#endif}/*********************************************************************** * void pm_cpu_suspend(void) * * This is called externally to do the CPU suspend. * ***********************************************************************/void pm_cpu_suspend(void){ pm_cpu_suspend_enter(); do_pm_cpu_suspend(); pm_cpu_suspend_exit();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -