1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * arch/arm/mach-lpc32xx/suspend.S 4 * 5 * Original authors: Dmitry Chigirev, Vitaly W< 6 * Modified by Kevin Wells <kevin.wells@nxp.com 7 * 8 * 2005 (c) MontaVista Software, Inc. 9 */ 10 #include <linux/linkage.h> 11 #include <asm/assembler.h> 12 #include "lpc32xx.h" 13 14 /* Using named register defines makes the code 15 #define WORK1_REG r0 16 #define WORK2_REG r1 17 #define SAVED_HCLK_DIV_REG r2 18 #define SAVED_HCLK_PLL_REG r3 19 #define SAVED_DRAM_CLKCTRL_REG r4 20 #define SAVED_PWR_CTRL_REG r5 21 #define CLKPWRBASE_REG r6 22 #define EMCBASE_REG r7 23 24 #define LPC32XX_EMC_STATUS_OFFS 0x04 25 #define LPC32XX_EMC_STATUS_BUSY 0x1 26 #define LPC32XX_EMC_STATUS_SELF_RFSH 0x4 27 28 #define LPC32XX_CLKPWR_PWR_CTRL_OFFS 0x44 29 #define LPC32XX_CLKPWR_HCLK_DIV_OFFS 0x40 30 #define LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS 0x58 31 32 #define CLKPWR_PCLK_DIV_MASK 0xFFFF 33 34 .text 35 36 ENTRY(lpc32xx_sys_suspend) 37 @ Save a copy of the used registers in 38 adr r0, tmp_stack_end 39 stmfd r0!, {r3 - r7, sp, lr} 40 41 @ Load a few common register addresses 42 adr WORK1_REG, reg_bases 43 ldr CLKPWRBASE_REG, [WORK1_REG, #0 44 ldr EMCBASE_REG, [WORK1_REG, #4] 45 46 ldr SAVED_PWR_CTRL_REG, [CLKPWRBAS 47 #LPC32XX_CLKPWR_PWR_CTRL_OFFS] 48 orr WORK1_REG, SAVED_PWR_CTRL_REG, 49 50 @ Wait for SDRAM busy status to go bus 51 @ This guarantees a small windows wher 52 1: 53 ldr WORK2_REG, [EMCBASE_REG, #LPC3 54 and WORK2_REG, WORK2_REG, #LPC32XX 55 cmp WORK2_REG, #LPC32XX_EMC_STATUS 56 bne 1b @ Branch while idle 57 2: 58 ldr WORK2_REG, [EMCBASE_REG, #LPC3 59 and WORK2_REG, WORK2_REG, #LPC32XX 60 cmp WORK2_REG, #LPC32XX_EMC_STATUS 61 beq 2b @ Branch until idle 62 63 @ Setup self-refresh with support for 64 @ self-refresh mode 65 str WORK1_REG, [CLKPWRBASE_REG, #L 66 orr WORK2_REG, WORK1_REG, #LPC32XX 67 str WORK2_REG, [CLKPWRBASE_REG, #L 68 str WORK1_REG, [CLKPWRBASE_REG, #L 69 70 @ Wait for self-refresh acknowledge, c 71 @ will automatically stop on start of 72 3: 73 ldr WORK2_REG, [EMCBASE_REG, #LPC3 74 and WORK2_REG, WORK2_REG, #LPC32XX 75 cmp WORK2_REG, #LPC32XX_EMC_STATUS 76 bne 3b @ Branch until self-refresh 77 78 @ Enter direct-run mode from run mode 79 bic WORK1_REG, WORK1_REG, #LPC32XX 80 str WORK1_REG, [CLKPWRBASE_REG, #L 81 82 @ Safe disable of DRAM clock in EMC bl 83 @ issues on restart 84 ldr SAVED_HCLK_DIV_REG, [CLKPWRBAS 85 #LPC32XX_CLKPWR_HCLK_DIV_OFFS] 86 and WORK2_REG, SAVED_HCLK_DIV_REG, 87 str WORK2_REG, [CLKPWRBASE_REG, #L 88 89 @ Save HCLK PLL state and disable HCLK 90 ldr SAVED_HCLK_PLL_REG, [CLKPWRBAS 91 #LPC32XX_CLKPWR_HCLKPLL_CTRL_O 92 bic WORK2_REG, SAVED_HCLK_PLL_REG, 93 str WORK2_REG, [CLKPWRBASE_REG, #L 94 95 @ Enter stop mode until an enabled eve 96 orr WORK1_REG, WORK1_REG, #LPC32XX 97 str WORK1_REG, [CLKPWRBASE_REG, #L 98 .rept 9 99 nop 100 .endr 101 102 @ Clear stop status 103 bic WORK1_REG, WORK1_REG, #LPC32XX 104 105 @ Restore original HCLK PLL value and 106 str SAVED_HCLK_PLL_REG, [CLKPWRBAS 107 #LPC32XX_CLKPWR_HCLKPLL_CTRL_O 108 4: 109 ldr WORK2_REG, [CLKPWRBASE_REG, #L 110 and WORK2_REG, WORK2_REG, #LPC32XX 111 bne 4b 112 113 @ Re-enter run mode with self-refresh 114 @ update yet. DRAM is still in self-re 115 str SAVED_PWR_CTRL_REG, [CLKPWRBAS 116 #LPC32XX_CLKPWR_PWR_CTRL_OFFS] 117 118 @ Restore original DRAM clock mode to 119 str SAVED_HCLK_DIV_REG, [CLKPWRBAS 120 #LPC32XX_CLKPWR_HCLK_DIV_OFFS] 121 122 @ Clear self-refresh mode 123 orr WORK1_REG, SAVED_PWR_CTRL_REG, 124 #LPC32XX_CLKPWR_UPD_SDRAM_SELF 125 str WORK1_REG, [CLKPWRBASE_REG, #L 126 str SAVED_PWR_CTRL_REG, [CLKPWRBAS 127 #LPC32XX_CLKPWR_PWR_CTRL_OFFS] 128 129 @ Wait for EMC to clear self-refresh m 130 5: 131 ldr WORK2_REG, [EMCBASE_REG, #LPC3 132 and WORK2_REG, WORK2_REG, #LPC32XX 133 bne 5b @ Branch until self-refresh 134 135 @ restore regs and return 136 adr r0, tmp_stack 137 ldmfd r0!, {r3 - r7, sp, pc} 138 139 reg_bases: 140 .long IO_ADDRESS(LPC32XX_CLK_PM_BASE 141 .long IO_ADDRESS(LPC32XX_EMC_BASE) 142 143 tmp_stack: 144 .long 0, 0, 0, 0, 0, 0, 0 145 tmp_stack_end: 146 147 ENTRY(lpc32xx_sys_suspend_sz) 148 .word . - lpc32xx_sys_suspend
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.