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 /* Both ldrne below are here to preload their address in the TLB */ 101 ldr tmp1, [r0, #PM_DATA_SHDWC] 102 str tmp1, .shdwc 103 cmp tmp1, #0 104 ldrne tmp2, [tmp1, #0] 105 ldr tmp1, [r0, #PM_DATA_SFRBU] 106 str tmp1, .sfr 107 cmp tmp1, #0 108 ldrne tmp2, [tmp1, #0x10] 109 110 /* Active the self-refresh mode */ 111 mov r0, #SRAMC_SELF_FRESH_ACTIVE 112 bl at91_sramc_self_refresh 113 114 ldr r0, .pm_mode 115 cmp r0, #AT91_PM_SLOW_CLOCK 116 beq slow_clock 117 cmp r0, #AT91_PM_BACKUP 118 beq backup_mode 119 120 /* Wait for interrupt */ 121 ldr pmc, .pmc_base 122 at91_cpu_idle 123 b exit_suspend 124 125slow_clock: 126 bl at91_slowck_mode 127 b exit_suspend 128backup_mode: 129 bl at91_backup_mode 130 b exit_suspend 131 132exit_suspend: 133 /* Exit the self-refresh mode */ 134 mov r0, #SRAMC_SELF_FRESH_EXIT 135 bl at91_sramc_self_refresh 136 137 /* Restore registers, and return */ 138 ldmfd sp!, {r4 - r12, pc} 139ENDPROC(at91_pm_suspend_in_sram) 140 141ENTRY(at91_backup_mode) 142 /*BUMEN*/ 143 ldr r0, .sfr 144 mov tmp1, #0x1 145 str tmp1, [r0, #0x10] 146 147 /* Shutdown */ 148 ldr r0, .shdwc 149 mov tmp1, #0xA5000000 150 add tmp1, tmp1, #0x1 151 str tmp1, [r0, #0] 152ENDPROC(at91_backup_mode) 153 154ENTRY(at91_slowck_mode) 155 ldr pmc, .pmc_base 156 157 /* Save Master clock setting */ 158 ldr tmp1, [pmc, #AT91_PMC_MCKR] 159 str tmp1, .saved_mckr 160 161 /* 162 * Set the Master clock source to slow clock 163 */ 164 bic tmp1, tmp1, #AT91_PMC_CSS 165 str tmp1, [pmc, #AT91_PMC_MCKR] 166 167 wait_mckrdy 168 169 /* Save PLLA setting and disable it */ 170 ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 171 str tmp1, .saved_pllar 172 173 mov tmp1, #AT91_PMC_PLLCOUNT 174 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 175 str tmp1, [pmc, #AT91_CKGR_PLLAR] 176 177 /* Turn off the main oscillator */ 178 ldr tmp1, [pmc, #AT91_CKGR_MOR] 179 bic tmp1, tmp1, #AT91_PMC_MOSCEN 180 orr tmp1, tmp1, #AT91_PMC_KEY 181 str tmp1, [pmc, #AT91_CKGR_MOR] 182 183 /* Wait for interrupt */ 184 at91_cpu_idle 185 186 /* Turn on the main oscillator */ 187 ldr tmp1, [pmc, #AT91_CKGR_MOR] 188 orr tmp1, tmp1, #AT91_PMC_MOSCEN 189 orr tmp1, tmp1, #AT91_PMC_KEY 190 str tmp1, [pmc, #AT91_CKGR_MOR] 191 192 wait_moscrdy 193 194 /* Restore PLLA setting */ 195 ldr tmp1, .saved_pllar 196 str tmp1, [pmc, #AT91_CKGR_PLLAR] 197 198 tst tmp1, #(AT91_PMC_MUL & 0xff0000) 199 bne 3f 200 tst tmp1, #(AT91_PMC_MUL & ~0xff0000) 201 beq 4f 2023: 203 wait_pllalock 2044: 205 206 /* 207 * Restore master clock setting 208 */ 209 ldr tmp1, .saved_mckr 210 str tmp1, [pmc, #AT91_PMC_MCKR] 211 212 wait_mckrdy 213 214 mov pc, lr 215ENDPROC(at91_slowck_mode) 216 217/* 218 * void at91_sramc_self_refresh(unsigned int is_active) 219 * 220 * @input param: 221 * @r0: 1 - active self-refresh mode 222 * 0 - exit self-refresh mode 223 * register usage: 224 * @r1: memory type 225 * @r2: base address of the sram controller 226 */ 227 228ENTRY(at91_sramc_self_refresh) 229 ldr r1, .memtype 230 ldr r2, .sramc_base 231 232 cmp r1, #AT91_MEMCTRL_MC 233 bne ddrc_sf 234 235 /* 236 * at91rm9200 Memory controller 237 */ 238 239 /* 240 * For exiting the self-refresh mode, do nothing, 241 * automatically exit the self-refresh mode. 242 */ 243 tst r0, #SRAMC_SELF_FRESH_ACTIVE 244 beq exit_sramc_sf 245 246 /* Active SDRAM self-refresh mode */ 247 mov r3, #1 248 str r3, [r2, #AT91_MC_SDRAMC_SRR] 249 b exit_sramc_sf 250 251ddrc_sf: 252 cmp r1, #AT91_MEMCTRL_DDRSDR 253 bne sdramc_sf 254 255 /* 256 * DDR Memory controller 257 */ 258 tst r0, #SRAMC_SELF_FRESH_ACTIVE 259 beq ddrc_exit_sf 260 261 /* LPDDR1 --> force DDR2 mode during self-refresh */ 262 ldr r3, [r2, #AT91_DDRSDRC_MDR] 263 str r3, .saved_sam9_mdr 264 bic r3, r3, #~AT91_DDRSDRC_MD 265 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 266 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 267 biceq r3, r3, #AT91_DDRSDRC_MD 268 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 269 streq r3, [r2, #AT91_DDRSDRC_MDR] 270 271 /* Active DDRC self-refresh mode */ 272 ldr r3, [r2, #AT91_DDRSDRC_LPR] 273 str r3, .saved_sam9_lpr 274 bic r3, r3, #AT91_DDRSDRC_LPCB 275 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 276 str r3, [r2, #AT91_DDRSDRC_LPR] 277 278 /* If using the 2nd ddr controller */ 279 ldr r2, .sramc1_base 280 cmp r2, #0 281 beq no_2nd_ddrc 282 283 ldr r3, [r2, #AT91_DDRSDRC_MDR] 284 str r3, .saved_sam9_mdr1 285 bic r3, r3, #~AT91_DDRSDRC_MD 286 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 287 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 288 biceq r3, r3, #AT91_DDRSDRC_MD 289 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 290 streq r3, [r2, #AT91_DDRSDRC_MDR] 291 292 /* Active DDRC self-refresh mode */ 293 ldr r3, [r2, #AT91_DDRSDRC_LPR] 294 str r3, .saved_sam9_lpr1 295 bic r3, r3, #AT91_DDRSDRC_LPCB 296 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 297 str r3, [r2, #AT91_DDRSDRC_LPR] 298 299no_2nd_ddrc: 300 b exit_sramc_sf 301 302ddrc_exit_sf: 303 /* Restore MDR in case of LPDDR1 */ 304 ldr r3, .saved_sam9_mdr 305 str r3, [r2, #AT91_DDRSDRC_MDR] 306 /* Restore LPR on AT91 with DDRAM */ 307 ldr r3, .saved_sam9_lpr 308 str r3, [r2, #AT91_DDRSDRC_LPR] 309 310 /* If using the 2nd ddr controller */ 311 ldr r2, .sramc1_base 312 cmp r2, #0 313 ldrne r3, .saved_sam9_mdr1 314 strne r3, [r2, #AT91_DDRSDRC_MDR] 315 ldrne r3, .saved_sam9_lpr1 316 strne r3, [r2, #AT91_DDRSDRC_LPR] 317 318 b exit_sramc_sf 319 320 /* 321 * SDRAMC Memory controller 322 */ 323sdramc_sf: 324 tst r0, #SRAMC_SELF_FRESH_ACTIVE 325 beq sdramc_exit_sf 326 327 /* Active SDRAMC self-refresh mode */ 328 ldr r3, [r2, #AT91_SDRAMC_LPR] 329 str r3, .saved_sam9_lpr 330 bic r3, r3, #AT91_SDRAMC_LPCB 331 orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH 332 str r3, [r2, #AT91_SDRAMC_LPR] 333 334sdramc_exit_sf: 335 ldr r3, .saved_sam9_lpr 336 str r3, [r2, #AT91_SDRAMC_LPR] 337 338exit_sramc_sf: 339 mov pc, lr 340ENDPROC(at91_sramc_self_refresh) 341 342.pmc_base: 343 .word 0 344.sramc_base: 345 .word 0 346.sramc1_base: 347 .word 0 348.shdwc: 349 .word 0 350.sfr: 351 .word 0 352.memtype: 353 .word 0 354.pm_mode: 355 .word 0 356.saved_mckr: 357 .word 0 358.saved_pllar: 359 .word 0 360.saved_sam9_lpr: 361 .word 0 362.saved_sam9_lpr1: 363 .word 0 364.saved_sam9_mdr: 365 .word 0 366.saved_sam9_mdr1: 367 .word 0 368 369ENTRY(at91_pm_suspend_in_sram_sz) 370 .word .-at91_pm_suspend_in_sram 371