diff options
author | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-09-27 13:29:50 +0300 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2017-05-15 12:55:17 +0300 |
commit | 24a0f5c539f944248cbb2e3502830dcb7fd2a96e (patch) | |
tree | a74851bff5a3dab7f8872937c58d0ecb8edcee6b /arch/arm/mach-at91/pm_suspend.S | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff) | |
download | linux-24a0f5c539f944248cbb2e3502830dcb7fd2a96e.tar.xz |
ARM: at91: pm: Add sama5d2 backup mode
The sama5d2 has a mode were it is possible to cut power to the SoC while
keeping the RAM in self refresh.
Resuming from that mode needs support in the firmware/bootloader.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Wenyou Yang <wenyou.yang@atmel.com>
Diffstat (limited to 'arch/arm/mach-at91/pm_suspend.S')
-rw-r--r-- | arch/arm/mach-at91/pm_suspend.S | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 96781daa671a..daca91feea6a 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -97,15 +97,61 @@ ENTRY(at91_pm_suspend_in_sram) str tmp1, .memtype ldr tmp1, [r0, #PM_DATA_MODE] str tmp1, .pm_mode + /* Both ldrne below are here to preload their address in the TLB */ + ldr tmp1, [r0, #PM_DATA_SHDWC] + str tmp1, .shdwc + cmp tmp1, #0 + ldrne tmp2, [tmp1, #0] + ldr tmp1, [r0, #PM_DATA_SFRBU] + str tmp1, .sfr + cmp tmp1, #0 + ldrne tmp2, [tmp1, #0x10] /* Active the self-refresh mode */ mov r0, #SRAMC_SELF_FRESH_ACTIVE bl at91_sramc_self_refresh ldr r0, .pm_mode - tst r0, #AT91_PM_SLOW_CLOCK - beq skip_disable_main_clock + cmp r0, #AT91_PM_SLOW_CLOCK + beq slow_clock + cmp r0, #AT91_PM_BACKUP + beq backup_mode + /* Wait for interrupt */ + ldr pmc, .pmc_base + at91_cpu_idle + b exit_suspend + +slow_clock: + bl at91_slowck_mode + b exit_suspend +backup_mode: + bl at91_backup_mode + b exit_suspend + +exit_suspend: + /* Exit the self-refresh mode */ + mov r0, #SRAMC_SELF_FRESH_EXIT + bl at91_sramc_self_refresh + + /* Restore registers, and return */ + ldmfd sp!, {r4 - r12, pc} +ENDPROC(at91_pm_suspend_in_sram) + +ENTRY(at91_backup_mode) + /*BUMEN*/ + ldr r0, .sfr + mov tmp1, #0x1 + str tmp1, [r0, #0x10] + + /* Shutdown */ + ldr r0, .shdwc + mov tmp1, #0xA5000000 + add tmp1, tmp1, #0x1 + str tmp1, [r0, #0] +ENDPROC(at91_backup_mode) + +ENTRY(at91_slowck_mode) ldr pmc, .pmc_base /* Save Master clock setting */ @@ -134,18 +180,9 @@ ENTRY(at91_pm_suspend_in_sram) orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] -skip_disable_main_clock: - ldr pmc, .pmc_base - /* Wait for interrupt */ at91_cpu_idle - ldr r0, .pm_mode - tst r0, #AT91_PM_SLOW_CLOCK - beq skip_enable_main_clock - - ldr pmc, .pmc_base - /* Turn on the main oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCEN @@ -174,14 +211,8 @@ skip_disable_main_clock: wait_mckrdy -skip_enable_main_clock: - /* Exit the self-refresh mode */ - mov r0, #SRAMC_SELF_FRESH_EXIT - bl at91_sramc_self_refresh - - /* Restore registers, and return */ - ldmfd sp!, {r4 - r12, pc} -ENDPROC(at91_pm_suspend_in_sram) + mov pc, lr +ENDPROC(at91_slowck_mode) /* * void at91_sramc_self_refresh(unsigned int is_active) @@ -314,6 +345,10 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .sramc1_base: .word 0 +.shdwc: + .word 0 +.sfr: + .word 0 .memtype: .word 0 .pm_mode: |