1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ 2/* 3 * Copyright (c) 2021, Microchip 4 */ 5 6#include <arm.h> 7#include <arm32_macros.S> 8#include <asm.S> 9#include <at91_pmc.h> 10#include <drivers/sam/at91_ddr.h> 11#include <generated/pm-defines.h> 12 13#include "at91_pm.h" 14 15#define SRAMC_SELF_FRESH_ACTIVE 0x01 16#define SRAMC_SELF_FRESH_EXIT 0x00 17 18pmc .req r0 19tmp1 .req r4 20tmp2 .req r5 21tmp3 .req r6 22 23/* 24 * Wait until master clock is ready (after switching master clock source) 25 */ 26.macro wait_mckrdy 271: ldr tmp1, [pmc, #AT91_PMC_SR] 28 tst tmp1, #AT91_PMC_MCKRDY 29 beq 1b 30.endm 31 32/* 33 * Wait until master oscillator has stabilized. 34 */ 35.macro wait_moscrdy 361: ldr tmp1, [pmc, #AT91_PMC_SR] 37 tst tmp1, #AT91_PMC_MOSCS 38 beq 1b 39.endm 40 41/* 42 * Wait for main oscillator selection is done 43 */ 44.macro wait_moscsels 451: ldr tmp1, [pmc, #AT91_PMC_SR] 46 tst tmp1, #AT91_PMC_MOSCSELS 47 beq 1b 48.endm 49 50/* 51 * Put the processor to enter the idle state 52 */ 53.macro at91_cpu_idle 54 55 mov tmp1, #AT91_PMC_PCK 56 str tmp1, [pmc, #AT91_PMC_SCDR] 57 58 dsb 59 60 wfi @ Wait For Interrupt 61 62.endm 63 64.section .text.psci.suspend 65 66.arm 67 68 69#define SUSPEND_FUNC(__name) \ 70__name: 71 72#define SUSPEND_END_FUNC(__name) \ 73 .size __name, .-__name 74 75.macro check_fit_in_sram since 76 .if (. - \since) > 0x10000 77 .error "Suspend assembly code exceeds dedicated SRAM size" 78 .endif 79.endm 80 81/* 82 * void at91_suspend_sram_fn(struct at91_pm_data*) 83 * @input param: 84 * @r0: base address of struct at91_pm_data 85 */ 86.align 3 87.global at91_pm_suspend_in_sram 88SUSPEND_FUNC(at91_pm_suspend_in_sram) 89 /* Save registers on stack */ 90 stmfd sp!, {r4 - r12, lr} 91 92 /* Drain write buffer */ 93 mov tmp1, #0 94 mcr p15, 0, tmp1, c7, c10, 4 95 96 ldr tmp1, [r0, #PM_DATA_PMC] 97 str tmp1, .pmc_base 98 ldr tmp1, [r0, #PM_DATA_RAMC0] 99 str tmp1, .sramc_base 100 ldr tmp1, [r0, #PM_DATA_MODE] 101 str tmp1, .pm_mode 102 /* Both ldrne below are here to preload their address in the TLB */ 103 ldr tmp1, [r0, #PM_DATA_SHDWC] 104 str tmp1, .shdwc 105 cmp tmp1, #0 106 ldrne tmp2, [tmp1, #0] 107 ldr tmp1, [r0, #PM_DATA_SFRBU] 108 str tmp1, .sfrbu 109 cmp tmp1, #0 110 ldrne tmp2, [tmp1, #0x10] 111 112 /* Active the self-refresh mode */ 113 mov r0, #SRAMC_SELF_FRESH_ACTIVE 114 bl at91_sramc_self_refresh 115 116 ldr r0, .pm_mode 117 cmp r0, #AT91_PM_STANDBY 118 beq standby 119 cmp r0, #AT91_PM_BACKUP 120 beq backup_mode 121 122 bl at91_ulp_mode 123 b exit_suspend 124 125standby: 126 /* Wait for interrupt */ 127 ldr pmc, .pmc_base 128 at91_cpu_idle 129 b exit_suspend 130 131backup_mode: 132 bl at91_backup_mode 133 b exit_suspend 134 135exit_suspend: 136 /* Exit the self-refresh mode */ 137 mov r0, #SRAMC_SELF_FRESH_EXIT 138 bl at91_sramc_self_refresh 139 140 /* Restore registers, and return */ 141 ldmfd sp!, {r4 - r12, pc} 142SUSPEND_END_FUNC(at91_pm_suspend_in_sram) 143 144SUSPEND_FUNC(at91_backup_mode) 145 /* Switch the master clock source to slow clock. */ 146 ldr pmc, .pmc_base 147 ldr tmp1, [pmc, #AT91_PMC_MCKR] 148 bic tmp1, tmp1, #AT91_PMC_CSS 149 str tmp1, [pmc, #AT91_PMC_MCKR] 150 151 wait_mckrdy 152 153 /*BUMEN*/ 154 ldr r0, .sfrbu 155 mov tmp1, #0x1 156 str tmp1, [r0, #0x10] 157 158 /* Shutdown */ 159 ldr r0, .shdwc 160 mov tmp1, #0xA5000000 161 add tmp1, tmp1, #0x1 162 str tmp1, [r0, #0] 163SUSPEND_END_FUNC(at91_backup_mode) 164 165.macro at91_pm_ulp0_mode 166 ldr pmc, .pmc_base 167 ldr tmp2, .pm_mode 168 169 /* Check if ULP0 fast variant has been requested. */ 170 cmp tmp2, #AT91_PM_ULP0_FAST 171 bne 0f 172 173 /* Set highest prescaler for power saving */ 174 ldr tmp1, [pmc, #AT91_PMC_MCKR] 175 bic tmp1, tmp1, #AT91_PMC_PRES 176 orr tmp1, tmp1, #AT91_PMC_PRES_64 177 str tmp1, [pmc, #AT91_PMC_MCKR] 178 wait_mckrdy 179 b 1f 180 1810: 182 /* Turn off the crystal oscillator */ 183 ldr tmp1, [pmc, #AT91_CKGR_MOR] 184 bic tmp1, tmp1, #AT91_PMC_MOSCEN 185 orr tmp1, tmp1, #AT91_PMC_KEY 186 str tmp1, [pmc, #AT91_CKGR_MOR] 187 188 /* Save RC oscillator state */ 189 ldr tmp1, [pmc, #AT91_PMC_SR] 190 str tmp1, .saved_osc_status 191 tst tmp1, #AT91_PMC_MOSCRCS 192 bne 1f 193 194 /* Turn off RC oscillator */ 195 ldr tmp1, [pmc, #AT91_CKGR_MOR] 196 bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 197 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 198 orr tmp1, tmp1, #AT91_PMC_KEY 199 str tmp1, [pmc, #AT91_CKGR_MOR] 200 201 /* Wait main RC disabled done */ 2022: ldr tmp1, [pmc, #AT91_PMC_SR] 203 tst tmp1, #AT91_PMC_MOSCRCS 204 bne 2b 205 206 /* Wait for interrupt */ 2071: at91_cpu_idle 208 209 /* Check if ULP0 fast variant has been requested. */ 210 cmp tmp2, #AT91_PM_ULP0_FAST 211 bne 5f 212 213 /* Set lowest prescaler for fast resume. */ 214 ldr tmp1, [pmc, #AT91_PMC_MCKR] 215 bic tmp1, tmp1, #AT91_PMC_PRES 216 str tmp1, [pmc, #AT91_PMC_MCKR] 217 wait_mckrdy 218 b 6f 219 2205: /* Restore RC oscillator state */ 221 ldr tmp1, .saved_osc_status 222 tst tmp1, #AT91_PMC_MOSCRCS 223 beq 4f 224 225 /* Turn on RC oscillator */ 226 ldr tmp1, [pmc, #AT91_CKGR_MOR] 227 orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 228 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 229 orr tmp1, tmp1, #AT91_PMC_KEY 230 str tmp1, [pmc, #AT91_CKGR_MOR] 231 232 /* Wait main RC stabilization */ 2333: ldr tmp1, [pmc, #AT91_PMC_SR] 234 tst tmp1, #AT91_PMC_MOSCRCS 235 beq 3b 236 237 /* Turn on the crystal oscillator */ 2384: ldr tmp1, [pmc, #AT91_CKGR_MOR] 239 orr tmp1, tmp1, #AT91_PMC_MOSCEN 240 orr tmp1, tmp1, #AT91_PMC_KEY 241 str tmp1, [pmc, #AT91_CKGR_MOR] 242 243 wait_moscrdy 2446: 245.endm 246 247/** 248 * Note: This procedure only applies on the platform which uses 249 * the external crystal oscillator as a main clock source. 250 */ 251.macro at91_pm_ulp1_mode 252 ldr pmc, .pmc_base 253 254 /* Save RC oscillator state and check if it is enabled. */ 255 ldr tmp1, [pmc, #AT91_PMC_SR] 256 str tmp1, .saved_osc_status 257 tst tmp1, #AT91_PMC_MOSCRCS 258 bne 2f 259 260 /* Enable RC oscillator */ 261 ldr tmp1, [pmc, #AT91_CKGR_MOR] 262 orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 263 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 264 orr tmp1, tmp1, #AT91_PMC_KEY 265 str tmp1, [pmc, #AT91_CKGR_MOR] 266 267 /* Wait main RC stabilization */ 2681: ldr tmp1, [pmc, #AT91_PMC_SR] 269 tst tmp1, #AT91_PMC_MOSCRCS 270 beq 1b 271 272 /* Switch the main clock source to 12-MHz RC oscillator */ 2732: ldr tmp1, [pmc, #AT91_CKGR_MOR] 274 bic tmp1, tmp1, #AT91_PMC_MOSCSEL 275 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 276 orr tmp1, tmp1, #AT91_PMC_KEY 277 str tmp1, [pmc, #AT91_CKGR_MOR] 278 279 wait_moscsels 280 281 /* Disable the crystal oscillator */ 282 ldr tmp1, [pmc, #AT91_CKGR_MOR] 283 bic tmp1, tmp1, #AT91_PMC_MOSCEN 284 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 285 orr tmp1, tmp1, #AT91_PMC_KEY 286 str tmp1, [pmc, #AT91_CKGR_MOR] 287 288 /* Switch the master clock source to main clock */ 289 ldr tmp1, [pmc, #AT91_PMC_MCKR] 290 bic tmp1, tmp1, #AT91_PMC_CSS 291 orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 292 str tmp1, [pmc, #AT91_PMC_MCKR] 293 294 wait_mckrdy 295 296 /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */ 297 ldr tmp1, [pmc, #AT91_CKGR_MOR] 298 orr tmp1, tmp1, #AT91_PMC_WAITMODE 299 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 300 orr tmp1, tmp1, #AT91_PMC_KEY 301 str tmp1, [pmc, #AT91_CKGR_MOR] 302 303 /* Quirk for SAM9X60's PMC */ 304 nop 305 nop 306 307 wait_mckrdy 308 309 /* Enable the crystal oscillator */ 310 ldr tmp1, [pmc, #AT91_CKGR_MOR] 311 orr tmp1, tmp1, #AT91_PMC_MOSCEN 312 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 313 orr tmp1, tmp1, #AT91_PMC_KEY 314 str tmp1, [pmc, #AT91_CKGR_MOR] 315 316 wait_moscrdy 317 318 /* Switch the master clock source to slow clock */ 319 ldr tmp1, [pmc, #AT91_PMC_MCKR] 320 bic tmp1, tmp1, #AT91_PMC_CSS 321 str tmp1, [pmc, #AT91_PMC_MCKR] 322 323 wait_mckrdy 324 325 /* Switch main clock source to crystal oscillator */ 326 ldr tmp1, [pmc, #AT91_CKGR_MOR] 327 orr tmp1, tmp1, #AT91_PMC_MOSCSEL 328 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 329 orr tmp1, tmp1, #AT91_PMC_KEY 330 str tmp1, [pmc, #AT91_CKGR_MOR] 331 332 wait_moscsels 333 334 /* Switch the master clock source to main clock */ 335 ldr tmp1, [pmc, #AT91_PMC_MCKR] 336 bic tmp1, tmp1, #AT91_PMC_CSS 337 orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 338 str tmp1, [pmc, #AT91_PMC_MCKR] 339 340 wait_mckrdy 341 342 /* Restore RC oscillator state */ 343 ldr tmp1, .saved_osc_status 344 tst tmp1, #AT91_PMC_MOSCRCS 345 bne 3f 346 347 /* Disable RC oscillator */ 348 ldr tmp1, [pmc, #AT91_CKGR_MOR] 349 bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 350 bic tmp1, tmp1, #AT91_PMC_KEY_MASK 351 orr tmp1, tmp1, #AT91_PMC_KEY 352 str tmp1, [pmc, #AT91_CKGR_MOR] 353 354 /* Wait RC oscillator disable done */ 3554: ldr tmp1, [pmc, #AT91_PMC_SR] 356 tst tmp1, #AT91_PMC_MOSCRCS 357 bne 4b 358 3593: 360.endm 361 362.macro at91_plla_disable 363 /* Save PLLA setting and disable it */ 364 ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 365 str tmp1, .saved_pllar 366 367 /* Disable PLLA. */ 368 mov tmp1, #AT91_PMC_PLLCOUNT 369 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 370 str tmp1, [pmc, #AT91_CKGR_PLLAR] 3712: 372.endm 373 374.macro at91_plla_enable 375 ldr tmp2, .saved_pllar 376 377 /* Restore PLLA setting */ 378 str tmp2, [pmc, #AT91_CKGR_PLLAR] 379 380 /* Enable PLLA. */ 381 tst tmp2, #(AT91_PMC_MUL & 0xff0000) 382 bne 1f 383 tst tmp2, #(AT91_PMC_MUL & ~0xff0000) 384 beq 2f 385 3861: ldr tmp1, [pmc, #AT91_PMC_SR] 387 tst tmp1, #AT91_PMC_LOCKA 388 beq 1b 3892: 390.endm 391 392SUSPEND_FUNC(at91_ulp_mode) 393 ldr pmc, .pmc_base 394 ldr tmp3, .pm_mode 395 396 /* Save Master clock setting */ 397 ldr tmp1, [pmc, #AT91_PMC_MCKR] 398 str tmp1, .saved_mckr 399 400 /* 401 * Set master clock source to: 402 * - MAINCK if using ULP0 fast variant 403 * - slow clock, otherwise 404 */ 405 bic tmp1, tmp1, #AT91_PMC_CSS 406 cmp tmp3, #AT91_PM_ULP0_FAST 407 bne save_mck 408 orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 409save_mck: 410 str tmp1, [pmc, #AT91_PMC_MCKR] 411 412 wait_mckrdy 413 414 at91_plla_disable 415 416 cmp tmp3, #AT91_PM_ULP1 417 beq ulp1_mode 418 419 at91_pm_ulp0_mode 420 b ulp_exit 421 422ulp1_mode: 423 at91_pm_ulp1_mode 424 b ulp_exit 425 426ulp_exit: 427 ldr pmc, .pmc_base 428 429 at91_plla_enable 430 431 /* 432 * Restore master clock setting 433 */ 434 ldr tmp2, .saved_mckr 435 str tmp2, [pmc, #AT91_PMC_MCKR] 436 437 wait_mckrdy 438 439 mov pc, lr 440SUSPEND_END_FUNC(at91_ulp_mode) 441 442/* 443 * void at91_sramc_self_refresh(unsigned int is_active) 444 * 445 * @input param: 446 * @r0: 1 - active self-refresh mode 447 * 0 - exit self-refresh mode 448 * register usage: 449 * @r2: base address of the sram controller 450 */ 451 452SUSPEND_FUNC(at91_sramc_self_refresh) 453 ldr r2, .sramc_base 454 455 /* 456 * DDR Memory controller 457 */ 458 tst r0, #SRAMC_SELF_FRESH_ACTIVE 459 beq ddrc_exit_sf 460 461 /* LPDDR1 --> force DDR2 mode during self-refresh */ 462 ldr r3, [r2, #AT91_DDRSDRC_MDR] 463 str r3, .saved_sam9_mdr 464 bic r3, r3, #~AT91_DDRSDRC_MD 465 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 466 ldreq r3, [r2, #AT91_DDRSDRC_MDR] 467 biceq r3, r3, #AT91_DDRSDRC_MD 468 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 469 streq r3, [r2, #AT91_DDRSDRC_MDR] 470 471 /* Active DDRC self-refresh mode */ 472 ldr r3, [r2, #AT91_DDRSDRC_LPR] 473 str r3, .saved_sam9_lpr 474 bic r3, r3, #AT91_DDRSDRC_LPCB 475 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 476 str r3, [r2, #AT91_DDRSDRC_LPR] 477 478 b exit_sramc_sf 479 480ddrc_exit_sf: 481 /* Restore MDR in case of LPDDR1 */ 482 ldr r3, .saved_sam9_mdr 483 str r3, [r2, #AT91_DDRSDRC_MDR] 484 /* Restore LPR on AT91 with DDRAM */ 485 ldr r3, .saved_sam9_lpr 486 str r3, [r2, #AT91_DDRSDRC_LPR] 487 488exit_sramc_sf: 489 mov pc, lr 490SUSPEND_END_FUNC(at91_sramc_self_refresh) 491 492.pmc_base: 493 .word 0 494.sramc_base: 495 .word 0 496.shdwc: 497 .word 0 498.sfrbu: 499 .word 0 500.pm_mode: 501 .word 0 502.saved_mckr: 503 .word 0 504.saved_pllar: 505 .word 0 506.saved_sam9_lpr: 507 .word 0 508.saved_sam9_mdr: 509 .word 0 510.saved_osc_status: 511 .word 0 512 513.global at91_pm_suspend_in_sram_sz 514at91_pm_suspend_in_sram_sz: 515 .word .-at91_pm_suspend_in_sram 516 517check_fit_in_sram at91_pm_suspend_in_sram 518