1/* 2 * arch/arm/mach-at91/pm_slow_clock.S 3 * 4 * Copyright (C) 2006 Savin Zlobec 5 * 6 * AT91SAM9 support: 7 * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14#include <linux/linkage.h> 15#include <linux/clk/at91_pmc.h> 16#include <mach/at91_ramc.h> 17#include "pm.h" 18 19#define SRAMC_SELF_FRESH_ACTIVE 0x01 20#define SRAMC_SELF_FRESH_EXIT 0x00 21 22pmc .req r0 23tmp1 .req r4 24tmp2 .req r5 25 26/* 27 * Wait until master clock is ready (after switching master clock source) 28 */ 29 .macro wait_mckrdy 301: ldr tmp1, [pmc, #AT91_PMC_SR] 31 tst tmp1, #AT91_PMC_MCKRDY 32 beq 1b 33 .endm 34 35/* 36 * Wait until master oscillator has stabilized. 37 */ 38 .macro wait_moscrdy 391: ldr tmp1, [pmc, #AT91_PMC_SR] 40 tst tmp1, #AT91_PMC_MOSCS 41 beq 1b 42 .endm 43 44/* 45 * Wait until PLLA has locked. 46 */ 47 .macro wait_pllalock 481: ldr tmp1, [pmc, #AT91_PMC_SR] 49 tst tmp1, #AT91_PMC_LOCKA 50 beq 1b 51 .endm 52 53/* 54 * Put the processor to enter the idle state 55 */ 56 .macro at91_cpu_idle 57 58#if defined(CONFIG_CPU_V7) 59 mov tmp1, #AT91_PMC_PCK 60 str tmp1, [pmc, #AT91_PMC_SCDR] 61 62 dsb 63 64 wfi @ Wait For Interrupt 65#else 66 mcr p15, 0, tmp1, c7, c0, 4 67#endif 68 69 .endm 70 71 .text 72 73 .arm 74 75/* 76 * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc, 77 * void __iomem *ramc1, int memctrl) 78 * @input param: 79 * @r0: base address of AT91_PMC 80 * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS) 81 * @r2: base address of second SDRAM Controller or 0 if not present 82 * @r3: pm information 83 */ 84/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ 85 .align 3 86ENTRY(at91_pm_suspend_in_sram) 87 /* Save registers on stack */ 88 stmfd sp!, {r4 - r12, lr} 89 90 /* Drain write buffer */ 91 mov tmp1, #0 92 mcr p15, 0, tmp1, c7, c10, 4 93 94 str r0, .pmc_base 95 str r1, .sramc_base 96 str r2, .sramc1_base 97 98 and r0, r3, #AT91_PM_MEMTYPE_MASK 99 str r0, .memtype 100 101 lsr r0, r3, #AT91_PM_MODE_OFFSET 102 and r0, r0, #AT91_PM_MODE_MASK 103 str r0, .pm_mode 104 105 /* Active the self-refresh mode */ 106 mov r0, #SRAMC_SELF_FRESH_ACTIVE 107 bl at91_sramc_self_refresh 108 109 ldr r0, .pm_mode 110 tst r0, #AT91_PM_SLOW_CLOCK 111 beq skip_disable_main_clock 112 113 ldr pmc, .pmc_base 114 115 /* Save Master clock setting */ 116 ldr tmp1, [pmc, #AT91_PMC_MCKR] 117 str tmp1, .saved_mckr 118 119 /* 120 * Set the Master clock source to slow clock 121 */ 122 bic tmp1, tmp1, #AT91_PMC_CSS 123 str tmp1, [pmc, #AT91_PMC_MCKR] 124 125 wait_mckrdy 126 127 /* Save PLLA setting and disable it */ 128 ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 129 str tmp1, .saved_pllar 130 131 mov tmp1, #AT91_PMC_PLLCOUNT 132 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 133 str tmp1, [pmc, #AT91_CKGR_PLLAR] 134 135 /* Turn off the main oscillator */ 136 ldr tmp1, [pmc, #AT91_CKGR_MOR] 137 bic tmp1, tmp1, #AT91_PMC_MOSCEN 138 orr tmp1, tmp1, #AT91_PMC_KEY 139 str tmp1, [pmc, #AT91_CKGR_MOR] 140 141skip_disable_main_clock: 142 ldr pmc, .pmc_base 143 144 /* Wait for interrupt */ 145 at91_cpu_idle 146 147 ldr r0, .pm_mode 148 tst r0, #AT91_PM_SLOW_CLOCK 149 beq skip_enable_main_clock 150 151 ldr pmc, .pmc_base 152 153 /* Turn on the main oscillator */ 154 ldr tmp1, [pmc, #AT91_CKGR_MOR] 155 orr tmp1, tmp1, #AT91_PMC_MOSCEN 156 orr tmp1, tmp1, #AT91_PMC_KEY 157 str tmp1, [pmc, #AT91_CKGR_MOR] 158 159 wait_moscrdy 160 161 /* Restore PLLA setting */ 162 ldr tmp1, .saved_pllar 163 str tmp1, [pmc, #AT91_CKGR_PLLAR] 164 165 tst tmp1, #(AT91_PMC_MUL & 0xff0000) 166 bne 3f 167 tst tmp1, #(AT91_PMC_MUL & ~0xff0000) 168 beq 4f 1693: 170 wait_pllalock 1714: 172 173 /* 174 * Restore master clock setting 175 */ 176 ldr tmp1, .saved_mckr 177 str tmp1, [pmc, #AT91_PMC_MCKR] 178 179 wait_mckrdy 180 181skip_enable_main_clock: 182 /* Exit the self-refresh mode */ 183 mov r0, #SRAMC_SELF_FRESH_EXIT 184 bl at91_sramc_self_refresh 185 186 /* Restore registers, and return */ 187 ldmfd sp!, {r4 - r12, pc} 188ENDPROC(at91_pm_suspend_in_sram) 189 190/* 191 * void at91_sramc_self_refresh(unsigned int is_active) 192 * 193 * @input param: 194 * @r0: 1 - active self-refresh mode 195 * 0 - exit self-refresh mode 196 * register usage: 197 * @r1: memory type 198 * @r2: base address of the sram controller 199 */ 200 201ENTRY(at91_sramc_self_refresh) 202 ldr r1, .memtype 203 ldr r2, .sramc_base 204 205 cmp r1, #AT91_MEMCTRL_MC 206 bne ddrc_sf 207 208 /* 209 * at91rm9200 Memory controller 210 */ 211 212 /* 213 * For exiting the self-refresh mode, do nothing, 214 * automatically exit the self-refresh mode. 215 */ 216 tst r0, #SRAMC_SELF_FRESH_ACTIVE 217 beq exit_sramc_sf 218 219 /* Active SDRAM self-refresh mode */ 220 mov r3, #1 221 str r3, [r2, #AT91RM9200_SDRAMC_SRR] 222 b exit_sramc_sf 223 224ddrc_sf: 225 cmp r1, #AT91_MEMCTRL_DDRSDR 226 bne sdramc_sf 227 228 /* 229 * DDR Memory controller 230 */ 231 tst r0, #SRAMC_SELF_FRESH_ACTIVE 232 beq ddrc_exit_sf 233 234 /* LPDDR1 --> force DDR2 mode during self-refresh */ 235 ldr r3, [r2, #AT91_DDRSDRC_MDR] 236 str r3, .saved_sam9_mdr 237 bic r3, r3, #~AT91_DDRSDRC_MD 238 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 239 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 240 biceq r3, r3, #AT91_DDRSDRC_MD 241 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 242 streq r3, [r2, #AT91_DDRSDRC_MDR] 243 244 /* Active DDRC self-refresh mode */ 245 ldr r3, [r2, #AT91_DDRSDRC_LPR] 246 str r3, .saved_sam9_lpr 247 bic r3, r3, #AT91_DDRSDRC_LPCB 248 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 249 str r3, [r2, #AT91_DDRSDRC_LPR] 250 251 /* If using the 2nd ddr controller */ 252 ldr r2, .sramc1_base 253 cmp r2, #0 254 beq no_2nd_ddrc 255 256 ldr r3, [r2, #AT91_DDRSDRC_MDR] 257 str r3, .saved_sam9_mdr1 258 bic r3, r3, #~AT91_DDRSDRC_MD 259 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 260 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 261 biceq r3, r3, #AT91_DDRSDRC_MD 262 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 263 streq r3, [r2, #AT91_DDRSDRC_MDR] 264 265 /* Active DDRC self-refresh mode */ 266 ldr r3, [r2, #AT91_DDRSDRC_LPR] 267 str r3, .saved_sam9_lpr1 268 bic r3, r3, #AT91_DDRSDRC_LPCB 269 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 270 str r3, [r2, #AT91_DDRSDRC_LPR] 271 272no_2nd_ddrc: 273 b exit_sramc_sf 274 275ddrc_exit_sf: 276 /* Restore MDR in case of LPDDR1 */ 277 ldr r3, .saved_sam9_mdr 278 str r3, [r2, #AT91_DDRSDRC_MDR] 279 /* Restore LPR on AT91 with DDRAM */ 280 ldr r3, .saved_sam9_lpr 281 str r3, [r2, #AT91_DDRSDRC_LPR] 282 283 /* If using the 2nd ddr controller */ 284 ldr r2, .sramc1_base 285 cmp r2, #0 286 ldrne r3, .saved_sam9_mdr1 287 strne r3, [r2, #AT91_DDRSDRC_MDR] 288 ldrne r3, .saved_sam9_lpr1 289 strne r3, [r2, #AT91_DDRSDRC_LPR] 290 291 b exit_sramc_sf 292 293 /* 294 * SDRAMC Memory controller 295 */ 296sdramc_sf: 297 tst r0, #SRAMC_SELF_FRESH_ACTIVE 298 beq sdramc_exit_sf 299 300 /* Active SDRAMC self-refresh mode */ 301 ldr r3, [r2, #AT91_SDRAMC_LPR] 302 str r3, .saved_sam9_lpr 303 bic r3, r3, #AT91_SDRAMC_LPCB 304 orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH 305 str r3, [r2, #AT91_SDRAMC_LPR] 306 307sdramc_exit_sf: 308 ldr r3, .saved_sam9_lpr 309 str r3, [r2, #AT91_SDRAMC_LPR] 310 311exit_sramc_sf: 312 mov pc, lr 313ENDPROC(at91_sramc_self_refresh) 314 315.pmc_base: 316 .word 0 317.sramc_base: 318 .word 0 319.sramc1_base: 320 .word 0 321.memtype: 322 .word 0 323.pm_mode: 324 .word 0 325.saved_mckr: 326 .word 0 327.saved_pllar: 328 .word 0 329.saved_sam9_lpr: 330 .word 0 331.saved_sam9_lpr1: 332 .word 0 333.saved_sam9_mdr: 334 .word 0 335.saved_sam9_mdr1: 336 .word 0 337 338ENTRY(at91_pm_suspend_in_sram_sz) 339 .word .-at91_pm_suspend_in_sram 340