115300b40SClément Léger/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ 215300b40SClément Léger/* 3dc0db863SClément Léger * This file was imported from Linux arch/arm/mach-at91/pm_suspend.S and 4dc0db863SClément Léger * relicensed with dual GPL-2.0/BSD-2-Clause with Microchip agreement. 5dc0db863SClément Léger * 615300b40SClément Léger * Copyright (c) 2021, Microchip 715300b40SClément Léger */ 815300b40SClément Léger 915300b40SClément Léger#include <arm.h> 1015300b40SClément Léger#include <arm32_macros.S> 1115300b40SClément Léger#include <asm.S> 1215300b40SClément Léger#include <at91_pmc.h> 139ba91637STony Han#ifdef CFG_SAMA7G5 149ba91637STony Han#include <drivers/sam/sama7-ddr.h> 159ba91637STony Han#else 1615300b40SClément Léger#include <drivers/sam/at91_ddr.h> 179ba91637STony Han#endif 1815300b40SClément Léger#include <generated/pm-defines.h> 1915300b40SClément Léger 2015300b40SClément Léger#include "at91_pm.h" 2115300b40SClément Léger 2215300b40SClément Léger#define SRAMC_SELF_FRESH_ACTIVE 0x01 2315300b40SClément Léger#define SRAMC_SELF_FRESH_EXIT 0x00 2415300b40SClément Léger 2515300b40SClément Légerpmc .req r0 2615300b40SClément Légertmp1 .req r4 2715300b40SClément Légertmp2 .req r5 2815300b40SClément Légertmp3 .req r6 2915300b40SClément Léger 3015300b40SClément Léger/* 3115300b40SClément Léger * Wait until master clock is ready (after switching master clock source) 32b22418ebSTony Han * @r_mckid: register holding master clock identifier 33b22418ebSTony Han * 34b22418ebSTony Han * Side effects: overwrites tmp1 3515300b40SClément Léger */ 36b22418ebSTony Han.macro wait_mckrdy r_mckid 37b22418ebSTony Han#ifdef CFG_SAMA7G5 38b22418ebSTony Han cmp \r_mckid, #0 39b22418ebSTony Han beq 1f 40b22418ebSTony Han2: ldr tmp1, [pmc, #AT91_PMC_SR] 41b22418ebSTony Han tst tmp1, #AT91_PMC_MCKXRDY 42b22418ebSTony Han beq 2b 43b22418ebSTony Han b 3f 44b22418ebSTony Han#endif 4515300b40SClément Léger1: ldr tmp1, [pmc, #AT91_PMC_SR] 4615300b40SClément Léger tst tmp1, #AT91_PMC_MCKRDY 4715300b40SClément Léger beq 1b 48b22418ebSTony Han3: 4915300b40SClément Léger.endm 5015300b40SClément Léger 5115300b40SClément Léger/* 5215300b40SClément Léger * Wait until master oscillator has stabilized. 5315300b40SClément Léger */ 5415300b40SClément Léger.macro wait_moscrdy 5515300b40SClément Léger1: ldr tmp1, [pmc, #AT91_PMC_SR] 5615300b40SClément Léger tst tmp1, #AT91_PMC_MOSCS 5715300b40SClément Léger beq 1b 5815300b40SClément Léger.endm 5915300b40SClément Léger 6015300b40SClément Léger/* 6115300b40SClément Léger * Wait for main oscillator selection is done 6215300b40SClément Léger */ 6315300b40SClément Léger.macro wait_moscsels 6415300b40SClément Léger1: ldr tmp1, [pmc, #AT91_PMC_SR] 6515300b40SClément Léger tst tmp1, #AT91_PMC_MOSCSELS 6615300b40SClément Léger beq 1b 6715300b40SClément Léger.endm 6815300b40SClément Léger 6915300b40SClément Léger/* 7015300b40SClément Léger * Put the processor to enter the idle state 7115300b40SClément Léger */ 7215300b40SClément Léger.macro at91_cpu_idle 7315300b40SClément Léger 7415300b40SClément Léger mov tmp1, #AT91_PMC_PCK 7515300b40SClément Léger str tmp1, [pmc, #AT91_PMC_SCDR] 7615300b40SClément Léger 7715300b40SClément Léger dsb 7815300b40SClément Léger 7915300b40SClément Léger wfi @ Wait For Interrupt 8015300b40SClément Léger 8115300b40SClément Léger.endm 8215300b40SClément Léger 8315300b40SClément Léger.section .text.psci.suspend 8415300b40SClément Léger 8515300b40SClément Léger.arm 8615300b40SClément Léger 879ba91637STony Han#ifdef CFG_SAMA7G5 889ba91637STony Han/* 899ba91637STony Han * Enable self-refresh 909ba91637STony Han * 919ba91637STony Han * Side effects: overwrites tmp1, tmp2, tmp3 929ba91637STony Han */ 939ba91637STony Han.macro at91_sramc_self_refresh_ena 949ba91637STony Han dsb 959ba91637STony Han 969ba91637STony Han ldr tmp2, .sramc_base 979ba91637STony Han 989ba91637STony Han /* Disable all AXI ports. */ 999ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_0] 1009ba91637STony Han bic tmp1, tmp1, #0x1 1019ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_0] 1029ba91637STony Han 1039ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_1] 1049ba91637STony Han bic tmp1, tmp1, #0x1 1059ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_1] 1069ba91637STony Han 1079ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_2] 1089ba91637STony Han bic tmp1, tmp1, #0x1 1099ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_2] 1109ba91637STony Han 1119ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_3] 1129ba91637STony Han bic tmp1, tmp1, #0x1 1139ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_3] 1149ba91637STony Han 1159ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_4] 1169ba91637STony Han bic tmp1, tmp1, #0x1 1179ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_4] 1189ba91637STony Han 1199ba91637STony Hansr_ena_1: 1209ba91637STony Han /* Wait for all ports to disable. */ 1219ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PSTAT] 1229ba91637STony Han ldr tmp3, =UDDRC_PSTAT_ALL_PORTS 1239ba91637STony Han tst tmp1, tmp3 1249ba91637STony Han bne sr_ena_1 1259ba91637STony Han 1269ba91637STony Han /* Switch to self-refresh. */ 1279ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PWRCTL] 1289ba91637STony Han orr tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW 1299ba91637STony Han str tmp1, [tmp2, #UDDRC_PWRCTL] 1309ba91637STony Han 1319ba91637STony Hansr_ena_2: 1329ba91637STony Han /* Wait for self-refresh enter. */ 1339ba91637STony Han ldr tmp1, [tmp2, #UDDRC_STAT] 1349ba91637STony Han bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK 1359ba91637STony Han cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW 1369ba91637STony Han bne sr_ena_2 1379ba91637STony Han 1389ba91637STony Han ldr tmp2, .sramc_phy_base 1399ba91637STony Han 1409ba91637STony Han /* Disable DX DLLs for non-backup modes. */ 1419ba91637STony Han ldr tmp1, .pm_mode 1429ba91637STony Han cmp tmp1, #AT91_PM_BACKUP 1439ba91637STony Han beq sr_ena_3 1449ba91637STony Han 1459ba91637STony Han /* Do not soft reset the AC DLL. */ 1469ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_ACDLLCR] 1479ba91637STony Han bic tmp1, tmp1, #DDR3PHY_ACDLLCR_DLLSRST 1489ba91637STony Han str tmp1, [tmp2, #DDR3PHY_ACDLLCR] 1499ba91637STony Han 1509ba91637STony Han /* Disable DX DLLs. */ 1519ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DX0DLLCR] 1529ba91637STony Han orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 1539ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DX0DLLCR] 1549ba91637STony Han 1559ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DX1DLLCR] 1569ba91637STony Han orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 1579ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DX1DLLCR] 1589ba91637STony Han 1599ba91637STony Hansr_ena_3: 1609ba91637STony Han /* Power down DDR PHY data receivers. */ 1619ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DXCCR] 1629ba91637STony Han orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR 1639ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DXCCR] 1649ba91637STony Han 1659ba91637STony Han /* Power down ADDR/CMD IO. */ 1669ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_ACIOCR] 1679ba91637STony Han orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD 1689ba91637STony Han orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0 1699ba91637STony Han orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0 1709ba91637STony Han str tmp1, [tmp2, #DDR3PHY_ACIOCR] 1719ba91637STony Han 1729ba91637STony Han /* Power down ODT. */ 1739ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DSGCR] 1749ba91637STony Han orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0 1759ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DSGCR] 1769ba91637STony Han.endm 1779ba91637STony Han 1789ba91637STony Han/* 1799ba91637STony Han * Disable self-refresh 1809ba91637STony Han * 1819ba91637STony Han * Side effects: overwrites tmp1, tmp2 1829ba91637STony Han */ 1839ba91637STony Han.macro at91_sramc_self_refresh_dis 1849ba91637STony Han ldr tmp2, .sramc_phy_base 1859ba91637STony Han 1869ba91637STony Han /* Power up DDR PHY data receivers. */ 1879ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DXCCR] 1889ba91637STony Han bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR 1899ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DXCCR] 1909ba91637STony Han 1919ba91637STony Han /* Power up the output of CK and CS pins. */ 1929ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_ACIOCR] 1939ba91637STony Han bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD 1949ba91637STony Han bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0 1959ba91637STony Han bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0 1969ba91637STony Han str tmp1, [tmp2, #DDR3PHY_ACIOCR] 1979ba91637STony Han 1989ba91637STony Han /* Power up ODT. */ 1999ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DSGCR] 2009ba91637STony Han bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0 2019ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DSGCR] 2029ba91637STony Han 2039ba91637STony Han /* Enable DX DLLs. */ 2049ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DX0DLLCR] 2059ba91637STony Han bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 2069ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DX0DLLCR] 2079ba91637STony Han 2089ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_DX1DLLCR] 2099ba91637STony Han bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 2109ba91637STony Han str tmp1, [tmp2, #DDR3PHY_DX1DLLCR] 2119ba91637STony Han 2129ba91637STony Han ldr tmp2, .sramc_base 2139ba91637STony Han 2149ba91637STony Han /* Enable quasi-dynamic programming. */ 2159ba91637STony Han mov tmp1, #0 2169ba91637STony Han str tmp1, [tmp2, #UDDRC_SWCTRL] 2179ba91637STony Han 2189ba91637STony Han /* De-assert SDRAM initialization. */ 2199ba91637STony Han ldr tmp1, [tmp2, #UDDRC_DFIMISC] 2209ba91637STony Han bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN 2219ba91637STony Han str tmp1, [tmp2, #UDDRC_DFIMISC] 2229ba91637STony Han 2239ba91637STony Han /* Quasi-dynamic programming done. */ 2249ba91637STony Han mov tmp1, #UDDRC_SWCTRL_SW_DONE 2259ba91637STony Han str tmp1, [tmp2, #UDDRC_SWCTRL] 2269ba91637STony Han 2279ba91637STony Hansr_dis_1: 2289ba91637STony Han ldr tmp1, [tmp2, #UDDRC_SWSTAT] 2299ba91637STony Han tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK 2309ba91637STony Han beq sr_dis_1 2319ba91637STony Han 2329ba91637STony Han ldr tmp2, .sramc_phy_base 2339ba91637STony Han 2349ba91637STony Han /* DLL soft-reset + DLL lock wait + ITM reset */ 2359ba91637STony Han mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \ 2369ba91637STony Han DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST) 2379ba91637STony Han str tmp1, [tmp2, #DDR3PHY_PIR] 2389ba91637STony Han 2399ba91637STony Hansr_dis_4: 2409ba91637STony Han /* Wait for it. */ 2419ba91637STony Han ldr tmp1, [tmp2, #DDR3PHY_PGSR] 2429ba91637STony Han tst tmp1, #DDR3PHY_PGSR_IDONE 2439ba91637STony Han beq sr_dis_4 2449ba91637STony Han 2459ba91637STony Han ldr tmp2, .sramc_base 2469ba91637STony Han 2479ba91637STony Han /* Enable quasi-dynamic programming. */ 2489ba91637STony Han mov tmp1, #0 2499ba91637STony Han str tmp1, [tmp2, #UDDRC_SWCTRL] 2509ba91637STony Han 2519ba91637STony Han /* Assert PHY init complete enable signal. */ 2529ba91637STony Han ldr tmp1, [tmp2, #UDDRC_DFIMISC] 2539ba91637STony Han orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN 2549ba91637STony Han str tmp1, [tmp2, #UDDRC_DFIMISC] 2559ba91637STony Han 2569ba91637STony Han /* Programming is done. Set sw_done. */ 2579ba91637STony Han mov tmp1, #UDDRC_SWCTRL_SW_DONE 2589ba91637STony Han str tmp1, [tmp2, #UDDRC_SWCTRL] 2599ba91637STony Han 2609ba91637STony Hansr_dis_5: 2619ba91637STony Han /* Wait for it. */ 2629ba91637STony Han ldr tmp1, [tmp2, #UDDRC_SWSTAT] 2639ba91637STony Han tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK 2649ba91637STony Han beq sr_dis_5 2659ba91637STony Han 2669ba91637STony Han /* Trigger self-refresh exit. */ 2679ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PWRCTL] 2689ba91637STony Han bic tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW 2699ba91637STony Han str tmp1, [tmp2, #UDDRC_PWRCTL] 2709ba91637STony Han 2719ba91637STony Hansr_dis_6: 2729ba91637STony Han /* Wait for self-refresh exit done. */ 2739ba91637STony Han ldr tmp1, [tmp2, #UDDRC_STAT] 2749ba91637STony Han bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK 2759ba91637STony Han cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL 2769ba91637STony Han bne sr_dis_6 2779ba91637STony Han 2789ba91637STony Han /* Enable all AXI ports. */ 2799ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_0] 2809ba91637STony Han orr tmp1, tmp1, #0x1 2819ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_0] 2829ba91637STony Han 2839ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_1] 2849ba91637STony Han orr tmp1, tmp1, #0x1 2859ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_1] 2869ba91637STony Han 2879ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_2] 2889ba91637STony Han orr tmp1, tmp1, #0x1 2899ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_2] 2909ba91637STony Han 2919ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_3] 2929ba91637STony Han orr tmp1, tmp1, #0x1 2939ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_3] 2949ba91637STony Han 2959ba91637STony Han ldr tmp1, [tmp2, #UDDRC_PCTRL_4] 2969ba91637STony Han orr tmp1, tmp1, #0x1 2979ba91637STony Han str tmp1, [tmp2, #UDDRC_PCTRL_4] 2989ba91637STony Han 2999ba91637STony Han dsb 3009ba91637STony Han.endm 3019ba91637STony Han#endif 30215300b40SClément Léger 30315300b40SClément Léger#define SUSPEND_FUNC(__name) \ 30415300b40SClément Léger__name: 30515300b40SClément Léger 30615300b40SClément Léger#define SUSPEND_END_FUNC(__name) \ 30715300b40SClément Léger .size __name, .-__name 30815300b40SClément Léger 30915300b40SClément Léger.macro check_fit_in_sram since 31015300b40SClément Léger .if (. - \since) > 0x10000 31115300b40SClément Léger .error "Suspend assembly code exceeds dedicated SRAM size" 31215300b40SClément Léger .endif 31315300b40SClément Léger.endm 31415300b40SClément Léger 31515300b40SClément Léger/* 31615300b40SClément Léger * void at91_suspend_sram_fn(struct at91_pm_data*) 31715300b40SClément Léger * @input param: 31815300b40SClément Léger * @r0: base address of struct at91_pm_data 31915300b40SClément Léger */ 32015300b40SClément Léger.align 3 32115300b40SClément Léger.global at91_pm_suspend_in_sram 32215300b40SClément LégerSUSPEND_FUNC(at91_pm_suspend_in_sram) 32315300b40SClément Léger /* Save registers on stack */ 32415300b40SClément Léger stmfd sp!, {r4 - r12, lr} 32515300b40SClément Léger 32615300b40SClément Léger /* Drain write buffer */ 32715300b40SClément Léger mov tmp1, #0 32815300b40SClément Léger mcr p15, 0, tmp1, c7, c10, 4 32915300b40SClément Léger 330*f73055a1STony Han write_tlbiall 331*f73055a1STony Han isb 332*f73055a1STony Han 333*f73055a1STony Han /* 334*f73055a1STony Han * ldrne below are here to preload their address in the TLB as access 335*f73055a1STony Han * to RAM may be limited while in self-refresh. 336*f73055a1STony Han */ 33715300b40SClément Léger ldr tmp1, [r0, #PM_DATA_PMC] 33815300b40SClément Léger str tmp1, .pmc_base 339*f73055a1STony Han cmp tmp1, #0 340*f73055a1STony Han ldrne tmp2, [tmp1, #0] 341*f73055a1STony Han 34215300b40SClément Léger ldr tmp1, [r0, #PM_DATA_RAMC0] 34315300b40SClément Léger str tmp1, .sramc_base 344*f73055a1STony Han cmp tmp1, #0 345*f73055a1STony Han ldrne tmp2, [tmp1, #0] 346*f73055a1STony Han 34746f0e733STony Han ldr tmp1, [r0, #PM_DATA_RAMC_PHY] 34846f0e733STony Han str tmp1, .sramc_phy_base 349*f73055a1STony Han cmp tmp1, #0 350*f73055a1STony Han ldrne tmp2, [tmp1, #0] 351*f73055a1STony Han 35215300b40SClément Léger ldr tmp1, [r0, #PM_DATA_MODE] 35315300b40SClément Léger str tmp1, .pm_mode 35415300b40SClément Léger /* Both ldrne below are here to preload their address in the TLB */ 35515300b40SClément Léger ldr tmp1, [r0, #PM_DATA_SHDWC] 35615300b40SClément Léger str tmp1, .shdwc 35715300b40SClément Léger cmp tmp1, #0 35815300b40SClément Léger ldrne tmp2, [tmp1, #0] 35915300b40SClément Léger ldr tmp1, [r0, #PM_DATA_SFRBU] 36015300b40SClément Léger str tmp1, .sfrbu 36115300b40SClément Léger cmp tmp1, #0 36215300b40SClément Léger ldrne tmp2, [tmp1, #0x10] 36315300b40SClément Léger 36415300b40SClément Léger /* Active the self-refresh mode */ 3659ba91637STony Han#ifdef CFG_SAMA5D2 36615300b40SClément Léger mov r0, #SRAMC_SELF_FRESH_ACTIVE 36715300b40SClément Léger bl at91_sramc_self_refresh 3689ba91637STony Han#endif 3699ba91637STony Han#ifdef CFG_SAMA7G5 3709ba91637STony Han at91_sramc_self_refresh_ena 3719ba91637STony Han#endif 37215300b40SClément Léger 37315300b40SClément Léger ldr r0, .pm_mode 37415300b40SClément Léger cmp r0, #AT91_PM_STANDBY 37515300b40SClément Léger beq standby 37615300b40SClément Léger cmp r0, #AT91_PM_BACKUP 37715300b40SClément Léger beq backup_mode 37815300b40SClément Léger 37915300b40SClément Léger bl at91_ulp_mode 38015300b40SClément Léger b exit_suspend 38115300b40SClément Léger 38215300b40SClément Légerstandby: 38315300b40SClément Léger /* Wait for interrupt */ 38415300b40SClément Léger ldr pmc, .pmc_base 38515300b40SClément Léger at91_cpu_idle 38615300b40SClément Léger b exit_suspend 38715300b40SClément Léger 38815300b40SClément Légerbackup_mode: 38915300b40SClément Léger bl at91_backup_mode 39015300b40SClément Léger b exit_suspend 39115300b40SClément Léger 39215300b40SClément Légerexit_suspend: 39315300b40SClément Léger /* Exit the self-refresh mode */ 3949ba91637STony Han#ifdef CFG_SAMA5D2 39515300b40SClément Léger mov r0, #SRAMC_SELF_FRESH_EXIT 39615300b40SClément Léger bl at91_sramc_self_refresh 3979ba91637STony Han#endif 3989ba91637STony Han#ifdef CFG_SAMA7G5 3999ba91637STony Han at91_sramc_self_refresh_dis 4009ba91637STony Han#endif 40115300b40SClément Léger 40215300b40SClément Léger /* Restore registers, and return */ 40315300b40SClément Léger ldmfd sp!, {r4 - r12, pc} 40415300b40SClément LégerSUSPEND_END_FUNC(at91_pm_suspend_in_sram) 40515300b40SClément Léger 40615300b40SClément LégerSUSPEND_FUNC(at91_backup_mode) 40715300b40SClément Léger /* Switch the master clock source to slow clock. */ 40815300b40SClément Léger ldr pmc, .pmc_base 40915300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 41015300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_CSS 41115300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 41215300b40SClément Léger 413b22418ebSTony Han mov tmp3, #0 414b22418ebSTony Han wait_mckrdy tmp3 41515300b40SClément Léger 41615300b40SClément Léger /*BUMEN*/ 41715300b40SClément Léger ldr r0, .sfrbu 41815300b40SClément Léger mov tmp1, #0x1 41915300b40SClément Léger str tmp1, [r0, #0x10] 42015300b40SClément Léger 42115300b40SClément Léger /* Shutdown */ 42215300b40SClément Léger ldr r0, .shdwc 42315300b40SClément Léger mov tmp1, #0xA5000000 42415300b40SClément Léger add tmp1, tmp1, #0x1 4256ea2ed2aSTony Han#ifdef CFG_SAMA7G5 4266ea2ed2aSTony Han /* LPM Pad Enable: The LPM pad is set high */ 4276ea2ed2aSTony Han orr tmp1, tmp1, #0x200000 4286ea2ed2aSTony Han#endif 42915300b40SClément Léger str tmp1, [r0, #0] 43015300b40SClément LégerSUSPEND_END_FUNC(at91_backup_mode) 43115300b40SClément Léger 4326ea2ed2aSTony Han/* 4336ea2ed2aSTony Han * Set LPM 4346ea2ed2aSTony Han * @ena: 0 - disable LPM 4356ea2ed2aSTony Han * 1 - enable LPM 4366ea2ed2aSTony Han * 4376ea2ed2aSTony Han * Side effects: overwrites tmp1, tmp3 4386ea2ed2aSTony Han */ 4396ea2ed2aSTony Han.macro at91_set_lpm ena 4406ea2ed2aSTony Han#ifdef CFG_SAMA7G5 4416ea2ed2aSTony Han mov tmp1, #\ena 4426ea2ed2aSTony Han cmp tmp1, #1 4436ea2ed2aSTony Han movne tmp3, #0x400000 /* LPM Pad Disable: The LPM pad is set low */ 4446ea2ed2aSTony Han moveq tmp3, #0x200000 /* LPM Pad Enable: The LPM pad is set high */ 4456ea2ed2aSTony Han add tmp3, #0xA5000000 4466ea2ed2aSTony Han ldr tmp1, .shdwc 4476ea2ed2aSTony Han cmp tmp1, #0 4486ea2ed2aSTony Han strne tmp3, [tmp1] 4496ea2ed2aSTony Han#endif 4506ea2ed2aSTony Han.endm 4516ea2ed2aSTony Han 45215300b40SClément Léger.macro at91_pm_ulp0_mode 45315300b40SClément Léger ldr pmc, .pmc_base 45415300b40SClément Léger ldr tmp2, .pm_mode 45515300b40SClément Léger 45615300b40SClément Léger /* Check if ULP0 fast variant has been requested. */ 45715300b40SClément Léger cmp tmp2, #AT91_PM_ULP0_FAST 45815300b40SClément Léger bne 0f 45915300b40SClément Léger 46015300b40SClément Léger /* Set highest prescaler for power saving */ 46115300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 46215300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_PRES 46315300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_PRES_64 46415300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 465b22418ebSTony Han 466b22418ebSTony Han mov tmp3, #0 467b22418ebSTony Han wait_mckrdy tmp3 46815300b40SClément Léger b 1f 46915300b40SClément Léger 47015300b40SClément Léger0: 47115300b40SClément Léger /* Turn off the crystal oscillator */ 47215300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 47315300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_MOSCEN 47415300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 47515300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 47615300b40SClément Léger 47715300b40SClément Léger /* Save RC oscillator state */ 47815300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_SR] 47915300b40SClément Léger str tmp1, .saved_osc_status 48015300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 4816ea2ed2aSTony Han bne 7f 48215300b40SClément Léger 48315300b40SClément Léger /* Turn off RC oscillator */ 48415300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 48515300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 48615300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 48715300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 48815300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 48915300b40SClément Léger 49015300b40SClément Léger /* Wait main RC disabled done */ 49115300b40SClément Léger2: ldr tmp1, [pmc, #AT91_PMC_SR] 49215300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 49315300b40SClément Léger bne 2b 49415300b40SClément Léger 4956ea2ed2aSTony Han /* Enable LPM. */ 4966ea2ed2aSTony Han7: at91_set_lpm 1 4976ea2ed2aSTony Han 49815300b40SClément Léger /* Wait for interrupt */ 49915300b40SClément Léger1: at91_cpu_idle 50015300b40SClément Léger 50115300b40SClément Léger /* Check if ULP0 fast variant has been requested. */ 50215300b40SClément Léger cmp tmp2, #AT91_PM_ULP0_FAST 5036ea2ed2aSTony Han bne 8f 50415300b40SClément Léger 50515300b40SClément Léger /* Set lowest prescaler for fast resume. */ 50615300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 50715300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_PRES 50815300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 509b22418ebSTony Han 510b22418ebSTony Han mov tmp3, #0 511b22418ebSTony Han wait_mckrdy tmp3 51215300b40SClément Léger b 6f 51315300b40SClément Léger 5146ea2ed2aSTony Han8: at91_set_lpm 0 5156ea2ed2aSTony Han 51615300b40SClément Léger5: /* Restore RC oscillator state */ 51715300b40SClément Léger ldr tmp1, .saved_osc_status 51815300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 51915300b40SClément Léger beq 4f 52015300b40SClément Léger 52115300b40SClément Léger /* Turn on RC oscillator */ 52215300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 52315300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 52415300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 52515300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 52615300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 52715300b40SClément Léger 52815300b40SClément Léger /* Wait main RC stabilization */ 52915300b40SClément Léger3: ldr tmp1, [pmc, #AT91_PMC_SR] 53015300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 53115300b40SClément Léger beq 3b 53215300b40SClément Léger 53315300b40SClément Léger /* Turn on the crystal oscillator */ 53415300b40SClément Léger4: ldr tmp1, [pmc, #AT91_CKGR_MOR] 53515300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_MOSCEN 53615300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 53715300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 53815300b40SClément Léger 53915300b40SClément Léger wait_moscrdy 54015300b40SClément Léger6: 54115300b40SClément Léger.endm 54215300b40SClément Léger 54315300b40SClément Léger/** 54415300b40SClément Léger * Note: This procedure only applies on the platform which uses 54515300b40SClément Léger * the external crystal oscillator as a main clock source. 54615300b40SClément Léger */ 54715300b40SClément Léger.macro at91_pm_ulp1_mode 54815300b40SClément Léger ldr pmc, .pmc_base 54915300b40SClément Léger 55015300b40SClément Léger /* Save RC oscillator state and check if it is enabled. */ 55115300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_SR] 55215300b40SClément Léger str tmp1, .saved_osc_status 55315300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 55415300b40SClément Léger bne 2f 55515300b40SClément Léger 55615300b40SClément Léger /* Enable RC oscillator */ 55715300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 55815300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 55915300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 56015300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 56115300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 56215300b40SClément Léger 56315300b40SClément Léger /* Wait main RC stabilization */ 56415300b40SClément Léger1: ldr tmp1, [pmc, #AT91_PMC_SR] 56515300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 56615300b40SClément Léger beq 1b 56715300b40SClément Léger 56815300b40SClément Léger /* Switch the main clock source to 12-MHz RC oscillator */ 56915300b40SClément Léger2: ldr tmp1, [pmc, #AT91_CKGR_MOR] 57015300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_MOSCSEL 57115300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 57215300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 57315300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 57415300b40SClément Léger 57515300b40SClément Léger wait_moscsels 57615300b40SClément Léger 57715300b40SClément Léger /* Disable the crystal oscillator */ 57815300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 57915300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_MOSCEN 58015300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 58115300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 58215300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 58315300b40SClément Léger 58415300b40SClément Léger /* Switch the master clock source to main clock */ 58515300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 58615300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_CSS 58715300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 58815300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 58915300b40SClément Léger 590b22418ebSTony Han mov tmp3, #0 591b22418ebSTony Han wait_mckrdy tmp3 59215300b40SClément Léger 5936ea2ed2aSTony Han /* Enable LPM */ 5946ea2ed2aSTony Han at91_set_lpm 1 5956ea2ed2aSTony Han 59615300b40SClément Léger /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */ 59715300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 59815300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_WAITMODE 59915300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 60015300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 60115300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 60215300b40SClément Léger 60315300b40SClément Léger /* Quirk for SAM9X60's PMC */ 60415300b40SClément Léger nop 60515300b40SClément Léger nop 60615300b40SClément Léger 6076ea2ed2aSTony Han mov tmp3, #0 608b22418ebSTony Han wait_mckrdy tmp3 60915300b40SClément Léger 6106ea2ed2aSTony Han /* Disable LPM. */ 6116ea2ed2aSTony Han at91_set_lpm 0 6126ea2ed2aSTony Han 61315300b40SClément Léger /* Enable the crystal oscillator */ 61415300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 61515300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_MOSCEN 61615300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 61715300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 61815300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 61915300b40SClément Léger 62015300b40SClément Léger wait_moscrdy 62115300b40SClément Léger 62215300b40SClément Léger /* Switch the master clock source to slow clock */ 62315300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 62415300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_CSS 62515300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 62615300b40SClément Léger 6276ea2ed2aSTony Han mov tmp3, #0 628b22418ebSTony Han wait_mckrdy tmp3 62915300b40SClément Léger 63015300b40SClément Léger /* Switch main clock source to crystal oscillator */ 63115300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 63215300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_MOSCSEL 63315300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 63415300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 63515300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 63615300b40SClément Léger 63715300b40SClément Léger wait_moscsels 63815300b40SClément Léger 63915300b40SClément Léger /* Switch the master clock source to main clock */ 64015300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 64115300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_CSS 64215300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 64315300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 64415300b40SClément Léger 645b22418ebSTony Han wait_mckrdy tmp3 64615300b40SClément Léger 64715300b40SClément Léger /* Restore RC oscillator state */ 64815300b40SClément Léger ldr tmp1, .saved_osc_status 64915300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 65015300b40SClément Léger bne 3f 65115300b40SClément Léger 65215300b40SClément Léger /* Disable RC oscillator */ 65315300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_MOR] 65415300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 65515300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_KEY_MASK 65615300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_KEY 65715300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_MOR] 65815300b40SClément Léger 65915300b40SClément Léger /* Wait RC oscillator disable done */ 66015300b40SClément Léger4: ldr tmp1, [pmc, #AT91_PMC_SR] 66115300b40SClément Léger tst tmp1, #AT91_PMC_MOSCRCS 66215300b40SClément Léger bne 4b 66315300b40SClément Léger 66415300b40SClément Léger3: 66515300b40SClément Léger.endm 66615300b40SClément Léger 66761ecdd1dSTony Han/* 66861ecdd1dSTony Han * Save PLLA setting and disable it 66961ecdd1dSTony Han * 67061ecdd1dSTony Han * Side effects: overwrites tmp1, tmp2 67161ecdd1dSTony Han */ 67215300b40SClément Léger.macro at91_plla_disable 67361ecdd1dSTony Han#ifdef CFG_SAMA7G5 67461ecdd1dSTony Han /* Save PLLA settings */ 67561ecdd1dSTony Han ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT] 67661ecdd1dSTony Han bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID 67761ecdd1dSTony Han str tmp2, [pmc, #AT91_PMC_PLL_UPDT] 67861ecdd1dSTony Han 67961ecdd1dSTony Han /* save div */ 68061ecdd1dSTony Han mov tmp1, #0 68161ecdd1dSTony Han ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0] 68261ecdd1dSTony Han bic tmp2, tmp2, #0xffffff00 68361ecdd1dSTony Han orr tmp1, tmp1, tmp2 68461ecdd1dSTony Han 68561ecdd1dSTony Han /* save mul */ 68661ecdd1dSTony Han ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL1] 68761ecdd1dSTony Han bic tmp2, tmp2, #0xffffff 68861ecdd1dSTony Han orr tmp1, tmp1, tmp2 68961ecdd1dSTony Han str tmp1, .saved_pllar 69061ecdd1dSTony Han 69161ecdd1dSTony Han /* step 2 */ 69261ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 69361ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 69461ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 69561ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 69661ecdd1dSTony Han 69761ecdd1dSTony Han /* step 3 */ 69861ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 69961ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK 70061ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 70161ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 70261ecdd1dSTony Han 70361ecdd1dSTony Han /* step 4 */ 70461ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 70561ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 70661ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 70761ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 70861ecdd1dSTony Han 70961ecdd1dSTony Han /* step 5 */ 71061ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 71161ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 71261ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 71361ecdd1dSTony Han 71461ecdd1dSTony Han /* step 6 */ 71561ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 71661ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 71761ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 71861ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 71961ecdd1dSTony Han#else 72015300b40SClément Léger /* Save PLLA setting and disable it */ 72115300b40SClément Léger ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 72215300b40SClément Léger str tmp1, .saved_pllar 72315300b40SClément Léger 72415300b40SClément Léger /* Disable PLLA. */ 72515300b40SClément Léger mov tmp1, #AT91_PMC_PLLCOUNT 72615300b40SClément Léger orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 72715300b40SClément Léger str tmp1, [pmc, #AT91_CKGR_PLLAR] 72861ecdd1dSTony Han#endif 72915300b40SClément Léger2: 73015300b40SClément Léger.endm 73115300b40SClément Léger 73261ecdd1dSTony Han/* 73361ecdd1dSTony Han * Enable PLLA with the saved setting 73461ecdd1dSTony Han * 73561ecdd1dSTony Han * Side effects: overwrites tmp1, tmp2 73661ecdd1dSTony Han */ 73715300b40SClément Léger.macro at91_plla_enable 73861ecdd1dSTony Han#ifdef CFG_SAMA7G5 73961ecdd1dSTony Han /* step 1 */ 74061ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 74161ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 74261ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 74361ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 74461ecdd1dSTony Han 74561ecdd1dSTony Han /* step 2 */ 74661ecdd1dSTony Han ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA 74761ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_ACR] 74861ecdd1dSTony Han 74961ecdd1dSTony Han /* step 3 */ 75061ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL1] 75161ecdd1dSTony Han ldr tmp2, .saved_pllar 75261ecdd1dSTony Han bic tmp2, tmp2, #0xffffff 75361ecdd1dSTony Han orr tmp1, tmp1, tmp2 75461ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_CTRL1] 75561ecdd1dSTony Han 75661ecdd1dSTony Han /* step 4 */ 75761ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 75861ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 75961ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 76061ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 76161ecdd1dSTony Han 76261ecdd1dSTony Han /* step 5 */ 76361ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 76461ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK 76561ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 76661ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK 76761ecdd1dSTony Han bic tmp1, tmp1, #0xff 76861ecdd1dSTony Han ldr tmp2, .saved_pllar 76961ecdd1dSTony Han bic tmp2, tmp2, #0xffffff00 77061ecdd1dSTony Han orr tmp1, tmp1, tmp2 77161ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 77261ecdd1dSTony Han 77361ecdd1dSTony Han /* step 6 */ 77461ecdd1dSTony Han ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 77561ecdd1dSTony Han orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 77661ecdd1dSTony Han bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 77761ecdd1dSTony Han str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 77861ecdd1dSTony Han 77961ecdd1dSTony Han /* step 7 */ 78061ecdd1dSTony Han3: ldr tmp1, [pmc, #AT91_PMC_PLL_ISR0] 78161ecdd1dSTony Han tst tmp1, #0x1 78261ecdd1dSTony Han beq 3b 78361ecdd1dSTony Han#else 78415300b40SClément Léger ldr tmp2, .saved_pllar 78515300b40SClément Léger 78615300b40SClément Léger /* Restore PLLA setting */ 78715300b40SClément Léger str tmp2, [pmc, #AT91_CKGR_PLLAR] 78815300b40SClément Léger 78915300b40SClément Léger /* Enable PLLA. */ 79015300b40SClément Léger tst tmp2, #(AT91_PMC_MUL & 0xff0000) 79115300b40SClément Léger bne 1f 79215300b40SClément Léger tst tmp2, #(AT91_PMC_MUL & ~0xff0000) 79315300b40SClément Léger beq 2f 79415300b40SClément Léger 79515300b40SClément Léger1: ldr tmp1, [pmc, #AT91_PMC_SR] 79615300b40SClément Léger tst tmp1, #AT91_PMC_LOCKA 79715300b40SClément Léger beq 1b 79815300b40SClément Léger2: 79961ecdd1dSTony Han#endif 80015300b40SClément Léger.endm 80115300b40SClément Léger 802735a1effSTony Han#ifdef CFG_SAMA7G5 803735a1effSTony Han/* 804735a1effSTony Han * at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock 805735a1effSTony Han * 806735a1effSTony Han * Side effects: overwrites tmp1, tmp2, tmp3 807735a1effSTony Han */ 808735a1effSTony Han.macro at91_mckx_ps_enable 809735a1effSTony Han ldr pmc, .pmc_base 810735a1effSTony Han 811735a1effSTony Han /* There are 4 MCKs we need to handle: MCK1..4 */ 812735a1effSTony Han mov tmp1, #1 813735a1effSTony Hane_loop: 814735a1effSTony Han /* Write MCK ID to retrieve the settings */ 815735a1effSTony Han str tmp1, [pmc, #AT91_PMC_MCR_V2] 816735a1effSTony Han ldr tmp2, [pmc, #AT91_PMC_MCR_V2] 817735a1effSTony Han 818735a1effSTony Han cmp tmp1, #1 819735a1effSTony Han streq tmp2, .saved_mck1 820735a1effSTony Han cmp tmp1, #2 821735a1effSTony Han streq tmp2, .saved_mck2 822735a1effSTony Han cmp tmp1, #3 823735a1effSTony Han streq tmp2, .saved_mck3 824735a1effSTony Han cmp tmp1, #4 825735a1effSTony Han streq tmp2, .saved_mck4 826735a1effSTony Han 827735a1effSTony Han /* Use CSS=MD_SLOW_CLK and DIV=64. */ 828735a1effSTony Han bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK 829735a1effSTony Han bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK 830735a1effSTony Han orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK 831735a1effSTony Han orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64 832735a1effSTony Han orr tmp2, tmp2, #AT91_PMC_MCR_V2_CMD 833735a1effSTony Han str tmp2, [pmc, #AT91_PMC_MCR_V2] 834735a1effSTony Han 835735a1effSTony Han mov tmp2, tmp1 836735a1effSTony Han wait_mckrdy tmp1 837735a1effSTony Han mov tmp1, tmp2 838735a1effSTony Han 839735a1effSTony Han add tmp1, tmp1, #1 840735a1effSTony Han cmp tmp1, #5 841735a1effSTony Han bne e_loop 842735a1effSTony Han.endm 843735a1effSTony Han 844735a1effSTony Han/* 845735a1effSTony Han * at91_mckx_ps_restore: restore MCK1..4 settings 846735a1effSTony Han * 847735a1effSTony Han * Side effects: overwrites tmp1, tmp2, tmp3 848735a1effSTony Han */ 849735a1effSTony Han.macro at91_mckx_ps_restore 850735a1effSTony Han ldr pmc, .pmc_base 851735a1effSTony Han 852735a1effSTony Han /* There are 4 MCKs we need to handle: MCK1..4 */ 853735a1effSTony Han mov tmp1, #1 854735a1effSTony Han ldr tmp2, .saved_mck1 855735a1effSTony Hanr_loop: 856735a1effSTony Han cmp tmp1, #2 857735a1effSTony Han ldreq tmp2, .saved_mck2 858735a1effSTony Han cmp tmp1, #3 859735a1effSTony Han ldreq tmp2, .saved_mck3 860735a1effSTony Han cmp tmp1, #4 861735a1effSTony Han ldreq tmp2, .saved_mck4 862735a1effSTony Han 863735a1effSTony Han /* Write MCK ID to retrieve the settings */ 864735a1effSTony Han str tmp1, [pmc, #AT91_PMC_MCR_V2] 865735a1effSTony Han ldr tmp3, [pmc, #AT91_PMC_MCR_V2] 866735a1effSTony Han 867735a1effSTony Han /* We need to restore CSS and DIV. */ 868735a1effSTony Han bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK 869735a1effSTony Han bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK 870735a1effSTony Han orr tmp3, tmp3, tmp2 871735a1effSTony Han bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK 872735a1effSTony Han orr tmp3, tmp3, tmp1 873735a1effSTony Han orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD 874735a1effSTony Han str tmp3, [pmc, #AT91_PMC_MCR_V2] 875735a1effSTony Han 876735a1effSTony Han mov tmp2, tmp1 877735a1effSTony Han wait_mckrdy tmp1 878735a1effSTony Han mov tmp1, tmp2 879735a1effSTony Han 880735a1effSTony Han add tmp1, tmp1, #1 881735a1effSTony Han cmp tmp1, #5 882735a1effSTony Han bne r_loop 883735a1effSTony Han.endm 884735a1effSTony Han#endif 885735a1effSTony Han 88615300b40SClément LégerSUSPEND_FUNC(at91_ulp_mode) 887735a1effSTony Han#ifdef CFG_SAMA7G5 888735a1effSTony Han at91_mckx_ps_enable 889735a1effSTony Han#endif 890735a1effSTony Han 89115300b40SClément Léger ldr pmc, .pmc_base 89215300b40SClément Léger ldr tmp3, .pm_mode 89315300b40SClément Léger 89415300b40SClément Léger /* Save Master clock setting */ 89515300b40SClément Léger ldr tmp1, [pmc, #AT91_PMC_MCKR] 89615300b40SClément Léger str tmp1, .saved_mckr 89715300b40SClément Léger 89815300b40SClément Léger /* 89915300b40SClément Léger * Set master clock source to: 90015300b40SClément Léger * - MAINCK if using ULP0 fast variant 90115300b40SClément Léger * - slow clock, otherwise 90215300b40SClément Léger */ 90315300b40SClément Léger bic tmp1, tmp1, #AT91_PMC_CSS 90415300b40SClément Léger cmp tmp3, #AT91_PM_ULP0_FAST 90515300b40SClément Léger bne save_mck 90615300b40SClément Léger orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 90715300b40SClément Légersave_mck: 90815300b40SClément Léger str tmp1, [pmc, #AT91_PMC_MCKR] 90915300b40SClément Léger 910b22418ebSTony Han mov tmp3, #0 911b22418ebSTony Han wait_mckrdy tmp3 91215300b40SClément Léger 91315300b40SClément Léger at91_plla_disable 91415300b40SClément Léger 915b22418ebSTony Han ldr tmp3, .pm_mode 91615300b40SClément Léger cmp tmp3, #AT91_PM_ULP1 91715300b40SClément Léger beq ulp1_mode 91815300b40SClément Léger 91915300b40SClément Léger at91_pm_ulp0_mode 92015300b40SClément Léger b ulp_exit 92115300b40SClément Léger 92215300b40SClément Légerulp1_mode: 92315300b40SClément Léger at91_pm_ulp1_mode 92415300b40SClément Léger b ulp_exit 92515300b40SClément Léger 92615300b40SClément Légerulp_exit: 92715300b40SClément Léger ldr pmc, .pmc_base 92815300b40SClément Léger 92915300b40SClément Léger at91_plla_enable 93015300b40SClément Léger 93115300b40SClément Léger /* 93215300b40SClément Léger * Restore master clock setting 93315300b40SClément Léger */ 93415300b40SClément Léger ldr tmp2, .saved_mckr 93515300b40SClément Léger str tmp2, [pmc, #AT91_PMC_MCKR] 93615300b40SClément Léger 937b22418ebSTony Han mov tmp3, #0 938b22418ebSTony Han wait_mckrdy tmp3 93915300b40SClément Léger 940735a1effSTony Han#ifdef CFG_SAMA7G5 941735a1effSTony Han at91_mckx_ps_restore 942735a1effSTony Han#endif 943735a1effSTony Han 94415300b40SClément Léger mov pc, lr 94515300b40SClément LégerSUSPEND_END_FUNC(at91_ulp_mode) 94615300b40SClément Léger 9479ba91637STony Han#ifdef CFG_SAMA5D2 94815300b40SClément Léger/* 94915300b40SClément Léger * void at91_sramc_self_refresh(unsigned int is_active) 95015300b40SClément Léger * 95115300b40SClément Léger * @input param: 95215300b40SClément Léger * @r0: 1 - active self-refresh mode 95315300b40SClément Léger * 0 - exit self-refresh mode 95415300b40SClément Léger * register usage: 95515300b40SClément Léger * @r2: base address of the sram controller 95615300b40SClément Léger */ 95715300b40SClément Léger 95815300b40SClément LégerSUSPEND_FUNC(at91_sramc_self_refresh) 95915300b40SClément Léger ldr r2, .sramc_base 96015300b40SClément Léger 96115300b40SClément Léger /* 96215300b40SClément Léger * DDR Memory controller 96315300b40SClément Léger */ 96415300b40SClément Léger tst r0, #SRAMC_SELF_FRESH_ACTIVE 96515300b40SClément Léger beq ddrc_exit_sf 96615300b40SClément Léger 96715300b40SClément Léger /* LPDDR1 --> force DDR2 mode during self-refresh */ 96815300b40SClément Léger ldr r3, [r2, #AT91_DDRSDRC_MDR] 96915300b40SClément Léger str r3, .saved_sam9_mdr 97015300b40SClément Léger bic r3, r3, #~AT91_DDRSDRC_MD 97115300b40SClément Léger cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 97215300b40SClément Léger ldreq r3, [r2, #AT91_DDRSDRC_MDR] 97315300b40SClément Léger biceq r3, r3, #AT91_DDRSDRC_MD 97415300b40SClément Léger orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 97515300b40SClément Léger streq r3, [r2, #AT91_DDRSDRC_MDR] 97615300b40SClément Léger 97715300b40SClément Léger /* Active DDRC self-refresh mode */ 97815300b40SClément Léger ldr r3, [r2, #AT91_DDRSDRC_LPR] 97915300b40SClément Léger str r3, .saved_sam9_lpr 98015300b40SClément Léger bic r3, r3, #AT91_DDRSDRC_LPCB 98115300b40SClément Léger orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 98215300b40SClément Léger str r3, [r2, #AT91_DDRSDRC_LPR] 98315300b40SClément Léger 98415300b40SClément Léger b exit_sramc_sf 98515300b40SClément Léger 98615300b40SClément Légerddrc_exit_sf: 98715300b40SClément Léger /* Restore MDR in case of LPDDR1 */ 98815300b40SClément Léger ldr r3, .saved_sam9_mdr 98915300b40SClément Léger str r3, [r2, #AT91_DDRSDRC_MDR] 99015300b40SClément Léger /* Restore LPR on AT91 with DDRAM */ 99115300b40SClément Léger ldr r3, .saved_sam9_lpr 99215300b40SClément Léger str r3, [r2, #AT91_DDRSDRC_LPR] 99315300b40SClément Léger 99415300b40SClément Légerexit_sramc_sf: 99515300b40SClément Léger mov pc, lr 99615300b40SClément LégerSUSPEND_END_FUNC(at91_sramc_self_refresh) 9979ba91637STony Han#endif 99815300b40SClément Léger 99915300b40SClément Léger.pmc_base: 100015300b40SClément Léger .word 0 100115300b40SClément Léger.sramc_base: 100215300b40SClément Léger .word 0 100346f0e733STony Han.sramc_phy_base: 100446f0e733STony Han .word 0 100515300b40SClément Léger.shdwc: 100615300b40SClément Léger .word 0 100715300b40SClément Léger.sfrbu: 100815300b40SClément Léger .word 0 100915300b40SClément Léger.pm_mode: 101015300b40SClément Léger .word 0 101115300b40SClément Léger.saved_mckr: 101215300b40SClément Léger .word 0 101315300b40SClément Léger.saved_pllar: 101415300b40SClément Léger .word 0 101515300b40SClément Léger.saved_sam9_lpr: 101615300b40SClément Léger .word 0 101715300b40SClément Léger.saved_sam9_mdr: 101815300b40SClément Léger .word 0 101915300b40SClément Léger.saved_osc_status: 102015300b40SClément Léger .word 0 1021735a1effSTony Han#ifdef CFG_SAMA7G5 1022735a1effSTony Han.saved_mck1: 1023735a1effSTony Han .word 0 1024735a1effSTony Han.saved_mck2: 1025735a1effSTony Han .word 0 1026735a1effSTony Han.saved_mck3: 1027735a1effSTony Han .word 0 1028735a1effSTony Han.saved_mck4: 1029735a1effSTony Han .word 0 1030735a1effSTony Han#endif 103115300b40SClément Léger 103215300b40SClément Léger.global at91_pm_suspend_in_sram_sz 103315300b40SClément Légerat91_pm_suspend_in_sram_sz: 103415300b40SClément Léger .word .-at91_pm_suspend_in_sram 103515300b40SClément Léger 103615300b40SClément Légercheck_fit_in_sram at91_pm_suspend_in_sram 1037