162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/mach-at91/pm_slow_clock.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006 Savin Zlobec 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * AT91SAM9 support: 862306a36Sopenharmony_ci * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <linux/linkage.h> 1162306a36Sopenharmony_ci#include <linux/clk/at91_pmc.h> 1262306a36Sopenharmony_ci#include "pm.h" 1362306a36Sopenharmony_ci#include "pm_data-offsets.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7 1662306a36Sopenharmony_ci.arch armv7-a 1762306a36Sopenharmony_ci#endif 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define SRAMC_SELF_FRESH_ACTIVE 0x01 2062306a36Sopenharmony_ci#define SRAMC_SELF_FRESH_EXIT 0x00 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cipmc .req r0 2362306a36Sopenharmony_citmp1 .req r4 2462306a36Sopenharmony_citmp2 .req r5 2562306a36Sopenharmony_citmp3 .req r6 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * Wait until master clock is ready (after switching master clock source) 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * @r_mckid: register holding master clock identifier 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * Side effects: overwrites r7, r8 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci .macro wait_mckrdy r_mckid 3562306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 3662306a36Sopenharmony_ci cmp \r_mckid, #0 3762306a36Sopenharmony_ci beq 1f 3862306a36Sopenharmony_ci mov r7, #AT91_PMC_MCKXRDY 3962306a36Sopenharmony_ci b 2f 4062306a36Sopenharmony_ci#endif 4162306a36Sopenharmony_ci1: mov r7, #AT91_PMC_MCKRDY 4262306a36Sopenharmony_ci2: ldr r8, [pmc, #AT91_PMC_SR] 4362306a36Sopenharmony_ci and r8, r7 4462306a36Sopenharmony_ci cmp r8, r7 4562306a36Sopenharmony_ci bne 2b 4662306a36Sopenharmony_ci .endm 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * Wait until master oscillator has stabilized. 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * Side effects: overwrites r7 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci .macro wait_moscrdy 5462306a36Sopenharmony_ci1: ldr r7, [pmc, #AT91_PMC_SR] 5562306a36Sopenharmony_ci tst r7, #AT91_PMC_MOSCS 5662306a36Sopenharmony_ci beq 1b 5762306a36Sopenharmony_ci .endm 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* 6062306a36Sopenharmony_ci * Wait for main oscillator selection is done 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * Side effects: overwrites r7 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci .macro wait_moscsels 6562306a36Sopenharmony_ci1: ldr r7, [pmc, #AT91_PMC_SR] 6662306a36Sopenharmony_ci tst r7, #AT91_PMC_MOSCSELS 6762306a36Sopenharmony_ci beq 1b 6862306a36Sopenharmony_ci .endm 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 7162306a36Sopenharmony_ci * Put the processor to enter the idle state 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * Side effects: overwrites r7 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci .macro at91_cpu_idle 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#if defined(CONFIG_CPU_V7) 7862306a36Sopenharmony_ci mov r7, #AT91_PMC_PCK 7962306a36Sopenharmony_ci str r7, [pmc, #AT91_PMC_SCDR] 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci dsb 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci wfi @ Wait For Interrupt 8462306a36Sopenharmony_ci#else 8562306a36Sopenharmony_ci mcr p15, 0, tmp1, c7, c0, 4 8662306a36Sopenharmony_ci#endif 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci .endm 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/** 9162306a36Sopenharmony_ci * Set state for 2.5V low power regulator 9262306a36Sopenharmony_ci * @ena: 0 - disable regulator 9362306a36Sopenharmony_ci * 1 - enable regulator 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * Side effects: overwrites r7, r8, r9, r10 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci .macro at91_2_5V_reg_set_low_power ena 9862306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 9962306a36Sopenharmony_ci ldr r7, .sfrbu 10062306a36Sopenharmony_ci mov r8, #\ena 10162306a36Sopenharmony_ci ldr r9, [r7, #AT91_SFRBU_25LDOCR] 10262306a36Sopenharmony_ci orr r9, r9, #AT91_SFRBU_25LDOCR_LP 10362306a36Sopenharmony_ci cmp r8, #1 10462306a36Sopenharmony_ci beq lp_done_\ena 10562306a36Sopenharmony_ci bic r9, r9, #AT91_SFRBU_25LDOCR_LP 10662306a36Sopenharmony_cilp_done_\ena: 10762306a36Sopenharmony_ci ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY 10862306a36Sopenharmony_ci orr r9, r9, r10 10962306a36Sopenharmony_ci str r9, [r7, #AT91_SFRBU_25LDOCR] 11062306a36Sopenharmony_ci#endif 11162306a36Sopenharmony_ci .endm 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci .macro at91_backup_set_lpm reg 11462306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 11562306a36Sopenharmony_ci orr \reg, \reg, #0x200000 11662306a36Sopenharmony_ci#endif 11762306a36Sopenharmony_ci .endm 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci .text 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci .arm 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 12462306a36Sopenharmony_ci/** 12562306a36Sopenharmony_ci * Enable self-refresh 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci.macro at91_sramc_self_refresh_ena 13062306a36Sopenharmony_ci ldr r2, .sramc_base 13162306a36Sopenharmony_ci ldr r3, .sramc_phy_base 13262306a36Sopenharmony_ci ldr r7, .pm_mode 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci dsb 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* Disable all AXI ports. */ 13762306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_0] 13862306a36Sopenharmony_ci bic tmp1, tmp1, #0x1 13962306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_0] 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_1] 14262306a36Sopenharmony_ci bic tmp1, tmp1, #0x1 14362306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_1] 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_2] 14662306a36Sopenharmony_ci bic tmp1, tmp1, #0x1 14762306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_2] 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_3] 15062306a36Sopenharmony_ci bic tmp1, tmp1, #0x1 15162306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_3] 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_4] 15462306a36Sopenharmony_ci bic tmp1, tmp1, #0x1 15562306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_4] 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cisr_ena_1: 15862306a36Sopenharmony_ci /* Wait for all ports to disable. */ 15962306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PSTAT] 16062306a36Sopenharmony_ci ldr tmp2, =UDDRC_PSTAT_ALL_PORTS 16162306a36Sopenharmony_ci tst tmp1, tmp2 16262306a36Sopenharmony_ci bne sr_ena_1 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* Switch to self-refresh. */ 16562306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PWRCTL] 16662306a36Sopenharmony_ci orr tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW 16762306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PWRCTL] 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cisr_ena_2: 17062306a36Sopenharmony_ci /* Wait for self-refresh enter. */ 17162306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_STAT] 17262306a36Sopenharmony_ci bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK 17362306a36Sopenharmony_ci cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW 17462306a36Sopenharmony_ci bne sr_ena_2 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* Disable DX DLLs for non-backup modes. */ 17762306a36Sopenharmony_ci cmp r7, #AT91_PM_BACKUP 17862306a36Sopenharmony_ci beq sr_ena_3 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Do not soft reset the AC DLL. */ 18162306a36Sopenharmony_ci ldr tmp1, [r3, DDR3PHY_ACDLLCR] 18262306a36Sopenharmony_ci bic tmp1, tmp1, DDR3PHY_ACDLLCR_DLLSRST 18362306a36Sopenharmony_ci str tmp1, [r3, DDR3PHY_ACDLLCR] 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Disable DX DLLs. */ 18662306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DX0DLLCR] 18762306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 18862306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DX0DLLCR] 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DX1DLLCR] 19162306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 19262306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DX1DLLCR] 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cisr_ena_3: 19562306a36Sopenharmony_ci /* Power down DDR PHY data receivers. */ 19662306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DXCCR] 19762306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR 19862306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DXCCR] 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* Power down ADDR/CMD IO. */ 20162306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_ACIOCR] 20262306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD 20362306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0 20462306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0 20562306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_ACIOCR] 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* Power down ODT. */ 20862306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DSGCR] 20962306a36Sopenharmony_ci orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0 21062306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DSGCR] 21162306a36Sopenharmony_ci.endm 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/** 21462306a36Sopenharmony_ci * Disable self-refresh 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_ci.macro at91_sramc_self_refresh_dis 21962306a36Sopenharmony_ci ldr r2, .sramc_base 22062306a36Sopenharmony_ci ldr r3, .sramc_phy_base 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* Power up DDR PHY data receivers. */ 22362306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DXCCR] 22462306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR 22562306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DXCCR] 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci /* Power up the output of CK and CS pins. */ 22862306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_ACIOCR] 22962306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD 23062306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0 23162306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0 23262306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_ACIOCR] 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* Power up ODT. */ 23562306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DSGCR] 23662306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0 23762306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DSGCR] 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Enable DX DLLs. */ 24062306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DX0DLLCR] 24162306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 24262306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DX0DLLCR] 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_DX1DLLCR] 24562306a36Sopenharmony_ci bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS 24662306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_DX1DLLCR] 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* Enable quasi-dynamic programming. */ 24962306a36Sopenharmony_ci mov tmp1, #0 25062306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_SWCTRL] 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* De-assert SDRAM initialization. */ 25362306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_DFIMISC] 25462306a36Sopenharmony_ci bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN 25562306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_DFIMISC] 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* Quasi-dynamic programming done. */ 25862306a36Sopenharmony_ci mov tmp1, #UDDRC_SWCTRL_SW_DONE 25962306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_SWCTRL] 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cisr_dis_1: 26262306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_SWSTAT] 26362306a36Sopenharmony_ci tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK 26462306a36Sopenharmony_ci beq sr_dis_1 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* DLL soft-reset + DLL lock wait + ITM reset */ 26762306a36Sopenharmony_ci mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \ 26862306a36Sopenharmony_ci DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST) 26962306a36Sopenharmony_ci str tmp1, [r3, #DDR3PHY_PIR] 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cisr_dis_4: 27262306a36Sopenharmony_ci /* Wait for it. */ 27362306a36Sopenharmony_ci ldr tmp1, [r3, #DDR3PHY_PGSR] 27462306a36Sopenharmony_ci tst tmp1, #DDR3PHY_PGSR_IDONE 27562306a36Sopenharmony_ci beq sr_dis_4 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* Enable quasi-dynamic programming. */ 27862306a36Sopenharmony_ci mov tmp1, #0 27962306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_SWCTRL] 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Assert PHY init complete enable signal. */ 28262306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_DFIMISC] 28362306a36Sopenharmony_ci orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN 28462306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_DFIMISC] 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* Programming is done. Set sw_done. */ 28762306a36Sopenharmony_ci mov tmp1, #UDDRC_SWCTRL_SW_DONE 28862306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_SWCTRL] 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cisr_dis_5: 29162306a36Sopenharmony_ci /* Wait for it. */ 29262306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_SWSTAT] 29362306a36Sopenharmony_ci tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK 29462306a36Sopenharmony_ci beq sr_dis_5 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Trigger self-refresh exit. */ 29762306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PWRCTL] 29862306a36Sopenharmony_ci bic tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW 29962306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PWRCTL] 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cisr_dis_6: 30262306a36Sopenharmony_ci /* Wait for self-refresh exit done. */ 30362306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_STAT] 30462306a36Sopenharmony_ci bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK 30562306a36Sopenharmony_ci cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL 30662306a36Sopenharmony_ci bne sr_dis_6 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* Enable all AXI ports. */ 30962306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_0] 31062306a36Sopenharmony_ci orr tmp1, tmp1, #0x1 31162306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_0] 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_1] 31462306a36Sopenharmony_ci orr tmp1, tmp1, #0x1 31562306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_1] 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_2] 31862306a36Sopenharmony_ci orr tmp1, tmp1, #0x1 31962306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_2] 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_3] 32262306a36Sopenharmony_ci orr tmp1, tmp1, #0x1 32362306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_3] 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ldr tmp1, [r2, #UDDRC_PCTRL_4] 32662306a36Sopenharmony_ci orr tmp1, tmp1, #0x1 32762306a36Sopenharmony_ci str tmp1, [r2, #UDDRC_PCTRL_4] 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci dsb 33062306a36Sopenharmony_ci.endm 33162306a36Sopenharmony_ci#else 33262306a36Sopenharmony_ci/** 33362306a36Sopenharmony_ci * Enable self-refresh 33462306a36Sopenharmony_ci * 33562306a36Sopenharmony_ci * register usage: 33662306a36Sopenharmony_ci * @r1: memory type 33762306a36Sopenharmony_ci * @r2: base address of the sram controller 33862306a36Sopenharmony_ci * @r3: temporary 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci.macro at91_sramc_self_refresh_ena 34162306a36Sopenharmony_ci ldr r1, .memtype 34262306a36Sopenharmony_ci ldr r2, .sramc_base 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci cmp r1, #AT91_MEMCTRL_MC 34562306a36Sopenharmony_ci bne sr_ena_ddrc_sf 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* Active SDRAM self-refresh mode */ 34862306a36Sopenharmony_ci mov r3, #1 34962306a36Sopenharmony_ci str r3, [r2, #AT91_MC_SDRAMC_SRR] 35062306a36Sopenharmony_ci b sr_ena_exit 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cisr_ena_ddrc_sf: 35362306a36Sopenharmony_ci cmp r1, #AT91_MEMCTRL_DDRSDR 35462306a36Sopenharmony_ci bne sr_ena_sdramc_sf 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * DDR Memory controller 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci /* LPDDR1 --> force DDR2 mode during self-refresh */ 36162306a36Sopenharmony_ci ldr r3, [r2, #AT91_DDRSDRC_MDR] 36262306a36Sopenharmony_ci str r3, .saved_sam9_mdr 36362306a36Sopenharmony_ci bic r3, r3, #~AT91_DDRSDRC_MD 36462306a36Sopenharmony_ci cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 36562306a36Sopenharmony_ci ldreq r3, [r2, #AT91_DDRSDRC_MDR] 36662306a36Sopenharmony_ci biceq r3, r3, #AT91_DDRSDRC_MD 36762306a36Sopenharmony_ci orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 36862306a36Sopenharmony_ci streq r3, [r2, #AT91_DDRSDRC_MDR] 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci /* Active DDRC self-refresh mode */ 37162306a36Sopenharmony_ci ldr r3, [r2, #AT91_DDRSDRC_LPR] 37262306a36Sopenharmony_ci str r3, .saved_sam9_lpr 37362306a36Sopenharmony_ci bic r3, r3, #AT91_DDRSDRC_LPCB 37462306a36Sopenharmony_ci orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 37562306a36Sopenharmony_ci str r3, [r2, #AT91_DDRSDRC_LPR] 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* If using the 2nd ddr controller */ 37862306a36Sopenharmony_ci ldr r2, .sramc1_base 37962306a36Sopenharmony_ci cmp r2, #0 38062306a36Sopenharmony_ci beq sr_ena_no_2nd_ddrc 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci ldr r3, [r2, #AT91_DDRSDRC_MDR] 38362306a36Sopenharmony_ci str r3, .saved_sam9_mdr1 38462306a36Sopenharmony_ci bic r3, r3, #~AT91_DDRSDRC_MD 38562306a36Sopenharmony_ci cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR 38662306a36Sopenharmony_ci ldreq r3, [r2, #AT91_DDRSDRC_MDR] 38762306a36Sopenharmony_ci biceq r3, r3, #AT91_DDRSDRC_MD 38862306a36Sopenharmony_ci orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 38962306a36Sopenharmony_ci streq r3, [r2, #AT91_DDRSDRC_MDR] 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* Active DDRC self-refresh mode */ 39262306a36Sopenharmony_ci ldr r3, [r2, #AT91_DDRSDRC_LPR] 39362306a36Sopenharmony_ci str r3, .saved_sam9_lpr1 39462306a36Sopenharmony_ci bic r3, r3, #AT91_DDRSDRC_LPCB 39562306a36Sopenharmony_ci orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH 39662306a36Sopenharmony_ci str r3, [r2, #AT91_DDRSDRC_LPR] 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cisr_ena_no_2nd_ddrc: 39962306a36Sopenharmony_ci b sr_ena_exit 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* 40262306a36Sopenharmony_ci * SDRAMC Memory controller 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_cisr_ena_sdramc_sf: 40562306a36Sopenharmony_ci /* Active SDRAMC self-refresh mode */ 40662306a36Sopenharmony_ci ldr r3, [r2, #AT91_SDRAMC_LPR] 40762306a36Sopenharmony_ci str r3, .saved_sam9_lpr 40862306a36Sopenharmony_ci bic r3, r3, #AT91_SDRAMC_LPCB 40962306a36Sopenharmony_ci orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH 41062306a36Sopenharmony_ci str r3, [r2, #AT91_SDRAMC_LPR] 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci ldr r3, .saved_sam9_lpr 41362306a36Sopenharmony_ci str r3, [r2, #AT91_SDRAMC_LPR] 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cisr_ena_exit: 41662306a36Sopenharmony_ci.endm 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci/** 41962306a36Sopenharmony_ci * Disable self-refresh 42062306a36Sopenharmony_ci * 42162306a36Sopenharmony_ci * register usage: 42262306a36Sopenharmony_ci * @r1: memory type 42362306a36Sopenharmony_ci * @r2: base address of the sram controller 42462306a36Sopenharmony_ci * @r3: temporary 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci.macro at91_sramc_self_refresh_dis 42762306a36Sopenharmony_ci ldr r1, .memtype 42862306a36Sopenharmony_ci ldr r2, .sramc_base 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci cmp r1, #AT91_MEMCTRL_MC 43162306a36Sopenharmony_ci bne sr_dis_ddrc_exit_sf 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* 43462306a36Sopenharmony_ci * at91rm9200 Memory controller 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* 43862306a36Sopenharmony_ci * For exiting the self-refresh mode, do nothing, 43962306a36Sopenharmony_ci * automatically exit the self-refresh mode. 44062306a36Sopenharmony_ci */ 44162306a36Sopenharmony_ci b sr_dis_exit 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cisr_dis_ddrc_exit_sf: 44462306a36Sopenharmony_ci cmp r1, #AT91_MEMCTRL_DDRSDR 44562306a36Sopenharmony_ci bne sdramc_exit_sf 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* DDR Memory controller */ 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* Restore MDR in case of LPDDR1 */ 45062306a36Sopenharmony_ci ldr r3, .saved_sam9_mdr 45162306a36Sopenharmony_ci str r3, [r2, #AT91_DDRSDRC_MDR] 45262306a36Sopenharmony_ci /* Restore LPR on AT91 with DDRAM */ 45362306a36Sopenharmony_ci ldr r3, .saved_sam9_lpr 45462306a36Sopenharmony_ci str r3, [r2, #AT91_DDRSDRC_LPR] 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci /* If using the 2nd ddr controller */ 45762306a36Sopenharmony_ci ldr r2, .sramc1_base 45862306a36Sopenharmony_ci cmp r2, #0 45962306a36Sopenharmony_ci ldrne r3, .saved_sam9_mdr1 46062306a36Sopenharmony_ci strne r3, [r2, #AT91_DDRSDRC_MDR] 46162306a36Sopenharmony_ci ldrne r3, .saved_sam9_lpr1 46262306a36Sopenharmony_ci strne r3, [r2, #AT91_DDRSDRC_LPR] 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci b sr_dis_exit 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cisdramc_exit_sf: 46762306a36Sopenharmony_ci /* SDRAMC Memory controller */ 46862306a36Sopenharmony_ci ldr r3, .saved_sam9_lpr 46962306a36Sopenharmony_ci str r3, [r2, #AT91_SDRAMC_LPR] 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cisr_dis_exit: 47262306a36Sopenharmony_ci.endm 47362306a36Sopenharmony_ci#endif 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci.macro at91_pm_ulp0_mode 47662306a36Sopenharmony_ci ldr pmc, .pmc_base 47762306a36Sopenharmony_ci ldr tmp2, .pm_mode 47862306a36Sopenharmony_ci ldr tmp3, .mckr_offset 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* Check if ULP0 fast variant has been requested. */ 48162306a36Sopenharmony_ci cmp tmp2, #AT91_PM_ULP0_FAST 48262306a36Sopenharmony_ci bne 0f 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci /* Set highest prescaler for power saving */ 48562306a36Sopenharmony_ci ldr tmp1, [pmc, tmp3] 48662306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PRES 48762306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PRES_64 48862306a36Sopenharmony_ci str tmp1, [pmc, tmp3] 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci mov tmp3, #0 49162306a36Sopenharmony_ci wait_mckrdy tmp3 49262306a36Sopenharmony_ci b 1f 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci0: 49562306a36Sopenharmony_ci /* Turn off the crystal oscillator */ 49662306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 49762306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_MOSCEN 49862306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 49962306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* Save RC oscillator state */ 50262306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_SR] 50362306a36Sopenharmony_ci str tmp1, .saved_osc_status 50462306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 50562306a36Sopenharmony_ci bne 1f 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci /* Turn off RC oscillator */ 50862306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 50962306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 51062306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 51162306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 51262306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* Wait main RC disabled done */ 51562306a36Sopenharmony_ci2: ldr tmp1, [pmc, #AT91_PMC_SR] 51662306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 51762306a36Sopenharmony_ci bne 2b 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* Wait for interrupt */ 52062306a36Sopenharmony_ci1: at91_cpu_idle 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* Check if ULP0 fast variant has been requested. */ 52362306a36Sopenharmony_ci cmp tmp2, #AT91_PM_ULP0_FAST 52462306a36Sopenharmony_ci bne 5f 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* Set lowest prescaler for fast resume. */ 52762306a36Sopenharmony_ci ldr tmp3, .mckr_offset 52862306a36Sopenharmony_ci ldr tmp1, [pmc, tmp3] 52962306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PRES 53062306a36Sopenharmony_ci str tmp1, [pmc, tmp3] 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci mov tmp3, #0 53362306a36Sopenharmony_ci wait_mckrdy tmp3 53462306a36Sopenharmony_ci b 6f 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci5: /* Restore RC oscillator state */ 53762306a36Sopenharmony_ci ldr tmp1, .saved_osc_status 53862306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 53962306a36Sopenharmony_ci beq 4f 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* Turn on RC oscillator */ 54262306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 54362306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 54462306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 54562306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 54662306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* Wait main RC stabilization */ 54962306a36Sopenharmony_ci3: ldr tmp1, [pmc, #AT91_PMC_SR] 55062306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 55162306a36Sopenharmony_ci beq 3b 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci /* Turn on the crystal oscillator */ 55462306a36Sopenharmony_ci4: ldr tmp1, [pmc, #AT91_CKGR_MOR] 55562306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_MOSCEN 55662306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 55762306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci wait_moscrdy 56062306a36Sopenharmony_ci6: 56162306a36Sopenharmony_ci.endm 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci/** 56462306a36Sopenharmony_ci * Note: This procedure only applies on the platform which uses 56562306a36Sopenharmony_ci * the external crystal oscillator as a main clock source. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci.macro at91_pm_ulp1_mode 56862306a36Sopenharmony_ci ldr pmc, .pmc_base 56962306a36Sopenharmony_ci ldr tmp2, .mckr_offset 57062306a36Sopenharmony_ci mov tmp3, #0 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci /* Save RC oscillator state and check if it is enabled. */ 57362306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_SR] 57462306a36Sopenharmony_ci str tmp1, .saved_osc_status 57562306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 57662306a36Sopenharmony_ci bne 2f 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* Enable RC oscillator */ 57962306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 58062306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_MOSCRCEN 58162306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 58262306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 58362306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /* Wait main RC stabilization */ 58662306a36Sopenharmony_ci1: ldr tmp1, [pmc, #AT91_PMC_SR] 58762306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 58862306a36Sopenharmony_ci beq 1b 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci /* Switch the main clock source to 12-MHz RC oscillator */ 59162306a36Sopenharmony_ci2: ldr tmp1, [pmc, #AT91_CKGR_MOR] 59262306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_MOSCSEL 59362306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 59462306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 59562306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci wait_moscsels 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Disable the crystal oscillator */ 60062306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 60162306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_MOSCEN 60262306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 60362306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 60462306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Switch the master clock source to main clock */ 60762306a36Sopenharmony_ci ldr tmp1, [pmc, tmp2] 60862306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_CSS 60962306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 61062306a36Sopenharmony_ci str tmp1, [pmc, tmp2] 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci wait_mckrdy tmp3 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */ 61562306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 61662306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_WAITMODE 61762306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 61862306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 61962306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* Quirk for SAM9X60's PMC */ 62262306a36Sopenharmony_ci nop 62362306a36Sopenharmony_ci nop 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci wait_mckrdy tmp3 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* Enable the crystal oscillator */ 62862306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 62962306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_MOSCEN 63062306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 63162306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 63262306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci wait_moscrdy 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* Switch the master clock source to slow clock */ 63762306a36Sopenharmony_ci ldr tmp1, [pmc, tmp2] 63862306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_CSS 63962306a36Sopenharmony_ci str tmp1, [pmc, tmp2] 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci wait_mckrdy tmp3 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* Switch main clock source to crystal oscillator */ 64462306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 64562306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_MOSCSEL 64662306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 64762306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 64862306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci wait_moscsels 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci /* Switch the master clock source to main clock */ 65362306a36Sopenharmony_ci ldr tmp1, [pmc, tmp2] 65462306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_CSS 65562306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 65662306a36Sopenharmony_ci str tmp1, [pmc, tmp2] 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci wait_mckrdy tmp3 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* Restore RC oscillator state */ 66162306a36Sopenharmony_ci ldr tmp1, .saved_osc_status 66262306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 66362306a36Sopenharmony_ci bne 3f 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci /* Disable RC oscillator */ 66662306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_MOR] 66762306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_MOSCRCEN 66862306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_KEY_MASK 66962306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_KEY 67062306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_MOR] 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* Wait RC oscillator disable done */ 67362306a36Sopenharmony_ci4: ldr tmp1, [pmc, #AT91_PMC_SR] 67462306a36Sopenharmony_ci tst tmp1, #AT91_PMC_MOSCRCS 67562306a36Sopenharmony_ci bne 4b 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci3: 67862306a36Sopenharmony_ci.endm 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci.macro at91_plla_disable 68162306a36Sopenharmony_ci /* Save PLLA setting and disable it */ 68262306a36Sopenharmony_ci ldr tmp1, .pmc_version 68362306a36Sopenharmony_ci cmp tmp1, #AT91_PMC_V1 68462306a36Sopenharmony_ci beq 1f 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL 68762306a36Sopenharmony_ci /* Save PLLA settings. */ 68862306a36Sopenharmony_ci ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT] 68962306a36Sopenharmony_ci bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID 69062306a36Sopenharmony_ci str tmp2, [pmc, #AT91_PMC_PLL_UPDT] 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci /* save div. */ 69362306a36Sopenharmony_ci mov tmp1, #0 69462306a36Sopenharmony_ci ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0] 69562306a36Sopenharmony_ci bic tmp2, tmp2, #0xffffff00 69662306a36Sopenharmony_ci orr tmp1, tmp1, tmp2 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci /* save mul. */ 69962306a36Sopenharmony_ci ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL1] 70062306a36Sopenharmony_ci bic tmp2, tmp2, #0xffffff 70162306a36Sopenharmony_ci orr tmp1, tmp1, tmp2 70262306a36Sopenharmony_ci str tmp1, .saved_pllar 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* step 2. */ 70562306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 70662306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 70762306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 70862306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci /* step 3. */ 71162306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 71262306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK 71362306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 71462306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* step 4. */ 71762306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 71862306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 71962306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 72062306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci /* step 5. */ 72362306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 72462306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 72562306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci /* step 7. */ 72862306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 72962306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 73062306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 73162306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci b 2f 73462306a36Sopenharmony_ci#endif 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci1: /* Save PLLA setting and disable it */ 73762306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_CKGR_PLLAR] 73862306a36Sopenharmony_ci str tmp1, .saved_pllar 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci /* Disable PLLA. */ 74162306a36Sopenharmony_ci mov tmp1, #AT91_PMC_PLLCOUNT 74262306a36Sopenharmony_ci orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ 74362306a36Sopenharmony_ci str tmp1, [pmc, #AT91_CKGR_PLLAR] 74462306a36Sopenharmony_ci2: 74562306a36Sopenharmony_ci.endm 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci.macro at91_plla_enable 74862306a36Sopenharmony_ci ldr tmp2, .saved_pllar 74962306a36Sopenharmony_ci ldr tmp3, .pmc_version 75062306a36Sopenharmony_ci cmp tmp3, #AT91_PMC_V1 75162306a36Sopenharmony_ci beq 4f 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL 75462306a36Sopenharmony_ci /* step 1. */ 75562306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 75662306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 75762306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 75862306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci /* step 2. */ 76162306a36Sopenharmony_ci ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA 76262306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_ACR] 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci /* step 3. */ 76562306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL1] 76662306a36Sopenharmony_ci mov tmp3, tmp2 76762306a36Sopenharmony_ci bic tmp3, tmp3, #0xffffff 76862306a36Sopenharmony_ci orr tmp1, tmp1, tmp3 76962306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_CTRL1] 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci /* step 8. */ 77262306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 77362306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 77462306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 77562306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* step 9. */ 77862306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 77962306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK 78062306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL 78162306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK 78262306a36Sopenharmony_ci bic tmp1, tmp1, #0xff 78362306a36Sopenharmony_ci mov tmp3, tmp2 78462306a36Sopenharmony_ci bic tmp3, tmp3, #0xffffff00 78562306a36Sopenharmony_ci orr tmp1, tmp1, tmp3 78662306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci /* step 10. */ 78962306a36Sopenharmony_ci ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] 79062306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE 79162306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID 79262306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_PLL_UPDT] 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* step 11. */ 79562306a36Sopenharmony_ci3: ldr tmp1, [pmc, #AT91_PMC_PLL_ISR0] 79662306a36Sopenharmony_ci tst tmp1, #0x1 79762306a36Sopenharmony_ci beq 3b 79862306a36Sopenharmony_ci b 2f 79962306a36Sopenharmony_ci#endif 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* Restore PLLA setting */ 80262306a36Sopenharmony_ci4: str tmp2, [pmc, #AT91_CKGR_PLLAR] 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci /* Enable PLLA. */ 80562306a36Sopenharmony_ci tst tmp2, #(AT91_PMC_MUL & 0xff0000) 80662306a36Sopenharmony_ci bne 1f 80762306a36Sopenharmony_ci tst tmp2, #(AT91_PMC_MUL & ~0xff0000) 80862306a36Sopenharmony_ci beq 2f 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci1: ldr tmp1, [pmc, #AT91_PMC_SR] 81162306a36Sopenharmony_ci tst tmp1, #AT91_PMC_LOCKA 81262306a36Sopenharmony_ci beq 1b 81362306a36Sopenharmony_ci2: 81462306a36Sopenharmony_ci.endm 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci/** 81762306a36Sopenharmony_ci * at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock 81862306a36Sopenharmony_ci * 81962306a36Sopenharmony_ci * Side effects: overwrites tmp1, tmp2 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci.macro at91_mckx_ps_enable 82262306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 82362306a36Sopenharmony_ci ldr pmc, .pmc_base 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci /* There are 4 MCKs we need to handle: MCK1..4 */ 82662306a36Sopenharmony_ci mov tmp1, #1 82762306a36Sopenharmony_cie_loop: cmp tmp1, #5 82862306a36Sopenharmony_ci beq e_done 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* Write MCK ID to retrieve the settings. */ 83162306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_MCR_V2] 83262306a36Sopenharmony_ci ldr tmp2, [pmc, #AT91_PMC_MCR_V2] 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cie_save_mck1: 83562306a36Sopenharmony_ci cmp tmp1, #1 83662306a36Sopenharmony_ci bne e_save_mck2 83762306a36Sopenharmony_ci str tmp2, .saved_mck1 83862306a36Sopenharmony_ci b e_ps 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_cie_save_mck2: 84162306a36Sopenharmony_ci cmp tmp1, #2 84262306a36Sopenharmony_ci bne e_save_mck3 84362306a36Sopenharmony_ci str tmp2, .saved_mck2 84462306a36Sopenharmony_ci b e_ps 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_cie_save_mck3: 84762306a36Sopenharmony_ci cmp tmp1, #3 84862306a36Sopenharmony_ci bne e_save_mck4 84962306a36Sopenharmony_ci str tmp2, .saved_mck3 85062306a36Sopenharmony_ci b e_ps 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cie_save_mck4: 85362306a36Sopenharmony_ci str tmp2, .saved_mck4 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cie_ps: 85662306a36Sopenharmony_ci /* Use CSS=MAINCK and DIV=1. */ 85762306a36Sopenharmony_ci bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS 85862306a36Sopenharmony_ci bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV 85962306a36Sopenharmony_ci orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK 86062306a36Sopenharmony_ci orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1 86162306a36Sopenharmony_ci str tmp2, [pmc, #AT91_PMC_MCR_V2] 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci wait_mckrdy tmp1 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci add tmp1, tmp1, #1 86662306a36Sopenharmony_ci b e_loop 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_cie_done: 86962306a36Sopenharmony_ci#endif 87062306a36Sopenharmony_ci.endm 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci/** 87362306a36Sopenharmony_ci * at91_mckx_ps_restore: restore MCK1..4 settings 87462306a36Sopenharmony_ci * 87562306a36Sopenharmony_ci * Side effects: overwrites tmp1, tmp2 87662306a36Sopenharmony_ci */ 87762306a36Sopenharmony_ci.macro at91_mckx_ps_restore 87862306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 87962306a36Sopenharmony_ci ldr pmc, .pmc_base 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci /* There are 4 MCKs we need to handle: MCK1..4 */ 88262306a36Sopenharmony_ci mov tmp1, #1 88362306a36Sopenharmony_cir_loop: cmp tmp1, #5 88462306a36Sopenharmony_ci beq r_done 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cir_save_mck1: 88762306a36Sopenharmony_ci cmp tmp1, #1 88862306a36Sopenharmony_ci bne r_save_mck2 88962306a36Sopenharmony_ci ldr tmp2, .saved_mck1 89062306a36Sopenharmony_ci b r_ps 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cir_save_mck2: 89362306a36Sopenharmony_ci cmp tmp1, #2 89462306a36Sopenharmony_ci bne r_save_mck3 89562306a36Sopenharmony_ci ldr tmp2, .saved_mck2 89662306a36Sopenharmony_ci b r_ps 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cir_save_mck3: 89962306a36Sopenharmony_ci cmp tmp1, #3 90062306a36Sopenharmony_ci bne r_save_mck4 90162306a36Sopenharmony_ci ldr tmp2, .saved_mck3 90262306a36Sopenharmony_ci b r_ps 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_cir_save_mck4: 90562306a36Sopenharmony_ci ldr tmp2, .saved_mck4 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cir_ps: 90862306a36Sopenharmony_ci /* Write MCK ID to retrieve the settings. */ 90962306a36Sopenharmony_ci str tmp1, [pmc, #AT91_PMC_MCR_V2] 91062306a36Sopenharmony_ci ldr tmp3, [pmc, #AT91_PMC_MCR_V2] 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci /* We need to restore CSS and DIV. */ 91362306a36Sopenharmony_ci bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS 91462306a36Sopenharmony_ci bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV 91562306a36Sopenharmony_ci orr tmp3, tmp3, tmp2 91662306a36Sopenharmony_ci bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK 91762306a36Sopenharmony_ci orr tmp3, tmp3, tmp1 91862306a36Sopenharmony_ci orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD 91962306a36Sopenharmony_ci str tmp2, [pmc, #AT91_PMC_MCR_V2] 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci wait_mckrdy tmp1 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci add tmp1, tmp1, #1 92462306a36Sopenharmony_ci b r_loop 92562306a36Sopenharmony_cir_done: 92662306a36Sopenharmony_ci#endif 92762306a36Sopenharmony_ci.endm 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci.macro at91_ulp_mode 93062306a36Sopenharmony_ci at91_mckx_ps_enable 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci ldr pmc, .pmc_base 93362306a36Sopenharmony_ci ldr tmp2, .mckr_offset 93462306a36Sopenharmony_ci ldr tmp3, .pm_mode 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci /* Save Master clock setting */ 93762306a36Sopenharmony_ci ldr tmp1, [pmc, tmp2] 93862306a36Sopenharmony_ci str tmp1, .saved_mckr 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci /* 94162306a36Sopenharmony_ci * Set master clock source to: 94262306a36Sopenharmony_ci * - MAINCK if using ULP0 fast variant 94362306a36Sopenharmony_ci * - slow clock, otherwise 94462306a36Sopenharmony_ci */ 94562306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_CSS 94662306a36Sopenharmony_ci cmp tmp3, #AT91_PM_ULP0_FAST 94762306a36Sopenharmony_ci bne save_mck 94862306a36Sopenharmony_ci orr tmp1, tmp1, #AT91_PMC_CSS_MAIN 94962306a36Sopenharmony_cisave_mck: 95062306a36Sopenharmony_ci str tmp1, [pmc, tmp2] 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci mov tmp3, #0 95362306a36Sopenharmony_ci wait_mckrdy tmp3 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci at91_plla_disable 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci /* Enable low power mode for 2.5V regulator. */ 95862306a36Sopenharmony_ci at91_2_5V_reg_set_low_power 1 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci ldr tmp3, .pm_mode 96162306a36Sopenharmony_ci cmp tmp3, #AT91_PM_ULP1 96262306a36Sopenharmony_ci beq ulp1_mode 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci at91_pm_ulp0_mode 96562306a36Sopenharmony_ci b ulp_exit 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ciulp1_mode: 96862306a36Sopenharmony_ci at91_pm_ulp1_mode 96962306a36Sopenharmony_ci b ulp_exit 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ciulp_exit: 97262306a36Sopenharmony_ci /* Disable low power mode for 2.5V regulator. */ 97362306a36Sopenharmony_ci at91_2_5V_reg_set_low_power 0 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci ldr pmc, .pmc_base 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci at91_plla_enable 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* 98062306a36Sopenharmony_ci * Restore master clock setting 98162306a36Sopenharmony_ci */ 98262306a36Sopenharmony_ci ldr tmp1, .mckr_offset 98362306a36Sopenharmony_ci ldr tmp2, .saved_mckr 98462306a36Sopenharmony_ci str tmp2, [pmc, tmp1] 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci mov tmp3, #0 98762306a36Sopenharmony_ci wait_mckrdy tmp3 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci at91_mckx_ps_restore 99062306a36Sopenharmony_ci.endm 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci.macro at91_backup_mode 99362306a36Sopenharmony_ci /* Switch the master clock source to slow clock. */ 99462306a36Sopenharmony_ci ldr pmc, .pmc_base 99562306a36Sopenharmony_ci ldr tmp2, .mckr_offset 99662306a36Sopenharmony_ci ldr tmp1, [pmc, tmp2] 99762306a36Sopenharmony_ci bic tmp1, tmp1, #AT91_PMC_CSS 99862306a36Sopenharmony_ci str tmp1, [pmc, tmp2] 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci mov tmp3, #0 100162306a36Sopenharmony_ci wait_mckrdy tmp3 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci /*BUMEN*/ 100462306a36Sopenharmony_ci ldr r0, .sfrbu 100562306a36Sopenharmony_ci mov tmp1, #0x1 100662306a36Sopenharmony_ci str tmp1, [r0, #0x10] 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci /* Wait for it. */ 100962306a36Sopenharmony_ci1: ldr tmp1, [r0, #0x10] 101062306a36Sopenharmony_ci tst tmp1, #0x1 101162306a36Sopenharmony_ci beq 1b 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci /* Shutdown */ 101462306a36Sopenharmony_ci ldr r0, .shdwc 101562306a36Sopenharmony_ci mov tmp1, #0xA5000000 101662306a36Sopenharmony_ci add tmp1, tmp1, #0x1 101762306a36Sopenharmony_ci at91_backup_set_lpm tmp1 101862306a36Sopenharmony_ci str tmp1, [r0, #0] 101962306a36Sopenharmony_ci.endm 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci/* 102262306a36Sopenharmony_ci * void at91_suspend_sram_fn(struct at91_pm_data*) 102362306a36Sopenharmony_ci * @input param: 102462306a36Sopenharmony_ci * @r0: base address of struct at91_pm_data 102562306a36Sopenharmony_ci */ 102662306a36Sopenharmony_ci/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ 102762306a36Sopenharmony_ci .align 3 102862306a36Sopenharmony_ciENTRY(at91_pm_suspend_in_sram) 102962306a36Sopenharmony_ci /* Save registers on stack */ 103062306a36Sopenharmony_ci stmfd sp!, {r4 - r12, lr} 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci /* Drain write buffer */ 103362306a36Sopenharmony_ci mov tmp1, #0 103462306a36Sopenharmony_ci mcr p15, 0, tmp1, c7, c10, 4 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci /* Flush tlb. */ 103762306a36Sopenharmony_ci mov r4, #0 103862306a36Sopenharmony_ci mcr p15, 0, r4, c8, c7, 0 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET] 104162306a36Sopenharmony_ci str tmp1, .mckr_offset 104262306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_PMC_VERSION] 104362306a36Sopenharmony_ci str tmp1, .pmc_version 104462306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_MEMCTRL] 104562306a36Sopenharmony_ci str tmp1, .memtype 104662306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_MODE] 104762306a36Sopenharmony_ci str tmp1, .pm_mode 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci /* 105062306a36Sopenharmony_ci * ldrne below are here to preload their address in the TLB as access 105162306a36Sopenharmony_ci * to RAM may be limited while in self-refresh. 105262306a36Sopenharmony_ci */ 105362306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_PMC] 105462306a36Sopenharmony_ci str tmp1, .pmc_base 105562306a36Sopenharmony_ci cmp tmp1, #0 105662306a36Sopenharmony_ci ldrne tmp2, [tmp1, #0] 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_RAMC0] 105962306a36Sopenharmony_ci str tmp1, .sramc_base 106062306a36Sopenharmony_ci cmp tmp1, #0 106162306a36Sopenharmony_ci ldrne tmp2, [tmp1, #0] 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_RAMC1] 106462306a36Sopenharmony_ci str tmp1, .sramc1_base 106562306a36Sopenharmony_ci cmp tmp1, #0 106662306a36Sopenharmony_ci ldrne tmp2, [tmp1, #0] 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci#ifndef CONFIG_SOC_SAM_V4_V5 106962306a36Sopenharmony_ci /* ldrne below are here to preload their address in the TLB */ 107062306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_RAMC_PHY] 107162306a36Sopenharmony_ci str tmp1, .sramc_phy_base 107262306a36Sopenharmony_ci cmp tmp1, #0 107362306a36Sopenharmony_ci ldrne tmp2, [tmp1, #0] 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_SHDWC] 107662306a36Sopenharmony_ci str tmp1, .shdwc 107762306a36Sopenharmony_ci cmp tmp1, #0 107862306a36Sopenharmony_ci ldrne tmp2, [tmp1, #0] 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci ldr tmp1, [r0, #PM_DATA_SFRBU] 108162306a36Sopenharmony_ci str tmp1, .sfrbu 108262306a36Sopenharmony_ci cmp tmp1, #0 108362306a36Sopenharmony_ci ldrne tmp2, [tmp1, #0x10] 108462306a36Sopenharmony_ci#endif 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci /* Active the self-refresh mode */ 108762306a36Sopenharmony_ci at91_sramc_self_refresh_ena 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci ldr r0, .pm_mode 109062306a36Sopenharmony_ci cmp r0, #AT91_PM_STANDBY 109162306a36Sopenharmony_ci beq standby 109262306a36Sopenharmony_ci cmp r0, #AT91_PM_BACKUP 109362306a36Sopenharmony_ci beq backup_mode 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci at91_ulp_mode 109662306a36Sopenharmony_ci b exit_suspend 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistandby: 109962306a36Sopenharmony_ci /* Wait for interrupt */ 110062306a36Sopenharmony_ci ldr pmc, .pmc_base 110162306a36Sopenharmony_ci at91_cpu_idle 110262306a36Sopenharmony_ci b exit_suspend 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_cibackup_mode: 110562306a36Sopenharmony_ci at91_backup_mode 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ciexit_suspend: 110862306a36Sopenharmony_ci /* Exit the self-refresh mode */ 110962306a36Sopenharmony_ci at91_sramc_self_refresh_dis 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci /* Restore registers, and return */ 111262306a36Sopenharmony_ci ldmfd sp!, {r4 - r12, pc} 111362306a36Sopenharmony_ciENDPROC(at91_pm_suspend_in_sram) 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci.pmc_base: 111662306a36Sopenharmony_ci .word 0 111762306a36Sopenharmony_ci.sramc_base: 111862306a36Sopenharmony_ci .word 0 111962306a36Sopenharmony_ci.sramc1_base: 112062306a36Sopenharmony_ci .word 0 112162306a36Sopenharmony_ci.sramc_phy_base: 112262306a36Sopenharmony_ci .word 0 112362306a36Sopenharmony_ci.shdwc: 112462306a36Sopenharmony_ci .word 0 112562306a36Sopenharmony_ci.sfrbu: 112662306a36Sopenharmony_ci .word 0 112762306a36Sopenharmony_ci.memtype: 112862306a36Sopenharmony_ci .word 0 112962306a36Sopenharmony_ci.pm_mode: 113062306a36Sopenharmony_ci .word 0 113162306a36Sopenharmony_ci.mckr_offset: 113262306a36Sopenharmony_ci .word 0 113362306a36Sopenharmony_ci.pmc_version: 113462306a36Sopenharmony_ci .word 0 113562306a36Sopenharmony_ci.saved_mckr: 113662306a36Sopenharmony_ci .word 0 113762306a36Sopenharmony_ci.saved_pllar: 113862306a36Sopenharmony_ci .word 0 113962306a36Sopenharmony_ci.saved_sam9_lpr: 114062306a36Sopenharmony_ci .word 0 114162306a36Sopenharmony_ci.saved_sam9_lpr1: 114262306a36Sopenharmony_ci .word 0 114362306a36Sopenharmony_ci.saved_sam9_mdr: 114462306a36Sopenharmony_ci .word 0 114562306a36Sopenharmony_ci.saved_sam9_mdr1: 114662306a36Sopenharmony_ci .word 0 114762306a36Sopenharmony_ci.saved_osc_status: 114862306a36Sopenharmony_ci .word 0 114962306a36Sopenharmony_ci#ifdef CONFIG_SOC_SAMA7 115062306a36Sopenharmony_ci.saved_mck1: 115162306a36Sopenharmony_ci .word 0 115262306a36Sopenharmony_ci.saved_mck2: 115362306a36Sopenharmony_ci .word 0 115462306a36Sopenharmony_ci.saved_mck3: 115562306a36Sopenharmony_ci .word 0 115662306a36Sopenharmony_ci.saved_mck4: 115762306a36Sopenharmony_ci .word 0 115862306a36Sopenharmony_ci#endif 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ciENTRY(at91_pm_suspend_in_sram_sz) 116162306a36Sopenharmony_ci .word .-at91_pm_suspend_in_sram 1162