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 "pm.h" 17#include "generated/at91_pm_data-offsets.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_suspend_sram_fn(struct at91_pm_data*) 77 * @input param: 78 * @r0: base address of struct at91_pm_data 79 */ 80/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ 81 .align 3 82ENTRY(at91_pm_suspend_in_sram) 83 /* Save registers on stack */ 84 stmfd sp!, {r4 - r12, lr} 85 86 /* Drain write buffer */ 87 mov tmp1, #0 88 mcr p15, 0, tmp1, c7, c10, 4 89 90 ldr tmp1, [r0, #PM_DATA_PMC] 91 str tmp1, .pmc_base 92 ldr tmp1, [r0, #PM_DATA_RAMC0] 93 str tmp1, .sramc_base 94 ldr tmp1, [r0, #PM_DATA_RAMC1] 95 str tmp1, .sramc1_base 96 ldr tmp1, [r0, #PM_DATA_MEMCTRL] 97 str tmp1, .memtype 98 ldr tmp1, [r0, #PM_DATA_MODE] 99 str tmp1, .pm_mode 100 101 /* Active the self-refresh mode */ 102 mov r0, #SRAMC_SELF_FRESH_ACTIVE 103 bl at91_sramc_self_refresh 104 105 ldr r0, .pm_mode 106 tst r0, #AT91_PM_SLOW_CLOCK 107 beq skip_disable_main_clock 108 109 ldr pmc, .pmc_base 110 111 /* Save Master clock setting */ 112 ldr tmp1, [pmc, #AT91_PMC_MCKR] 113 str tmp1, .saved_mckr 114 115 /* 116 * Set the Master clock source to slow clock 117 */ 118 bic tmp1, tmp1, #AT91_PMC_CSS 119 str tmp1, [pmc, #AT91_PMC_MCKR] 120 121 wait_mckrdy 122 123 /* Save PLLA setting and disable it */ 124 ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 125 str tmp1, .saved_pllar 126 127 mov tmp1, #AT91_PMC_PLLCOUNT 128 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 129 str tmp1, [pmc, #AT91_CKGR_PLLAR] 130 131 /* Turn off the main oscillator */ 132 ldr tmp1, [pmc, #AT91_CKGR_MOR] 133 bic tmp1, tmp1, #AT91_PMC_MOSCEN 134 orr tmp1, tmp1, #AT91_PMC_KEY 135 str tmp1, [pmc, #AT91_CKGR_MOR] 136 137skip_disable_main_clock: 138 ldr pmc, .pmc_base 139 140 /* Wait for interrupt */ 141 at91_cpu_idle 142 143 ldr r0, .pm_mode 144 tst r0, #AT91_PM_SLOW_CLOCK 145 beq skip_enable_main_clock 146 147 ldr pmc, .pmc_base 148 149 /* Turn on the main oscillator */ 150 ldr tmp1, [pmc, #AT91_CKGR_MOR] 151 orr tmp1, tmp1, #AT91_PMC_MOSCEN 152 orr tmp1, tmp1, #AT91_PMC_KEY 153 str tmp1, [pmc, #AT91_CKGR_MOR] 154 155 wait_moscrdy 156 157 /* Restore PLLA setting */ 158 ldr tmp1, .saved_pllar 159 str tmp1, [pmc, #AT91_CKGR_PLLAR] 160 161 tst tmp1, #(AT91_PMC_MUL & 0xff0000) 162 bne 3f 163 tst tmp1, #(AT91_PMC_MUL & ~0xff0000) 164 beq 4f 1653: 166 wait_pllalock 1674: 168 169 /* 170 * Restore master clock setting 171 */ 172 ldr tmp1, .saved_mckr 173 str tmp1, [pmc, #AT91_PMC_MCKR] 174 175 wait_mckrdy 176 177skip_enable_main_clock: 178 /* Exit the self-refresh mode */ 179 mov r0, #SRAMC_SELF_FRESH_EXIT 180 bl at91_sramc_self_refresh 181 182 /* Restore registers, and return */ 183 ldmfd sp!, {r4 - r12, pc} 184ENDPROC(at91_pm_suspend_in_sram) 185 186/* 187 * void at91_sramc_self_refresh(unsigned int is_active) 188 * 189 * @input param: 190 * @r0: 1 - active self-refresh mode 191 * 0 - exit self-refresh mode 192 * register usage: 193 * @r1: memory type 194 * @r2: base address of the sram controller 195 */ 196 197ENTRY(at91_sramc_self_refresh) 198 ldr r1, .memtype 199 ldr r2, .sramc_base 200 201 cmp r1, #AT91_MEMCTRL_MC 202 bne ddrc_sf 203 204 /* 205 * at91rm9200 Memory controller 206 */ 207 208 /* 209 * For exiting the self-refresh mode, do nothing, 210 * automatically exit the self-refresh mode. 211 */ 212 tst r0, #SRAMC_SELF_FRESH_ACTIVE 213 beq exit_sramc_sf 214 215 /* Active SDRAM self-refresh mode */ 216 mov r3, #1 217 str r3, [r2, #AT91_MC_SDRAMC_SRR] 218 b exit_sramc_sf 219 220ddrc_sf: 221 cmp r1, #AT91_MEMCTRL_DDRSDR 222 bne sdramc_sf 223 224 /* 225 * DDR Memory controller 226 */ 227 tst r0, #SRAMC_SELF_FRESH_ACTIVE 228 beq ddrc_exit_sf 229 230 /* LPDDR1 --> force DDR2 mode during self-refresh */ 231 ldr r3, [r2, #AT91_DDRSDRC_MDR] 232 str r3, .saved_sam9_mdr 233 bic r3, r3, #~AT91_DDRSDRC_MD 234 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 235 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 236 biceq r3, r3, #AT91_DDRSDRC_MD 237 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 238 streq r3, [r2, #AT91_DDRSDRC_MDR] 239 240 /* Active DDRC self-refresh mode */ 241 ldr r3, [r2, #AT91_DDRSDRC_LPR] 242 str r3, .saved_sam9_lpr 243 bic r3, r3, #AT91_DDRSDRC_LPCB 244 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 245 str r3, [r2, #AT91_DDRSDRC_LPR] 246 247 /* If using the 2nd ddr controller */ 248 ldr r2, .sramc1_base 249 cmp r2, #0 250 beq no_2nd_ddrc 251 252 ldr r3, [r2, #AT91_DDRSDRC_MDR] 253 str r3, .saved_sam9_mdr1 254 bic r3, r3, #~AT91_DDRSDRC_MD 255 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 256 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 257 biceq r3, r3, #AT91_DDRSDRC_MD 258 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 259 streq r3, [r2, #AT91_DDRSDRC_MDR] 260 261 /* Active DDRC self-refresh mode */ 262 ldr r3, [r2, #AT91_DDRSDRC_LPR] 263 str r3, .saved_sam9_lpr1 264 bic r3, r3, #AT91_DDRSDRC_LPCB 265 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 266 str r3, [r2, #AT91_DDRSDRC_LPR] 267 268no_2nd_ddrc: 269 b exit_sramc_sf 270 271ddrc_exit_sf: 272 /* Restore MDR in case of LPDDR1 */ 273 ldr r3, .saved_sam9_mdr 274 str r3, [r2, #AT91_DDRSDRC_MDR] 275 /* Restore LPR on AT91 with DDRAM */ 276 ldr r3, .saved_sam9_lpr 277 str r3, [r2, #AT91_DDRSDRC_LPR] 278 279 /* If using the 2nd ddr controller */ 280 ldr r2, .sramc1_base 281 cmp r2, #0 282 ldrne r3, .saved_sam9_mdr1 283 strne r3, [r2, #AT91_DDRSDRC_MDR] 284 ldrne r3, .saved_sam9_lpr1 285 strne r3, [r2, #AT91_DDRSDRC_LPR] 286 287 b exit_sramc_sf 288 289 /* 290 * SDRAMC Memory controller 291 */ 292sdramc_sf: 293 tst r0, #SRAMC_SELF_FRESH_ACTIVE 294 beq sdramc_exit_sf 295 296 /* Active SDRAMC self-refresh mode */ 297 ldr r3, [r2, #AT91_SDRAMC_LPR] 298 str r3, .saved_sam9_lpr 299 bic r3, r3, #AT91_SDRAMC_LPCB 300 orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH 301 str r3, [r2, #AT91_SDRAMC_LPR] 302 303sdramc_exit_sf: 304 ldr r3, .saved_sam9_lpr 305 str r3, [r2, #AT91_SDRAMC_LPR] 306 307exit_sramc_sf: 308 mov pc, lr 309ENDPROC(at91_sramc_self_refresh) 310 311.pmc_base: 312 .word 0 313.sramc_base: 314 .word 0 315.sramc1_base: 316 .word 0 317.memtype: 318 .word 0 319.pm_mode: 320 .word 0 321.saved_mckr: 322 .word 0 323.saved_pllar: 324 .word 0 325.saved_sam9_lpr: 326 .word 0 327.saved_sam9_lpr1: 328 .word 0 329.saved_sam9_mdr: 330 .word 0 331.saved_sam9_mdr1: 332 .word 0 333 334ENTRY(at91_pm_suspend_in_sram_sz) 335 .word .-at91_pm_suspend_in_sram 336