Root/
1 | /* |
2 | * arch/arm/mach-lpc32xx/suspend.S |
3 | * |
4 | * Original authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com> |
5 | * Modified by Kevin Wells <kevin.wells@nxp.com> |
6 | * |
7 | * 2005 (c) MontaVista Software, Inc. This file is licensed under |
8 | * the terms of the GNU General Public License version 2. This program |
9 | * is licensed "as is" without any warranty of any kind, whether express |
10 | * or implied. |
11 | */ |
12 | #include <linux/linkage.h> |
13 | #include <asm/assembler.h> |
14 | #include <mach/platform.h> |
15 | #include <mach/hardware.h> |
16 | |
17 | /* Using named register defines makes the code easier to follow */ |
18 | #define WORK1_REG r0 |
19 | #define WORK2_REG r1 |
20 | #define SAVED_HCLK_DIV_REG r2 |
21 | #define SAVED_HCLK_PLL_REG r3 |
22 | #define SAVED_DRAM_CLKCTRL_REG r4 |
23 | #define SAVED_PWR_CTRL_REG r5 |
24 | #define CLKPWRBASE_REG r6 |
25 | #define EMCBASE_REG r7 |
26 | |
27 | #define LPC32XX_EMC_STATUS_OFFS 0x04 |
28 | #define LPC32XX_EMC_STATUS_BUSY 0x1 |
29 | #define LPC32XX_EMC_STATUS_SELF_RFSH 0x4 |
30 | |
31 | #define LPC32XX_CLKPWR_PWR_CTRL_OFFS 0x44 |
32 | #define LPC32XX_CLKPWR_HCLK_DIV_OFFS 0x40 |
33 | #define LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS 0x58 |
34 | |
35 | #define CLKPWR_PCLK_DIV_MASK 0xFFFFFE7F |
36 | |
37 | .text |
38 | |
39 | ENTRY(lpc32xx_sys_suspend) |
40 | @ Save a copy of the used registers in IRAM, r0 is corrupted |
41 | adr r0, tmp_stack_end |
42 | stmfd r0!, {r3 - r7, sp, lr} |
43 | |
44 | @ Load a few common register addresses |
45 | adr WORK1_REG, reg_bases |
46 | ldr CLKPWRBASE_REG, [WORK1_REG, #0] |
47 | ldr EMCBASE_REG, [WORK1_REG, #4] |
48 | |
49 | ldr SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\ |
50 | #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
51 | orr WORK1_REG, SAVED_PWR_CTRL_REG, #LPC32XX_CLKPWR_SDRAM_SELF_RFSH |
52 | |
53 | @ Wait for SDRAM busy status to go busy and then idle |
54 | @ This guarantees a small windows where DRAM isn't busy |
55 | 1: |
56 | ldr WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS] |
57 | and WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY |
58 | cmp WORK2_REG, #LPC32XX_EMC_STATUS_BUSY |
59 | bne 1b @ Branch while idle |
60 | 2: |
61 | ldr WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS] |
62 | and WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY |
63 | cmp WORK2_REG, #LPC32XX_EMC_STATUS_BUSY |
64 | beq 2b @ Branch until idle |
65 | |
66 | @ Setup self-refresh with support for manual exit of |
67 | @ self-refresh mode |
68 | str WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
69 | orr WORK2_REG, WORK1_REG, #LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH |
70 | str WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
71 | str WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
72 | |
73 | @ Wait for self-refresh acknowledge, clocks to the DRAM device |
74 | @ will automatically stop on start of self-refresh |
75 | 3: |
76 | ldr WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS] |
77 | and WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH |
78 | cmp WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH |
79 | bne 3b @ Branch until self-refresh mode starts |
80 | |
81 | @ Enter direct-run mode from run mode |
82 | bic WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_SELECT_RUN_MODE |
83 | str WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
84 | |
85 | @ Safe disable of DRAM clock in EMC block, prevents DDR sync |
86 | @ issues on restart |
87 | ldr SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\ |
88 | #LPC32XX_CLKPWR_HCLK_DIV_OFFS] |
89 | and WORK2_REG, SAVED_HCLK_DIV_REG, #CLKPWR_PCLK_DIV_MASK |
90 | str WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLK_DIV_OFFS] |
91 | |
92 | @ Save HCLK PLL state and disable HCLK PLL |
93 | ldr SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\ |
94 | #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS] |
95 | bic WORK2_REG, SAVED_HCLK_PLL_REG, #LPC32XX_CLKPWR_HCLKPLL_POWER_UP |
96 | str WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS] |
97 | |
98 | @ Enter stop mode until an enabled event occurs |
99 | orr WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL |
100 | str WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
101 | .rept 9 |
102 | nop |
103 | .endr |
104 | |
105 | @ Clear stop status |
106 | bic WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL |
107 | |
108 | @ Restore original HCLK PLL value and wait for PLL lock |
109 | str SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\ |
110 | #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS] |
111 | 4: |
112 | ldr WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS] |
113 | and WORK2_REG, WORK2_REG, #LPC32XX_CLKPWR_HCLKPLL_PLL_STS |
114 | bne 4b |
115 | |
116 | @ Re-enter run mode with self-refresh flag cleared, but no DRAM |
117 | @ update yet. DRAM is still in self-refresh |
118 | str SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\ |
119 | #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
120 | |
121 | @ Restore original DRAM clock mode to restore DRAM clocks |
122 | str SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\ |
123 | #LPC32XX_CLKPWR_HCLK_DIV_OFFS] |
124 | |
125 | @ Clear self-refresh mode |
126 | orr WORK1_REG, SAVED_PWR_CTRL_REG,\ |
127 | #LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH |
128 | str WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
129 | str SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\ |
130 | #LPC32XX_CLKPWR_PWR_CTRL_OFFS] |
131 | |
132 | @ Wait for EMC to clear self-refresh mode |
133 | 5: |
134 | ldr WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS] |
135 | and WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH |
136 | bne 5b @ Branch until self-refresh has exited |
137 | |
138 | @ restore regs and return |
139 | adr r0, tmp_stack |
140 | ldmfd r0!, {r3 - r7, sp, pc} |
141 | |
142 | reg_bases: |
143 | .long IO_ADDRESS(LPC32XX_CLK_PM_BASE) |
144 | .long IO_ADDRESS(LPC32XX_EMC_BASE) |
145 | |
146 | tmp_stack: |
147 | .long 0, 0, 0, 0, 0, 0, 0 |
148 | tmp_stack_end: |
149 | |
150 | ENTRY(lpc32xx_sys_suspend_sz) |
151 | .word . - lpc32xx_sys_suspend |
152 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9