1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * arch/arm/mach-at91/pm_slow_clock.S 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2006 Savin Zlobec 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * AT91SAM9 support: 8*4882a593Smuzhiyun * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee> 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun#include <linux/linkage.h> 11*4882a593Smuzhiyun#include <linux/clk/at91_pmc.h> 12*4882a593Smuzhiyun#include "pm.h" 13*4882a593Smuzhiyun#include "pm_data-offsets.h" 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun#define SRAMC_SELF_FRESH_ACTIVE 0x01 16*4882a593Smuzhiyun#define SRAMC_SELF_FRESH_EXIT 0x00 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunpmc .req r0 19*4882a593Smuzhiyuntmp1 .req r4 20*4882a593Smuzhiyuntmp2 .req r5 21*4882a593Smuzhiyuntmp3 .req r6 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun/* 24*4882a593Smuzhiyun * Wait until master clock is ready (after switching master clock source) 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun .macro wait_mckrdy 27*4882a593Smuzhiyun1: ldr tmp1, [pmc, #AT91_PMC_SR] 28*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MCKRDY 29*4882a593Smuzhiyun beq 1b 30*4882a593Smuzhiyun .endm 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun/* 33*4882a593Smuzhiyun * Wait until master oscillator has stabilized. 34*4882a593Smuzhiyun */ 35*4882a593Smuzhiyun .macro wait_moscrdy 36*4882a593Smuzhiyun1: ldr tmp1, [pmc, #AT91_PMC_SR] 37*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCS 38*4882a593Smuzhiyun beq 1b 39*4882a593Smuzhiyun .endm 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun/* 42*4882a593Smuzhiyun * Wait for main oscillator selection is done 43*4882a593Smuzhiyun */ 44*4882a593Smuzhiyun .macro wait_moscsels 45*4882a593Smuzhiyun1: ldr tmp1, [pmc, #AT91_PMC_SR] 46*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCSELS 47*4882a593Smuzhiyun beq 1b 48*4882a593Smuzhiyun .endm 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun/* 51*4882a593Smuzhiyun * Put the processor to enter the idle state 52*4882a593Smuzhiyun */ 53*4882a593Smuzhiyun .macro at91_cpu_idle 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun#if defined(CONFIG_CPU_V7) 56*4882a593Smuzhiyun mov tmp1, #AT91_PMC_PCK 57*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_SCDR] 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun dsb 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun wfi @ Wait For Interrupt 62*4882a593Smuzhiyun#else 63*4882a593Smuzhiyun mcr p15, 0, tmp1, c7, c0, 4 64*4882a593Smuzhiyun#endif 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun .endm 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun .text 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun .arm 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun/* 73*4882a593Smuzhiyun * void at91_suspend_sram_fn(struct at91_pm_data*) 74*4882a593Smuzhiyun * @input param: 75*4882a593Smuzhiyun * @r0: base address of struct at91_pm_data 76*4882a593Smuzhiyun */ 77*4882a593Smuzhiyun/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ 78*4882a593Smuzhiyun .align 3 79*4882a593SmuzhiyunENTRY(at91_pm_suspend_in_sram) 80*4882a593Smuzhiyun /* Save registers on stack */ 81*4882a593Smuzhiyun stmfd sp!, {r4 - r12, lr} 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun /* Drain write buffer */ 84*4882a593Smuzhiyun mov tmp1, #0 85*4882a593Smuzhiyun mcr p15, 0, tmp1, c7, c10, 4 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_PMC] 88*4882a593Smuzhiyun str tmp1, .pmc_base 89*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_RAMC0] 90*4882a593Smuzhiyun str tmp1, .sramc_base 91*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_RAMC1] 92*4882a593Smuzhiyun str tmp1, .sramc1_base 93*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_MEMCTRL] 94*4882a593Smuzhiyun str tmp1, .memtype 95*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_MODE] 96*4882a593Smuzhiyun str tmp1, .pm_mode 97*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET] 98*4882a593Smuzhiyun str tmp1, .mckr_offset 99*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_PMC_VERSION] 100*4882a593Smuzhiyun str tmp1, .pmc_version 101*4882a593Smuzhiyun /* Both ldrne below are here to preload their address in the TLB */ 102*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_SHDWC] 103*4882a593Smuzhiyun str tmp1, .shdwc 104*4882a593Smuzhiyun cmp tmp1, #0 105*4882a593Smuzhiyun ldrne tmp2, [tmp1, #0] 106*4882a593Smuzhiyun ldr tmp1, [r0, #PM_DATA_SFRBU] 107*4882a593Smuzhiyun str tmp1, .sfrbu 108*4882a593Smuzhiyun cmp tmp1, #0 109*4882a593Smuzhiyun ldrne tmp2, [tmp1, #0x10] 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun /* Active the self-refresh mode */ 112*4882a593Smuzhiyun mov r0, #SRAMC_SELF_FRESH_ACTIVE 113*4882a593Smuzhiyun bl at91_sramc_self_refresh 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun ldr r0, .pm_mode 116*4882a593Smuzhiyun cmp r0, #AT91_PM_STANDBY 117*4882a593Smuzhiyun beq standby 118*4882a593Smuzhiyun cmp r0, #AT91_PM_BACKUP 119*4882a593Smuzhiyun beq backup_mode 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun bl at91_ulp_mode 122*4882a593Smuzhiyun b exit_suspend 123*4882a593Smuzhiyun 124*4882a593Smuzhiyunstandby: 125*4882a593Smuzhiyun /* Wait for interrupt */ 126*4882a593Smuzhiyun ldr pmc, .pmc_base 127*4882a593Smuzhiyun at91_cpu_idle 128*4882a593Smuzhiyun b exit_suspend 129*4882a593Smuzhiyun 130*4882a593Smuzhiyunbackup_mode: 131*4882a593Smuzhiyun bl at91_backup_mode 132*4882a593Smuzhiyun b exit_suspend 133*4882a593Smuzhiyun 134*4882a593Smuzhiyunexit_suspend: 135*4882a593Smuzhiyun /* Exit the self-refresh mode */ 136*4882a593Smuzhiyun mov r0, #SRAMC_SELF_FRESH_EXIT 137*4882a593Smuzhiyun bl at91_sramc_self_refresh 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun /* Restore registers, and return */ 140*4882a593Smuzhiyun ldmfd sp!, {r4 - r12, pc} 141*4882a593SmuzhiyunENDPROC(at91_pm_suspend_in_sram) 142*4882a593Smuzhiyun 143*4882a593SmuzhiyunENTRY(at91_backup_mode) 144*4882a593Smuzhiyun /* Switch the master clock source to slow clock. */ 145*4882a593Smuzhiyun ldr pmc, .pmc_base 146*4882a593Smuzhiyun ldr tmp2, .mckr_offset 147*4882a593Smuzhiyun ldr tmp1, [pmc, tmp2] 148*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_CSS 149*4882a593Smuzhiyun str tmp1, [pmc, tmp2] 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun wait_mckrdy 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun /*BUMEN*/ 154*4882a593Smuzhiyun ldr r0, .sfrbu 155*4882a593Smuzhiyun mov tmp1, #0x1 156*4882a593Smuzhiyun str tmp1, [r0, #0x10] 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun /* Shutdown */ 159*4882a593Smuzhiyun ldr r0, .shdwc 160*4882a593Smuzhiyun mov tmp1, #0xA5000000 161*4882a593Smuzhiyun add tmp1, tmp1, #0x1 162*4882a593Smuzhiyun str tmp1, [r0, #0] 163*4882a593SmuzhiyunENDPROC(at91_backup_mode) 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun.macro at91_pm_ulp0_mode 166*4882a593Smuzhiyun ldr pmc, .pmc_base 167*4882a593Smuzhiyun ldr tmp2, .pm_mode 168*4882a593Smuzhiyun ldr tmp3, .mckr_offset 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun /* Check if ULP0 fast variant has been requested. */ 171*4882a593Smuzhiyun cmp tmp2, #AT91_PM_ULP0_FAST 172*4882a593Smuzhiyun bne 0f 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun /* Set highest prescaler for power saving */ 175*4882a593Smuzhiyun ldr tmp1, [pmc, tmp3] 176*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PRES 177*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PRES_64 178*4882a593Smuzhiyun str tmp1, [pmc, tmp3] 179*4882a593Smuzhiyun wait_mckrdy 180*4882a593Smuzhiyun b 1f 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun0: 183*4882a593Smuzhiyun /* Turn off the crystal oscillator */ 184*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 185*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_MOSCEN 186*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 187*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun /* Save RC oscillator state */ 190*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_SR] 191*4882a593Smuzhiyun str tmp1, .saved_osc_status 192*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 193*4882a593Smuzhiyun bne 1f 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun /* Turn off RC oscillator */ 196*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 197*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 198*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 199*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 200*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun /* Wait main RC disabled done */ 203*4882a593Smuzhiyun2: ldr tmp1, [pmc, #AT91_PMC_SR] 204*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 205*4882a593Smuzhiyun bne 2b 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun /* Wait for interrupt */ 208*4882a593Smuzhiyun1: at91_cpu_idle 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun /* Check if ULP0 fast variant has been requested. */ 211*4882a593Smuzhiyun cmp tmp2, #AT91_PM_ULP0_FAST 212*4882a593Smuzhiyun bne 5f 213*4882a593Smuzhiyun 214*4882a593Smuzhiyun /* Set lowest prescaler for fast resume. */ 215*4882a593Smuzhiyun ldr tmp1, [pmc, tmp3] 216*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PRES 217*4882a593Smuzhiyun str tmp1, [pmc, tmp3] 218*4882a593Smuzhiyun wait_mckrdy 219*4882a593Smuzhiyun b 6f 220*4882a593Smuzhiyun 221*4882a593Smuzhiyun5: /* Restore RC oscillator state */ 222*4882a593Smuzhiyun ldr tmp1, .saved_osc_status 223*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 224*4882a593Smuzhiyun beq 4f 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun /* Turn on RC oscillator */ 227*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 228*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 229*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 230*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 231*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun /* Wait main RC stabilization */ 234*4882a593Smuzhiyun3: ldr tmp1, [pmc, #AT91_PMC_SR] 235*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 236*4882a593Smuzhiyun beq 3b 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun /* Turn on the crystal oscillator */ 239*4882a593Smuzhiyun4: ldr tmp1, [pmc, #AT91_CKGR_MOR] 240*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_MOSCEN 241*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 242*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 243*4882a593Smuzhiyun 244*4882a593Smuzhiyun wait_moscrdy 245*4882a593Smuzhiyun6: 246*4882a593Smuzhiyun.endm 247*4882a593Smuzhiyun 248*4882a593Smuzhiyun/** 249*4882a593Smuzhiyun * Note: This procedure only applies on the platform which uses 250*4882a593Smuzhiyun * the external crystal oscillator as a main clock source. 251*4882a593Smuzhiyun */ 252*4882a593Smuzhiyun.macro at91_pm_ulp1_mode 253*4882a593Smuzhiyun ldr pmc, .pmc_base 254*4882a593Smuzhiyun ldr tmp2, .mckr_offset 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun /* Save RC oscillator state and check if it is enabled. */ 257*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_SR] 258*4882a593Smuzhiyun str tmp1, .saved_osc_status 259*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 260*4882a593Smuzhiyun bne 2f 261*4882a593Smuzhiyun 262*4882a593Smuzhiyun /* Enable RC oscillator */ 263*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 264*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 265*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 266*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 267*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 268*4882a593Smuzhiyun 269*4882a593Smuzhiyun /* Wait main RC stabilization */ 270*4882a593Smuzhiyun1: ldr tmp1, [pmc, #AT91_PMC_SR] 271*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 272*4882a593Smuzhiyun beq 1b 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun /* Switch the main clock source to 12-MHz RC oscillator */ 275*4882a593Smuzhiyun2: ldr tmp1, [pmc, #AT91_CKGR_MOR] 276*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_MOSCSEL 277*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 278*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 279*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 280*4882a593Smuzhiyun 281*4882a593Smuzhiyun wait_moscsels 282*4882a593Smuzhiyun 283*4882a593Smuzhiyun /* Disable the crystal oscillator */ 284*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 285*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_MOSCEN 286*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 287*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 288*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 289*4882a593Smuzhiyun 290*4882a593Smuzhiyun /* Switch the master clock source to main clock */ 291*4882a593Smuzhiyun ldr tmp1, [pmc, tmp2] 292*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_CSS 293*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 294*4882a593Smuzhiyun str tmp1, [pmc, tmp2] 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun wait_mckrdy 297*4882a593Smuzhiyun 298*4882a593Smuzhiyun /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */ 299*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 300*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_WAITMODE 301*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 302*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 303*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 304*4882a593Smuzhiyun 305*4882a593Smuzhiyun /* Quirk for SAM9X60's PMC */ 306*4882a593Smuzhiyun nop 307*4882a593Smuzhiyun nop 308*4882a593Smuzhiyun 309*4882a593Smuzhiyun wait_mckrdy 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun /* Enable the crystal oscillator */ 312*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 313*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_MOSCEN 314*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 315*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 316*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 317*4882a593Smuzhiyun 318*4882a593Smuzhiyun wait_moscrdy 319*4882a593Smuzhiyun 320*4882a593Smuzhiyun /* Switch the master clock source to slow clock */ 321*4882a593Smuzhiyun ldr tmp1, [pmc, tmp2] 322*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_CSS 323*4882a593Smuzhiyun str tmp1, [pmc, tmp2] 324*4882a593Smuzhiyun 325*4882a593Smuzhiyun wait_mckrdy 326*4882a593Smuzhiyun 327*4882a593Smuzhiyun /* Switch main clock source to crystal oscillator */ 328*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 329*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_MOSCSEL 330*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 331*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 332*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 333*4882a593Smuzhiyun 334*4882a593Smuzhiyun wait_moscsels 335*4882a593Smuzhiyun 336*4882a593Smuzhiyun /* Switch the master clock source to main clock */ 337*4882a593Smuzhiyun ldr tmp1, [pmc, tmp2] 338*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_CSS 339*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 340*4882a593Smuzhiyun str tmp1, [pmc, tmp2] 341*4882a593Smuzhiyun 342*4882a593Smuzhiyun wait_mckrdy 343*4882a593Smuzhiyun 344*4882a593Smuzhiyun /* Restore RC oscillator state */ 345*4882a593Smuzhiyun ldr tmp1, .saved_osc_status 346*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 347*4882a593Smuzhiyun bne 3f 348*4882a593Smuzhiyun 349*4882a593Smuzhiyun /* Disable RC oscillator */ 350*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_MOR] 351*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 352*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_KEY_MASK 353*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_KEY 354*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_MOR] 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun /* Wait RC oscillator disable done */ 357*4882a593Smuzhiyun4: ldr tmp1, [pmc, #AT91_PMC_SR] 358*4882a593Smuzhiyun tst tmp1, #AT91_PMC_MOSCRCS 359*4882a593Smuzhiyun bne 4b 360*4882a593Smuzhiyun 361*4882a593Smuzhiyun3: 362*4882a593Smuzhiyun.endm 363*4882a593Smuzhiyun 364*4882a593Smuzhiyun.macro at91_plla_disable 365*4882a593Smuzhiyun /* Save PLLA setting and disable it */ 366*4882a593Smuzhiyun ldr tmp1, .pmc_version 367*4882a593Smuzhiyun cmp tmp1, #AT91_PMC_V1 368*4882a593Smuzhiyun beq 1f 369*4882a593Smuzhiyun 370*4882a593Smuzhiyun#ifdef CONFIG_SOC_SAM9X60 371*4882a593Smuzhiyun /* Save PLLA settings. */ 372*4882a593Smuzhiyun ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT] 373*4882a593Smuzhiyun bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID 374*4882a593Smuzhiyun str tmp2, [pmc, #AT91_PMC_PLL_UPDT] 375*4882a593Smuzhiyun 376*4882a593Smuzhiyun /* save div. */ 377*4882a593Smuzhiyun mov tmp1, #0 378*4882a593Smuzhiyun ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0] 379*4882a593Smuzhiyun bic tmp2, tmp2, #0xffffff00 380*4882a593Smuzhiyun orr tmp1, tmp1, tmp2 381*4882a593Smuzhiyun 382*4882a593Smuzhiyun /* save mul. */ 383*4882a593Smuzhiyun ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL1] 384*4882a593Smuzhiyun bic tmp2, tmp2, #0xffffff 385*4882a593Smuzhiyun orr tmp1, tmp1, tmp2 386*4882a593Smuzhiyun str tmp1, .saved_pllar 387*4882a593Smuzhiyun 388*4882a593Smuzhiyun /* step 2. */ 389*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 390*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 391*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 392*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 393*4882a593Smuzhiyun 394*4882a593Smuzhiyun /* step 3. */ 395*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 396*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK 397*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 398*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 399*4882a593Smuzhiyun 400*4882a593Smuzhiyun /* step 4. */ 401*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 402*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 403*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 404*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 405*4882a593Smuzhiyun 406*4882a593Smuzhiyun /* step 5. */ 407*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 408*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 409*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 410*4882a593Smuzhiyun 411*4882a593Smuzhiyun /* step 7. */ 412*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 413*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 414*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 415*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 416*4882a593Smuzhiyun 417*4882a593Smuzhiyun b 2f 418*4882a593Smuzhiyun#endif 419*4882a593Smuzhiyun 420*4882a593Smuzhiyun1: /* Save PLLA setting and disable it */ 421*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 422*4882a593Smuzhiyun str tmp1, .saved_pllar 423*4882a593Smuzhiyun 424*4882a593Smuzhiyun /* Disable PLLA. */ 425*4882a593Smuzhiyun mov tmp1, #AT91_PMC_PLLCOUNT 426*4882a593Smuzhiyun orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 427*4882a593Smuzhiyun str tmp1, [pmc, #AT91_CKGR_PLLAR] 428*4882a593Smuzhiyun2: 429*4882a593Smuzhiyun.endm 430*4882a593Smuzhiyun 431*4882a593Smuzhiyun.macro at91_plla_enable 432*4882a593Smuzhiyun ldr tmp2, .saved_pllar 433*4882a593Smuzhiyun ldr tmp3, .pmc_version 434*4882a593Smuzhiyun cmp tmp3, #AT91_PMC_V1 435*4882a593Smuzhiyun beq 4f 436*4882a593Smuzhiyun 437*4882a593Smuzhiyun#ifdef CONFIG_SOC_SAM9X60 438*4882a593Smuzhiyun /* step 1. */ 439*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 440*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 441*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 442*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 443*4882a593Smuzhiyun 444*4882a593Smuzhiyun /* step 2. */ 445*4882a593Smuzhiyun ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA 446*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_ACR] 447*4882a593Smuzhiyun 448*4882a593Smuzhiyun /* step 3. */ 449*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL1] 450*4882a593Smuzhiyun mov tmp3, tmp2 451*4882a593Smuzhiyun bic tmp3, tmp3, #0xffffff 452*4882a593Smuzhiyun orr tmp1, tmp1, tmp3 453*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_CTRL1] 454*4882a593Smuzhiyun 455*4882a593Smuzhiyun /* step 8. */ 456*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 457*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 458*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 459*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 460*4882a593Smuzhiyun 461*4882a593Smuzhiyun /* step 9. */ 462*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 463*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK 464*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 465*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK 466*4882a593Smuzhiyun bic tmp1, tmp1, #0xff 467*4882a593Smuzhiyun mov tmp3, tmp2 468*4882a593Smuzhiyun bic tmp3, tmp3, #0xffffff00 469*4882a593Smuzhiyun orr tmp1, tmp1, tmp3 470*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 471*4882a593Smuzhiyun 472*4882a593Smuzhiyun /* step 10. */ 473*4882a593Smuzhiyun ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 474*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 475*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 476*4882a593Smuzhiyun str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 477*4882a593Smuzhiyun 478*4882a593Smuzhiyun /* step 11. */ 479*4882a593Smuzhiyun3: ldr tmp1, [pmc, #AT91_PMC_PLL_ISR0] 480*4882a593Smuzhiyun tst tmp1, #0x1 481*4882a593Smuzhiyun beq 3b 482*4882a593Smuzhiyun b 2f 483*4882a593Smuzhiyun#endif 484*4882a593Smuzhiyun 485*4882a593Smuzhiyun /* Restore PLLA setting */ 486*4882a593Smuzhiyun4: str tmp2, [pmc, #AT91_CKGR_PLLAR] 487*4882a593Smuzhiyun 488*4882a593Smuzhiyun /* Enable PLLA. */ 489*4882a593Smuzhiyun tst tmp2, #(AT91_PMC_MUL & 0xff0000) 490*4882a593Smuzhiyun bne 1f 491*4882a593Smuzhiyun tst tmp2, #(AT91_PMC_MUL & ~0xff0000) 492*4882a593Smuzhiyun beq 2f 493*4882a593Smuzhiyun 494*4882a593Smuzhiyun1: ldr tmp1, [pmc, #AT91_PMC_SR] 495*4882a593Smuzhiyun tst tmp1, #AT91_PMC_LOCKA 496*4882a593Smuzhiyun beq 1b 497*4882a593Smuzhiyun2: 498*4882a593Smuzhiyun.endm 499*4882a593Smuzhiyun 500*4882a593SmuzhiyunENTRY(at91_ulp_mode) 501*4882a593Smuzhiyun ldr pmc, .pmc_base 502*4882a593Smuzhiyun ldr tmp2, .mckr_offset 503*4882a593Smuzhiyun ldr tmp3, .pm_mode 504*4882a593Smuzhiyun 505*4882a593Smuzhiyun /* Save Master clock setting */ 506*4882a593Smuzhiyun ldr tmp1, [pmc, tmp2] 507*4882a593Smuzhiyun str tmp1, .saved_mckr 508*4882a593Smuzhiyun 509*4882a593Smuzhiyun /* 510*4882a593Smuzhiyun * Set master clock source to: 511*4882a593Smuzhiyun * - MAINCK if using ULP0 fast variant 512*4882a593Smuzhiyun * - slow clock, otherwise 513*4882a593Smuzhiyun */ 514*4882a593Smuzhiyun bic tmp1, tmp1, #AT91_PMC_CSS 515*4882a593Smuzhiyun cmp tmp3, #AT91_PM_ULP0_FAST 516*4882a593Smuzhiyun bne save_mck 517*4882a593Smuzhiyun orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 518*4882a593Smuzhiyunsave_mck: 519*4882a593Smuzhiyun str tmp1, [pmc, tmp2] 520*4882a593Smuzhiyun 521*4882a593Smuzhiyun wait_mckrdy 522*4882a593Smuzhiyun 523*4882a593Smuzhiyun at91_plla_disable 524*4882a593Smuzhiyun 525*4882a593Smuzhiyun cmp tmp3, #AT91_PM_ULP1 526*4882a593Smuzhiyun beq ulp1_mode 527*4882a593Smuzhiyun 528*4882a593Smuzhiyun at91_pm_ulp0_mode 529*4882a593Smuzhiyun b ulp_exit 530*4882a593Smuzhiyun 531*4882a593Smuzhiyunulp1_mode: 532*4882a593Smuzhiyun at91_pm_ulp1_mode 533*4882a593Smuzhiyun b ulp_exit 534*4882a593Smuzhiyun 535*4882a593Smuzhiyunulp_exit: 536*4882a593Smuzhiyun ldr pmc, .pmc_base 537*4882a593Smuzhiyun 538*4882a593Smuzhiyun at91_plla_enable 539*4882a593Smuzhiyun 540*4882a593Smuzhiyun /* 541*4882a593Smuzhiyun * Restore master clock setting 542*4882a593Smuzhiyun */ 543*4882a593Smuzhiyun ldr tmp1, .mckr_offset 544*4882a593Smuzhiyun ldr tmp2, .saved_mckr 545*4882a593Smuzhiyun str tmp2, [pmc, tmp1] 546*4882a593Smuzhiyun 547*4882a593Smuzhiyun wait_mckrdy 548*4882a593Smuzhiyun 549*4882a593Smuzhiyun mov pc, lr 550*4882a593SmuzhiyunENDPROC(at91_ulp_mode) 551*4882a593Smuzhiyun 552*4882a593Smuzhiyun/* 553*4882a593Smuzhiyun * void at91_sramc_self_refresh(unsigned int is_active) 554*4882a593Smuzhiyun * 555*4882a593Smuzhiyun * @input param: 556*4882a593Smuzhiyun * @r0: 1 - active self-refresh mode 557*4882a593Smuzhiyun * 0 - exit self-refresh mode 558*4882a593Smuzhiyun * register usage: 559*4882a593Smuzhiyun * @r1: memory type 560*4882a593Smuzhiyun * @r2: base address of the sram controller 561*4882a593Smuzhiyun */ 562*4882a593Smuzhiyun 563*4882a593SmuzhiyunENTRY(at91_sramc_self_refresh) 564*4882a593Smuzhiyun ldr r1, .memtype 565*4882a593Smuzhiyun ldr r2, .sramc_base 566*4882a593Smuzhiyun 567*4882a593Smuzhiyun cmp r1, #AT91_MEMCTRL_MC 568*4882a593Smuzhiyun bne ddrc_sf 569*4882a593Smuzhiyun 570*4882a593Smuzhiyun /* 571*4882a593Smuzhiyun * at91rm9200 Memory controller 572*4882a593Smuzhiyun */ 573*4882a593Smuzhiyun 574*4882a593Smuzhiyun /* 575*4882a593Smuzhiyun * For exiting the self-refresh mode, do nothing, 576*4882a593Smuzhiyun * automatically exit the self-refresh mode. 577*4882a593Smuzhiyun */ 578*4882a593Smuzhiyun tst r0, #SRAMC_SELF_FRESH_ACTIVE 579*4882a593Smuzhiyun beq exit_sramc_sf 580*4882a593Smuzhiyun 581*4882a593Smuzhiyun /* Active SDRAM self-refresh mode */ 582*4882a593Smuzhiyun mov r3, #1 583*4882a593Smuzhiyun str r3, [r2, #AT91_MC_SDRAMC_SRR] 584*4882a593Smuzhiyun b exit_sramc_sf 585*4882a593Smuzhiyun 586*4882a593Smuzhiyunddrc_sf: 587*4882a593Smuzhiyun cmp r1, #AT91_MEMCTRL_DDRSDR 588*4882a593Smuzhiyun bne sdramc_sf 589*4882a593Smuzhiyun 590*4882a593Smuzhiyun /* 591*4882a593Smuzhiyun * DDR Memory controller 592*4882a593Smuzhiyun */ 593*4882a593Smuzhiyun tst r0, #SRAMC_SELF_FRESH_ACTIVE 594*4882a593Smuzhiyun beq ddrc_exit_sf 595*4882a593Smuzhiyun 596*4882a593Smuzhiyun /* LPDDR1 --> force DDR2 mode during self-refresh */ 597*4882a593Smuzhiyun ldr r3, [r2, #AT91_DDRSDRC_MDR] 598*4882a593Smuzhiyun str r3, .saved_sam9_mdr 599*4882a593Smuzhiyun bic r3, r3, #~AT91_DDRSDRC_MD 600*4882a593Smuzhiyun cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 601*4882a593Smuzhiyun ldreq r3, [r2, #AT91_DDRSDRC_MDR] 602*4882a593Smuzhiyun biceq r3, r3, #AT91_DDRSDRC_MD 603*4882a593Smuzhiyun orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 604*4882a593Smuzhiyun streq r3, [r2, #AT91_DDRSDRC_MDR] 605*4882a593Smuzhiyun 606*4882a593Smuzhiyun /* Active DDRC self-refresh mode */ 607*4882a593Smuzhiyun ldr r3, [r2, #AT91_DDRSDRC_LPR] 608*4882a593Smuzhiyun str r3, .saved_sam9_lpr 609*4882a593Smuzhiyun bic r3, r3, #AT91_DDRSDRC_LPCB 610*4882a593Smuzhiyun orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 611*4882a593Smuzhiyun str r3, [r2, #AT91_DDRSDRC_LPR] 612*4882a593Smuzhiyun 613*4882a593Smuzhiyun /* If using the 2nd ddr controller */ 614*4882a593Smuzhiyun ldr r2, .sramc1_base 615*4882a593Smuzhiyun cmp r2, #0 616*4882a593Smuzhiyun beq no_2nd_ddrc 617*4882a593Smuzhiyun 618*4882a593Smuzhiyun ldr r3, [r2, #AT91_DDRSDRC_MDR] 619*4882a593Smuzhiyun str r3, .saved_sam9_mdr1 620*4882a593Smuzhiyun bic r3, r3, #~AT91_DDRSDRC_MD 621*4882a593Smuzhiyun cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 622*4882a593Smuzhiyun ldreq r3, [r2, #AT91_DDRSDRC_MDR] 623*4882a593Smuzhiyun biceq r3, r3, #AT91_DDRSDRC_MD 624*4882a593Smuzhiyun orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 625*4882a593Smuzhiyun streq r3, [r2, #AT91_DDRSDRC_MDR] 626*4882a593Smuzhiyun 627*4882a593Smuzhiyun /* Active DDRC self-refresh mode */ 628*4882a593Smuzhiyun ldr r3, [r2, #AT91_DDRSDRC_LPR] 629*4882a593Smuzhiyun str r3, .saved_sam9_lpr1 630*4882a593Smuzhiyun bic r3, r3, #AT91_DDRSDRC_LPCB 631*4882a593Smuzhiyun orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 632*4882a593Smuzhiyun str r3, [r2, #AT91_DDRSDRC_LPR] 633*4882a593Smuzhiyun 634*4882a593Smuzhiyunno_2nd_ddrc: 635*4882a593Smuzhiyun b exit_sramc_sf 636*4882a593Smuzhiyun 637*4882a593Smuzhiyunddrc_exit_sf: 638*4882a593Smuzhiyun /* Restore MDR in case of LPDDR1 */ 639*4882a593Smuzhiyun ldr r3, .saved_sam9_mdr 640*4882a593Smuzhiyun str r3, [r2, #AT91_DDRSDRC_MDR] 641*4882a593Smuzhiyun /* Restore LPR on AT91 with DDRAM */ 642*4882a593Smuzhiyun ldr r3, .saved_sam9_lpr 643*4882a593Smuzhiyun str r3, [r2, #AT91_DDRSDRC_LPR] 644*4882a593Smuzhiyun 645*4882a593Smuzhiyun /* If using the 2nd ddr controller */ 646*4882a593Smuzhiyun ldr r2, .sramc1_base 647*4882a593Smuzhiyun cmp r2, #0 648*4882a593Smuzhiyun ldrne r3, .saved_sam9_mdr1 649*4882a593Smuzhiyun strne r3, [r2, #AT91_DDRSDRC_MDR] 650*4882a593Smuzhiyun ldrne r3, .saved_sam9_lpr1 651*4882a593Smuzhiyun strne r3, [r2, #AT91_DDRSDRC_LPR] 652*4882a593Smuzhiyun 653*4882a593Smuzhiyun b exit_sramc_sf 654*4882a593Smuzhiyun 655*4882a593Smuzhiyun /* 656*4882a593Smuzhiyun * SDRAMC Memory controller 657*4882a593Smuzhiyun */ 658*4882a593Smuzhiyunsdramc_sf: 659*4882a593Smuzhiyun tst r0, #SRAMC_SELF_FRESH_ACTIVE 660*4882a593Smuzhiyun beq sdramc_exit_sf 661*4882a593Smuzhiyun 662*4882a593Smuzhiyun /* Active SDRAMC self-refresh mode */ 663*4882a593Smuzhiyun ldr r3, [r2, #AT91_SDRAMC_LPR] 664*4882a593Smuzhiyun str r3, .saved_sam9_lpr 665*4882a593Smuzhiyun bic r3, r3, #AT91_SDRAMC_LPCB 666*4882a593Smuzhiyun orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH 667*4882a593Smuzhiyun str r3, [r2, #AT91_SDRAMC_LPR] 668*4882a593Smuzhiyun 669*4882a593Smuzhiyunsdramc_exit_sf: 670*4882a593Smuzhiyun ldr r3, .saved_sam9_lpr 671*4882a593Smuzhiyun str r3, [r2, #AT91_SDRAMC_LPR] 672*4882a593Smuzhiyun 673*4882a593Smuzhiyunexit_sramc_sf: 674*4882a593Smuzhiyun mov pc, lr 675*4882a593SmuzhiyunENDPROC(at91_sramc_self_refresh) 676*4882a593Smuzhiyun 677*4882a593Smuzhiyun.pmc_base: 678*4882a593Smuzhiyun .word 0 679*4882a593Smuzhiyun.sramc_base: 680*4882a593Smuzhiyun .word 0 681*4882a593Smuzhiyun.sramc1_base: 682*4882a593Smuzhiyun .word 0 683*4882a593Smuzhiyun.shdwc: 684*4882a593Smuzhiyun .word 0 685*4882a593Smuzhiyun.sfrbu: 686*4882a593Smuzhiyun .word 0 687*4882a593Smuzhiyun.memtype: 688*4882a593Smuzhiyun .word 0 689*4882a593Smuzhiyun.pm_mode: 690*4882a593Smuzhiyun .word 0 691*4882a593Smuzhiyun.mckr_offset: 692*4882a593Smuzhiyun .word 0 693*4882a593Smuzhiyun.pmc_version: 694*4882a593Smuzhiyun .word 0 695*4882a593Smuzhiyun.saved_mckr: 696*4882a593Smuzhiyun .word 0 697*4882a593Smuzhiyun.saved_pllar: 698*4882a593Smuzhiyun .word 0 699*4882a593Smuzhiyun.saved_sam9_lpr: 700*4882a593Smuzhiyun .word 0 701*4882a593Smuzhiyun.saved_sam9_lpr1: 702*4882a593Smuzhiyun .word 0 703*4882a593Smuzhiyun.saved_sam9_mdr: 704*4882a593Smuzhiyun .word 0 705*4882a593Smuzhiyun.saved_sam9_mdr1: 706*4882a593Smuzhiyun .word 0 707*4882a593Smuzhiyun.saved_osc_status: 708*4882a593Smuzhiyun .word 0 709*4882a593Smuzhiyun 710*4882a593SmuzhiyunENTRY(at91_pm_suspend_in_sram_sz) 711*4882a593Smuzhiyun .word .-at91_pm_suspend_in_sram 712